Logo

Popover

Anchored overlay content with trigger, close controls, alignment, controlled state, forms, custom styling, and RTL support.

Preview

Usage

TS

import { FrButtonModule } from '@frame-ui-ng/components/button';
import { FrInputModule } from '@frame-ui-ng/components/input';
import { FrPopoverModule } from '@frame-ui-ng/components/popover';

HTML

<frame-popover>
  <button frButton appearance="outline" [frPopoverTrigger]="panel" type="button">
    Open quick note
  </button>

  <ng-template #panel="frPopoverContent" frPopoverContent side="bottom" align="center">
    <div frPopoverPanel>
      <div frPopoverHeader>
        <h3 frPopoverTitle>Review reminder</h3>
        <p frPopoverDescription>
          Capture the next thing your team should check before publishing.
        </p>
      </div>
      <div frPopoverFooter>
        <button frButton appearance="outline" frPopoverClose type="button">Later</button>
        <button frButton frPopoverClose type="button">Mark done</button>
      </div>
    </div>
  </ng-template>
</frame-popover>

Examples

Basic

Use a trigger and content template to show dismissible rich content.

Align

Use the content alignment input to align the panel with the trigger edge or center.

With Form

Place form fields and actions inside the popover body and footer.

Controlled

Bind the open state when the popover should also be opened from elsewhere in the UI.

RTL support

Popover content inherits document direction and supports aligned RTL placement.

Custom Styling

Override popover tokens on the trigger or an ancestor to customize panel width, surface, radius, shadow, text, and motion.

Token Inspector

Inspect the popover panel, header, title, description, body, footer, and close affordance.

Release checklist

Inspect the panel, header, body, footer, and close token hooks.

Design Tokens

Popover defines tokens for the overlay surface, header rhythm, title and description text, body and footer spacing, close affordances, and entry motion.

SCSS


  --frame-popover-content-width: 20rem;
  --frame-popover-content-padding: 1rem;
  --frame-popover-content-radius: var(--frame-radius-md);
  --frame-popover-content-bg: var(--frame-surface);
  --frame-popover-content-color: var(--frame-surface-foreground);
  --frame-popover-content-border: var(--frame-border);
  --frame-popover-content-shadow: var(--frame-shadow-md);
  --frame-popover-content-gap: 0.875rem;
  --frame-popover-header-gap: 0.25rem;
  --frame-popover-title-color: var(--frame-foreground);
  --frame-popover-title-font-size: 0.875rem;
  --frame-popover-title-font-weight: 600;
  --frame-popover-description-color: var(--frame-muted-foreground);
  --frame-popover-description-font-size: 0.875rem;
  --frame-popover-body-gap: 0.75rem;
  --frame-popover-footer-gap: 0.5rem;
  --frame-popover-close-radius: var(--frame-radius-sm);
  --frame-popover-close-hover-bg: var(--frame-accent);
  --frame-popover-motion-duration: 140ms;
  --frame-popover-motion-distance: 0.25rem;
  --frame-popover-motion-scale: 0.96;