Active Foundation · Example
A note anchored to its row
A note anchored to its rowClient
- Ada Jansen
- Bram de Vries
- Chloé Martin
Full source examples/ui/anchored-popover.tsx
// apps/docs/examples/ui/anchored-popover.tsx'use client';
import {useState} from 'react';
import { AnchoredPopover, AnchoredPopoverContent,} from '@workspace/active-ui/components/composed/anchored-popover';import {Button} from '@workspace/active-ui/components/primitives/button';
const ROWS = [ {id: 'r1', name: 'Ada Jansen', note: 'Address changed on 3 March.'}, { id: 'r2', name: 'Bram de Vries', note: 'Statement returned as undeliverable.', }, {id: 'r3', name: 'Chloé Martin', note: 'No remarks.'},];
/** * A popover that floats next to an element that is not its trigger: here * the whole row, opened by the button at its end. The popover is * controlled; the row is its `anchor`. */export default function AnchoredPopoverExample() { const [open, setOpen] = useState<{ id: string; row: HTMLElement; } | null>(null); const note = ROWS.find((row) => row.id === open?.id); return ( <> <ul className="w-full max-w-md divide-y rounded-md border"> {ROWS.map((row) => ( <li key={row.id} className="flex items-center justify-between gap-3 px-3 py-2 text-sm" > {row.name} <Button size="sm" variant="ghost" aria-expanded={open?.id === row.id} onClick={(event) => { // The row around the button is the anchor. const element = event.currentTarget.closest('li'); setOpen( open?.id === row.id || !element ? null : {id: row.id, row: element}, ); }} > Note </Button> </li> ))} </ul> <AnchoredPopover open={open !== null} onOpenChange={(next) => { if (!next) setOpen(null); }} > <AnchoredPopoverContent anchor={open?.row} side="bottom" align="end" aria-label={note ? `Note on ${note.name}` : undefined} > <p className="font-medium">{note?.name}</p> <p className="text-muted-foreground">{note?.note}</p> </AnchoredPopoverContent> </AnchoredPopover> </> );}