Popover
Popover displays a floating panel on click or hover to surface additional
content, forms, or actions. It wraps the Spar headless Popover primitive and
adds Takeoff visual vocabulary — variant, close button, and arrow slots.
Usage
import { Popover } from '@takeoff-ui/react-spar';
<Popover>
<Popover.Trigger />
<Popover.Content>
<Popover.Header />
<Popover.Description />
<Popover.Arrow />
<Popover.Close />
</Popover.Content>
</Popover>
Playground
Header & Description
Use Popover.Header and Popover.Description to structure the content with a
title and supporting text. Both are styling slots — no behavior is attached.
Variants
The variant prop controls the visual appearance of the popover content.
Placement
Arrow
Close Button
Controlled
Accessibility & Keyboard
- Trigger uses
aria-expandedandaria-controlspointing to the content. - Content has
role="dialog"(orrole="popover"). - Focus is trapped inside the content when
modalistrue. - Escape key dismisses the popover and returns focus to the trigger.
- Click outside the popover dismisses it (non-modal mode).
| Key | Behavior |
|---|---|
| Escape | Dismiss the popover. |
| Tab | Navigate focusable content. |
| Enter | Activate trigger / close button. |
API Reference
Popover
See Spar Popover docs for primitive behavior.
Props
| Name | Type | Default | Description |
|---|---|---|---|
| children | React.React.ReactNode | - | PopoverTrigger and PopoverContent components |
| id | string | - | Custom base ID for ARIA relationships. If not provided, one will be generated automatically. Sub-element IDs are derived as ${id}-trigger and ${id}-content. |
| disabled | boolean | false | Disables all popover triggers (prevents opening) |
| open | boolean | - | Controlled state for popover visibility |
| defaultOpen | boolean | false | Initial open state for uncontrolled mode |
| modal | boolean | false | Whether popover should behave modally (focus trap + backdrop) |
Events
| Name | Type | Default | Description |
|---|---|---|---|
| onOpenChange | (open: boolean) => void | - | Callback when popover open state changes |
Popover.Content
Props
| Name | Type | Default | Description |
|---|---|---|---|
| children | React.React.ReactNode | - | |
| variant | PopoverVariant | 'white' | Color variant. |
| classNames | Partial<Record<"root", string>> | - | Per-slot extra classes. |
| slotProps | Partial<Record<"root", React.HTMLAttributes<HTMLElement>>> | - | Per-slot HTML-attribute overrides. |
| container | HTMLElement | null | document.body | Portal container element. Content is portaled to document.body by default. |
| trapFocus | boolean | false | Whether to trap focus within content |
| side | Side | 'bottom' | Side of trigger to position against |
| align | Align | 'center' | Alignment relative to trigger |
| className | string | - |
Events
| Name | Type | Default | Description |
|---|---|---|---|
| onOpenAutoFocus | (event: Event) => void | - | Called when popover opens and focus moves inside |
| onCloseAutoFocus | (event: Event) => void | - | Called when popover closes and focus returns to trigger |
| onEscapeKeyDown | (event: KeyboardEvent) => void | - | Called when escape is pressed |
| onPointerDownOutside | (event: PointerEvent) => void | - | Called when pointer down occurs outside the content |
| onInteractOutside | (event: PointerEvent | FocusEvent) => void | - | Called when interaction occurs outside the content |
| onFocusOutside | (event: FocusEvent) => void | - | Called when focus moves outside the content |
Data attributes
| Attribute | Applied when | Purpose |
|---|---|---|
| data-slot="root" | Always | Stable selector for wrapper styling on the root slot. |
| data-variant | Always | Reflects the resolved variant for theme recipe scoping. |
Popover.Trigger
Data attributes
| Attribute | Applied when | Purpose |
|---|---|---|
| data-slot="root" | Always | Stable selector for wrapper styling on the root slot. |
Popover.Arrow
Data attributes
| Attribute | Applied when | Purpose |
|---|---|---|
| data-slot="root" | Always | Stable selector for the arrow. |
Popover.Close
Data attributes
| Attribute | Applied when | Purpose |
|---|---|---|
| data-slot="root" | Always | Stable selector for the close button. |
Type Definitions
| Name | Definition |
|---|---|
| PopoverVariant | 'white' | 'dark' | 'info' | 'success' | 'warning' | 'danger' | 'neutral' |
| Side | 'top' | 'right' | 'bottom' | 'left' |
| Align | 'start' | 'center' | 'end' |
| PopoverTriggerRenderProps | { isOpen: boolean; disabled: boolean; open: () => void; close: () => void; toggle: () => void } |
| PopoverCloseRenderProps | { isOpen: boolean; close: () => void } |