Skip to content

Popover

Show a small task or extra detail in a panel anchored to a control.

import { Popover, PopoverClose, PopoverContent, PopoverDescription, PopoverHeader, PopoverTitle, PopoverTrigger } from '@youj/react'

Installation & usage

npm i @youj/react

For an app already set up with npx @youj/cli init, which installs the peers (@youj/core, @youj/motion, motion and Base UI) and wires the provider. New app? Start at Installation.

Use Popover for a small task or detail tied to a control, such as sharing, filters or a quick setting. The page stays usable by default. Use a Dialog when the task must be completed or dismissed first. Use a Tooltip for a short visual label.

import { Button, Popover, PopoverContent, PopoverDescription, PopoverHeader, PopoverTitle, PopoverTrigger } from '@youj/react'

export function SharePopover() {
  return (
    <Popover>
      <PopoverTrigger render={<Button variant="outline" />}>Share</PopoverTrigger>
      <PopoverContent align="end">
        <PopoverHeader>
          <PopoverTitle>Share youj-web</PopoverTitle>
          <PopoverDescription>Invite teammates by email.</PopoverDescription>
        </PopoverHeader>
        <InviteForm />
      </PopoverContent>
    </Popover>
  )
}

PopoverTrigger renders a button. Pass render to use your own Button and keep its variants. PopoverContent brings the portal, the positioner and the popup in one part, so placement props go straight on it. PopoverClose closes the popover from inside, for a Done or Cancel button.

Reference

Propscontainer, presentation (2)

Props

PopoverContent

PopoverContent props
PropType
containerHTMLElement | ShadowRoot | RefObject<HTMLElement | ShadowRoot | null>

Where the portal renders. Default: the provider's portal container, else document.body.

–
presentationOverlayPresentation
'auto''sheet''popover'

auto (the default) is a popover under a pointer and a bottom sheet on touch; force either one.

default 'auto'

'auto'

Popover takes Base UI's root props (open, defaultOpen, onOpenChange, modal), and PopoverTrigger takes the trigger's (openOnHover, delay, closeDelay, render). PopoverHeader, PopoverTitle, PopoverDescription and PopoverClose add no props of their own.

TouchOn a touch device the popover is a bottom sheet

Touch

On a touch device the popover is a bottom sheet. It rises from the bottom of the screen over a scrim, spans the screen's width and has a grab handle. Pull it down, tap outside it or press Escape to close it, and focus returns to the trigger. Your content and its horizontal padding stay the same; placement props (side, align, offsets) don't apply, since a finger would cover anything anchored to the trigger. A field inside raises the on-screen keyboard, and the sheet moves up to stay above it.

On touch, Popover is modal unless you pass modal, so the page under the sheet doesn't scroll. A control inside that handles its own drag, such as a slider or a canvas, can carry data-sheet-no-drag so dragging it never pulls the sheet away.

presentation on PopoverContent chooses: auto (the default) is a popover under a mouse or trackpad and a sheet on touch, sheet always uses the sheet, and popover keeps the anchored popover on touch too. Touch follows the device, not the screen width, and YoujProvider's device can force it for a part of the page.

MotionOpen, close, keyboard open, Escape close · reduced motion

Motion

Motion tokens
MomentTokens
Openscale .96 → 1 and fade, from the anchor point (yj-pop)
duration.fastease.enter

140ms · cubic-bezier(0.16, 1, 0.3, 1)

140mscubic-bezier(0.16, 1, 0.3, 1)
Closegets out of the way faster than it arrived
duration.instantease.exit

80ms · cubic-bezier(0.4, 0, 1, 1)

80mscubic-bezier(0.4, 0, 1, 1)
Keyboard open, Escape closeBase UI sets data-instant
no token

0ms

0ms

Reduced motion

The popover appears and disappears at once. Focus handling, placement and content are unchanged.

The popup's transform-origin is the point Base UI anchors it to, so it scales out of the trigger, not out of its own center. It animates on transitions, not keyframes, so reopening a popover while it closes reverses it from where it is.

Reduced motion

The popover appears in place and closes at once. Its portal carries the nearest YoujProvider's settings, so a provider set to reducedMotion="always" reaches it even though it renders outside the provider's DOM.

AccessibilityKeyboard, ARIA, focus

Accessibility

  • The popup is a dialog, named by PopoverTitle and described by PopoverDescription. The trigger carries aria-expanded and aria-haspopup="dialog".
  • Opening moves focus to the first focusable element inside, or to the popup itself. Closing returns focus to the trigger.
  • Under a mouse or trackpad it isn't modal by default: the rest of the page stays usable, and a press outside closes the popover. Pass modal to Popover to trap focus and lock scrolling instead. On touch it's modal unless you pass modal={false}.
KeyAction
Enter / SpaceOpens or closes the popover from the trigger.
TabMoves through the popover's content.
EscapeCloses the popover and returns focus to the trigger.