import { ReactNode } from 'react'; import { Placement } from '@floating-ui/react'; import { PopoverTrigger } from './PopoverTrigger'; import { DisableCloseOnEscapeOrClickProps } from '../../../types'; import { OpenCloseTransitionStateEffects } from '../../../internal/hooks'; /** ARIA role of the beta Popover popup. */ export type PopoverRole = "dialog" | "listbox" | "tree" | "grid"; /** * Sub-options for `placement="auto"`. Constrains which sides `autoPlacement()` * may choose from. Ignored when a specific placement is set. */ export type PopoverAutoPlacementConfig = { /** Limits which sides autoPlacement() considers. Defaults to all sides. */ allowedPlacements?: Placement[]; }; /** * Sub-options for a specific placement (e.g. `"bottom"`). Overrides the default * opposite-side fallback sequence used by `flip()`. Ignored when `placement="auto"`. */ export type PopoverFlipPlacementConfig = { /** Explicit fallback sequence for flip(). Overrides the default opposite-side fallback. */ fallbackPlacements?: Placement[]; }; type PopoverPropsBase = { /** Content to render inside the popover tree. */ children?: ReactNode; /** Controlled open state. */ open?: boolean; /** Initial open state for uncontrolled mode. @default false */ defaultOpen?: boolean; /** Fires when the popover closes for any non-hover reason. */ onClose?: () => void; /** Fires when the user clicks outside the popover. Not fired when disableCloseOnClickOutside is set. */ onClickOutside?: (e: globalThis.MouseEvent) => void; /** Whether to show the arrow/caret indicator. @default false */ enableCaret?: boolean; /** Whether to remove default padding from the content area. @default false */ noPadding?: boolean; /** Whether the popover width should match the trigger element width. @default false */ matchReferenceWidth?: boolean; /** Whether the popover should have a fixed width of 40dvw. @default false */ fixedWidth?: boolean; /** Fills available viewport height between the trigger and viewport edge. @default false */ fillAvailableHeight?: boolean; /** Maximum height of the popover content. */ maxHeight?: number | string; /** Constrains the popover to available viewport height. @default false */ fitScreen?: boolean; /** Minimum height of the popover content. @default "2.875rem" */ minHeight?: number | string; } & DisableCloseOnEscapeOrClickProps & OpenCloseTransitionStateEffects; /** * Role-specific props for `role="dialog"` (default). * * Only dialog popovers use `FloatingFocusManager` — focus moves into the content * on open. The `modal`, `openOnHover`, and `delay` props are only meaningful * in this context. */ type DialogRoleProps = { /** * The ARIA role of the popup. Drives `aria-haspopup` on the trigger and * `role` on the content via Floating UI's `useRole`. * * @default "dialog" */ role?: "dialog"; /** Traps focus until closed (modal) or closes on Tab-out (non-modal). @default false */ modal?: boolean; /** * Whether the popover opens on hover instead of click. @default false * * @remarks * Hover-triggered popovers should contain only readable text — no interactive * elements (buttons, links, inputs). The content is intentionally removed from * the tab order so Tab moves cleanly between page elements. Interactive content * inside a hover-triggered popover is unreachable by keyboard users. Use a * click-triggered popover (default) when the content includes interactive elements. */ openOnHover?: boolean; /** Delay in ms before opening on hover. @default 100 */ delay?: number; }; /** * Role-specific props for combobox popup roles (`listbox`, `tree`, `grid`). * * These roles follow the ARIA combobox pattern — focus stays on the trigger and * the inner component (e.g. `Listbox`) owns the role and keyboard navigation. * `FloatingFocusManager` is disabled. `modal`, `openOnHover`, and `delay` are * not applicable and are excluded at the type level. * * @remarks * Floating UI adds `role="combobox"` to the trigger element for these roles. * The `combobox` ARIA role only accepts names from `aria-label` or * `aria-labelledby` — visible text content is not used. Always provide an * explicit `aria-label` on `Popover.Button` or your custom trigger. * * @example * // ✅ Correct — explicit aria-label required for non-dialog roles * * Open * * ... * * */ type NonDialogRoleProps = { /** The ARIA role of the popup. */ role: Exclude; modal?: never; openOnHover?: never; delay?: never; }; type WithAutoPlacement = { /** * Uses `autoPlacement()` — picks the side with the most space. Pass * a specific placement (e.g. `"bottom"`) to express a preferred side * with `flip()` fallback instead. */ placement?: "auto"; /** Sub-options for `autoPlacement()`. */ placementConfig?: PopoverAutoPlacementConfig; }; type WithSpecificPlacement = { /** * Preferred placement relative to the trigger. Floating UI's `flip()` * middleware will adapt to the opposite side if there is not enough space. * Pass `"auto"` to let Floating UI pick the best side automatically. * * @default "bottom" */ placement: Placement; /** Sub-options for `flip()`. */ placementConfig?: PopoverFlipPlacementConfig; }; export type PopoverDialogRoleProps = (PopoverPropsBase & DialogRoleProps & WithAutoPlacement) | (PopoverPropsBase & DialogRoleProps & WithSpecificPlacement); export type PopoverNonDialogRoleProps = (PopoverPropsBase & NonDialogRoleProps & WithAutoPlacement) | (PopoverPropsBase & NonDialogRoleProps & WithSpecificPlacement); /** * Props for the beta Popover component. * * Two independent discriminated unions are combined: * - **Role**: `role="dialog"` (default) enables `FloatingFocusManager` and accepts `modal`, * `openOnHover`, and `delay`. Non-dialog roles (`listbox`, `tree`, `grid`) disable * focus management — the inner component owns focus and keyboard navigation. * - **Placement**: `placement="auto"` uses `autoPlacement()` and accepts * `placementConfig.allowedPlacements`. Specific placements use `flip()` and accept * `placementConfig.fallbackPlacements`. * * @extends DisableCloseOnEscapeOrClickProps * @extends OpenCloseTransitionStateEffects */ export type PopoverProps = PopoverDialogRoleProps | PopoverNonDialogRoleProps; /** * Beta Popover component for displaying floating content relative to a trigger element. * * Built on three layers: * - HTML Popover API (`popover="manual"`) for top-layer rendering without z-index management * - Floating UI (`@floating-ui/react`) for JavaScript-based positioning * - Floating UI interaction hooks for correct ARIA attributes and keyboard behavior * * Features: * - Correct ARIA linkage: `aria-controls`, `aria-haspopup` with role string, `aria-expanded` * - `FloatingFocusManager` for both modal (focus trapped) and non-modal (Tab-out closes) * - `safePolygon()` hover zone replaces CSS `::before` hover bridge * - `role` prop drives both `aria-haspopup` on trigger and `role` on content * - Controlled and uncontrolled modes via `open` / `defaultOpen` * - Imperative handle exposing `openPopover` and `closePopover` * - Animation lifecycle callbacks via `onOpenAnimationStart` etc. * * @example * * Open * *

Popover content

* Close *
*
* * @example * * * {(props) => } * * * * Done * * * * @example * * Hover me * Hover content * */ export declare const Popover: import('react').ForwardRefExoticComponent> & { /** * PopoverTrigger component for creating custom trigger elements. * * Features: * - Render prop pattern for full control over the trigger element * - ARIA attributes and event handlers injected via getReferenceProps * * @example * * {(props) => ( * * )} * */ Trigger: typeof PopoverTrigger; /** * PopoverContent component for the main popover content area. * * Features: * - HTML Popover API top-layer rendering (popover="manual") * - Floating UI positioning via refs.setFloating and floatingStyles * - FloatingFocusManager for focus trapping (modal) or Tab-out closing (non-modal) * - Arrow/caret indicator with position computed from middlewareData.arrow * - Scroll position reset when the popover opens * - Optional scrollerRef for external scroll access * * @example * *

Popover content

* Close *
*/ Content: import('react').ForwardRefExoticComponent, HTMLDivElement>, "ref">, "popover"> & { scrollerRef?: import('react').RefObject; hideWhileClosed?: boolean; } & import('react').RefAttributes>; /** * PopoverClose component for closing the popover. * * Features: * - Supports all Button component props and styling * - Closes the popover on click via closePopover * - Automatic tracking ID generation for analytics * * @example * Close * * @example * * Cancel * */ Close: import('react').ForwardRefExoticComponent>; /** * PopoverButton component for creating button-style triggers. * * Features: * - Button styling and behavior with all Button props * - ARIA attributes and event handlers injected via getReferenceProps * - Automatic tracking ID generation for analytics * * @example * Click to open * * @example * * Information * */ Button: import('react').ForwardRefExoticComponent>; }; export {};