Components
Popover

Popover

An overlay that displays additional information or options when triggered.

Loading...

You can explore the popover component in the following curated examples.

Anatomy

<Popover.Root>
  <Popover.Trigger />
  <Popover.Anchor />
  <Popover.Positioner>
    <Popover.Arrow>
      <Popover.ArrowTip />
    </Popover.Arrow>
    <Popover.Content>
      <Popover.Title />
      <Popover.Description />
      <Popover.CloseTrigger />
    </Popover.Content>
  </Popover.Positioner>
</Popover.Root>

Examples

Controlled

Use the open and onOpenChange props to control the open state of the popover.

Root Provider

An alternative way to control the popover is to use the RootProvider component and the usePopover hook. This way you can access the state and methods from outside the component.

Arrow

Use Popover.Arrow and Popover.ArrowTip to render an arrow pointing to the trigger.

Placement

To change the placement of the popover, set the positioning prop.

Close Behavior

The popover is designed to close on blur and when the esc key is pressed.

  • To prevent it from closing on blur (clicking or focusing outside), pass the closeOnInteractOutside prop and set it to false.
  • To prevent it from closing when the esc key is pressed, pass the closeOnEsc prop and set it to false.

Modality

In some cases, you might want the popover to be modal. This means that it'll:

  • trap focus within its content
  • block scrolling on the body
  • disable pointer interactions outside the popover
  • hide content behind the popover from screen readers

To make the popover modal, set the modal prop to true. When modal={true}, we set the portalled attribute to true as well.

Anchor

Use Popover.Anchor to position the popover relative to a different element than the trigger.

Same Width

Use positioning.sameWidth to make the popover match the width of its trigger element.

Dialog Integration

When rendering a popover inside a dialog, you have two options for proper layering:

  1. Keep the Portal with lazyMount and unmountOnExit - This ensures the popover is properly unmounted when the dialog closes, preventing stale DOM nodes.

  2. Remove the Portal - Render the popover inline within the dialog content. This works well but may have z-index considerations.

Nested

Popovers can be nested within each other. Each nested popover maintains its own open state and positioning.

Guides

Available Size

The following css variables are exposed to the Popover.Positioner which you can use to style the Popover.Content

/* width of the popover trigger */
--reference-width: <pixel-value>;
/* width of the available viewport */
--available-width: <pixel-value>;
/* height of the available viewport */
--available-height: <pixel-value>;

For example, if you want to make sure the maximum height doesn't exceed the available height, use the following css:

[data-scope='popover'][data-part='content'] {
  max-height: calc(var(--available-height) - 100px);
}

API Reference

Props

Root

PropDefaultType
autoFocustrue
boolean

Whether to automatically set focus on the first focusable content within the popover when opened.

closeOnEscapetrue
boolean

Whether to close the popover when the escape key is pressed.

closeOnInteractOutsidetrue
boolean

Whether to close the popover when the user clicks outside of the popover.

defaultOpen
boolean

The initial open state of the popover when rendered. Use when you don't need to control the open state of the popover.

id
string

The unique identifier of the machine.

ids
Partial<{ anchor: string trigger: string content: string title: string description: string closeTrigger: string positioner: string arrow: string }>

The ids of the elements in the popover. Useful for composition.

immediate
boolean

Whether to synchronize the present change immediately or defer it to the next frame

initialFocusEl
() => HTMLElement | null

The element to focus on when the popover is opened.

lazyMountfalse
boolean

Whether to enable lazy mounting

modalfalse
boolean

Whether the popover should be modal. When set to `true`: - interaction with outside elements will be disabled - only popover content will be visible to screen readers - scrolling is blocked - focus is trapped within the popover

onEscapeKeyDown
(event: KeyboardEvent) => void

Function called when the escape key is pressed

onExitComplete
VoidFunction

Function called when the animation ends in the closed state

onFocusOutside
(event: FocusOutsideEvent) => void

Function called when the focus is moved outside the component

onInteractOutside
(event: InteractOutsideEvent) => void

Function called when an interaction happens outside the component

onOpenChange
(details: OpenChangeDetails) => void

Function invoked when the popover opens or closes

onPointerDownOutside
(event: PointerDownOutsideEvent) => void

Function called when the pointer is pressed down outside the component

onRequestDismiss
(event: LayerDismissEvent) => void

Function called when this layer is closed due to a parent layer being closed

open
boolean

The controlled open state of the popover

persistentElements
(() => Element | null)[]

Returns the persistent elements that: - should not have pointer-events disabled - should not trigger the dismiss event

portalledtrue
boolean

Whether the popover is portalled. This will proxy the tabbing behavior regardless of the DOM position of the popover content.

positioning
PositioningOptions

The user provided options used to position the popover content

present
boolean

Whether the node is present (controlled by the user)

skipAnimationOnMountfalse
boolean

Whether to allow the initial presence animation.

unmountOnExitfalse
boolean

Whether to unmount on exit.

Anchor

Renders a <div> element.

PropDefaultType
asChild
boolean

Use the provided child element as the default rendered element, combining their props and behavior.

For more details, read our Composition guide.

Arrow

Renders a <div> element.

PropDefaultType
asChild
boolean

Use the provided child element as the default rendered element, combining their props and behavior.

For more details, read our Composition guide.
CSS VariableDescription
--arrow-sizeThe size of the arrow
--arrow-size-halfHalf the size of the arrow
--arrow-backgroundUse this variable to style the arrow background
--arrow-offsetThe offset position of the arrow

ArrowTip

Renders a <div> element.

PropDefaultType
asChild
boolean

Use the provided child element as the default rendered element, combining their props and behavior.

For more details, read our Composition guide.

CloseTrigger

Renders a <button> element.

PropDefaultType
asChild
boolean

Use the provided child element as the default rendered element, combining their props and behavior.

For more details, read our Composition guide.

Content

Renders a <div> element.

PropDefaultType
asChild
boolean

Use the provided child element as the default rendered element, combining their props and behavior.

For more details, read our Composition guide.
AttributeDescription
[data-scope]popover
[data-part]content
[data-state]"open" | "closed"
[data-nested]popover
[data-has-nested]popover
[data-expanded]Present when expanded
[data-placement]The placement of the content
CSS VariableDescription
--layer-indexThe index of the dismissable in the layer stack
--nested-layer-countThe number of nested popovers

Description

Renders a <div> element.

PropDefaultType
asChild
boolean

Use the provided child element as the default rendered element, combining their props and behavior.

For more details, read our Composition guide.

Indicator

Renders a <div> element.

PropDefaultType
asChild
boolean

Use the provided child element as the default rendered element, combining their props and behavior.

For more details, read our Composition guide.
AttributeDescription
[data-scope]popover
[data-part]indicator
[data-state]"open" | "closed"

Positioner

Renders a <div> element.

PropDefaultType
asChild
boolean

Use the provided child element as the default rendered element, combining their props and behavior.

For more details, read our Composition guide.
CSS VariableDescription
--reference-widthThe width of the reference element
--reference-heightThe height of the root
--available-widthThe available width in viewport
--available-heightThe available height in viewport
--xThe x position for transform
--yThe y position for transform
--z-indexThe z-index value
--transform-originThe transform origin for animations

RootProvider

PropDefaultType
value
UsePopoverReturn

immediate
boolean

Whether to synchronize the present change immediately or defer it to the next frame

lazyMountfalse
boolean

Whether to enable lazy mounting

onExitComplete
VoidFunction

Function called when the animation ends in the closed state

present
boolean

Whether the node is present (controlled by the user)

skipAnimationOnMountfalse
boolean

Whether to allow the initial presence animation.

unmountOnExitfalse
boolean

Whether to unmount on exit.

Title

Renders a <div> element.

PropDefaultType
asChild
boolean

Use the provided child element as the default rendered element, combining their props and behavior.

For more details, read our Composition guide.

Trigger

Renders a <button> element.

PropDefaultType
asChild
boolean

Use the provided child element as the default rendered element, combining their props and behavior.

For more details, read our Composition guide.
AttributeDescription
[data-scope]popover
[data-part]trigger
[data-placement]The placement of the trigger
[data-state]"open" | "closed"

Context

API

PropertyType
portalled
boolean

Whether the popover is portalled.

open
boolean

Whether the popover is open

setOpen
(open: boolean) => void

Function to open or close the popover

reposition
(options?: Partial<PositioningOptions>) => void

Function to reposition the popover

Accessibility

Keyboard Support

KeyDescription
Space
Opens/closes the popover.
Enter
Opens/closes the popover.
Tab
Moves focus to the next focusable element within the content.
Note: If there are no focusable elements, focus is moved to the next focusable element after the trigger.
Shift + Tab
Moves focus to the previous focusable element within the content
Note: If there are no focusable elements, focus is moved to the trigger.
Esc
Closes the popover and moves focus to the trigger.