Popover

Shows a few lines next to a control.

Opening

  • pressdefault

  • Token budget

    PopoverInfo

  • openOnHover

Usage

When to use it
Use
A small task beside its control: share a link, set one value, pick a filter.
Use
The explanation of a term beside it (PopoverInfo).
Use
A preview of a linked thing on hover, for a pointer (openOnHover).
Not for
A list of actions. Use Dropdown menu.
Not for
A one-line name for an icon button. Use Tooltip.
Not for
A decision the page must wait for. Use Dialog.
Not for
More than 320px of content. Use Sheet.

Rules

8 rules
Must
Use PopoverInfo for an info icon that explains a term, never a Tooltip. Because a tooltip never opens on touch and closes when the pointer leaves, so the definition is unreadable on a phone.
Must
Pass title (it names the button "About <title>") or label to PopoverInfo. Because without either every info button is named "More information" and a screen reader cannot tell them apart.
Must
Write plain text only in a PopoverInfo; put a link beside the term, or use a Popover. Because focus never enters a PopoverInfo, so a link inside it cannot be reached by keyboard.
Must
Make an openOnHover trigger a link that works on its own, and show nothing the linked page does not. Because touch and keyboard never see a hover preview, so the link has to reach the same facts alone.
Never
Put actions in a hover preview; move them to a DropdownMenu or the linked page. Because a peek closes when the pointer leaves and never opens on touch, so the actions slip away or never appear.
Must
Give a popover at most one ink Button; Done or Cancel beside it is variant="secondary" (paper). Because the popover's actions are one group, and two ink pills split the eye.
Never
Add a shadow or an arrow; the ring and the 6px offset tie the panel to its trigger. Because Glaze has no shadows, every shadow class draws nothing, and an arrow breaks the ring's one edge.
Should
Lead a hover preview with the name and one line of what it is, then two to four facts with numbers.

State order

4 states, highest first
1
pinned
2
open
3
peeking
4
closed

Accessibility

4 checks
The panel is a dialog named by PopoverTitle; Tab moves through its content and leaving it closes it.
A peek never takes focus; a pinned preview shows a Close preview button.
PopoverInfo's text is also its button's description, so focus alone reads it.
Hover previews never open on touch; PopoverInfo opens by tap.

Keyboard

3 keys
Enter, Space
Opens or closes it from the trigger; pins a peeking preview.
Escape
Closes this popover only and returns focus to the trigger.
Tab
Moves through the content; past the last control it closes and moves on.

Edge cases

6 edge cases
Long content
The title wraps and the panel scrolls inside the available height.
Opened at a screen edge
The panel flips and shifts to stay 8px inside.
Phone, 390 wide
The panel keeps 288px, or the available width when that is less.
Inside a Dialog
Escape closes the popover first; focus returns to its trigger.
Right to left
The panel lays out right to left inside an RTL portal scope.
Reduced motion
It cuts in and out instead of fading.

API

7 props
Popover open, defaultOpen, onOpenChange
Base UI default false
Popover defaultPreview
'peeking' | 'pinned'
PopoverTrigger openOnHover, delay, closeDelay
boolean, number default false, 600, 300
PopoverContent side, align, sideOffset
Base UI default 'bottom', 'center', 6
PopoverContent collisionPadding
number default 8
PopoverInfo title, label
ReactNode, string default 'About ' + title
PopoverInfo side, align
Base UI default 'top', 'center'

Tokens

15 tokens
--paper
#ffffff
--line
rgb(5 5 5 / 0.10)
--radius-overlay
10px
--popover
288px
--space-3
12px
--type-label
500 13px/1.35 var(--font-sans)
--type-body-sm
400 13px/1.5 var(--font-sans)
--text-1
rgb(5 5 5 / 0.80)
--text-2
rgb(5 5 5 / 0.60)
--hover
rgb(5 5 5 / 0.06)
--pressed
rgb(5 5 5 / 0.10)
--z-overlay
50
--dur-overlay
200ms
--dur-state
160ms
--ease-out
cubic-bezier(0.2, 0.8, 0.2, 1)

Install

For your coding agent

GitHub

Please star me pookie

141

A new design system every week

Leave your email before you copy the prompt.