<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
Popover is part of the main Kappa package. Ark UI owns state, focus management, outside dismissal, collision handling, modality, and accessible relationships.
Barrel
import {
Popover,
PopoverRoot,
PopoverTrigger,
PopoverContent,
PopoverTitle,
PopoverDescription,
PopoverClose,
} from "@dicehub/kappa";Granular
import {
Popover,
PopoverRoot,
PopoverTrigger,
PopoverContent,
PopoverTitle,
PopoverDescription,
PopoverClose,
} from "@dicehub/kappa/components/popover";Usage
Put Trigger and Content inside Popover.Root. Content adds a safe Vue Teleport, positioner, surface, and arrow. Useas-child to merge behavior into one Kappa Button.
<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
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.CloseKappa follows the Ark UI Popoverstate and part contract. Popover.Content composes the commonPositioner and Teleport path; use the public Positioner when you need a manual advanced composition.
PopoverandPopover.Rootare the same root component.- Content defaults to
bodyTeleport. Set:teleport="false"for an in-place integration. - Use
Anchorwhen the surface should measure a reference element other than Trigger. - Use
CloseorCloseTriggerso Ark UI restores focus after dismissal.
<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
Basic Content
Compose a title, description, metrics, and a close action inside the default surface.
<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
Pass Ark UI positioning options to choose a side. Collision handling keeps the surface in the viewport.
<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
Popover content can contain inputs and actions. Close through the compound Close part so focus returns correctly.
<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
Use v-model:open when application state must own visibility. Keep Root mounted while its value changes.
<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
Anchor positions the surface against a separate reference element while Trigger remains the keyboard action.
<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
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.
<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
Disabled triggers stay unavailable, while modal popovers block outside interaction through Ark UI.
<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
Use logical spacing and a dir attribute for Arabic, Hebrew, and other right-to-left content.
<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
- Render a visible
Titleand normally aDescription. Use an explicitaria-labelonly 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
initialFocusElorfinalFocusElfor a safer target. - Use
modalfor 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"onPopover.Rootfor right-to-left positioning and directional behavior; the inherited Ark locale is used whendiris omitted. - Open and close motion stops under
prefers-reduced-motion; forced colors retain a visible boundary.
Markdown sibling
Every rendered docs page has a sibling .md URL for copy and automation:/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
Popover.Root
| 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
| 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
| 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
| 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
| 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
| 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. |