Popovers are floating overlays that contain additional information or interactive content.

Popover

Usage

  • Use Popover for supplementary content that is too long and detailed for a Tooltip but does not warrant a Modal or a new page.
  • Use Popover for both static text and interactive content such as buttons, links, or forms.
  • Use Tooltip instead for short, non-interactive text that appears on hover and focus and dismisses when the user moves away.
  • Use Modal instead when the user must complete a focused task, such as a confirmation or form, before returning to the page. Popovers overlay page content but never render it inert.
  • Never nest a Popover inside another Popover. Rework the flow, write the content inline or on another page, or use a Modal.

Appearance

  • Show the arrow by default (withArrow, defaults to true) to visually connect the Popover to its trigger.
  • Hide the arrow (withArrow={false}) only when the trigger association is already evident or the layout is dense.
  • Use PopoverTrigger for an inline text trigger that blends with surrounding content.
  • Add an underline (isUnderlined on PopoverTrigger) to make the trigger visually distinct within body text.
  • Use PopoverTriggerButton for a prominent, button-styled call to action.
  • Build a custom trigger by passing a component to PopoverTrigger's as prop.

Behaviors

  • Popovers open on trigger click by default (shouldTriggerOnClick, defaults to true).
  • Enable hover opening (shouldTriggerOnHover={true}) only when absolutely necessary. Hover-opened Popovers appear after a 250ms delay.
  • Popovers animate in and out with a fade and a directional slide matching their placement. The transition duration defaults to 125ms; override it with animationTransitionDuration in milliseconds.
  • Popovers dismiss on outside click, Escape key, and focus loss. Focus returns to the trigger after closing.
  • Disable close-on-focus-loss (shouldCloseOnFocusOut={false}) for a persistent Popover that requires an explicit outside click or Escape press.
  • Enable dragging (isDraggable={true}) to let users reposition the Popover. Dragging supports mouse and keyboard — Space enters drag mode, arrow keys move the Popover.
  • Set placement to position the Popover on any side of its trigger. Default is bottom. Placement is a preference, not a guarantee — the Popover repositions in smaller viewports to stay visible.

Content

  • Write headers and descriptions in sentence case.
  • Write a header that summarizes the topic or intention, and a description that explains it. Never repeat the trigger text in the header without adding context.
  • Limit content to a maximum of three sentences. Use a Modal or move content into the page flow for anything longer.
  • Label interactive elements with specific action verbs that describe what will happen (e.g., "Resume campaign"). Never use generic labels like "OK" or "Click here".

Implementation Notes

  • Popover supports a shorthand API: pass header and description (both strings) directly to Popover for text-only content with no subcomponent composition. The Popover renders them into a PopoverContent internally.
  • For rich or interactive content, compose PopoverContent as a child of Popover, alongside the trigger. Use PopoverContentHeader and PopoverContentDescription inside it for the standard text layout.
  • The shorthand props and composed PopoverContent are additive — both render if both are supplied.
  • The content prop is deprecated. Use description instead; the component falls back to content only when description is unset.
  • PopoverTriggerButton renders a Button and accepts every Button prop (variant, size, icon, iconPosition, isIconOnly). It also derives its active state from the Popover's open state automatically.
  • Render PopoverPrimitiveDragHandle (exported from the Popover primitive) inside PopoverContent to provide the handle for isDraggable. The Popover does not render one on its own.
  • Enable shouldTrapFocus when the Popover contains interactive elements, so focus stays inside while it is open.
  • Control the open state externally with isOpen paired with onOpenChange. Use defaultIsOpen for an uncontrolled initial state.
  • Disable the whole Popover conditionally with isDisabled.
  • Adjust the hover delay through floatingPluginOptions.hover.delay; fine-tune positioning with middlewareOptions (offset, flip, shift, size) and additionalMiddleware.
  • unsafe_popoverClassName, unsafe_popoverContentClassName, and unsafe_popoverStyle are last-resort styling overrides.
  • React passes content via children. Ember yields via the default block, which also exposes the Floating UI context as a block param.
  • In Ember, components take the Pluma prefix (<PlumaPopover>, <PlumaPopoverTrigger>, <PlumaPopoverTriggerButton>, <PlumaPopoverContent>) and all props are @ args: <PlumaPopover @placement="bottom" @withArrow={{false}}>.
  • In Ember, pass @isCustom={{true}} to PlumaPopoverTrigger to yield the trigger bindings for a fully custom trigger element instead of rendering one.

On this page