Skip to content

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

ComponentDescription
PopoverRoot component managing open/close state (Radix Popover.Root)
PopoverTriggerElement that opens popover on click (Radix Popover.Trigger)
PopoverContentFloating panel with variant styling, rendered via Portal
PopoverArrowArrow indicator pointing to the trigger
PopoverCloseButton 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

KeyAction
Enter / SpaceOpen popover (on trigger)
EscapeClose the popover
TabNavigate within popover content
  • Tooltip — Lightweight text hint on hover/focus
  • Modal — Full dialog overlay for focused interactions