Skip to content
SuperCoach

Components · Overlays

Popover

Beta

Rich content anchored to a control.

When to use

  • To show more detail about a value, anchored to it: the macro breakdown behind a day's calories, the sets behind a weekly volume.
  • For a small interactive panel tied to one control: share a program link, pick a color for a calendar tag, set a quick reminder.
  • When the content has buttons, links or fields, which a Tooltip can't hold.

When not to use

  • For a plain text hint on an icon: use a Tooltip.
  • For a list of actions: use a dropdown menu, which has menu keyboard behavior.
  • For a task with several fields that must be saved: use a Dialog or a Sheet.
  • To preview a linked item on hover: use a Hover card.

Anatomy

Open the popover above to see its parts: the trigger (a button that stays visible), and the content panel next to it, with an optional header (title and description) and the body. There is no arrow and no close button; the coach closes it with Escape, by clicking outside, or with the trigger.

Variants

VariantUse for
Information (macro breakdown)Read-only detail about the trigger's value
Interactive (share link)One small task: copy, pick, toggle. Results apply right away

Width is w-72 by default. Pass a wider step, such as w-80, for content with an input and a button.

States

StateWhat changesToken
ClosedOnly the trigger shows, with aria-expanded="false"none
OpenPanel fades and zooms in next to the trigger, on the popover layerbg-popover, text-popover-foreground, shadow-md, z-(--z-popover)
FocusMoves into the panel on open; returns to the trigger on closenone: the panel itself has no ring (outline-hidden)

Usage guidelines

  • Open on click, never on hover. Hover is a Hover card.
  • Keep it small: a title, a few lines or one control, and no scrolling.
  • Changes inside a popover apply immediately. If they need a Save button, use a dialog.
  • Name the content with aria-labelledby pointing at PopoverTitle, as in the examples.

Macro breakdown

Protein140 g · 30%
Carbs190 g · 41%
Do.A titled panel with a few lines of detail about the value that opened it.

Edit nutrition plan

Don't.A whole form in a popover. It closes on an outside click and the edits are lost; use a dialog.

Content guidelines

  • Title: a noun phrase for what's inside: "Macro breakdown", "Share program". Sentence case.
  • The trigger's label says what opens or shows the value it explains: "Tuesday: 1,860 kcal".
  • Arabic: units after the number with a space ("140 غ"), Western digits (QUESTIONS Q22).

Accessibility

KeyDoes
Enter or Space on the triggerOpens or closes the popover; focus moves into it
Tab / Shift+TabMoves through the popover's controls. Focus isn't trapped; tabbing past the end closes it
EscapeCloses it and returns focus to the trigger
  • The trigger gets aria-haspopup="dialog", aria-expanded and aria-controls. The content has role="dialog".
  • PopoverTitle is a div, so it doesn't name the panel on its own. Give it an id and pass aria-labelledby to PopoverContent. A screen reader then announces "Macro breakdown, dialog".
  • Status messages inside, such as "Link copied", use role="status".

RTL

The panel is centered under the trigger by default, so it looks the same in both directions. side and align are physical in Radix: align="start" lines up with the left edge in both directions, and side="right" stays right. Pass them from the direction when it matters, as in Sheet. URLs and codes inside keep dir="ltr".

Tokens used

Read from components/ui/popover.tsx at build time, so this list changes when the component does. Opacity modifiers such as /90 are shadcn hover and focus tints on top of the token.

Semantic color tokens used by this component
TokenUtilitiesSuperCoachCoach
--muted-foregroundtext-muted-foregroundneutral-600neutral-600
--popoverbg-popoverwhitewhite
--popover-foregroundtext-popover-foregroundneutral-950neutral-950
  • Layerz-(--z-popover)
  • Radiusrounded-md
  • Shadowshadow-md
  • Typefont-medium
  • Typetext-sm

Props

<Popover>

Also takes every prop of Radix Popover.Root

No props of its own.

<PopoverTrigger>

Also takes every prop of Radix Popover.Trigger

No props of its own.

<PopoverContent>

Also takes every prop of Radix Popover.Content

No props of its own.

<PopoverAnchor>

Also takes every prop of Radix Popover.Anchor

No props of its own.

<PopoverHeader>

Also takes every prop of <div>

No props of its own.

<PopoverTitle>

Also takes every prop of <h2>

No props of its own.

<PopoverDescription>

Also takes every prop of <p>

No props of its own.

PopoverContent defaults to align="center" and sideOffset={4}.

Replaces in coach-admin

From the read-only audit of coach-admin: 10 style values, 10 uses.

coach-admin's shared Popover (.popover-anchor) and the billing details popover become this component.

Classes and selectors

  • .popover-anchor__panel5
  • .billing-details-popover__panel-header1
  • .popover-anchor__panel-title1
  • .billing-details-popover__trigger1
  • .billing-details-popover__download-btn1

Files

  • src/reusableComponents/Popover/Popover.scss7

The inventory lists the first 12 locations of each value, so file counts are a lower bound.

SCSS variables in these styles

  • $spacing-smnot a color: spacing, size or layout
  • $overlay-surface-bgnot a color: spacing, size or layout
  • $spacing-mdnot a color: spacing, size or layout
  • $overlay-surface-shadow-softnot a color: spacing, size or layout
  • $z-index-popovernot a color: spacing, size or layout

Tooltip, Hover card, Dialog.