Components

Popover

Radix-powered floating panel anchored to a trigger. w-72 rounded-md bg-popover shadow-md p-4. Used for supplementary content (settings snippets, help, notifications) that doesn't warrant a Dialog. Also the canonical surface for feature Tutorial popovers.

Updated Jul 17, 2026 by Leonardo Posada

Anatomy

  1. 1
    Popover (root)

    Radix Root that manages open/close state. Uncontrolled by default.

  2. 2
    PopoverTrigger

    Any focusable element. Pass asChild so the Popover wraps YOUR element instead of adding its own.

  3. 3
    PopoverAnchor

    Optional. Anchors the content to a different element than the trigger (advanced positioning).

  4. 4
    PopoverContent

    The floating panel: w-72 rounded-md border bg-popover shadow-md p-4, portalled to body, animated in via animate-dialog-in.

States

Open / Closed. Focus is trapped inside the panel while open; clicking outside or pressing Esc closes it. Portal escapes any overflow-hidden ancestor.

Closed / Open
<Popover>
  <PopoverTrigger asChild>
    <Button variant="outline">Open</Button>
  </PopoverTrigger>
  <PopoverContent>Content</PopoverContent>
</Popover>
Use Popover for feature Tutorials
Yuno's onboarding pattern for new features and sections lives in a Popover — not a Dialog and not a Tooltip. The 'Feature tutorial' recipe (Skip / Step X of N / Got it!) is the canonical shape. Ship every new feature announcement with this composition so users get a consistent, dismissible signal.

Recipes

Ready-to-copy compositions covering the most common Yuno usages of this atom.

Feature tutorial (Skip · Step X of N · Got it!)

The canonical Yuno pattern for onboarding new features and sections. Title + description + Skip (ghost) / step counter (muted center) / Got it! (primary right). Reach for this recipe every time you ship a new feature that needs a hint.

function TutorialPopover() {
  const [step, setStep] = React.useState(1);
  const total = 3;
  return (
    <Popover>
      <PopoverTrigger asChild>
        <Button variant="outline">Show tutorial</Button>
      </PopoverTrigger>
      <PopoverContent align="start" className="w-80">
        <div className="grid gap-2">
          <div className="text-base font-medium text-foreground">Tutorial title</div>
          <p className="text-sm text-muted-foreground">
            Example text: Now you can personalize your experience…
          </p>
        </div>
        <div className="mt-4 flex items-center justify-between gap-3">
          <Button variant="outline" size="sm">Skip</Button>
          <span className="text-sm text-muted-foreground">Step {step} of {total}</span>
          <Button size="sm" onClick={() => setStep((s) => s + 1)}>
            {step < total ? "Next" : "Got it!"}
          </Button>
        </div>
      </PopoverContent>
    </Popover>
  );
}
Onboarding tip (single Got it!)

One-shot tip that highlights a new UI area. Title + description + single primary 'Got it!' aligned right. Shorter than a tutorial and dismissible in one click.

<Popover>
  <PopoverTrigger asChild>
    <Button variant="outline">Show tip</Button>
  </PopoverTrigger>
  <PopoverContent align="start" className="w-80">
    <div className="grid gap-2">
      <div className="text-base font-medium text-foreground">Customize your table!</div>
      <p className="text-sm text-muted-foreground">
        Now you can personalize your experience according to your preferences.
        You can customize, rearrange, hide/show, and resize the columns.
      </p>
    </div>
    <div className="mt-4 flex justify-end">
      <Button size="sm">Got it!</Button>
    </div>
  </PopoverContent>
</Popover>
Settings form (inline dimensions)

Small form fields inside a popover, launched from a control button. Use for quick tweaks that don't warrant leaving the current context.

<Popover>
  <PopoverTrigger asChild>
    <Button variant="outline">Dimensions</Button>
  </PopoverTrigger>
  <PopoverContent align="start" className="w-80">
    <div className="grid gap-3">
      <div className="grid gap-1">
        <div className="text-base font-medium text-foreground">Dimensions</div>
        <p className="text-sm text-muted-foreground">Set the dimensions for the layer.</p>
      </div>
      <div className="grid grid-cols-3 items-center gap-3">
        <Label htmlFor="width" className="text-right">Width</Label>
        <Input id="width" defaultValue="100%" className="col-span-2 h-8" />
      </div>
      <div className="grid grid-cols-3 items-center gap-3">
        <Label htmlFor="maxWidth" className="text-right">Max. width</Label>
        <Input id="maxWidth" defaultValue="300px" className="col-span-2 h-8" />
      </div>
    </div>
  </PopoverContent>
</Popover>
Notifications tray

Bell IconButton opens a wider popover with a scrollable list of notifications. Common in the top bar utilities cluster.

<Popover>
  <PopoverTrigger asChild>
    <Button variant="ghost" size="icon" aria-label="Notifications">
      <BellSimple weight="light" />
    </Button>
  </PopoverTrigger>
  <PopoverContent align="end" className="w-80 p-0">
    <div className="border-b px-4 py-3 text-sm font-medium">Notifications</div>
    <ul className="grid gap-0.5 p-2">
      {items.map(n => (
        <li key={n.id} className="rounded-sm p-3 text-sm hover:bg-accent">
          <div className="text-foreground">{n.title}</div>
          <div className="text-xs text-muted-foreground">{n.time}</div>
        </li>
      ))}
    </ul>
  </PopoverContent>
</Popover>

Import

Copy this import line at the top of the file where you compose this atom.

PopoverAnchor is also exported for advanced positioning.
import {
  Popover,
  PopoverContent,
  PopoverTrigger,
} from "@/components/ui/popover";

Props

Everything else from the underlying HTML or Radix primitive is forwarded via ...props.

PropTypeDefaultDescription
Popover.open / defaultOpenbooleanControlled or uncontrolled open state. Controlled needs onOpenChange.
Popover.onOpenChange(open: boolean) => voidFires whenever the panel opens or closes.
Popover.modalbooleanfalseWhen true, blocks interaction with outside elements — behaves closer to a Dialog.
PopoverTrigger.asChildbooleanfalseMerges props onto the child element (Radix Slot). Always pass when wrapping a real element (Button, IconButton).
PopoverContent.side"top" | "right" | "bottom" | "left""bottom"Preferred side. Radix auto-flips if there's no room.
PopoverContent.align"start" | "center" | "end""center"Alignment along the side. Tutorials usually use align='start'; notifications trays use align='end'.
PopoverContent.sideOffsetnumber4Distance in px between trigger and content.
PopoverContent.classNamestringMerged. Default is w-72 p-4. Override w-* for wider panels (notifications, tutorials use w-80). Use p-0 when you handle padding per-section.
PopoverAnchorcomponentOptional anchor different from the trigger. Advanced — most Popovers don't need it.

When to use

  • Small forms or previews launched from a control.
  • Notifications tray triggered by the bell IconButton.
  • Feature tutorials and onboarding tips over new sections.
  • Non-critical supplementary content anchored to a trigger.

When not to use

  • For focused editing that needs the full page context — use Sheet or Dialog.
  • For informational tooltips — use Tooltip.
  • For critical decisions the user must not miss — use Dialog.

Usage

Do
  • Keep the content under 400px tall.
  • Anchor it to a real trigger — never floating without one.
  • For tutorials, always include Skip so users can dismiss the whole flow.
  • For onboarding tips, provide a single primary Got it! so the action is unambiguous.
Don't
  • Don't stack Popovers.
  • Don't rely on a Popover for critical decisions — use Dialog.
  • Don't hide destructive actions inside a Popover — they need a Dialog confirmation.
  • Don't skip the animation — animate-dialog-in is the Yuno default.

Related

Cross-links to atoms and patterns you may reach for next.

  • DialogFor blocking decisions or critical modals that need the user's full attention.
  • SheetFor focused editing that needs more room than a Popover.
  • TooltipFor hover hints without interactive content.
  • Hover cardFor preview-on-hover with richer content than a Tooltip.
  • Dropdown menuWhen the panel should offer a list of actions instead of free-form content.