Popover
Advanced popover component with smart positioning, collision detection, and smooth animations for displaying rich content
Installation
Install the Popover component using the nocta-ui CLI:
npx nocta-ui add popover
Then import the component:
import {
Popover,
PopoverTrigger,
PopoverContent
} from '@/components/ui/popover';
Basic Usage
The Popover component provides a floating panel that appears on demand, perfect for displaying additional information or controls.
Positioning
Control where the popover appears relative to the trigger with the side
prop.
Alignment
Fine-tune the alignment of the popover relative to the trigger using the align
prop.
Offsets
Adjust the distance and alignment offset of the popover from the trigger.
Custom Triggers
Use the asChild
prop to render custom trigger elements while maintaining popover functionality.
Controlled State
Control the popover's open state programmatically using the open
and onOpenChange
props.
Rich Content
Popovers can contain complex content including forms, menus, and interactive elements.
Form Integration
Popovers work great for inline forms and quick actions.
Collision Detection
The popover automatically detects viewport edges and flips position to stay visible.
Try these popovers near the edges of the viewport
Keyboard Navigation
The Popover component includes comprehensive keyboard support:
- Escape: Close the popover and return focus to trigger
- Enter/Space: Open popover when trigger is focused
- Tab: Navigate through focusable elements inside popover
- Click outside: Close popover when clicking outside
Accessibility Features
The Popover component is built with accessibility in mind:
- ARIA Attributes: Proper
role
,aria-expanded
,aria-controls
, andaria-haspopup
attributes - Focus Management: Focus is properly managed when opening/closing
- Keyboard Navigation: Full keyboard support for all interactions
- Screen Reader Support: Announces popover state changes
- Portal Rendering: Content is rendered in a portal to avoid z-index issues
Advanced Usage
Event Handling
Handle specific events for custom behavior:
<Popover>
<PopoverTrigger>Custom Events</PopoverTrigger>
<PopoverContent
onEscapeKeyDown={(event) => {
console.log('Escape pressed');
// event.preventDefault() to prevent default close behavior
}}
onPointerDownOutside={(event) => {
console.log('Clicked outside');
// event.preventDefault() to prevent default close behavior
}}
>
<p>Content with custom event handling</p>
</PopoverContent>
</Popover>
Custom Styling
Customize the appearance with className props:
<Popover>
<PopoverTrigger className="custom-trigger-styles">
Custom Styled Trigger
</PopoverTrigger>
<PopoverContent className="custom-content-styles w-96 p-6">
<p>Custom styled content</p>
</PopoverContent>
</Popover>
Conditional Rendering
Show different content based on state:
const [user, setUser] = useState(null);
<Popover>
<PopoverTrigger>User Menu</PopoverTrigger>
<PopoverContent>
{user ? (
<UserProfile user={user} />
) : (
<LoginForm onLogin={setUser} />
)}
</PopoverContent>
</Popover>
Props
Popover
Prop | Type | Default | Description |
---|---|---|---|
open | boolean | — | Controlled open state |
defaultOpen | boolean | false | Default open state |
onOpenChange | (open: boolean) => void | — | Callback when open state changes |
PopoverTrigger
Prop | Type | Default | Description |
---|---|---|---|
asChild | boolean | false | Render as child element instead of button |
className | string | '' | Additional CSS classes |
PopoverContent
Prop | Type | Default | Description |
---|---|---|---|
side | 'top' | 'right' | 'bottom' | 'left' | 'bottom' | Preferred side to display popover |
align | 'start' | 'center' | 'end' | 'center' | Alignment relative to trigger |
sideOffset | number | 8 | Distance from trigger in pixels |
alignOffset | number | 0 | Alignment offset in pixels |
avoidCollisions | boolean | true | Whether to flip position to avoid viewport edges |
className | string | '' | Additional CSS classes |
onEscapeKeyDown | (event: KeyboardEvent) => void | — | Callback when Escape key is pressed |
onPointerDownOutside | (event: PointerEvent) => void | — | Callback when clicking outside |
The Popover component also accepts all standard HTML attributes for their respective elements.