Skip to content

Popover

A small non-modal panel anchored to a button, for extra detail or a quick edit. Esc closes it and focus returns.

  • Free core, MIT
  • Version 2.0.0-rc.1
  • APG pattern: Disclosure (non-modal)

Examples

These are the real React components. Use them with a mouse, touch or keyboard, and switch the theme and density for every example at once.

Default

Show the code

Default, code

<PopoverTrigger>
  <Button variant="outline">Billing contact</Button>
  <Popover {...args} />
</PopoverTrigger>

Open

Show the code

Open, code

<PopoverTrigger defaultOpen>
  <Button variant="outline">Billing contact</Button>
  <Popover {...args} showArrow />
</PopoverTrigger>

With a field

Show the code

With a field, code

const RenameExample = ({ open }: { open?: boolean }) => (
  <PopoverTrigger defaultOpen={open}>
      <Button variant="outline">Rename</Button>
      <Popover title="Rename project">
        <div className="flex flex-col gap-stack-sm">
          <TextField label="Project name" defaultValue="Northwind" />
          <Button slot="close">Save</Button>
        </div>
      </Popover>
  </PopoverTrigger>
);

<RenameExample />

With a field, open

Show the code

With a field, open, code

const RenameExample = ({ open }: { open?: boolean }) => (
  <PopoverTrigger defaultOpen={open}>
      <Button variant="outline">Rename</Button>
      <Popover title="Rename project">
        <div className="flex flex-col gap-stack-sm">
          <TextField label="Project name" defaultValue="Northwind" />
          <Button slot="close">Save</Button>
        </div>
      </Popover>
  </PopoverTrigger>
);

<RenameExample open />

From an icon button

Show the code

From an icon button, code

<PopoverTrigger>
  <IconButton icon={Info} label="About seats" variant="outline" showTooltip={false} />
  <Popover aria-label="About seats" placement="end">Each seat is one person who can sign in. Team plans start at two seats.</Popover>
</PopoverTrigger>

Coach mark (arrow)

Show the code

Coach mark (arrow), code

<div className="flex min-h-72 items-center justify-center">
  <PopoverTrigger defaultOpen>
    <Button variant="outline">Filters</Button>
    <Popover {...args} showArrow />
  </PopoverTrigger>
</div>

Tokens

The 15 design tokens Popover reads, with the value each has in the theme and density chosen above. Change a token and the component follows, in Figma and in code.

Show all 15 tokens
Tokens Popover reads
TokenValue nowCSS variable
color.text.default…--sd-color-text-default
color.text.disabled…--sd-color-text-disabled
elevation.2…--sd-elevation-2
layer.dropdown…--sd-layer-dropdown
listbox.bg…--sd-listbox-bg
listbox.border…--sd-listbox-border
listbox.option-fg…--sd-listbox-option-fg
listbox.option-height…--sd-listbox-option-height
listbox.option-hover…--sd-listbox-option-hover
listbox.radius…--sd-listbox-radius
radius.sm…--sd-radius-sm
spacing.gap.sm…--sd-spacing-gap-sm
spacing.inset.lg…--sd-spacing-inset-lg
spacing.inset.md…--sd-spacing-inset-md
spacing.stack.sm…--sd-spacing-stack-sm

Install

The npm package isn’t published yet. When it is, this is the install line; until then, this page runs the same build of the package (from commit fa3abf8).

Install

npm i @superduperui/react @superduperui/tokens

Import

import { Popover, PopoverTrigger, popoverSurface, popoverItem } from "@superduperui/react"

Props

Popover also takes the props of the React Aria component it’s built on.

Popover props
PropTypeWhat it does
titlestringOptional visible heading. Without one, give the popover an `aria-label`.
childrenReactNodePanel content: text, links, fields. Optional when the title says it all.
placement'top' | 'bottom' | 'start' | 'end'Default 'bottom'Side of the trigger the panel opens on (it flips when there is no room). Default bottom.
showArrowbooleanDefault falseDraw a small arrow pointing at the trigger, from whichever side the panel opens on (coach marks). Default false.
aria-labelstringAccessible name when there is no title.

When to use it

Use it for

  • Extra detail about a control (what a seat is)
  • A quick, short edit next to the thing it changes
  • A coach mark pointing at a new control: showArrow with any placement (top, bottom, start or end); the arrow follows the side

Use something else for

  • A task that blocks the page or needs confirming: use Dialog
  • A list of actions: use Menu
  • A label for an icon: use the IconButton tooltip
  • The only copy of information the user needs to finish a task

Accessibility

Screen readers announce "Billing contact, button" then on open "Billing contact, dialog".

WCAG 2.2 AAA criteria the component meets in Comfortable density: 1.4.6, 1.4.9, 2.1.3, 2.3.2, 2.4.13, 2.5.5, 2.5.6, 2.3.3.

Compact density meets AA (2.5.8, 24px targets), not AAA.

What your product still has to do

  • Keep popover content short; anything a task depends on also lives on the page

This release’s test results

Test results for Popover in this release
axe-core (WCAG A, AA, AAA and best practice)140 runs across every story, theme, density and width: 0 violations
Rendered text contrast135 text runs: 0 below 7:1, lowest 11.42:1
Target size16 targets: 0 under 44px in Comfortable
Focus appearance (2.4.13)18 focus stops in 3 browser engines: all pass
Keyboard scriptChromium 5 of 5, Firefox 5 of 5, WebKit 5 of 5

Manual passes with VoiceOver and NVDA haven’t been done yet.

Keyboard

Each step is scripted and run in Chromium, Firefox and WebKit.

Popover keyboard steps
KeyWhat happens
TabTab reaches the trigger
EnterEnter opens the panel and focus moves into it
TabTab moves to the field inside the panel
EscapeEsc closes the panel and focus returns to the trigger
EnterEnter on the trigger opens it again

In Figma

The Figma component is Popover, with Placement (Bottom, Top, Start, End); Width (Default, Wide). The Figma library isn’t published yet.

Figma to code: Placement → placement (Bottom = "bottom", Top = "top", Start = "start", End = "end"); Title → title when Show title; Show arrow → showArrow; Content → children; Width (Default, Wide; preview only).