# Popover

> A small panel that belongs to a button: it rises off the trigger from the nearest point, flips to fit, and hands focus to what is inside.

Popovers often appear from nowhere, cover their trigger and leave focus behind. This one rises off its trigger from the point nearest to it, flips and shifts to stay in the window, moves focus to the first field inside, and on Escape gives focus back to the trigger. For a list of actions, use the dropdown menu.

## Install

```bash
npx shadcn@latest add https://hairlineui.com/r/popover.json
```

Needs React 19, Tailwind CSS v4 and shadcn/ui theme variables (any style, light and dark). Icons from lucide-react.

- npm: `lucide-react`
- Hairline UI components it needs (the CLI installs them too): `ui-interaction-motion`
- Docs and live preview: https://hairlineui.com/ui/popover
- Registry item (source): https://hairlineui.com/r/popover.json

## Usage

```tsx
import { Popover } from "@/components/ui/popover";

<Popover label="Rename" trigger={<button>Rename</button>}>
  {({ close }) => <form onSubmit={(e) => { e.preventDefault(); save(); close(); }}>…</form>}
</Popover>
```

## Props

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `trigger` | `ReactElement` | – | The button; it gets aria-expanded and the click. |
| `children` | `ReactNode \| ({ close }) => ReactNode` | – | The content. |
| `side / align` | `Side / Align` | `"bottom" / "center"` | Where it sits. |
| `open / onOpenChange` | `boolean / (open) => void` | – | Control it. |
| `width` | `number` | `280` | Panel width. |
| `label` | `string` | – | Accessible name of the panel. |

## States

- **open**: Rises 6px from its side, out of a 4px blur, from 0.96 (320ms).
- **inside**: Focus on the first field or the panel.
- **close**: Escape returns focus to the trigger; a press outside just closes (180ms).

## What it handles

Positioning, focus handover, Escape and outside presses are where most popovers go wrong; this one does all four.

- **From the trigger**: transform-origin is the point on the trigger nearest the panel.
- **Stays in view**: Flips sides and shifts; follows scroll and resize.
- **Focus handover**: In to the first field, back to the trigger on Escape.
- **Close from inside**: children can be a function that receives close().

## Replaces

Radix Popover, floating-ui, focus management

## Where it fits

- **Quick edits**: Rename a file or set a due date without leaving the list.
- **Share settings**: A link with access options under a Share button.
- **Filters**: A few fields behind a Filter button.
- **Details on demand**: More about a plan, a user or a status.

## Notes

- Placement, presence and dismissal live in floating.ts, shared by tooltip, popover, dropdown and context menus: they all flip, shift, enter and leave the same way.
- The panel is role="dialog"; the trigger gets aria-haspopup and aria-expanded.
- Reduced motion: it fades.

License: MIT (https://hairlineui.com/license#components)
