Skip to content
Kappa
Popover
@dicehub/kappav0.4.2

Popover

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

<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

Typical part hierarchy
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 Popoverstate and part contract. Popover.Content composes the commonPositioner 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.
<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 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

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

PropTypeDefaultDescription
open / defaultOpenbooleanfalseControlled or initial visibility. Pair open with update:open.
dir"ltr" | "rtl"inherited localeOverrides the inherited Ark UI locale direction for positioning and directional behavior.
autoFocusbooleantrueMoves focus to the first focusable content when opened.
closeOnEscapebooleantrueCloses the top popover when Escape is pressed.
closeOnInteractOutsidebooleantrueCloses after an allowed outside interaction.
modalbooleanfalseBlocks outside interaction, hides outside content from assistive technology, and traps focus.
portalledbooleantruePreserves correct tab order when content is rendered outside its DOM position.
restoreFocusbooleantrueReturns focus to the opening trigger when the popover closes.
initialFocusEl / finalFocusEl() => HTMLElement | null-Override the elements that receive focus on open and close.
positioningPopoverPositioningOptionsbottom, 8 px gutterArk UI placement, collision, offset, and strategy options.
lazyMount / unmountOnExitbooleantrueDefer the popup DOM until first open and remove it after exit.
triggerValue / defaultTriggerValuestring | nullnullTracks which value-bearing Trigger opened the popover.
persistentElements(() => Element | null)[]-Outside elements that stay interactive and do not dismiss the layer.
translationsPopoverIntlTranslations-Localized accessibility strings consumed by Ark UI.
id / idsstring / objectgeneratedOverride the machine or individual part identifiers.

Popover.Content

PropTypeDefaultDescription
teleportbooleantrueMoves the positioner to teleportTo after mount.
teleportTostring | Element"body"Vue Teleport target for the popup.
showArrowbooleantrueShows the default Arrow and ArrowTip.
asChildbooleanfalseMerges content attributes into one child element.

Popover.Close

PropTypeDefaultDescription
asChildbooleanfalseMerges dismissal behavior onto one child control.
labelstringArk translationExplicit accessible-label override for custom or icon-only close controls; omit it to use translations.closeTriggerLabel.

Parts

PartElementDescription
Popover.RootrenderlessOwns open state, focus, modality, dismissal, and trigger state.
Popover.RootProviderrenderlessConnects parts to an external usePopover machine.
Popover.TriggerbuttonToggles the popover; asChild merges behavior onto a Kappa Button.
Popover.AnchordivOptional reference element for custom positioning.
Popover.ContentdivPortalled, positioned surface with a default arrow.
Popover.PositionerdivPublic positioner for advanced manual composition.
Popover.Arrow / ArrowTipdivPositioned arrow wrapper and visual tip; Content renders both by default.
Popover.TitledivVisible accessible name connected to Content; use asChild for a heading element.
Popover.DescriptiondivVisible accessible description connected to Content; use asChild for a paragraph element.
Popover.IndicatordivOptional state indicator for a trigger or custom control.
Popover.Close / CloseTriggerbuttonDismisses the popover; Ark's translations provide the default accessible name, while label is an explicit override.
Popover.ContextslotExposes reactive Ark UI state to a scoped slot.

Events

EventPayloadDescription
update:openbooleanDrives v-model:open.
openChangePopoverOpenChangeDetailsReports every visibility change.
update:triggerValuestring | nullDrives v-model:triggerValue.
triggerValueChangePopoverTriggerValueChangeDetailsReports the active value-bearing trigger.
escapeKeyDownKeyboardEventFires when Escape reaches the layer.
focusOutside / interactOutside / pointerDownOutsideArk outside eventInspect or prevent outside behavior.
requestDismissPopoverRequestDismissEventFires when a parent layer requests nested dismissal.
exitCompletevoidFires after the closed-state motion completes.

Exports

ExportDescription
PopoverCompound API exposing every named part.
PopoverRoot / PopoverContent / PopoverClose …Named unaugmented component exports.
PopoverProps / PopoverDirection / PopoverContentPropsPublic prop, direction, and content contracts.
PopoverOpenChangeDetails and outside-event typesTyped Ark UI event payloads.
usePopover / usePopoverContextArk UI hooks for external state and descendant access.
popoverAnatomyArk UI part anatomy metadata.
POPOVER_DEFAULT_POSITIONINGKappa's viewport-aware bottom placement.