Popover
A panel that opens next to its trigger and holds details or controls that belong to it.
A popover opens a panel next to its trigger, where users read details or use controls that belong to the trigger without leaving the page. A press on the trigger opens the popover and moves focus into it. The popover closes when users press the trigger again, press Escape, press outside of the popover or move focus out of it. The rest of the page stays usable while the popover is open. The trigger is a button without styles of its own, so the examples render it as a Button, and the content is 18rem wide.
Usage
Examples
Top Side
Triggers near the lower edge of a screen, such as the actions in a footer bar, leave little room below them. With side set to "top", the popover opens above its trigger instead. If the space above runs short, it moves below the trigger.
Right Side
In a narrow column, such as a list of stores along the left edge of a screen, a popover finds more room beside its trigger than below it. Set to "right", side opens it toward the wider area of the screen, and the entries further down the list stay readable.
Bottom Side
Reading runs from top to bottom, so details below a trigger follow the order in which users take in a screen. The popover takes this side by default, and side set to "bottom" states it explicitly. When the space below runs short, it opens above the trigger.
Left Side
Actions at the end of a table row sit close to the right edge of a screen, where little room remains beside them. With side set to "left", the popover opens toward the middle of the screen, next to the row it belongs to.
Open on Hover
Users who scan a screen want to see details without a press for each one. Once openOnHover is set on the trigger, the popover opens when the mouse pointer rests on the trigger, and it stays open while the pointer moves into the popover. Opened this way, it leaves focus where it is. On a touch screen, where no pointer rests on the trigger, a press opens the popover as before.
Open by Default
A popover can draw attention to a detail the moment a page loads, such as a figure that has changed since the last visit. Through defaultOpen it is open at first render, and users close it like any other popover once they have read it.
Controlled
In some workflows the application decides when the popover is open, for example to close it as soon as users have applied a change inside it. With open and onOpenChange, the application holds that state, so any part of the interface can open or close the popover.
Disabled Trigger
Not every item has details at every moment, for example a product that has no sales history yet. Set on the trigger, disabled keeps users from opening the popover, while the trigger stays in view and shows where the details will appear once they exist.
API Reference
Popover
| Prop | open |
|---|---|
| Type | boolean |
| Default | – |
| Description | Sets whether the popover is open and makes it controlled. Update it in onOpenChange. |
| Prop | defaultOpen |
|---|---|
| Type | boolean |
| Default | false |
| Description | Opens the popover at first render. The popover then tracks its open state itself. |
| Prop | onOpenChange |
|---|---|
| Type | (open: boolean, eventDetails: PopoverRootChangeEventDetails) => void |
| Default | – |
| Description | Runs when users open or close the popover. It receives the open state that follows. |
| Prop | onOpenChangeComplete |
|---|---|
| Type | (open: boolean) => void |
| Default | – |
| Description | Runs after the popover has opened or closed and its animations have finished. |
| Prop | modal |
|---|---|
| Type | boolean | "trap-focus" |
| Default | false |
| Description | Sets how the popover limits the rest of the page while it is open. With false, the rest of the page stays usable. With true, the page doesn't scroll and elements outside of the popover don't react to the pointer. When a touch opened the popover, the page still scrolls unless the popover is about as wide as the viewport. With true or "trap-focus", focus also stays in the popover, provided that the content holds a Popover.Close from @base-ui/react/popover. "trap-focus" leaves scrolling and the pointer as they are. A popover that users open by hover is never modal. |
| Prop | triggerId |
|---|---|
| Type | string | null |
| Default | – |
| Description | Sets the ID of the trigger that a controlled popover is associated with. A popover without open doesn't need it. |
| Prop | defaultTriggerId |
|---|---|
| Type | string | null |
| Default | – |
| Description | Sets the ID of the trigger that the popover is associated with when defaultOpen opens it at first render. |
| Prop | handle |
|---|---|
| Type | PopoverHandle<Payload> |
| Default | – |
| Description | Connects the popover with triggers that are rendered outside of it. Create the handle with Popover.createHandle() from @base-ui/react/popover. |
| Prop | actionsRef |
|---|---|
| Type | RefObject<PopoverRootActions | null> |
| Default | – |
| Description | Receives the functions close and unmount. close closes the popover from code, and unmount removes it from the DOM after a closing animation that the code controls itself. |
| Prop | children |
|---|---|
| Type | ReactNode | ((arg: { payload: Payload | undefined }) => ReactNode) |
| Default | – |
| Description | Holds the parts of the popover. A function receives the payload of the trigger that opened the popover. |
PopoverTrigger
| Prop | openOnHover |
|---|---|
| Type | boolean |
| Default | false |
| Description | Opens the popover when the mouse pointer rests on the trigger, in addition to a press. A popover that opens by hover doesn't move focus into itself. |
| Prop | delay |
|---|---|
| Type | number |
| Default | 300 |
| Description | Sets how many milliseconds the pointer must rest on the trigger before the popover opens. It has an effect only with openOnHover. |
| Prop | closeDelay |
|---|---|
| Type | number |
| Default | 0 |
| Description | Sets how many milliseconds the popover stays open after the pointer has left the trigger and the content. It has an effect only with openOnHover. |
| Prop | handle |
|---|---|
| Type | PopoverHandle<Payload> |
| Default | – |
| Description | Connects the trigger with a popover that it is rendered outside of. Pass the same handle to Popover. |
| Prop | payload |
|---|---|
| Type | Payload |
| Default | – |
| Description | Passes a value to the popover when this trigger opens it. A function as children of Popover receives it. |
| Prop | id |
|---|---|
| Type | string |
| Default | – |
| Description | Sets the ID of the trigger element. triggerId and defaultTriggerId of Popover refer to it. |
| Prop | render |
|---|---|
| Type | ReactElement | render function |
| Default | – |
| Description | Replaces the native element or composes the trigger with another component. |
| Prop | nativeButton |
|---|---|
| Type | boolean |
| Default | true |
| Description | Declares whether the rendered element is a native button. Set it to false when render returns a different element. |
| Prop | disabled |
|---|---|
| Type | boolean |
| Default | false |
| Description | Prevents users from opening the popover with this trigger. |
PopoverContent
| Prop | side |
|---|---|
| Type | "top" | "bottom" | "left" | "right" | "inline-end" | "inline-start" |
| Default | "bottom" |
| Description | Sets the side of the trigger that the content opens on. "inline-start" and "inline-end" follow the reading direction. The content moves to the opposite side when the chosen one has too little space, and to a side on the other axis when neither of the two has enough. |
| Prop | sideOffset |
|---|---|
| Type | number | OffsetFunction |
| Default | 4 |
| Description | Sets the distance between the trigger and the content in pixels. A function receives the side, the alignment and the dimensions of the trigger and the content, and returns the distance. |
| Prop | align |
|---|---|
| Type | "start" | "center" | "end" |
| Default | "center" |
| Description | Sets where the content lines up with the trigger along the chosen side: at its start, its center or its end. |
| Prop | alignOffset |
|---|---|
| Type | number | OffsetFunction |
| Default | 0 |
| Description | Moves the content along the alignment axis by a number of pixels. A function receives the same data as the one for sideOffset and returns the offset. |
| Prop | initialFocus |
|---|---|
| Type | boolean | RefObject<HTMLElement | null> | ((openType: InteractionType) => boolean | HTMLElement | null | void) |
| Default | – |
| Description | Determines the element that receives focus when the popover opens. Without it, focus moves to the first focusable element in the popover. It moves to the popover itself when the content has no such element or when a touch opened the popover. |
| Prop | finalFocus |
|---|---|
| Type | boolean | RefObject<HTMLElement | null> | ((closeType: InteractionType) => boolean | HTMLElement | null | void) |
| Default | – |
| Description | Determines the element that receives focus when the popover closes. Without it, focus returns to the trigger or to the element that had focus before. |
| Prop | render |
|---|---|
| Type | ReactElement | render function |
| Default | – |
| Description | Replaces the native element or composes the content with another component. |
PopoverHeader
PopoverHeader groups the title and the description. It renders a div and has no props of its own.
PopoverTitle
| Prop | render |
|---|---|
| Type | ReactElement | render function |
| Default | – |
| Description | Replaces the native element or composes the title with another component. |
PopoverDescription
| Prop | render |
|---|---|
| Type | ReactElement | render function |
| Default | – |
| Description | Replaces the native element or composes the description with another component. |