Skip to content

Popover

A floating panel anchored to a trigger, for rich or interactive content such as a small form, filters or details.

Preview

Installation

pnpm add @syntara/react @syntara/tokens
import { Popover } from '@syntara/react';

Usage

import { Button, DialogTrigger, Popover } from '@syntara/react';

export function Details() {
  return (
    <DialogTrigger>
      <Button variant="outline">Details</Button>
      <Popover showArrow placement="bottom">
        Submitted on 12 March by Priya Raman.
      </Popover>
    </DialogTrigger>
  );
}

Examples

With arrow

showArrow points at the trigger; placement picks the side.

Accessibility

KeysAction
EnterorSpaceOn the trigger: opens the popover and moves focus into it.
TaborShiftTabMoves between focusable elements inside the popover.
EscapeCloses the popover and returns focus to the trigger.
  • Inside a DialogTrigger the popover is a dialog labelled by its trigger; pass aria-labelledby to point at a heading inside instead.
  • Clicking outside closes it.
  • Overlays render in a portal on <body>, outside any ThemeScope. When it opens, the overlay looks up data-syntara-theme, data-syntara-scheme, data-syntara-density, dir and lang — each on the nearest ancestor that has it — starting from its trigger (or from where the component is rendered, when controlled), and copies them onto its own root — so it uses the same tenant tokens and direction as the page region it came from, and nested overlays inherit from their parent overlay.
  • The panel is glass: only text.default and text.subtle sit directly on it (the roles the theme engine solves to 4.5:1 over any backdrop); put other colours on an opaque role background. It grows out of its trigger (spring from 0.96 plus a 4px nudge, from --trigger-anchor-point); with prefers-reduced-motion it appears without moving.

Guidelines

Do

  • Use for supplementary, interactive content tied to one control.
  • Keep it small; use a Dialog or Sheet when the content needs more room.

Don’t

  • Don't use a Popover for a plain text hint — use a Tooltip.
  • Don't use it for a list of actions — use a Menu.

API reference

Popover

children
ReactNode

The content. Padded with card-inset.

showArrow
boolean

Draws an arrow pointing at the trigger.

Default false

placement
Placement

Preferred side and alignment, e.g. 'bottom start', 'top', 'end'. Flips when there is no room.

Default 'bottom'

offset
number

Distance from the trigger in px.

Default 6 (10 with arrow)

isNonModal
boolean

Lets users interact with the page while it is open (no focus trap, no outside-click dismissal).

Default false

triggerRef / isOpen / onOpenChange
RefObject<Element> / boolean / (isOpen: boolean) => void

For a popover anchored to an element without a DialogTrigger.

className
string | (state) => string

Merged onto the popover root. Set --popover-padding to change the padding.

Tokens

The semantic tokens this component reads, grouped by what they control. Swatches show this site’s theme; change a tenant’s brand and the component follows with no code change.

Colour3
text.defaultsurface.raisedborder.subtle
Type3
font.bodyfont.size.mdline-height.normal
Space and size4
space.4card-insetspace.1space.3
Shape1
radius.container
Depth4
glass.blurshadow.overlayglass.opacityhairline
Motion6
motion.duration.normalmotion.easing-outmotion.duration.springmotion.springmotion.duration.fastmotion.easing
Other2
sheenrim