Popover
An overlay that displays additional information or options when triggered.
You can explore the popover component in the following curated examples.
Popover Selection
Render a Popover after selecting some text.
Popover with Tooltip
Render a Popover with a Tooltip that shows upon hovering over the Popover Trigger.
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
closeOnInteractOutsideprop and set it tofalse. - To prevent it from closing when the esc key is pressed, pass the
closeOnEscprop and set it tofalse.
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:
-
Keep the Portal with
lazyMountandunmountOnExit- This ensures the popover is properly unmounted when the dialog closes, preventing stale DOM nodes. -
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
| Prop | Default | Type |
|---|---|---|
autoFocus | true | booleanWhether to automatically set focus on the first focusable content within the popover when opened. |
closeOnEscape | true | booleanWhether to close the popover when the escape key is pressed. |
closeOnInteractOutside | true | booleanWhether to close the popover when the user clicks outside of the popover. |
defaultOpen | booleanThe initial open state of the popover when rendered. Use when you don't need to control the open state of the popover. | |
id | stringThe 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 | booleanWhether to synchronize the present change immediately or defer it to the next frame | |
initialFocusEl | () => HTMLElement | nullThe element to focus on when the popover is opened. | |
lazyMount | false | booleanWhether to enable lazy mounting |
modal | false | booleanWhether 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) => voidFunction called when the escape key is pressed | |
onExitComplete | VoidFunctionFunction called when the animation ends in the closed state | |
onFocusOutside | (event: FocusOutsideEvent) => voidFunction called when the focus is moved outside the component | |
onInteractOutside | (event: InteractOutsideEvent) => voidFunction called when an interaction happens outside the component | |
onOpenChange | (details: OpenChangeDetails) => voidFunction invoked when the popover opens or closes | |
onPointerDownOutside | (event: PointerDownOutsideEvent) => voidFunction called when the pointer is pressed down outside the component | |
onRequestDismiss | (event: LayerDismissEvent) => voidFunction called when this layer is closed due to a parent layer being closed | |
open | booleanThe 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 | |
portalled | true | booleanWhether the popover is portalled. This will proxy the tabbing behavior regardless of the DOM position of the popover content. |
positioning | PositioningOptionsThe user provided options used to position the popover content | |
present | booleanWhether the node is present (controlled by the user) | |
skipAnimationOnMount | false | booleanWhether to allow the initial presence animation. |
unmountOnExit | false | booleanWhether to unmount on exit. |
Anchor
Renders a <div> element.
| Prop | Default | Type |
|---|---|---|
asChild | booleanUse 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.
| Prop | Default | Type |
|---|---|---|
asChild | booleanUse the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. |
| CSS Variable | Description |
|---|---|
--arrow-size | The size of the arrow |
--arrow-size-half | Half the size of the arrow |
--arrow-background | Use this variable to style the arrow background |
--arrow-offset | The offset position of the arrow |
ArrowTip
Renders a <div> element.
| Prop | Default | Type |
|---|---|---|
asChild | booleanUse 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.
| Prop | Default | Type |
|---|---|---|
asChild | booleanUse 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.
| Prop | Default | Type |
|---|---|---|
asChild | booleanUse the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. |
| Attribute | Description |
|---|---|
[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 Variable | Description |
|---|---|
--layer-index | The index of the dismissable in the layer stack |
--nested-layer-count | The number of nested popovers |
Description
Renders a <div> element.
| Prop | Default | Type |
|---|---|---|
asChild | booleanUse 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.
| Prop | Default | Type |
|---|---|---|
asChild | booleanUse the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. |
| Attribute | Description |
|---|---|
[data-scope] | popover |
[data-part] | indicator |
[data-state] | "open" | "closed" |
Positioner
Renders a <div> element.
| Prop | Default | Type |
|---|---|---|
asChild | booleanUse the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. |
| CSS Variable | Description |
|---|---|
--reference-width | The width of the reference element |
--reference-height | The height of the root |
--available-width | The available width in viewport |
--available-height | The available height in viewport |
--x | The x position for transform |
--y | The y position for transform |
--z-index | The z-index value |
--transform-origin | The transform origin for animations |
RootProvider
| Prop | Default | Type |
|---|---|---|
value | UsePopoverReturn | |
immediate | booleanWhether to synchronize the present change immediately or defer it to the next frame | |
lazyMount | false | booleanWhether to enable lazy mounting |
onExitComplete | VoidFunctionFunction called when the animation ends in the closed state | |
present | booleanWhether the node is present (controlled by the user) | |
skipAnimationOnMount | false | booleanWhether to allow the initial presence animation. |
unmountOnExit | false | booleanWhether to unmount on exit. |
Title
Renders a <div> element.
| Prop | Default | Type |
|---|---|---|
asChild | booleanUse 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.
| Prop | Default | Type |
|---|---|---|
asChild | booleanUse the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. |
| Attribute | Description |
|---|---|
[data-scope] | popover |
[data-part] | trigger |
[data-placement] | The placement of the trigger |
[data-state] | "open" | "closed" |
Context
API
| Property | Type |
|---|---|
portalled | booleanWhether the popover is portalled. |
open | booleanWhether the popover is open |
setOpen | (open: boolean) => voidFunction to open or close the popover |
reposition | (options?: Partial<PositioningOptions>) => voidFunction to reposition the popover |
Accessibility
Keyboard Support
| Key | Description |
|---|---|
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. |