`, and the panel is not rendered on the server at all — it appears after mount. Both are needed together: a `
` start tag closes an open `
` regardless of how deeply it is nested, so wrapping the trigger alone leaves the panel to break the paragraph instead. Withholding the panel costs nothing the server render was providing: it is hidden and `inert` until opened, and opening requires the client anyway. Without it, an SSR'd page with a popover in a paragraph emits invalid HTML. The parser repairs it by closing the `
` early, which makes the server DOM differ from the component tree — Svelte logs `node_invalid_placement_ssr` and then `hydration_mismatch`, and the layout visibly shifts on hydration. **Cost:** the panel is absent from the prerendered HTML, so a non-rendering crawler never sees its content and the first paint has nothing to show if the popover is meant to open immediately. Leave it off for popovers in block context, where the default markup is already valid. |
| offsetDistance | `number` | no | | Gap in px between the trigger edge and the popover. |
| onClickOutside | `() => void` | no | | Fires after an outside click closes the popover. Use for analytics or to clear ephemeral state on dismiss. Does NOT control whether the popover closes — that is governed by `closeOnClickOutside`. |
| onEscape | `() => void` | no | | Fires after Escape closes the popover. Use for analytics or to clear ephemeral state on dismiss. Does NOT control whether the popover closes — that is governed by `closeOnEscape`. |
| onOpenChange | `(open: boolean) => void` | no | | Fires when the popover opens or closes from user interaction (click, escape, click-outside). Receives the new open state. |
| open | `boolean` | no | | Controlled open state. Supports `bind:open`. |
| placement | `Placement` | no | | Where the popover appears relative to the trigger. All standard `Placement` values (side plus optional `-start`/`-end` alignment) are supported. |
| preset | `string` | no | | Apply a named preset registered via ``. Prefer this over `class` overrides when the requested look falls outside the semantic intent palette — presets keep hover/active/dark-mode logic coherent and make the custom look reusable across the project. |
| shiftPadding | `number` | no | | Minimum px padding from viewport edges when the popover shifts to stay visible. |
| slotClasses | `Partial>` | no | | Per-slot class overrides. Available slots: `base` (the floating panel). In the same Tailwind bucket `class` wins over the `slotClasses` entry for the element it lands on. Presets and provider defaults sit below both. |
| syncMinWidth | `boolean` | no | | Match the popover's *minimum* width to the trigger width while still letting content grow the panel beyond it. Useful for menu-style overlays where items longer than the trigger should not get truncated. Ignored when `syncWidth` is true (hard width wins). |
| syncWidth | `boolean` | no | | Match the popover width to the trigger width. Useful for select/autocomplete patterns where the floating panel should align with the input. |
| transitionDuration | `number` | no | | Override the enter/exit fade duration in ms. Defaults to the shared token `--blocks-popover-duration` (150ms; collapses to 1ms under `prefers-reduced-motion`). |
| transitionEasing | `string` | no | | Override the enter/exit easing as a CSS `` (e.g. `'linear'`, `'ease-out'`, `'cubic-bezier(0.4,0,0.2,1)'`). Defaults to the token `--blocks-popover-easing`. A CSS string, not a JS easing fn, because the popover motion is a pure CSS transition. |
| trigger | `Snippet` | no | | Trigger element that anchors and toggles the popover. Receives click/keyboard handlers when `autoTrigger` is true. |
| triggerElement | `HTMLElement` | no | | External trigger element ref. Use instead of the `trigger` snippet when the trigger lives outside the Popover tree. Supports `bind:triggerElement`. |
| unstyled | `boolean` | no | | Strip all default tv() classes (including the enter/exit motion). Combine with `class` or `slotClasses` for full custom styling; the panel always carries `data-state="open" | "closed"`, so custom motion can rebuild on that hook (see `popoverMotion` in popover.variants.ts for the reference implementation). |
| usePortal | `boolean` | no | true | Render the floating panel into the browser's top layer via the native `popover` attribute, so it cannot be clipped by `overflow: auto` ancestors. Set to `false` when the popover is itself embedded inside another floating surface (Dialog, Drawer, another Popover) — nested top-layer rendering stacks unpredictably across browsers and stealing focus from the parent surface is usually unwanted. In-flow mode positions the panel absolutely relative to the trigger's offset parent. |
| size | `'lg' | 'md' | 'sm'` | no | md | Controls the dimensions, padding, and text size of the Popover. Affects the component's physical footprint. Available options: lg, md, sm. |
Inherited from:
- PopoverVariants (external)
- Omit, 'children'> (omit-pattern)
### Types
```ts
type Placement = Side | `${Side}-${Alignment}`
```
```ts
type Side = 'top' | 'right' | 'bottom' | 'left'
```
```ts
type Alignment = 'start' | 'end'
```
### Slots (slotClasses keys)
`base`