Popover · Hover card
Popover — a panel anchored to what opened it, for a small form or a filter that does not deserve a dialog.
Beta · Feedback and status · packages/css/src/components/popover.css
.pui-popover (__head __title __hint __content __footer, 300) · .pui-hover-card (__who __texts __name __subtitle __description, 256). No arrow.
Sizes across, states down.
Popover — Beta
Section titled “Popover — Beta”- Title + Has title, Hint + Has hint — the head; Content is a swap (default: Slot) the consumer points at its own component — a Field, a Select, a Slider row, a Checkbox list — and Has content hides it; Has footer shows the exposed Button group (Cancel + a verb, small)
- One width, 300; the height follows the content
- No states: the trigger carries them; the panel is open or not
Use when a click on a control opens a few related controls — a filter’s fields, a colour, a small settings group — that close when done.
Do not use when the content is a list of actions (Dropdown menu) or options (Select menu); it must block the page (Dialog); it is a preview on hover (Hover card); it holds a form longer than four fields (Sheet).
Relates to Tooltip, Hover card, Dropdown menu, Dialog, Sheet, Date picker, Button group, Slot.
Anti-patterns an arrow on it · a popover inside a popover · a title that repeats the trigger’s label · a footer with two primary verbs · the slot placeholder left showing · a fill changed on the instance.
Keywords: popover, panel, anchored, filter, small form, bg-pop
Slot is the Figma stand-in for
children; it has no code side
Figma — page Popover & Hover card: Popover (1 variants) · Slot (1 variants)
shadcn: popover
Hover card — Beta
Section titled “Hover card — Beta”Hover card — a preview of a thing under the pointer: a publisher, a campaign, a person; appears on hover after a beat, never on touch.
- Name, Subtitle, Description + Has description; Avatar and Badge exposed (initials, tone, label); Has badge
- One width, 256; two or three lines of description at most — a preview, never a form or a table
- No states and no arrow; the trigger (a link, an Avatar, a table cell) carries the hover
Use when a row or a link names a thing the user may want a glance at without leaving — a publisher’s standing, a campaign’s numbers, a teammate’s role.
Do not use when the user must act (Popover, Dropdown menu); on a touch screen as the only way to the facts (a tap goes to the page); for help text (Tooltip); for a person’s full profile (a page).
Relates to Tooltip, Popover, Avatar, Badge, Table, Item.
Anti-patterns a form in it · a hover card with buttons · numbers that the row already shows · a hover card on a button · a fill changed on the instance.
Keywords: hover card, preview, profile card, publisher, peek
Figma — page Popover & Hover card: Hover card (1 variants)
shadcn: hover-card
The markup — copy this
Section titled “The markup — copy this”The class, the parts, and nothing that is not in the package. The same block opens popover.css.
<div class="pui-popover" role="dialog" aria-labelledby="t"> <div class="pui-popover__head"><p class="pui-popover__title">Filters</p><p class="pui-popover__hint">Applied on Apply.</p></div> <div class="pui-popover__content"> …fields… </div> <div class="pui-button-group pui-popover__footer"> …Reset · Apply (small)… </div></div> <div class="pui-hover-card"><div class="pui-hover-card__who"> …avatar, name, subtitle, badge… </div> <p class="pui-hover-card__description">14 active offers, 92 % fill rate</p></div>Keyboard the trigger holds the tab stop; focus moves in on open, Escape closes and returns it.Accessibility — measured, not assumed
Section titled “Accessibility — measured, not assumed”Every number here is measured on the rendered component: contrast (npm run contrast:render), the focus ring (npm run focus) and the keyboard (npm run keyboard). The floors are principle 12’s.
Contrast
Section titled “Contrast”| ink on ground | reads | floor | the matrix calls it | |
|---|---|---|---|---|
#1a6b36 on #d4f2de |
5.48 | 4.5 | Success badge (promised) | ok |
#544d4d on #ffffff |
8.24 | 4.5 | text.muted on surface.page (promised) | ok |
#110e56 on #d4d3f7 |
11.84 | 4.5 | Blue avatar initials (promised) | ok |
#0b0202 on #ffffff |
20.51 | 4.5 | text.default on surface.page (promised) | ok |
#ffffff on #0b0202 |
20.51 | 4.5 | Primary button label (promised) | ok |
5 distinct pair(s) rendered, 0 that axe calls a violation.
The focus ring
Section titled “The focus ring”4 of 4 focus stop(s) in this block meet WCAG 2.4.13 on screen — the same crop screenshotted focused and unfocused, and the difference measured.
Keyboard
Section titled “Keyboard”| role | tab stops | what the pattern requires | |
|---|---|---|---|
dialog .pui-popover |
4 | — | — |
What the consumer’s script owes. the trigger holds the tab stop; focus moves in on open, Escape closes and returns it.
Tab order across the whole library is document order over 344 stops, and Shift+Tab is its exact reverse — no keyboard trap anywhere (WCAG 2.1.2).
Pepper UI v1.5.0
The Mobupps design system. 386 tokens, 88 components, 65 pages in the workshop — every page of this site generated from the repository, so nothing here is typed twice.