Popover
Floating panel primitive for filters, menus, custom pickers, and lightweight inline workflows.
Overview
Popover is the shared floating-panel primitive used across shared UI and the brand dashboard.
It is the low-level building block behind many compact interactive surfaces such as:
- filter popovers
- toolbar popovers
- custom date pickers
- inline entity managers
Use Popover when the interaction needs a contextual floating panel anchored to a trigger. For ordinary dropdown selection, prefer higher-level components such as Select, AutocompleteSelect, or Menu when they already fit.
Compound API
| Part | Purpose |
|---|---|
Popover | Root container. |
Popover.Trigger | Uses an existing element as the trigger. |
Popover.Button | Shared built-in popover trigger button. |
Popover.Panel | Floating panel surface. |
usePopover | Accesses isOpen, open, close, and toggle inside a popover tree. |
Basic Usage
<Popover placement="bottom-start" offset={8}>
<Popover.Button leftAdornment="CalendarDays">
Choose Date
</Popover.Button>
<Popover.Panel className="w-64 p-2">
<DateSelector selected={selectedDate} onSelect={setSelectedDate} />
</Popover.Panel>
</Popover>With A Custom Trigger
Use Popover.Trigger when the anchor should be an existing component such as IconButton.
<Popover placement="bottom-start">
<Popover.Trigger>
<IconButton icon="Filter" label="Filters" />
</Popover.Trigger>
<Popover.Panel className="max-h-96 overflow-auto">
{/* panel content */}
</Popover.Panel>
</Popover>This is the same pattern used by shared DataTablePopover.
Closing From Panel Content
Popover.Panel supports a render prop so panel actions can call close().
<Popover>
<Popover.Button>Bulk Actions</Popover.Button>
<Popover.Panel>
{({ close }) => (
<div className="p-2">
<Button role="button" size="sm" onClick={() => { applyAction(); close(); }}>
Apply
</Button>
</div>
)}
</Popover.Panel>
</Popover>Root Render Prop
Popover itself also supports a render prop:
<Popover>
{({ isOpen, close }) => (
<>
<Popover.Button>{isOpen ? 'Open' : 'Closed'}</Popover.Button>
<Popover.Panel>{/* ... */}</Popover.Panel>
</>
)}
</Popover>This is useful when trigger or surrounding UI needs access to isOpen or close without manually using usePopover.
Props
Popover
| Prop | Type | Default | Description |
|---|---|---|---|
children | ReactNode | ({ isOpen, close }) => ReactNode | — | Required. Popover contents. |
offset | number | 8 | Space between trigger and panel. |
placement | Placement | 'bottom-start' | Floating UI placement. |
onClose | () => void | — | Called when the popover closes. |
Popover.Trigger
| Prop | Type | Description |
|---|---|---|
children | ReactElement | Required. Single trigger element. |
Popover.Button
| Prop | Type | Default | Description |
|---|---|---|---|
children | ReactNode | — | Button content. |
variant | 'default' | 'ghost' | 'default' | Trigger style variant. |
size | 'lg' | 'md' | 'sm' | 'xs' | 'md' | Trigger size. |
className | string | — | Additional classes. |
leftAdornment | IconName | — | Optional left icon. |
rightAdornment | IconName | — | Optional right icon. |
disabled | boolean | — | Disables interaction. |
Popover.Panel
| Prop | Type | Description |
|---|---|---|
children | ReactNode | ({ isOpen, close }) => ReactNode | Panel content or render prop. |
className | string | Additional panel classes. |
Important Conventions
Popover.Triggermust receive a single element that can accept a ref.- Prefer
Popover.Buttonwhen the trigger is just a normal design-system button. - Prefer the
Popover.Panelrender prop when panel actions should close the popover after acting. Popoversupports nested popovers, so you do not need to invent a separate floating-state pattern for nested menus.
Brand Dashboard And Shared Usage
| Pattern | Path | Notes |
|---|---|---|
| Shared toolbar/filter popover | fsai/packages/shared-ui/src/components/DataTable/toolbar/Popover.tsx | Canonical IconButton + Popover.Trigger composition. |
| Inline entity manager composition | fsai/packages/shared-ui/src/components/InlineEntityManager/InlineEntityManager.primitives.tsx | Uses usePopover() for local open/close behavior. |
| Rich text editor popovers | fsai/apps/brand-dashboard/src/components/RichTextEditor/RichTextEditor.tsx | Floating formatting controls anchored to toolbar buttons. |
| Portal-editor section picker | fsai/apps/brand-dashboard/src/pages/PortalEditor/components/AddSectionPopover/AddSectionPopover.tsx | Product-facing creation popover with permission gating. |
Guidelines
- Do use
Popoverfor compact anchored workflows and utilities - Do use higher-level components first when they already cover the interaction
- Do use
Popover.TriggerwithIconButtonfor toolbar actions - Don't use
Popoveras a replacement forModalorPanel