Popover
A floating panel anchored to a trigger for rich, interactive content.
Usage
Unlike a plain <button>, the trigger is wired to the popup through render — pass it your own Button (or any element) and the popover manages its aria-expanded, focus, and open/close. Every part lives in its own import under @appica/ui-react/popover.
Popover is a compound component built on Base UI's Popover. The root holds the open state; the parts compose the trigger and the portalled popup:
PopoverTrigger— the button that toggles the popover. Userenderto project it onto your ownButton(or any element). SetopenOnHoverto open it on hover.PopoverContent— the portalled, auto-positioned popup. It draws the card, border, shadow, and the optionalarrow, and accepts the shared floating props below.PopoverTitle— an<h2>that labels the popup (aria-labelledby).PopoverDescription— a<p>that describes it (aria-describedby).PopoverClose— a button that dismisses the popover; project it onto your ownButtonwithrender.
PopoverContent is the shared floating surface used across the library — DropdownMenu, Tooltip, Select, Combobox, and others reuse the same positioning props. They flatten the underlying Base UI Positioner so you can place the popup without reaching into the portal:
side(top/right/bottom/left) andalign(start/center/end) set the preferred placement; it still flips and shifts automatically to stay in view.sideOffset/alignOffsetnudge it off the anchor;collisionPaddingkeeps a gap from the viewport edge.positionerProps/portalPropsare escape hatches for the inner Positioner and Portal (style,render,dir, …);containerre-targets the portal.
Reach for a Popover when you need rich, interactive content floating beside a control — a form, a set of settings, a share sheet. For a list of actions, use a Dropdown Menu; for a plain text hint, use a Tooltip; for a hover preview of a link, use a Preview Card.
Examples
Form in a popover
Popovers can hold interactive content, including focusable form controls. Lay out Fields inside the popup and dismiss it with PopoverClose projected onto your action buttons — clicking either one closes the popover. Widen the popup past its default with a className (w-72 here).
Controlled
Drive the open state yourself with open + onOpenChange (or stay uncontrolled with defaultOpen). Here a status picker closes the popup the moment you choose an option — setOpen(false) straight from the row's handler — while the trigger reflects the current selection. Owning the state is what lets you close on select, open the popover from elsewhere, or keep it in sync with the rest of your UI.
Open on hover
Set openOnHover on the PopoverTrigger to reveal the popup on pointer rest (it still opens on click and keyboard). Tune the timing with delay / closeDelay. Use it for supplementary detail like a richer-than-tooltip hint — but remember hover isn't reachable on touch, so don't hide essential actions behind it.
Without an arrow
Pass arrow={false} to drop the pointer. The popup also pulls a little closer to the trigger and loses the thicker anchored border, for a flatter, menu-like surface.
Side & alignment
Position the popup with side (top / right / bottom / left) and align (start / center / end) on PopoverContent. Wherever you point it, it still flips and shifts automatically to stay within the viewport.
RTL
Every Appica UI component supports right-to-left layouts out of the box. Set the dir attribute on a container (commonly your <html> element) so CSS logical properties resolve correctly, and wrap your tree in DirectionProvider so direction-aware behavior — popup placement and alignment — follows the same direction.
The popup anchors from the trigger's leading edge and start/end alignment mirrors. For setup details and caveats, see the RTL guide.
Scoped RTL needs the direction on the positioner
The popup portals to <body>, so its start/end alignment mirrors from the document direction (read from CSS,
not from DirectionProvider) — automatic when <html dir="rtl">. If you instead scope RTL to a subtree of an LTR
page, set it on the positioner so alignment still mirrors: <PopoverContent positionerProps={{ dir: 'rtl' }}>. See
Floating popups in a scoped RTL region.
API reference
Popover wraps Base UI's Popover. Each part forwards every remaining prop to the matching Base UI primitive, so anything it accepts works here — the tables below list the Appica additions and the most common props. See the Base UI docs for the complete API.
Popover
The root. Holds the open state; renders no DOM of its own.
PopoverTrigger
The button that toggles the popover. Forwards Base UI's Popover.Trigger; use render to project it onto your own element.
PopoverContent
The portalled, auto-positioned popup. Draws the card and the optional arrow, and accepts the shared floating props. Defaults to side="bottom", align="center", and sideOffset={10} (or 6 without an arrow).
PopoverTitle
An <h2> that labels the popup. Rendering one sets the popup's aria-labelledby.
PopoverDescription
A <p> that describes the popup. Rendering one sets the popup's aria-describedby.
PopoverClose
A button that closes the popover. Forwards Base UI's Popover.Close; project it onto your own element with render.
Accessibility
- The trigger is a
buttonwitharia-haspopup="dialog"andaria-expanded; the popup hasrole="dialog". PopoverTitleandPopoverDescriptionwire the popup'saria-labelledby/aria-describedbyautomatically — prefer them over hand-rolled headings.- Enter / Space open the popover from the trigger, Escape closes it, and focus returns to the trigger on close.
- With
modal, focus is trapped inside the open popup and outside scroll/interaction is blocked; the default (false) leaves the rest of the page interactive. - Popup enter/exit transitions are skipped when the user prefers reduced motion.