> ## Documentation Index
> Fetch the complete documentation index at: https://docs.twenty.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Popover

> Display contextual content anchored to a trigger.

Use `Popover` for contextual information or lightweight controls. `Popup` includes positioning and a portal, so you can compose content directly inside it.

## Contextual content

```tsx theme={null}
import { Popover } from 'twenty-ui/surfaces';

export const ImportHelp = () => (
  <Popover.Root>
    <Popover.Trigger>Import help</Popover.Trigger>
    <Popover.Popup arrow>
      <Popover.Title>Import a CSV file</Popover.Title>
      <Popover.Description>
        Use a header row to identify your columns.
      </Popover.Description>
      <Popover.Close>Got it</Popover.Close>
    </Popover.Popup>
  </Popover.Root>
);
```

Use `Title` and `Description` to identify the popup. The trigger renders a button by default; `render` lets you supply a compatible element.

## Controlled state

```tsx theme={null}
import { useState } from 'react';
import { Popover } from 'twenty-ui/surfaces';

export const FilterPopover = () => {
  const [open, setOpen] = useState(false);

  return (
    <Popover.Root open={open} onOpenChange={setOpen}>
      <Popover.Trigger>Filters</Popover.Trigger>
      <Popover.Popup align="start">
        <Popover.Title>Record filters</Popover.Title>
        <Popover.Description>
          Choose which records to display.
        </Popover.Description>
        <label>
          <input type="checkbox" />
          Only my records
        </label>
        <Popover.Close>Done</Popover.Close>
      </Popover.Popup>
    </Popover.Root>
  );
};
```

`onOpenChange` receives the next boolean and event details. Use `defaultOpen` for uncontrolled initial state.

## Parts and placement

| Part                   | Purpose                                            |
| ---------------------- | -------------------------------------------------- |
| `Root`                 | Coordinates open state and interactions.           |
| `Trigger`              | Opens or closes the popup.                         |
| `Popup`                | Renders the positioned content and optional arrow. |
| `Title`, `Description` | Name and describe the popup.                       |
| `Close`                | Closes the popup.                                  |

`Popup` defaults to `side="bottom"`, `align="center"`, and `sideOffset={8}`. Set `arrow` to show an arrow. Set `container` to override the theme's portal container; see [theming](/ui/theming).

Escape closes the popup and focus returns to the trigger. Outside interaction dismisses it by default. Use the focus props on `Popup` when its content needs a specific initial or return focus target.

## Props

The reference is generated from the public component types. Native attributes, including accessible names and event handlers, are also accepted on parts that render elements.

### Popover.Root

<ParamField body="Root.actionsRef" type="RefObject<PopoverRootActions | null>">
  A ref to imperative actions.

  * `unmount`: Manually unmounts the popover.
    Call this after any externally controlled closing animation finishes.
  * `close`: Closes the popover imperatively when called.
</ParamField>

<ParamField body="Root.children" type="ReactNode | PayloadChildRenderFunction<Payload>">
  The content of the popover.
  This can be a regular React node or a render function that receives the `payload` of the active trigger.
</ParamField>

<ParamField body="Root.defaultOpen" type="boolean" default="false">
  Whether the popover is initially open.

  To render a controlled popover, use the `open` prop instead.
</ParamField>

<ParamField body="Root.defaultTriggerId" type="string | null">
  ID of the trigger that the popover is associated with.
  This is useful in conjunction with the `defaultOpen` prop to create an initially open popover.
</ParamField>

<ParamField body="Root.handle" type="PopoverHandle<Payload>">
  A handle to associate the popover with a trigger.
  If specified, allows external triggers to control the popover's open state.
</ParamField>

<ParamField body="Root.modal" type="boolean | &#x22;trap-focus&#x22;" default="false">
  Determines if the popover enters a modal state when open.

  * `true`: user interaction is limited to the popover: document page scroll is locked, and pointer interactions on outside elements are disabled.
  * `false`: user interaction with the rest of the document is allowed.
  * `'trap-focus'`: focus is trapped inside the popover, but document page scroll is not locked and pointer interactions outside of it remain enabled.

  On touch devices, a `true` modal blocks outside taps but leaves the page scrollable unless the popup spans nearly the full viewport width, matching native iOS behavior.

  When `modal` is `true`, focus trapping is enabled only if `<Popover.Close>` is rendered
  inside `<Popover.Popup>`. It can be visually hidden with your own CSS if needed, such as
  Tailwind's `sr-only` utility.

  When `modal` is `'trap-focus'`, render `<Popover.Close>` inside `<Popover.Popup>` so touch
  screen readers can escape the popup.
</ParamField>

<ParamField body="Root.onOpenChange" type="((open: boolean, eventDetails: PopoverRootChangeEventDetails) => void)">
  Event handler called when the popover is opened or closed.
</ParamField>

<ParamField body="Root.onOpenChangeComplete" type="((open: boolean) => void)">
  Event handler called after any animations complete when the popover is opened or closed.
</ParamField>

<ParamField body="Root.open" type="boolean">
  Whether the popover is currently open.
</ParamField>

<ParamField body="Root.triggerId" type="string | null">
  ID of the trigger that the popover is associated with.
  This is useful in conjunction with the `open` prop to create a controlled popover.
  There's no need to specify this prop when the popover is uncontrolled (that is, when the `open` prop is not set).
</ParamField>

### Popover.Trigger

<ParamField body="Trigger.className" type="string | ((state: PopoverTriggerState) => string | undefined)">
  CSS class applied to the element, or a function that
  returns a class based on the component's state.
</ParamField>

<ParamField body="Trigger.closeDelay" type="number" default="0">
  How long to wait before closing the popover that was opened on hover.
  Specified in milliseconds.

  Requires the `openOnHover` prop.
</ParamField>

<ParamField body="Trigger.delay" type="number" default="300">
  How long to wait before the popover may be opened on hover. Specified in milliseconds.

  Requires the `openOnHover` prop.
</ParamField>

<ParamField body="Trigger.handle" type="PopoverHandle<Payload>">
  A handle to associate the trigger with a popover.
</ParamField>

<ParamField body="Trigger.id" type="string">
  ID of the trigger. In addition to being forwarded to the rendered element,
  it is also used to specify the active trigger for the popover in controlled mode (with the PopoverRoot `triggerId` prop).
</ParamField>

<ParamField body="Trigger.nativeButton" type="boolean" default="true">
  Whether the component renders a native `<button>` element when replacing it
  via the `render` prop.
  Set to `false` if the rendered element is not a button (e.g. `<div>`).
</ParamField>

<ParamField body="Trigger.openOnHover" type="boolean" default="false">
  Whether the popover should also open when the trigger is hovered.
</ParamField>

<ParamField body="Trigger.payload" type="Payload">
  A payload to pass to the popover when it is opened.
</ParamField>

<ParamField body="Trigger.render" type="ReactElement<unknown, string | JSXElementConstructor<any>> | ComponentRenderFn<HTMLProps, PopoverTriggerState>">
  Allows you to replace the component's HTML element
  with a different tag, or compose it with another component.

  Accepts a `ReactElement` or a function that returns the element to render.
</ParamField>

<ParamField body="Trigger.style" type="CSSProperties | ((state: PopoverTriggerState) => CSSProperties | undefined)">
  Style applied to the element, or a function that
  returns a style object based on the component's state.
</ParamField>

### Popover.Popup

<ParamField body="Popup.align" type="&#x22;center&#x22; | &#x22;start&#x22; | &#x22;end&#x22;" default="center">
  Alignment of the popup along the anchor.
</ParamField>

<ParamField body="Popup.alignOffset" type="number">
  Offset in pixels along the alignment axis.
</ParamField>

<ParamField body="Popup.anchor" type="Element | VirtualElement | RefObject<Element | null> | (() => Element | VirtualElement | null) | null">
  Element or position the popup is anchored to. Defaults to the trigger.
</ParamField>

<ParamField body="Popup.arrow" type="boolean" default="false">
  Shows an arrow pointing at the anchor.
</ParamField>

<ParamField body="Popup.className" type="string | ((state: PopoverPopupState) => string | undefined)">
  CSS class applied to the element, or a function that
  returns a class based on the component's state.
</ParamField>

<ParamField body="Popup.container" type="HTMLElement | ShadowRoot | RefObject<HTMLElement | ShadowRoot | null> | null">
  Element the popup is portaled into. Defaults to the theme's portal
  container.
</ParamField>

<ParamField body="Popup.finalFocus" type="boolean | RefObject<HTMLElement | null> | ((closeType: InteractionType) => boolean | void | HTMLElement | null)">
  Determines the element to focus when the popover is closed.

  * `false`: Do not move focus.
  * `true`: Move focus based on the default behavior (trigger or previously focused element).
  * `RefObject`: Move focus to the ref element.
  * `function`: Called with the interaction type (`mouse`, `touch`, `pen`, or `keyboard`).
    Return an element to focus, `true` to use the default behavior, `null` to fall back to the default behavior, or `false`/`undefined` to do nothing.
</ParamField>

<ParamField body="Popup.initialFocus" type="boolean | RefObject<HTMLElement | null> | ((openType: InteractionType) => boolean | void | HTMLElement | null)">
  Determines the element to focus when the popover is opened.
  By default, focus moves to the first tabbable element inside the popup, except when the popover
  is opened by touch — then the popup itself is focused to avoid opening the virtual keyboard.

  * `false`: Do not move focus.
  * `true`: Move focus based on the default behavior (first tabbable element or popup).
  * `RefObject`: Move focus to the ref element.
  * `function`: Called with the interaction type (`mouse`, `touch`, `pen`, or `keyboard`).
    Return an element to focus, `true` to use the default behavior, `null` to fall back to the default behavior, or `false`/`undefined` to do nothing.
</ParamField>

<ParamField body="Popup.keepMounted" type="boolean">
  Keeps the popup mounted in the DOM while the popover is closed.
</ParamField>

<ParamField body="Popup.render" type="ReactElement<unknown, string | JSXElementConstructor<any>> | ComponentRenderFn<HTMLProps, PopoverPopupState>">
  Allows you to replace the component's HTML element
  with a different tag, or compose it with another component.

  Accepts a `ReactElement` or a function that returns the element to render.
</ParamField>

<ParamField body="Popup.side" type="&#x22;top&#x22; | &#x22;bottom&#x22; | &#x22;left&#x22; | &#x22;right&#x22; | &#x22;inline-end&#x22; | &#x22;inline-start&#x22;" default="bottom">
  Side of the anchor the popup is placed on.
</ParamField>

<ParamField body="Popup.sideOffset" type="number" default="8">
  Distance in pixels between the anchor and the popup.
</ParamField>

<ParamField body="Popup.style" type="CSSProperties | ((state: PopoverPopupState) => CSSProperties | undefined)">
  Style applied to the element, or a function that
  returns a style object based on the component's state.
</ParamField>

### Popover.Title

<ParamField body="Title.className" type="string | ((state: PopoverTitleState) => string | undefined)">
  CSS class applied to the element, or a function that
  returns a class based on the component's state.
</ParamField>

<ParamField body="Title.render" type="ReactElement<unknown, string | JSXElementConstructor<any>> | ComponentRenderFn<HTMLProps, PopoverTitleState>">
  Allows you to replace the component's HTML element
  with a different tag, or compose it with another component.

  Accepts a `ReactElement` or a function that returns the element to render.
</ParamField>

<ParamField body="Title.style" type="CSSProperties | ((state: PopoverTitleState) => CSSProperties | undefined)">
  Style applied to the element, or a function that
  returns a style object based on the component's state.
</ParamField>

### Popover.Description

<ParamField body="Description.className" type="string | ((state: PopoverDescriptionState) => string | undefined)">
  CSS class applied to the element, or a function that
  returns a class based on the component's state.
</ParamField>

<ParamField body="Description.render" type="ReactElement<unknown, string | JSXElementConstructor<any>> | ComponentRenderFn<HTMLProps, PopoverDescriptionState>">
  Allows you to replace the component's HTML element
  with a different tag, or compose it with another component.

  Accepts a `ReactElement` or a function that returns the element to render.
</ParamField>

<ParamField body="Description.style" type="CSSProperties | ((state: PopoverDescriptionState) => CSSProperties | undefined)">
  Style applied to the element, or a function that
  returns a style object based on the component's state.
</ParamField>

### Popover.Close

<ParamField body="Close.className" type="string | ((state: PopoverCloseState) => string | undefined)">
  CSS class applied to the element, or a function that
  returns a class based on the component's state.
</ParamField>

<ParamField body="Close.nativeButton" type="boolean" default="true">
  Whether the component renders a native `<button>` element when replacing it
  via the `render` prop.
  Set to `false` if the rendered element is not a button (for example, `<div>`).
</ParamField>

<ParamField body="Close.render" type="ReactElement<unknown, string | JSXElementConstructor<any>> | ComponentRenderFn<HTMLProps, PopoverCloseState>">
  Allows you to replace the component's HTML element
  with a different tag, or compose it with another component.

  Accepts a `ReactElement` or a function that returns the element to render.
</ParamField>

<ParamField body="Close.style" type="CSSProperties | ((state: PopoverCloseState) => CSSProperties | undefined)">
  Style applied to the element, or a function that
  returns a style object based on the component's state.
</ParamField>
