# Popover

[](https://ark-ui.com/docs/components/popover "View Ark UI documentation")

Presents focused, interactive content near a trigger without leaving the current workflow.

```vue
<script setup>
import { Button } from "@dicehub/kappa/components/button";
import { Popover } from "@dicehub/kappa/components/popover";
</script>

<template>
  <Popover.Root>
    <Popover.Trigger as-child><Button variant="outline">Run filters</Button></Popover.Trigger>
    <Popover.Content>
      <Popover.Title>Run filters</Popover.Title>
      <Popover.Description>Choose which result sets stay in the report.</Popover.Description>
      <Popover.Close as-child label="Apply filters"><Button variant="primary">Apply filters</Button></Popover.Close>
    </Popover.Content>
  </Popover.Root>
</template>
```

## [Installation](#installation)

Popover is part of the main Kappa package. Ark UI owns state, focus management, outside dismissal, collision handling, modality, and accessible relationships.

### [Barrel](#barrel)

```javascript
import {
  Popover,
  PopoverRoot,
  PopoverTrigger,
  PopoverContent,
  PopoverTitle,
  PopoverDescription,
  PopoverClose,
} from "@dicehub/kappa";
```

### [Granular](#granular)

```javascript
import {
  Popover,
  PopoverRoot,
  PopoverTrigger,
  PopoverContent,
  PopoverTitle,
  PopoverDescription,
  PopoverClose,
} from "@dicehub/kappa/components/popover";
```

## [Usage](#usage)

Put `Trigger` and `Content` inside `Popover.Root`. Content adds a safe Vue Teleport, positioner, surface, and arrow. Use`as-child` to merge behavior into one Kappa Button.

```vue
<script setup>
import { Button } from "@dicehub/kappa/components/button";
import { Popover } from "@dicehub/kappa/components/popover";
</script>

<template>
  <Popover.Root>
    <Popover.Trigger as-child><Button>Inspect run</Button></Popover.Trigger>
    <Popover.Content>
      <Popover.Title>Run 4189</Popover.Title>
      <Popover.Description>Run completed in 02:14:38.</Popover.Description>
      <p>Pressure residuals stayed below the configured limit.</p>
    </Popover.Content>
  </Popover.Root>
</template>
```

## [Composition](#composition)

Typical part hierarchy

```plaintext
Popover.Root
├── Popover.Anchor (optional custom reference)
├── Popover.Trigger
└── Popover.Content
    ├── Positioner + Teleport (automatic)
    ├── Popover.Arrow
    │   └── Popover.ArrowTip
    ├── Popover.Title
    ├── Popover.Description
    ├── interactive content
    └── Popover.Close
```

Kappa follows the [Ark UI Popover](https://ark-ui.com/docs/components/popover)state and part contract. `Popover.Content` composes the common`Positioner` and Teleport path; use the public `Positioner` when you need a manual advanced composition.

-   `Popover` and `Popover.Root` are the same root component.
-   Content defaults to `body` Teleport. Set `:teleport="false"` for an in-place integration.
-   Use `Anchor` when the surface should measure a reference element other than Trigger.
-   Use `Close` or `CloseTrigger` so Ark UI restores focus after dismissal.

```vue
<Popover.Root>
  <Popover.Anchor>Report context</Popover.Anchor>
  <Popover.Trigger as-child><Button>Open</Button></Popover.Trigger>
  <Popover.Content>
    <Popover.Title>Details</Popover.Title>
    <Popover.Description>Content accepts normal interactive markup.</Popover.Description>
    <Popover.Close as-child label="Done"><Button>Done</Button></Popover.Close>
    <template #arrow>
      <Popover.Arrow><Popover.ArrowTip /></Popover.Arrow>
    </template>
  </Popover.Content>
</Popover.Root>
```

## [Examples](#examples)

### [Basic Content](#basic)

Compose a title, description, metrics, and a close action inside the default surface.

```vue
<script setup>
import { Button } from "@dicehub/kappa/components/button";
import { Popover } from "@dicehub/kappa/components/popover";
</script>

<template>
  <Popover.Root>
    <Popover.Trigger as-child><Button>Inspect run</Button></Popover.Trigger>
    <Popover.Content>
      <Popover.Title>Run 4189</Popover.Title>
      <Popover.Description>Run completed in 02:14:38.</Popover.Description>
      <p>Pressure residuals stayed below the configured limit.</p>
    </Popover.Content>
  </Popover.Root>
</template>
```

### [Placement](#placement)

Pass Ark UI positioning options to choose a side. Collision handling keeps the surface in the viewport.

```vue
<script setup>
import { Button } from "@dicehub/kappa/components/button";
import { Popover } from "@dicehub/kappa/components/popover";

const placements = ["top", "bottom", "left", "right"];
</script>

<template>
  <Popover.Root v-for="placement in placements" :key="placement" :positioning="{ placement }">
    <Popover.Trigger as-child><Button size="sm">{{ placement }}</Button></Popover.Trigger>
    <Popover.Content>
      <Popover.Title>{{ placement }} placement</Popover.Title>
      <Popover.Description>Ark UI flips the surface when space is limited.</Popover.Description>
    </Popover.Content>
  </Popover.Root>
</template>
```

### [Interactive Form](#form)

Popover content can contain inputs and actions. Close through the compound Close part so focus returns correctly.

```vue
<script setup>
import { ref } from "vue";
import { Button } from "@dicehub/kappa/components/button";
import { Popover } from "@dicehub/kappa/components/popover";

const runLabel = ref("PIMPLE baseline 07");
</script>

<template>
  <Popover.Root>
    <Popover.Trigger as-child><Button>Edit run details</Button></Popover.Trigger>
    <Popover.Content>
      <Popover.Title>Edit run details</Popover.Title>
      <Popover.Description>Change the label used in reports and archives.</Popover.Description>
      <label>Run label <input v-model="runLabel" /></label>
      <Popover.Close as-child label="Save changes"><Button variant="primary">Save changes</Button></Popover.Close>
    </Popover.Content>
  </Popover.Root>
</template>
```

### [Controlled State](#controlled)

Use v-model:open when application state must own visibility. Keep Root mounted while its value changes.

```vue
<script setup>
import { ref } from "vue";
import { Button } from "@dicehub/kappa/components/button";
import { Popover } from "@dicehub/kappa/components/popover";

const open = ref(false);
</script>

<template>
  <Button @click="open = true">Open controlled popover</Button>
  <Popover.Root v-model:open="open">
    <Popover.Content>
      <Popover.Title>Controlled state</Popover.Title>
      <Popover.Description>The parent owns the open value.</Popover.Description>
      <Popover.Close as-child label="Done"><Button>Done</Button></Popover.Close>
    </Popover.Content>
  </Popover.Root>
</template>
```

### [Custom Anchor](#custom-anchor)

Anchor positions the surface against a separate reference element while Trigger remains the keyboard action.

```vue
<Popover.Root>
  <Popover.Anchor as-child>
    <span class="report-context">Report context · Run 4189</span>
  </Popover.Anchor>
  <Popover.Trigger as-child><Button aria-label="Open anchored details">Details</Button></Popover.Trigger>
  <Popover.Content>
    <Popover.Title>Anchored details</Popover.Title>
    <Popover.Description>Positioning uses the custom Anchor.</Popover.Description>
  </Popover.Content>
</Popover.Root>
```

### [Open on Hover](#open-on-hover)

Compose controlled state with short pointer delays when rich interactive content must open on hover. Click and keyboard activation remain available; use Tooltip for a short text label.

```vue
<script setup>
import { onBeforeUnmount, ref } from "vue";
import { Button } from "@dicehub/kappa/components/button";
import { Popover } from "@dicehub/kappa/components/popover";

const open = ref(false);
let timer;

function cancelTimer() {
  window.clearTimeout(timer);
}

function scheduleOpen() {
  cancelTimer();
  timer = window.setTimeout(() => (open.value = true), 200);
}

function scheduleClose() {
  cancelTimer();
  timer = window.setTimeout(() => (open.value = false), 150);
}

function keepOpen() {
  cancelTimer();
  open.value = true;
}

onBeforeUnmount(cancelTimer);
</script>

<template>
  <Popover.Root v-model:open="open" :auto-focus="false">
    <Popover.Trigger as-child>
      <Button @mouseenter="scheduleOpen" @mouseleave="scheduleClose">Hover or focus</Button>
    </Popover.Trigger>
    <Popover.Content
      @mouseenter="keepOpen"
      @mouseleave="scheduleClose"
      @focusin="keepOpen"
      @focusout="scheduleClose"
    >
      <Popover.Title>Hover-triggered content</Popover.Title>
      <Popover.Description>The surface stays open while you interact with it.</Popover.Description>
      <Popover.Close as-child label="Got it"><Button>Got it</Button></Popover.Close>
    </Popover.Content>
  </Popover.Root>
</template>
```

### [States and Modality](#states)

Disabled triggers stay unavailable, while modal popovers block outside interaction through Ark UI.

```vue
<Popover.Root>
  <Popover.Trigger as-child><Button disabled>Unavailable action</Button></Popover.Trigger>
  <Popover.Content>
    <Popover.Title>Unavailable action</Popover.Title>
    <Popover.Description>Validation must pass first.</Popover.Description>
  </Popover.Content>
</Popover.Root>

<Popover.Root :modal="true">
  <Popover.Trigger as-child><Button>Modal popover</Button></Popover.Trigger>
  <Popover.Content>
    <Popover.Title>Modal popover</Popover.Title>
    <Popover.Close as-child label="Close"><Button>Close</Button></Popover.Close>
  </Popover.Content>
</Popover.Root>
```

### [Right-to-left](#right-to-left)

Use logical spacing and a dir attribute for Arabic, Hebrew, and other right-to-left content.

```vue
<Popover.Root dir="rtl">
  <Popover.Trigger as-child><Button>فتح التفاصيل</Button></Popover.Trigger>
  <Popover.Content>
    <Popover.Title>تفاصيل المحاكاة</Popover.Title>
    <Popover.Description>النتائج جاهزة للمراجعة.</Popover.Description>
  </Popover.Content>
</Popover.Root>
```

## [Accessibility](#accessibility)

-   Render a visible `Title` and normally a `Description`. Use an explicit `aria-label` only when no visible title exists.
-   Keyboard users can open with Enter or Space, move through content with Tab, and close with Escape.
-   Focus returns to the opening Trigger after Escape, outside dismissal, or Close. Set `initialFocusEl` or `finalFocusEl` for a safer target.
-   Use `modal` for a short task that must block outside interaction. Keep the default non-modal mode for contextual content.
-   Disabled controls cannot receive focus. Do not use a disabled Trigger as the only way to discover essential information.
-   Set `dir="rtl"` on `Popover.Root` for right-to-left positioning and directional behavior; the inherited Ark locale is used when `dir` is omitted.
-   Open and close motion stops under `prefers-reduced-motion`; forced colors retain a visible boundary.

## [Markdown sibling](#markdown)

Every rendered docs page has a sibling `.md` URL for copy and automation:[/docs/components/popover.md](/docs/components/popover.md). The sibling contains the same headings, examples, API tables, and Ark UI link without interactive controls or the page table of contents.

## [API Reference](#api-reference)

### [Popover.Root](#root-api)

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `open / defaultOpen` | `boolean` | `false` | Controlled or initial visibility. Pair open with update:open. |
| `dir` | `"ltr" \| "rtl"` | `inherited locale` | Overrides the inherited Ark UI locale direction for positioning and directional behavior. |
| `autoFocus` | `boolean` | `true` | Moves focus to the first focusable content when opened. |
| `closeOnEscape` | `boolean` | `true` | Closes the top popover when Escape is pressed. |
| `closeOnInteractOutside` | `boolean` | `true` | Closes after an allowed outside interaction. |
| `modal` | `boolean` | `false` | Blocks outside interaction, hides outside content from assistive technology, and traps focus. |
| `portalled` | `boolean` | `true` | Preserves correct tab order when content is rendered outside its DOM position. |
| `restoreFocus` | `boolean` | `true` | Returns focus to the opening trigger when the popover closes. |
| `initialFocusEl / finalFocusEl` | `() => HTMLElement \| null` | `-` | Override the elements that receive focus on open and close. |
| `positioning` | `PopoverPositioningOptions` | `bottom, 8 px gutter` | Ark UI placement, collision, offset, and strategy options. |
| `lazyMount / unmountOnExit` | `boolean` | `true` | Defer the popup DOM until first open and remove it after exit. |
| `triggerValue / defaultTriggerValue` | `string \| null` | `null` | Tracks which value-bearing Trigger opened the popover. |
| `persistentElements` | `(() => Element \| null)[]` | `-` | Outside elements that stay interactive and do not dismiss the layer. |
| `translations` | `PopoverIntlTranslations` | `-` | Localized accessibility strings consumed by Ark UI. |
| `id / ids` | `string / object` | `generated` | Override the machine or individual part identifiers. |

### [Popover.Content](#content-api)

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `teleport` | `boolean` | `true` | Moves the positioner to teleportTo after mount. |
| `teleportTo` | `string \| Element` | `"body"` | Vue Teleport target for the popup. |
| `showArrow` | `boolean` | `true` | Shows the default Arrow and ArrowTip. |
| `asChild` | `boolean` | `false` | Merges content attributes into one child element. |

### [Popover.Close](#close-api)

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `asChild` | `boolean` | `false` | Merges dismissal behavior onto one child control. |
| `label` | `string` | `Ark translation` | Explicit accessible-label override for custom or icon-only close controls; omit it to use translations.closeTriggerLabel. |

### [Parts](#parts-api)

| Part | Element | Description |
| --- | --- | --- |
| `Popover.Root` | `renderless` | Owns open state, focus, modality, dismissal, and trigger state. |
| `Popover.RootProvider` | `renderless` | Connects parts to an external usePopover machine. |
| `Popover.Trigger` | `button` | Toggles the popover; asChild merges behavior onto a Kappa Button. |
| `Popover.Anchor` | `div` | Optional reference element for custom positioning. |
| `Popover.Content` | `div` | Portalled, positioned surface with a default arrow. |
| `Popover.Positioner` | `div` | Public positioner for advanced manual composition. |
| `Popover.Arrow / ArrowTip` | `div` | Positioned arrow wrapper and visual tip; Content renders both by default. |
| `Popover.Title` | `div` | Visible accessible name connected to Content; use asChild for a heading element. |
| `Popover.Description` | `div` | Visible accessible description connected to Content; use asChild for a paragraph element. |
| `Popover.Indicator` | `div` | Optional state indicator for a trigger or custom control. |
| `Popover.Close / CloseTrigger` | `button` | Dismisses the popover; Ark's translations provide the default accessible name, while label is an explicit override. |
| `Popover.Context` | `slot` | Exposes reactive Ark UI state to a scoped slot. |

### [Events](#events-api)

| Event | Payload | Description |
| --- | --- | --- |
| `update:open` | `boolean` | Drives v-model:open. |
| `openChange` | `PopoverOpenChangeDetails` | Reports every visibility change. |
| `update:triggerValue` | `string \| null` | Drives v-model:triggerValue. |
| `triggerValueChange` | `PopoverTriggerValueChangeDetails` | Reports the active value-bearing trigger. |
| `escapeKeyDown` | `KeyboardEvent` | Fires when Escape reaches the layer. |
| `focusOutside / interactOutside / pointerDownOutside` | `Ark outside event` | Inspect or prevent outside behavior. |
| `requestDismiss` | `PopoverRequestDismissEvent` | Fires when a parent layer requests nested dismissal. |
| `exitComplete` | `void` | Fires after the closed-state motion completes. |

### [Exports](#exports)

| Export | Description |
| --- | --- |
| `Popover` | Compound API exposing every named part. |
| `PopoverRoot / PopoverContent / PopoverClose …` | Named unaugmented component exports. |
| `PopoverProps / PopoverDirection / PopoverContentProps` | Public prop, direction, and content contracts. |
| `PopoverOpenChangeDetails and outside-event types` | Typed Ark UI event payloads. |
| `usePopover / usePopoverContext` | Ark UI hooks for external state and descendant access. |
| `popoverAnatomy` | Ark UI part anatomy metadata. |
| `POPOVER_DEFAULT_POSITIONING` | Kappa's viewport-aware bottom placement. |