Popover
The Popover component displays rich content in a floating panel when users click on a trigger element. Built on Radix UI Popover, it handles positioning, focus trapping, keyboard navigation, and click-outside dismissal automatically.
Import
import { Popover, PopoverTrigger, PopoverContent, PopoverArrow, PopoverClose,} from '@nim-ui/components';Basic Usage
Basic Popover
View Code
<Popover> <PopoverTrigger asChild> <Button variant="outline">Open Popover</Button> </PopoverTrigger> <PopoverContent> <p>This is a basic popover with some content.</p> </PopoverContent></Popover>Variants
Two visual styles: default (subtle border) and outline (thicker border).
Popover Variants
View Code
<PopoverContent variant="default">Default variant</PopoverContent><PopoverContent variant="outline">Outline variant</PopoverContent>Arrow
Use showArrow to display an arrow pointing to the trigger.
Popover with Arrow
View Code
<PopoverContent showArrow>Content with arrow</PopoverContent><PopoverContent variant="outline" showArrow>Outline with arrow</PopoverContent>Positioning
Control popover placement with the side prop. Radix automatically flips when there isn’t enough space.
Popover Sides
View Code
<PopoverContent side="top" showArrow>Top</PopoverContent><PopoverContent side="bottom" showArrow>Bottom</PopoverContent><PopoverContent side="left" showArrow>Left</PopoverContent><PopoverContent side="right" showArrow>Right</PopoverContent>Close Button
Use PopoverClose inside the content for an explicit close action.
Popover with Close
View Code
<Popover> <PopoverTrigger asChild> <Button>Open</Button> </PopoverTrigger> <PopoverContent> <p>Content here</p> <PopoverClose asChild> <Button variant="outline">Close</Button> </PopoverClose> </PopoverContent></Popover>Controlled Mode
function ControlledPopover() { const [open, setOpen] = useState(false);
return ( <Popover open={open} onOpenChange={setOpen}> <PopoverTrigger asChild> <Button>Controlled</Button> </PopoverTrigger> <PopoverContent> <p>Controlled popover</p> <Button onClick={() => setOpen(false)}>Close</Button> </PopoverContent> </Popover> );}Component Architecture
| Component | Description |
|---|---|
Popover | Root component managing open/close state (Radix Popover.Root) |
PopoverTrigger | Element that opens popover on click (Radix Popover.Trigger) |
PopoverContent | Floating panel with variant styling, rendered via Portal |
PopoverArrow | Arrow indicator pointing to the trigger |
PopoverClose | Button that closes the popover when clicked |
Props
Popover (Root)
| Name | Type | Default | Description |
|---|---|---|---|
open | boolean | - | Controlled open state |
defaultOpen | boolean | false | Initial open state for uncontrolled usage |
onOpenChange | (open: boolean) => void | - | Callback when the open state changes |
modal | boolean | false | When true, traps focus and makes background inert |
PopoverContent
| Name | Type | Default | Description |
|---|---|---|---|
variant | 'default' | 'outline' | 'default' | Visual style variant |
side | 'top' | 'bottom' | 'left' | 'right' | 'bottom' | Preferred side to display the popover |
sideOffset | number | 4 | Distance in px between the popover and the trigger |
showArrow | boolean | false | Show an arrow pointing to the trigger |
className | string | - | Additional CSS classes |
PopoverClose
| Name | Type | Default | Description |
|---|---|---|---|
asChild | boolean | false | Use child element as the close button |
Accessibility
Built on Radix UI Popover with full accessibility support:
- role=“dialog”: Content is announced as a dialog to screen readers
- Focus trapping: Focus is trapped within the popover while open
- Focus restoration: Focus returns to the trigger when the popover closes
- Escape key: Pressing Escape dismisses the popover
- Click outside: Clicking outside the popover closes it
- Portal rendering: Content renders outside the DOM hierarchy without affecting the accessibility tree
Keyboard Support
| Key | Action |
|---|---|
| Enter / Space | Open popover (on trigger) |
| Escape | Close the popover |
| Tab | Navigate within popover content |