import type { Placement } from "@floating-ui/react"; import type { ReactElement, ReactNode } from "react"; export type PopoverProps = { children: ReactNode; className?: string; /** * Required, and it becomes the panel's `aria-label`. A * `role="dialog"` takes **no accessible name from its content**, * so an unnamed one is announced as "dialog" and is unfindable * by `getByRole("dialog", { name })` — the same trap `Spinner` * walked into in M3 with `role="status"`. */ heading: string; isVisible: boolean; /** * Outside press and Escape both land here, through floating-ui's * `useDismiss`. Wire it to a `useVisibility()`'s `hide`. */ onDismiss: () => void; placement?: Placement; /** * The control the panel hangs off. **Cloned, not wrapped** — an * extra `
` around a button is how a toolbar's layout * quietly changes. */ trigger: ReactElement; }; /** * Replaces mux-magic's `@radix-ui/react-popover` re-export, and it * is a rewrite rather than a swap for one reason: Radix owns * `open`, so wrapping it leaves `useVisibility` and Radix both * believing they hold it. `@floating-ui/react` is the layer Radix, * Base UI, and Ark UI are all *built on*, and it is controlled by * construction — you pass state in and it never stores any. * * What floating-ui is used for is what only it can do: collision * handling (`flip`, `shift`), a real dismiss layer, and focus * management — all of it consolidated in `useAnchoredOverlay`. * Positioning strategy and the ARIA wiring come from the platform and * from `useRole`. * * ### Portalled, not the top layer * * The panel goes in a `FloatingPortal` to `document.body`. The top * layer (`popover="manual"`) was reached for first — it needs no * portal and no `z-index` — but it does not escape an * `overflow: hidden` ancestor's *clipping* in every case the fleet * hit, and a portal does. The objection a portal used to raise, that * it moves the panel out of a scoped `canvas` query, is answered two * ways: `useRole` writes `aria-controls` on the trigger pointing at * the panel `id`, so trigger→panel stays followable across the * boundary; and the story scopes panel queries to * `within(document.body)` while the structural `expectAgentDrivable` * needs no change. `strategy: "fixed"` keeps the coordinates * viewport-relative. */ export declare const Popover: ({ children, className, heading, isVisible, onDismiss, placement, trigger, }: PopoverProps) => ReactNode; //# sourceMappingURL=Popover.d.ts.map