Skip to main content

Popover

A floating panel anchored to a trigger that holds richer content than a tooltip, such as a short explanation, a link, or a small set of controls. Use for supplementary content the user opens on purpose. Don't use for essential information, confirmations or menus.

OverviewStyleAccessibility

Description

Anatomy

PartRequired?Notes
Trigger Required The button or link that opens the popover. Must be focusable, and carries aria-expanded and aria-controls.
Panel Required The floating surface that holds the content. Has a border, rounded corners and a soft shadow so it reads as sitting above the page.
Content Required Whatever the popover is for. Keep it short; if it needs scrolling or several steps, use a Modal or a page.
Arrow Optional A small pointer from the panel toward the trigger. Helps show which element opened the panel, especially when it moves to another side to stay on screen.

Variants

States

State Behaviour
Closed Default. The panel isn't in the page layout. The trigger shows aria-expanded="false".
Open The panel appears next to the trigger. Focus moves into it when it holds interactive content, or stays on the trigger when it holds read-only text.
Dismissed The user presses Escape, activates the trigger again, or moves focus or clicks outside. The panel closes and focus returns to the trigger.

Usage guidelines

Do / Don't

Do

Open a popover from a button or link the user chooses to activate, and label that trigger clearly.

Don't

Don't open a popover on page load or without a user action. It interrupts people and screen readers may not announce it.

Do

Keep the content to a few lines or a handful of controls, with a clear way to dismiss it.

Don't

Don't stack popovers or open a Modal from inside one. If the flow needs that, redesign it.

Layout & Spacing

The panel is as wide as its content, up to the width the page sets. It repositions itself to stay inside the viewport.

Element Spec
Background Raised surface colour. --orbit-popover-background
Border 1px, subtle border colour. --orbit-popover-border-width, --orbit-popover-border-color
Corner radius 8px. --orbit-popover-radius
Padding 24px on all sides. --orbit-popover-padding
Gap to the trigger 8px. --orbit-popover-offset
Arrow 8px square, overlapping the panel edge by half its size (worked out in code, because tokens can't be negative). --orbit-popover-arrow-size
Shadow Medium elevation, the same as Menu. --orbit-popover-shadow-*

Component tokens

These are framework-neutral CSS variables. In both Light and Dark the colours follow the Semantic surface and border tokens.

Token What it sets
--orbit-popover-background Panel fill (the raised surface).
--orbit-popover-border-color, -border-width Panel outline.
--orbit-popover-radius Corner radius of the panel.
--orbit-popover-padding Space between the panel edge and its content.
--orbit-popover-offset Gap between the trigger and the panel.
--orbit-popover-arrow-size Width and height of the arrow square.
`--orbit-popover-shadow-{offset-x offset-y
Element Token
Panel fill --orbit-popover-background
Panel outline --orbit-popover-border-color
Shadow colour --orbit-popover-shadow-color

Engineering notes

  • In the React Aria trial, the panel is Popover, with the trigger as a DialogTrigger and the content in a Dialog. Apply the --orbit-popover-* variables to the Popover through a class name. Treat this mapping as a proposal until Engineering confirms it in the trial.
  • Use the offset setting for the trigger gap rather than adding margin to the panel, so the positioning logic stays correct when the panel flips to another side.
  • The arrow is half outside the panel. Compute its overlap from --orbit-popover-arrow-size (for example calc(var(--orbit-popover-arrow-size) / -2)) instead of hard-coding it.
  • Pickers whose panel is a list of options (Combobox, Select) use the menu surface tokens so they look identical to each other. Use the popover tokens for content panels.

Keyboard interaction

KeyAction
Enter or Space On the trigger, opens the popover. Activating the trigger again closes it.
Tab Moves focus through the interactive content inside an open popover. Focus is not trapped; tabbing past the last item moves on to the next element in the page.
Escape Closes the popover and returns focus to the trigger.

Why it matters

People who use a keyboard or a screen reader can only reach a popover through its trigger, so the trigger must announce whether the panel is open and where it is. If focus doesn't move into interactive content, or doesn't return to the trigger on close, these users lose their place.

ARIA

Role or attributeWhen to useExample
aria-expanded On the trigger. true while the popover is open, false when closed. <button aria-expanded="true" aria-controls="filter-panel">Filters</button>
aria-controls On the trigger. Points to the id of the popover panel. <button aria-controls="filter-panel">Filters</button>
role="dialog" On the panel when it holds interactive content, with aria-label or aria-labelledby naming it. Not modal: content behind it stays available. <div id="filter-panel" role="dialog" aria-label="Filters">

Things to avoid

  • Don't open a popover on hover alone. If it must open on hover, it also has to open on keyboard focus, stay open while the pointer moves onto it, and be dismissible without moving the pointer (WCAG 1.4.13).
  • Don't trap focus in a popover. If it needs a focus trap, it should be a Modal.
  • Don't rely on the arrow or the shadow to show where the panel ends. The border and background already do that, and must keep their contrast.

Was this page helpful?

Updated 2 October 2026