Popover

Displays rich content in a portal, triggered by a button.

Preview Code
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.

Angular CLInpmpnpmyarnbun
Bash
ng g @ng-cn/core:c popover

Anatomy

Import all parts and piece them together.

Typescript
import {
  Popover,
  PopoverTrigger,
  PopoverContent,
  PopoverAnchor
} from '@/ui/popover';
Html
<Popover>
  <PopoverTrigger />
  <PopoverContent />
</Popover>

API Reference

Root

Contains all the parts of a popover.

PropTypeDefault
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.

PropTypeDefault
asChild boolean false
Change the component to render as the child element.
class string
Additional CSS classes to apply.

Data Attributes

AttributeValues
[data-state]"open" | "closed"

Anchor

An optional element to position the PopoverContent against. If not used, the content will position alongside the trigger.

PropTypeDefault
asChild boolean false
Change the component to render as the child element.

Content

The component that pops out when the popover is open.

PropTypeDefault
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

AttributeValues
[data-state]"open" | "closed"
[data-side]"top" | "right" | "bottom" | "left"
[data-align]"start" | "center" | "end"

Examples

Basic

A simple popover with some content.

Html
<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.

Html
<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.

Html
<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.

Html
// 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

KeyDescription
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.