# Popover

**An accessible popup anchored to a button.**

**Reference:** [View Source](https://github.com/jramke/fluid-primitives/tree/main/Resources/Private/Primitives/Popover) · [Zag.js Docs](https://zagjs.com/components/react/popover)

**PopoverExamples.html**

```html
<ui:popover.root>
    <ui:popover.trigger asChild="{true}">
        <ui:button>Open Popover</ui:button>
    </ui:popover.trigger>
    <ui:popover.content>
        <ui:popover.title>Notifications</ui:popover.title>
        <ui:popover.description>You are all caught up. Good job!</ui:popover.description>
    </ui:popover.content>
</ui:popover.root>

```

## Features

- Focus is managed and can be trapped within the popover
- Supports modal and non-modal modes
- Supports custom positioning with placement options
- Pressing `Escape` closes the popover
- Automatically adjusts position to stay in viewport

## Anatomy

```html
<primitives:popover.root>
    <primitives:popover.trigger />
    <primitives:popover.positioner>
        <primitives:popover.content>
            <primitives:popover.arrow />
            <primitives:popover.closeTrigger />
            <primitives:popover.title />
            <primitives:popover.description />
        </primitives:popover.content>
    </primitives:popover.positioner>
</primitives:popover.root>
```

## Installation

```bash
typo3 ui:add popover
```

Or copy the files manually from GitHub (https://github.com/jramke/fluid-primitives/tree/main/Resources/Private/Registry/Popover) into your project.

Read more about installing [Components and Primitives](/docs/core-concepts/primitives.md).

## Examples

### With Close Button

Show a close button inside the popover.

**PopoverExamples.html**

```html
<ui:popover.root>
    <ui:popover.trigger asChild="{true}">
        <ui:button>Open Popover</ui:button>
    </ui:popover.trigger>
    <ui:popover.content showCloseButton="{true}">
        <ui:popover.title>Closeable</ui:popover.title>
        <ui:popover.description>Click the X button to close.</ui:popover.description>
    </ui:popover.content>
</ui:popover.root>

```

### Custom Positioning

Control where the popover appears relative to the trigger.

**PopoverExamples.html**

```html
<ui:popover.root positioning="{placement: 'right'}">
    <ui:popover.trigger asChild="{true}">
        <ui:button>Open Right</ui:button>
    </ui:popover.trigger>
    <ui:popover.content>
        <ui:popover.title>Right Position</ui:popover.title>
        <ui:popover.description>This popover opens to the right.</ui:popover.description>
    </ui:popover.content>
</ui:popover.root>

```

### Modal Mode

Make the popover modal to trap focus and block interaction with the rest of the page.

**PopoverExamples.html**

```html
<ui:popover.root modal="{true}">
    <ui:popover.trigger asChild="{true}">
        <ui:button>Open Modal Popover</ui:button>
    </ui:popover.trigger>
    <ui:popover.content>
        <ui:popover.title>Modal Popover</ui:popover.title>
        <ui:popover.description>Focus is trapped within this popover.</ui:popover.description>
    </ui:popover.content>
</ui:popover.root>

```

### Localization

Default close trigger labels are shipped via XLF and follow the current Site Language. For per-template overrides, pass translated strings through the `translations` prop.

```html
<ui:popover.root
    translations="{
        closeTriggerLabel: f:translate(key: 'LLL:EXT:site_package/Resources/Private/Language/locallang.xlf:popover.close')
    }"
>
    ...
</ui:popover.root>
```

## API Reference

### popover.root

Provides popover state and context for the composed parts. Renders no wrapper element.

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `modal` | `boolean` | No | `false` | Whether the popover should be modal. |
| `portalled` | `boolean` | No | `true` | Whether the popover is portalled and proxies tabbing behavior regardless of DOM position. |
| `autoFocus` | `boolean` | No | `true` | Whether to automatically set focus on the first focusable content within the popover when opened. |
| `restoreFocus` | `boolean` | No | `true` | Whether to restore focus to the element that had focus before the popover was opened. |
| `closeOnInteractOutside` | `boolean` | No | `true` | Whether to close the popover when the user clicks outside of the popover. |
| `closeOnEscape` | `boolean` | No | `true` | Whether to close the popover when the escape key is pressed. |
| `positioning` | `array` | No | `-` | The user provided options used to position the popover content. |
| `defaultOpen` | `boolean` | No | `false` | The initial open state of the popover when rendered. Use when you don't need to control the open state of the popover. |
| `translations` | `array` | No | `-` | Localized popover labels. Use `f:translate` for per-template localization overrides when needed. |
| `rootId` | `string` | No | `-` | The root ID of the component, used for hydration and identification. |
| `ids` | `array` | No | `[]` | The IDs of of the component parts for composition. |
| `autoMount` | `boolean` | No | `true` | Whether the client initializes the component on its own. Set it to false to mount it yourself with `mount()` |

### popover.trigger

Opens and closes the popover. Renders a `<button>` element.

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `value` | `string` | No | `-` |  |
| `attributes` | `array` | No | `[]` | Additional attributes that should be rendered on the component where ui:attributes is used. |
| `asChild` | `boolean` | No | `-` | If true the component uses its child only without the component template. Like Radix UI asChild or Base UI render props. |
| `class` | `string` | No | `-` | The CSS class(es) to be applied to the component. |

#### Rendered data attributes

| Attribute | Description |
| --- | --- |
| `data-popover-trigger` | <uid> |
| `data-placement` | The placement of the trigger |
| `data-side` | The side of the trigger that the trigger is positioned on |
| `data-value` | The value of the item |
| `data-current` | Present when current |
| `data-state` | "open" \| "closed" |

### popover.positioner

Positions the popover content relative to the trigger. Renders a `<div>` element.

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `attributes` | `array` | No | `[]` | Additional attributes that should be rendered on the component where ui:attributes is used. |
| `asChild` | `boolean` | No | `-` | If true the component uses its child only without the component template. Like Radix UI asChild or Base UI render props. |
| `class` | `string` | No | `-` | The CSS class(es) to be applied to the component. |

#### Rendered data attributes

| Attribute | Description |
| --- | --- |
| `data-popover-positioner` | <uid> |
| `data-nested` | Present when the positioner is nested within another {{widget}} |
| `data-has-nested` | Present when the positioner has nested {{widget}}s |

### popover.content

Contains the popover panel content. Renders a `<div>` element.

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `attributes` | `array` | No | `[]` | Additional attributes that should be rendered on the component where ui:attributes is used. |
| `asChild` | `boolean` | No | `-` | If true the component uses its child only without the component template. Like Radix UI asChild or Base UI render props. |
| `class` | `string` | No | `-` | The CSS class(es) to be applied to the component. |

#### Rendered data attributes

| Attribute | Description |
| --- | --- |
| `data-popover-content` | <uid> |
| `data-state` | "open" \| "closed" |
| `data-expanded` | Present when expanded |
| `data-placement` | The placement of the content |
| `data-side` | The side of the trigger that the content is positioned on |
| `data-nested` | popover |
| `data-has-nested` | popover |

### popover.arrow

Displays a decorative arrow for the popover. Renders a `<div>` element.

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `attributes` | `array` | No | `[]` | Additional attributes that should be rendered on the component where ui:attributes is used. |
| `asChild` | `boolean` | No | `-` | If true the component uses its child only without the component template. Like Radix UI asChild or Base UI render props. |
| `class` | `string` | No | `-` | The CSS class(es) to be applied to the component. |

### popover.indicator

Displays a decorative state indicator. Renders a `<div>` element.

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `attributes` | `array` | No | `[]` | Additional attributes that should be rendered on the component where ui:attributes is used. |
| `asChild` | `boolean` | No | `-` | If true the component uses its child only without the component template. Like Radix UI asChild or Base UI render props. |
| `class` | `string` | No | `-` | The CSS class(es) to be applied to the component. |

#### Rendered data attributes

| Attribute | Description |
| --- | --- |
| `data-popover-indicator` | <uid> |
| `data-state` | "open" \| "closed" |

### popover.title

Provides the accessible title for the popover. Renders a `<div>` element.

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `attributes` | `array` | No | `[]` | Additional attributes that should be rendered on the component where ui:attributes is used. |
| `asChild` | `boolean` | No | `-` | If true the component uses its child only without the component template. Like Radix UI asChild or Base UI render props. |
| `class` | `string` | No | `-` | The CSS class(es) to be applied to the component. |

### popover.description

Provides supporting descriptive text for the popover. Renders a `<div>` element.

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `attributes` | `array` | No | `[]` | Additional attributes that should be rendered on the component where ui:attributes is used. |
| `asChild` | `boolean` | No | `-` | If true the component uses its child only without the component template. Like Radix UI asChild or Base UI render props. |
| `class` | `string` | No | `-` | The CSS class(es) to be applied to the component. |

### popover.closeTrigger

Closes the popover when activated. Renders a `<button>` element.

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `attributes` | `array` | No | `[]` | Additional attributes that should be rendered on the component where ui:attributes is used. |
| `asChild` | `boolean` | No | `-` | If true the component uses its child only without the component template. Like Radix UI asChild or Base UI render props. |
| `class` | `string` | No | `-` | The CSS class(es) to be applied to the component. |

### Machine JavaScript API

| Name | Type | Description |
| --- | --- | --- |
| `open` | `boolean` | Whether the popover is open |
| `setOpen` | `(open: boolean) => void` | Function to open or close the popover |
| `triggerValue` | `string \| null` | The trigger value |
| `setTriggerValue` | `(value: string \| null) => void` | Function to set the trigger value |
| `reposition` | `(options?: Partial<PositioningOptions>) => void` | Function to reposition the popover |
| `getTriggerState` | `(props?: TriggerProps) => TriggerState` | Returns the state of a specific trigger, including whether it's the currently active one |
| `getPositionerState` | `() => PositionerState` | Returns the state of the positioner |
| `getContentState` | `() => ContentState` | Returns the state of the content |

### Accessibility

| Key | Description |
| --- | --- |
| `Space`  | Opens/closes the popover. |
| `Enter`  | Opens/closes the popover. |
| `Tab`  | <span>Moves focus to the next focusable element within the content.<br /><strong>Note:</strong> If there are no focusable elements, focus is moved to the next focusable element after the trigger.</span> |
| `Shift + Tab`  | <span>Moves focus to the previous focusable element within the content<br /><strong>Note:</strong> If there are no focusable elements, focus is moved to the trigger.</span> |
| `Esc`  | <span>Closes the popover and moves focus to the trigger.</span> |
