# Popover

A small panel anchored to its trigger, for extra information or a few controls. The page stays usable while it's open. For a task that needs full attention, use [Modal](/components/modal.md).

```tsx
// demo.tsx
import {Button, Popover} from '@earendil-works/elanor-react';

export default function PopoverDemo() {
  return (
    <Popover.Root>
      <Popover.Trigger render={<Button hierarchy="secondary" />}>Usage limits</Popover.Trigger>
      <Popover.Portal>
        <Popover.Positioner>
          <Popover.Popup>
            <Popover.Title>Monthly usage</Popover.Title>
            <Popover.Description>
              Usage resets on the first day of each month. Unused credits don't carry over.
            </Popover.Description>
          </Popover.Popup>
        </Popover.Positioner>
      </Popover.Portal>
    </Popover.Root>
  );
}
```

## Usage

```tsx
import {Popover} from '@earendil-works/elanor-react';

<Popover.Root>
  <Popover.Trigger />
  <Popover.Portal>
    <Popover.Positioner>
      <Popover.Popup>
        <Popover.Title />
        <Popover.Description />
        <Popover.Close />
      </Popover.Popup>
    </Popover.Positioner>
  </Popover.Portal>
</Popover.Root>;
```

The trigger opens the popover on click. Escape, clicking outside, or `Popover.Close` closes it and returns focus to the trigger.

## Static rendering

On pages rendered on the server without React in the browser, use the static parts, and bind their behavior once the page has loaded:

```tsx
<Popover.StaticRoot>
  <Popover.StaticTrigger />
  <Popover.StaticPositioner side="bottom" align="start" sideOffset={4}>
    <Popover.StaticPopup>
      <Popover.StaticTitle />
      <Popover.StaticDescription />
      <Popover.StaticClose />
    </Popover.StaticPopup>
  </Popover.StaticPositioner>
</Popover.StaticRoot>
```

```ts
import {createPopover, enhance} from '@earendil-works/elanor-react';

enhance({popover: createPopover});
```

The positioner is a native popover in the top layer. The behavior places it next to the trigger on any `side`, flipping when the other side has more room, and opens and closes it with the same states and animation as the React parts; Escape and a press outside close it, and focus moves to the first focusable element. Without the behavior, the browser opens it in the middle of the window. Give `StaticRoot` an `id` to open the popover from other buttons too, with `popovertarget`.

## API

### `Popover.Root`

Accepts Base UI [`Popover.Root`](https://base-ui.com/react/components/popover.md) props.

### `Popover.Trigger`

Accepts Base UI [`Popover.Trigger`](https://base-ui.com/react/components/popover.md) props.

### `Popover.Portal`

Accepts Base UI [`Popover.Portal`](https://base-ui.com/react/components/popover.md) props.

### `Popover.Positioner`

Accepts Base UI [`Popover.Positioner`](https://base-ui.com/react/components/popover.md) props.

### `Popover.Popup`

Accepts Base UI [`Popover.Popup`](https://base-ui.com/react/components/popover.md) props.

### `Popover.Title`

Accepts Base UI [`Popover.Title`](https://base-ui.com/react/components/popover.md) props.

### `Popover.Description`

Accepts Base UI [`Popover.Description`](https://base-ui.com/react/components/popover.md) props.

### `Popover.Close`

Accepts Base UI [`Popover.Close`](https://base-ui.com/react/components/popover.md) props.

### `Popover.StaticRoot`

A popover for pages without React in the browser; `createPopover` makes it work. Renders no element.

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `id` | `string` | - | The popover's id, so other buttons can open it with `popovertarget`. Generated by default. |
| `children` | `ReactNode` | - |  |

Also accepts HTML attributes and `ref`.

### `Popover.StaticTrigger`

Renders `<button>`. Accepts its HTML attributes and `ref`.

### `Popover.StaticPositioner`

The popover in the top layer, placed next to the trigger. Holds the `StaticPopup`.

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `data-elanor` | `string` | - | The page's own behaviors for this element, attached after the component's. |
| `side` | `'top' \| 'bottom' \| 'left' \| 'right' \| 'inline-end' \| 'inline-start'` | `'bottom'` |  |
| `align` | `'center' \| 'start' \| 'end'` | `'center'` |  |
| `sideOffset` | `Extract<BasePopover.Positioner.Props['sideOffset'], number>` | `0` |  |

Renders `<div>`. Also accepts its HTML attributes and `ref`.

### `Popover.StaticPopup`

Renders `<div>`. Accepts its HTML attributes and `ref`.

### `Popover.StaticTitle`

Renders `<h2>`. Accepts its HTML attributes and `ref`.

### `Popover.StaticDescription`

Renders `<p>`. Accepts its HTML attributes and `ref`.

### `Popover.StaticClose`

Renders `<button>`. Accepts its HTML attributes and `ref`.
