# Popover

A popover positioned relative to an anchor element.

## Import

```
Copyts
import { Popover } from "@kobalte/core/popover";
// or
import { Root, Trigger, ... } from "@kobalte/core/popover";
// or (deprecated)
import { Popover } from "@kobalte/core";
```

```
Copyts
import { Popover } from "@kobalte/core/popover";
// or
import { Root, Trigger, ... } from "@kobalte/core/popover";
// or (deprecated)
import { Popover } from "@kobalte/core";
```

## Features

- Follow the [WAI ARIA Popover](https://www.w3.org/WAI/ARIA/apg/patterns/popovermodal/) design pattern.
- Supports modal and non-modal modes.
- Provides screen reader announcements via rendered title and description.
- Focus is fully managed and customizable.
- Optionally render a pointing arrow.
- Can be controlled or uncontrolled.

## Anatomy

The popover consists of:

- **Popover:** The root container for a popover.
- **Popover.Trigger:** The button that opens the popover.
- **Popover.Anchor:** An optional element to position the `Popover.Content` against.
- **Popover.Portal:** Portals its children into the `body` when the popover is open.
- **Popover.Content:** Contains the content to be rendered when the popover is open.
- **Popover.Arrow:** An optional arrow element to render alongside the popover.
- **Popover.CloseButton:** The button that closes the popover.
- **Popover.Title:** An accessible title to be announced when the popover is open.
- **Popover.Description:** An optional accessible description to be announced when the popover is open.

```
Copytsx
<Popover>
	<Popover.Trigger />
	<Popover.Anchor />
	<Popover.Portal>
		<Popover.Content>
			<Popover.Arrow />
			<Popover.CloseButton />
			<Popover.Title />
			<Popover.Description />
		</Popover.Content>
	</Popover.Portal>
</Popover>
```

```
Copytsx
<Popover>
	<Popover.Trigger />
	<Popover.Anchor />
	<Popover.Portal>
		<Popover.Content>
			<Popover.Arrow />
			<Popover.CloseButton />
			<Popover.Title />
			<Popover.Description />
		</Popover.Content>
	</Popover.Portal>
</Popover>
```

## Example

Open

index.tsxstyle.css

```
Copytsx
import { Popover } from "@kobalte/core/popover";
import { CrossIcon } from "some-icon-library";
import "./style.css";

function App() {
  return (
    <Popover>
      <Popover.Trigger class="popover__trigger">Open</Popover.Trigger>
      <Popover.Portal>
        <Popover.Content class="popover__content">
          <Popover.Arrow />
          <div class="popover__header">
            <Popover.Title class="popover__title">About Kobalte</Popover.Title>
            <Popover.CloseButton class="popover__close-button">
              <CrossIcon />
            </Popover.CloseButton>
          </div>
          <Popover.Description class="popover__description">
            A UI toolkit for building accessible web apps and design systems with SolidJS.
          </Popover.Description>
        </Popover.Content>
      </Popover.Portal>
    </Popover>
  );
}
```

```
Copytsx
import { Popover } from "@kobalte/core/popover";
import { CrossIcon } from "some-icon-library";
import "./style.css";

function App() {
  return (
    <Popover>
      <Popover.Trigger class="popover__trigger">Open</Popover.Trigger>
      <Popover.Portal>
        <Popover.Content class="popover__content">
          <Popover.Arrow />
          <div class="popover__header">
            <Popover.Title class="popover__title">About Kobalte</Popover.Title>
            <Popover.CloseButton class="popover__close-button">
              <CrossIcon />
            </Popover.CloseButton>
          </div>
          <Popover.Description class="popover__description">
            A UI toolkit for building accessible web apps and design systems with SolidJS.
          </Popover.Description>
        </Popover.Content>
      </Popover.Portal>
    </Popover>
  );
}
```

## Usage

### Default open

An initial, uncontrolled open value can be provided using the `defaultOpen` prop.

```
Copytsx
<Popover defaultOpen>...</Popover>
```

```
Copytsx
<Popover defaultOpen>...</Popover>
```

### Controlled open

The `open` prop can be used to make the open state controlled. The `onOpenChange` event is fired when the user presses the trigger, close button or interact outside, and receives the new value.

Open

```
Copytsx
import { createSignal } from "solid-js";

function ControlledExample() {
	const [open, setOpen] = createSignal(false);

	return (
		<Popover open={open()} onOpenChange={setOpen}>
			<Popover.Trigger>{open() ? "Close" : "Open"}</Popover.Trigger>
			<Popover.Portal>
				<Popover.Content>...</Popover.Content>
			</Popover.Portal>
		</Popover>
	);
}
```

```
Copytsx
import { createSignal } from "solid-js";

function ControlledExample() {
	const [open, setOpen] = createSignal(false);

	return (
		<Popover open={open()} onOpenChange={setOpen}>
			<Popover.Trigger>{open() ? "Close" : "Open"}</Popover.Trigger>
			<Popover.Portal>
				<Popover.Content>...</Popover.Content>
			</Popover.Portal>
		</Popover>
	);
}
```

### With custom anchor

Use the `Popover.Anchor` component to anchor the content to another element if you do not want to use the trigger as the anchor.

The popover opens when you click here.

But it's anchored to the whole div.

```
Copytsx
<Popover>
	<Popover.Anchor>
		<p>
			The popover opens when you click <Popover.Trigger>here</Popover.Trigger>.
		</p>
		<p>But it's anchored to the whole div.</p>
	</Popover.Anchor>
	<Popover.Portal>
		<Popover.Content>...</Popover.Content>
	</Popover.Portal>
</Popover>
```

```
Copytsx
<Popover>
	<Popover.Anchor>
		<p>
			The popover opens when you click <Popover.Trigger>here</Popover.Trigger>.
		</p>
		<p>But it's anchored to the whole div.</p>
	</Popover.Anchor>
	<Popover.Portal>
		<Popover.Content>...</Popover.Content>
	</Popover.Portal>
</Popover>
```

### Origin-aware animations

We expose a CSS custom property `--kb-popover-content-transform-origin` which can be used to animate the content from its computed origin.

```
Copycss
/* style.css */
.popover__content {
	transform-origin: var(--kb-popover-content-transform-origin);
	animation: contentHide 250ms ease-in forwards;
}

.popover__content[data-expanded] {
	animation: contentShow 250ms ease-out;
}

@keyframes contentShow {
	from {
		opacity: 0;
		transform: scale(0.96);
	}
	to {
		opacity: 1;
		transform: scale(1);
	}
}

@keyframes contentHide {
	from {
		opacity: 1;
		transform: scale(1);
	}
	to {
		opacity: 0;
		transform: scale(0.96);
	}
}
```

```
Copycss
/* style.css */
.popover__content {
	transform-origin: var(--kb-popover-content-transform-origin);
	animation: contentHide 250ms ease-in forwards;
}

.popover__content[data-expanded] {
	animation: contentShow 250ms ease-out;
}

@keyframes contentShow {
	from {
		opacity: 0;
		transform: scale(0.96);
	}
	to {
		opacity: 1;
		transform: scale(1);
	}
}

@keyframes contentHide {
	from {
		opacity: 1;
		transform: scale(1);
	}
	to {
		opacity: 0;
		transform: scale(0.96);
	}
}
```

## API Reference

### Popover

`Popover` is equivalent to the `Root` import from `@kobalte/core/popover` (and deprecated `Popover.Root`).

| Prop | Description |
| --- | --- |
| open | `boolean`<br> The controlled open state of the popover. |
| defaultOpen | `boolean`<br> The default open state when initially rendered. Useful when you do not need to control the open state. |
| onOpenChange | `(open: boolean) => void`<br> Event handler called when the open state of the popover changes. |
| id | `string`<br> A unique identifier for the component. The id is used to generate id attributes for nested components. If no id prop is provided, a generated id will be used. |
| modal | `boolean`<br> Whether the popover should be the only visible content for screen readers, when set to `true`: <br> \- interaction with outside elements will be disabled. <br> \- scroll will be locked. <br> \- focus will be locked inside the popover content. <br> \- elements outside the popover content will not be visible for screen readers. |
| preventScroll | `boolean`<br> Whether the scroll should be locked even if the popover is not modal. |
| forceMount | `boolean`<br> Used to force mounting the popover (portal and content) when more control is needed. Useful when controlling animation with SolidJS animation libraries. |
| translations | [`PopoverIntlTranslations`](https://github.com/kobaltedev/kobalte/blob/main/packages/core/src/popover/popover.intl.ts)<br> Localization strings. |

`Popover` also accepts the following props to customize the placement of the `Popover.Content`.

| Prop | Description |
| --- | --- |
| getAnchorRect | `(anchor?: HTMLElement) => AnchorRect  | undefined`<br> Function that returns the anchor element's DOMRect. |
| anchorRef | `Accessor<HTMLElement | undefined>`<br> A ref for the anchor element. Useful if you want to use an element outside `Popover` as the popover anchor. |
| placement | `Placement`<br> The placement of the popover. |
| gutter | `number`<br> The distance between the popover and the trigger/anchor element. By default, it's 0 plus half of the arrow offset, if it exists. |
| shift | `number`<br> The skidding of the popover along the anchor element. |
| flip | `boolean | string`<br> Controls the behavior of the popover when it overflows the viewport:<br> \- If a `boolean`, specifies whether the popover should flip to the opposite side when it overflows.<br> \- If a `string`, indicates the preferred fallback placements when it overflows.<br>The placements must be spaced-delimited, e.g. "top left". |
| slide | `boolean`<br> Whether the popover should slide when it overflows. |
| overlap | `boolean`<br> Whether the popover can overlap the anchor element when it overflows. |
| sameWidth | `boolean`<br> Whether the popover should have the same width as the anchor element. This will be exposed to CSS as `--kb-popper-anchor-width`. |
| fitViewport | `boolean`<br> Whether the popover should fit the viewport. If this is set to true, the popover content will have `maxWidth` and `maxHeight` set to the viewport size. This will be exposed to CSS as `--kb-popper-available-width` and `--kb-popper-available-height`. |
| hideWhenDetached | `boolean`<br> Whether to hide the popover when the anchor element becomes occluded. |
| detachedPadding | `number`<br> The minimum padding in order to consider the anchor element occluded. |
| arrowPadding | `number`<br> The minimum padding between the arrow and the popover corner. |
| overflowPadding | `number`<br> The minimum padding between the popover and the viewport edge. This will be exposed to CSS as `--kb-popper-overflow-padding`. |

### Popover.Trigger

`Popover.Trigger` consists of [Button](https://kobalte.dev/docs/core/components/button).

| Data attribute | Description |
| --- | --- |
| data-expanded | Present when the popover is open. |
| data-closed | Present when the popover is close. |

`Popover.Anchor` , `Popover.Content` , `Popover.Arrow`, `Popover.Title`, `Popover.Description` and `Popover.CloseButton` share the same data-attributes.

### Popover.Content

The popper positioner will copy the same `z-index` as the `Popover.Content`.

| Prop | Description |
| --- | --- |
| onOpenAutoFocus | `(event: Event) => void`<br> Event handler called when focus moves into the component after opening. It can be prevented by calling `event.preventDefault`. |
| onCloseAutoFocus | `(event: Event) => void`<br> Event handler called when focus moves to the trigger after closing. It can be prevented by calling `event.preventDefault`. |
| onEscapeKeyDown | `(event: KeyboardEvent) => void`<br> Event handler called when the escape key is down. It can be prevented by calling `event.preventDefault`. |
| onPointerDownOutside | `(event: PointerDownOutsideEvent) => void`<br> Event handler called when a pointer event occurs outside the bounds of the component. It can be prevented by calling `event.preventDefault`. |
| onFocusOutside | `(event: FocusOutsideEvent) => void`<br> Event handler called when the focus moves outside the bounds of the component. It can be prevented by calling `event.preventDefault`. |
| onInteractOutside | `(event: InteractOutsideEvent) => void`<br> Event handler called when an interaction (pointer or focus event) happens outside the bounds of the component. It can be prevented by calling `event.preventDefault`. |

### Popover.Arrow

| Prop | Description |
| --- | --- |
| size | `number`<br> The size of the arrow. |

## Rendered elements

| Component | Default rendered element |
| --- | --- |
| `Popover` | none |
| `Popover.Trigger` | `button` |
| `Popover.Anchor` | `div` |
| `Popover.Portal` | `Portal` |
| `Popover.Content` | `div` |
| `Popover.Arrow` | `div` |
| `Popover.CloseButton` | `button` |
| `Popover.Title` | `h2` |
| `Popover.Description` | `p` |

## Accessibility

### Keyboard Interactions

| Key | Description |
| --- | --- |
| `Space` | When focus is on the trigger, opens/closes the popover. |
| `Enter` | When focus is on the trigger, opens/closes the popover. |
| `Tab` | Moves focus to the next focusable element. |
| `Shift` \+ `Tab` | Moves focus to the previous focusable element. |
| `Esc` | Closes the popover and moves focus to the trigger. |

Previous[←Pagination](https://kobalte.dev/docs/core/components/pagination)Next[Progress→](https://kobalte.dev/docs/core/components/progress)