Popover
Displays rich content in a portal, triggered by a button.
Interactive
Features
Can be controlled or uncontrolled. Customize side, alignment, offsets, collision handling. Optionally render a pointing arrow. Focus is fully managed and customizable. Supports modal and non-modal modes. Dismissing and layering behavior is highly customizable.
Installation
Install the component from your command line.
ng g @ng-cn/core:c popoverAnatomy
Import all parts and piece them together.
import {
Popover,
PopoverTrigger,
PopoverContent,
PopoverAnchor
} from '@/ui/popover';<Popover>
<PopoverTrigger />
<PopoverContent />
</Popover>API Reference
Root
Contains all the parts of a popover.
| Prop | Type | Default |
|---|---|---|
| open | boolean | — |
| The controlled open state of the popover. | ||
| defaultOpen | boolean | false |
| The open state of the popover when initially rendered. Use when you do not need to control its open state. | ||
| modal | boolean | false |
| The modality of the popover. When set to true, interaction with outside elements will be disabled and only popover content will be visible to screen readers. |
Trigger
The button that toggles the popover.
| Prop | Type | Default |
|---|---|---|
| asChild | boolean | false |
| Change the component to render as the child element. | ||
| class | string | — |
| Additional CSS classes to apply. |
Data Attributes
| Attribute | Values |
|---|---|
| [data-state] | "open" | "closed" |
Anchor
An optional element to position the PopoverContent against. If not used, the content will position alongside the trigger.
| Prop | Type | Default |
|---|---|---|
| asChild | boolean | false |
| Change the component to render as the child element. |
Content
The component that pops out when the popover is open.
| Prop | Type | Default |
|---|---|---|
| side | 'top' | 'right' | 'bottom' | 'left' | 'bottom' |
| The preferred side of the anchor to render against when open. | ||
| sideOffset | number | 4 |
| The distance in pixels from the anchor. | ||
| align | 'start' | 'center' | 'end' | 'center' |
| The preferred alignment against the anchor. | ||
| alignOffset | number | 0 |
| An offset in pixels from the start or end alignment options. | ||
| avoidCollisions | boolean | true |
| When true, overrides the side and align preferences to prevent collisions. | ||
| class | string | — |
| Additional CSS classes to apply. |
Data Attributes
| Attribute | Values |
|---|---|
| [data-state] | "open" | "closed" |
| [data-side] | "top" | "right" | "bottom" | "left" |
| [data-align] | "start" | "center" | "end" |
Examples
Basic
A simple popover with some content.
<Popover>
<PopoverTrigger>
<Button variant="outline">Open popover</Button>
</PopoverTrigger>
<PopoverContent class="w-80">
<div class="grid gap-4">
<div class="space-y-2">
<h4 class="font-medium leading-none">Dimensions</h4>
<p class="text-sm text-muted-foreground">
Set the dimensions for the layer.
</p>
</div>
<div class="grid gap-2">
<Label htmlFor="width">Width</Label>
<Input id="width" defaultValue="100%" />
</div>
</div>
</PopoverContent>
</Popover>Positioning
Position the popover on different sides.
<div class="flex gap-4">
<Popover>
<PopoverTrigger><Button>Top</Button></PopoverTrigger>
<PopoverContent side="top">Top content</PopoverContent>
</Popover>
<Popover>
<PopoverTrigger><Button>Right</Button></PopoverTrigger>
<PopoverContent side="right">Right content</PopoverContent>
</Popover>
<Popover>
<PopoverTrigger><Button>Bottom</Button></PopoverTrigger>
<PopoverContent side="bottom">Bottom content</PopoverContent>
</Popover>
<Popover>
<PopoverTrigger><Button>Left</Button></PopoverTrigger>
<PopoverContent side="left">Left content</PopoverContent>
</Popover>
</div>With custom anchor
Anchor the popover to a different element.
<Popover>
<PopoverAnchor>
<div class="flex items-center gap-2">
<span>Anchor element</span>
<PopoverTrigger>
<Button size="icon" variant="ghost">
<lucide-icon [img]="InfoIcon" class="h-4 w-4" />
</Button>
</PopoverTrigger>
</div>
</PopoverAnchor>
<PopoverContent>
This popover is anchored to the parent element.
</PopoverContent>
</Popover>Controlled
Control the open state from outside.
// In your component:
isOpen = signal(false);
// In template:
<Popover [open]="isOpen()" (openChange)="isOpen.set($event)">
<PopoverTrigger>
<Button>Controlled</Button>
</PopoverTrigger>
<PopoverContent>
<p>Controlled popover content</p>
<Button (click)="isOpen.set(false)">Close</Button>
</PopoverContent>
</Popover>Accessibility
Adheres to the Dialog (Non-Modal) WAI-ARIA design pattern .
Keyboard Interactions
| Key | Description |
|---|---|
| Space | Opens/closes the popover. |
| Enter | Opens/closes the popover. |
| Tab | Moves focus to the next focusable element. |
| Shift + Tab | Moves focus to the previous focusable element. |
| Escape | Closes the popover and moves focus back to the trigger. |