Skip to content
buttery

v1.0.0

Source on GitHub

Version 1.0.0

Popover

A floating panel anchored to a trigger, on the floating surface in the dropdown layer.

import { Popover } from "@butteryui/core";

Demo

When to use it

Use it for

  • Small forms or option lists that belong to one control
  • Anything that should close on Escape or an outside click

Not for

  • Lists of actions: use Menu
  • Picking one value from a list: use Select
  • Hover hints: use Tooltip
  • Blocking decisions: use Dialog

Examples

Card nickname

A popover whose open state lives in the example, so the form inside can close it once the saved card has a nickname.

Gift card size

A trigger that opens the gift card's printed sizes; picking one closes the popover and shows on the trigger.

Order filter

A list's filter in a popover beside its title: each roast it toggles filters the orders at once.

Orders

Showing 6 of 6 orders

Harbor blend

Medium

Kiambu washed

Light

Night shift

Dark

Guji natural

Light

Espresso no. 4

Dark

Huila honey

Medium

Variants and states

Sides

8px from the trigger; it flips when there isn't room.

Long content

Taller than the space available, so it scrolls inside.

Scrim

A blurred scrim under a menu that opens over content; clicking it closes the menu.

Props

Popover

PropTypeDefaultDescription
openbooleanWhether the popover is open. Pair with onOpenChange to control it.
defaultOpenbooleanfalseWhether it starts open when uncontrolled. Defaults to false.
onOpenChange((open: boolean) => void)Called when the popover opens or closes.
modalbooleanfalseKeep focus inside and make the page inert while open. Defaults to false.
entrance"grow" | "instant""grow" from the trigger with a fade, or "instant", complete in the next frame, as app chrome moves. Defaults to what's set around it ("instant" inside AppShell layout="sidebar"), else "grow".
childrenReactNodeThe trigger and content: Popover.Trigger, Popover.Content and, optionally, Popover.Anchor.

Popover.Anchor

It also takes ComponentPropsWithRef<typeof RadixPopover.Anchor>.

Popover.Close

It also takes ComponentPropsWithRef<typeof RadixPopover.Close>.

Popover.Content

PropTypeDefaultDescription
scrim"dim" | "blur"Covers the page behind the open popover: "blur" for menus that open over content, "dim" to set it apart further. It fades in and out with the panel, and clicking it closes the popover. Defaults to no scrim.

It also takes Omit<ComponentPropsWithRef<typeof RadixPopover.Content>, "sideOffset" | "collisionPadding" | "avoidCollisions" | "forceMount" | "asChild">.

Popover.Trigger

It also takes ComponentPropsWithRef<typeof RadixPopover.Trigger>.

Accessibility

The trigger gets aria-expanded and aria-controls; the content is a dialog that takes focus on open, closes on Escape and returns focus to the trigger. In a field holding an unsaved edit, the first Escape puts the field back.

KeysWhat they do
Enter or SpaceOpens it from the trigger and moves focus to the first control inside, or to the panel when it has none
Tab or Shift+TabMoves through the controls inside it, wrapping from the last to the first
EscapeCloses it and puts focus back on the trigger; in a field holding an unsaved edit, the first Escape puts the field back

Motion

It appears with a `Presence` preset and leaves faster than it came, in about 60% of the time.

With reduced motion: It fades in and out over 100ms without growing from the trigger, and so does its scrim; with entrance="instant", the panel and its scrim show and go at once either way.

Layout

It's as wide and tall as its content, up to the room beside its trigger, and scrolls inside past that. It opens 8px from its trigger, flips or shifts to stay 8px inside the window and never covers the trigger; what's inside it brings its own hit areas.