Skip to Content
⭐️ Leave a star →
ComponentsPopover

Popover

Currently only available in React.

Floating panel anchored to a trigger. Closes on outside click or Escape by default. Controlled and uncontrolled. The component is unstyled and unpositioned — use Tailwind / CSS to anchor the Content relative to the Root.

Features

Closes on outside click and Escape (toggleable).
Can be controlled or uncontrolled.
forceMount keeps Content in the DOM for animation.
Close subcomponent for inline close buttons.
Full ARIA wiring: aria-haspopup / aria-expanded / aria-controls.

Example

import { Popover } from '@wire-ui/react' <Popover.Root> <Popover.Trigger>Open</Popover.Trigger> <Popover.Content side="bottom" align="center"> <p>Popover content</p> <Popover.Close>Close</Popover.Close> </Popover.Content> </Popover.Root>

Styling

Root, Trigger, and Content all expose data-state ("open" / "closed"). Content additionally exposes data-side and data-align. Position the Content manually — wire-ui does not auto-anchor.

<Popover.Content className=" absolute top-full mt-2 data-[state=closed]:hidden data-[state=open]:animate-in data-[side=top]:bottom-full data-[side=top]:top-auto data-[side=top]:mb-2 data-[side=top]:mt-0 " />

Using data attributes

[data-state="closed"] { display: none; } [data-state="open"] { animation: fadeIn 120ms ease-out; } [data-side="top"] { transform-origin: bottom; } [data-side="bottom"] { transform-origin: top; } [data-align="start"] { left: 0; } [data-align="center"] { left: 50%; transform: translateX(-50%); } [data-align="end"] { right: 0; }

Root props

PropTypeDefaultDescription
openbooleanControlled open state
defaultOpenbooleanfalseInitial open state (uncontrolled)
onOpenChange(open: boolean) => voidCalled when the open state changes
closeOnOutsideClickbooleantrueClose on outside click
closeOnEscapebooleantrueClose on Escape key

Trigger props

Accepts all standard <button> attributes. Clicking toggles the open state. Receives aria-haspopup="dialog", aria-expanded, and aria-controls automatically.

Content props

PropTypeDefaultDescription
side'top' | 'right' | 'bottom' | 'left''bottom'Side data attribute for position-aware styling
align'start' | 'center' | 'end''center'Alignment along the side
forceMountbooleanfalseKeep mounted in DOM when closed (use with data-state for animation)

Close props

Accepts all standard <button> attributes. Closes the popover on click.

Data attributes

AttributeElementValues
data-stateRoot, Trigger, Content"open" / "closed"
data-sideContent"top" / "right" / "bottom" / "left"
data-alignContent"start" / "center" / "end"
data-hoverTrigger, CloseMouse is over the button
data-focus-visibleTrigger, CloseButton has keyboard focus
data-activeTrigger, CloseButton is being pressed

Accessibility

  • Trigger renders as <button> with aria-haspopup="dialog", aria-expanded, and aria-controls.
  • Content is <div role="dialog"> with aria-labelledby pointing at the Trigger.
  • Focus is left up to the caller — wire-ui does not auto-focus Content (use a focused element inside it if needed).
  • Set closeOnOutsideClick={false} for click-resistant overlays; set closeOnEscape={false} to require an explicit Close.

Keyboard Interactions

KeyDescription
Space / EnterToggles the popover when Trigger is focused.
EscapeCloses the popover (when closeOnEscape is true).
TabMoves focus through Trigger, then into Content when open.
Last updated on

MIT License © 2026 wire-ui

Popover – Wire UI