<script setup>
import { Button } from "@dicehub/kappa/components/button";
import { HoverCard } from "@dicehub/kappa/components/hover-card";
</script>
<template>
<HoverCard.Root :open-delay="0">
<HoverCard.Trigger as-child><Button variant="outline">Inspect run</Button></HoverCard.Trigger>
<HoverCard.Content>
<h3>Run 4189</h3>
<p>Completed in 02:14:38. Residuals are within the acceptance limit.</p>
<a href="/runs/4189">Open run report</a>
</HoverCard.Content>
</HoverCard.Root>
</template>Installation
Hover Card is part of the main Kappa package. Ark UI owns pointer and focus behavior, open and close delays, active trigger state, outside interaction, and collision-aware positioning.
Barrel
import {
HoverCard,
HoverCardRoot,
HoverCardTrigger,
HoverCardContent,
HoverCardPositioner,
HoverCardArrow,
HoverCardArrowTip,
} from "@dicehub/kappa";Granular
import {
HoverCard,
HoverCardRoot,
HoverCardTrigger,
HoverCardContent,
HoverCardPositioner,
HoverCardArrow,
HoverCardArrowTip,
} from "@dicehub/kappa/components/hover-card";Usage
Put Trigger and Content inside Root. Content adds the viewport-aware Positioner, Vue Teleport, and default Arrow. Use as-child when the trigger should keep one native Button or link element.
<script setup>
import { Button } from "@dicehub/kappa/components/button";
import { HoverCard } from "@dicehub/kappa/components/hover-card";
</script>
<template>
<HoverCard.Root>
<HoverCard.Trigger as-child><Button>View solver profile</Button></HoverCard.Trigger>
<HoverCard.Content>
<h3>PIMPLE baseline</h3>
<p>Pressure-velocity coupling · 1,240 iterations · 8.4e-6 residual.</p>
<a href="/runs/pimple-baseline">Review the full run</a>
</HoverCard.Content>
</HoverCard.Root>
</template>Composition
HoverCard.Root
├── HoverCard.Trigger
└── HoverCard.Content
├── Positioner + Teleport (automatic)
├── HoverCard.Arrow
│ └── HoverCard.ArrowTip
└── interactive preview contentKappa follows the Ark UI Hover Cardstate contract. Content composes Positioner and the default arrow for the common case; use the named Positioner and arrow parts for advanced composition.
HoverCardandHoverCard.Rootare the same root component.- Content defaults to a
bodyTeleport. Set:teleport="false"for an in-place integration. - Hover Card content is interactive. Use Popover for a task that needs modal focus, form submission, or a primary action.
- Use
RootProvideranduseHoverCardwhen external machine state must be shared.
Examples
Interactive Preview
Use Hover Card for a compact preview that may contain a link. Its content stays interactive while the pointer moves from Trigger to Content.
<script setup>
import { Button } from "@dicehub/kappa/components/button";
import { HoverCard } from "@dicehub/kappa/components/hover-card";
</script>
<template>
<HoverCard.Root>
<HoverCard.Trigger as-child><Button>View solver profile</Button></HoverCard.Trigger>
<HoverCard.Content>
<h3>PIMPLE baseline</h3>
<p>Pressure-velocity coupling · 1,240 iterations · 8.4e-6 residual.</p>
<a href="/runs/pimple-baseline">Review the full run</a>
</HoverCard.Content>
</HoverCard.Root>
</template>Placement and Collision
Pass Ark UI positioning options to select a side. Collision handling keeps the surface inside the viewport.
<script setup>
import { Button } from "@dicehub/kappa/components/button";
import { HoverCard } from "@dicehub/kappa/components/hover-card";
const placements = ["top", "bottom", "left", "right"] as const;
</script>
<template>
<div class="placements">
<HoverCard.Root v-for="placement in placements" :key="placement" :open-delay="0" :positioning="{ placement }">
<HoverCard.Trigger as-child>
<Button :data-placement-control="placement" size="sm" variant="outline">{{ placement }}</Button>
</HoverCard.Trigger>
<HoverCard.Content><h3>{{ placement }} placement</h3><p>Ark UI flips the surface when the viewport is tight.</p></HoverCard.Content>
</HoverCard.Root>
</div>
</template>
<style scoped>
.placements {
display: grid;
grid-template-areas: ". top ." "left . right" ". bottom .";
grid-template-columns: repeat(3, minmax(0, 1fr));
place-items: center;
gap: 0.75rem 1rem;
}
[data-placement-control="top"] { grid-area: top; }
[data-placement-control="bottom"] { grid-area: bottom; }
[data-placement-control="left"] { grid-area: left; justify-self: start; }
[data-placement-control="right"] { grid-area: right; justify-self: end; }
</style>Delay Control
Tune openDelay and closeDelay for the density of the surrounding workflow. The installed Ark UI default is 600 ms open and 300 ms close.
<script setup>
import { Button } from "@dicehub/kappa/components/button";
import { HoverCard } from "@dicehub/kappa/components/hover-card";
</script>
<template>
<HoverCard.Root :open-delay="0" :close-delay="300">
<HoverCard.Trigger as-child><Button variant="outline">Immediate preview</Button></HoverCard.Trigger>
<HoverCard.Content><h3>Fast preview</h3><p>Use a short open delay for a dense comparison table.</p></HoverCard.Content>
</HoverCard.Root>
</template>Controlled State
Use v-model:open when application state must own visibility. Pointer and focus events still come from Ark UI.
<script setup>
import { ref } from "vue";
import { Button } from "@dicehub/kappa/components/button";
import { HoverCard } from "@dicehub/kappa/components/hover-card";
const open = ref(false);
</script>
<template>
<Button variant="outline" @click="open = !open">Toggle preview</Button>
<HoverCard.Root v-model:open="open" :open-delay="0">
<HoverCard.Trigger as-child><Button>Hover or focus</Button></HoverCard.Trigger>
<HoverCard.Content><h3>Controlled state</h3><p>The parent owns the open value.</p></HoverCard.Content>
</HoverCard.Root>
</template>Custom Arrow
Content renders an Arrow and ArrowTip by default. Replace them through the arrow slot when the surface needs a custom treatment.
<script setup>
import { Button } from "@dicehub/kappa/components/button";
import { HoverCard } from "@dicehub/kappa/components/hover-card";
</script>
<template>
<HoverCard.Root>
<HoverCard.Trigger as-child><Button>Custom arrow</Button></HoverCard.Trigger>
<HoverCard.Content>
<template #arrow>
<HoverCard.Arrow><HoverCard.ArrowTip /></HoverCard.Arrow>
</template>
<h3>Custom arrow slot</h3>
<p>Replace the default arrow when the surface needs a different visual.</p>
</HoverCard.Content>
</HoverCard.Root>
</template>Long Preview
Long copy wraps and scrolls within the viewport-aware surface. Keep required workflow actions in a Popover or full page instead.
<script setup>
import { Button } from "@dicehub/kappa/components/button";
import { HoverCard } from "@dicehub/kappa/components/hover-card";
</script>
<template>
<HoverCard.Root :open-delay="0">
<HoverCard.Trigger as-child><Button>Long preview</Button></HoverCard.Trigger>
<HoverCard.Content>
<h3>Convergence notes</h3>
<p>Long preview text wraps and scrolls inside the available viewport area. Keep the preview useful, but link to the full report for complete logs, tables, and actions.</p>
</HoverCard.Content>
</HoverCard.Root>
</template>Disabled
A disabled root prevents opening. Do not make essential information available only through a disabled trigger.
<script setup>
import { Button } from "@dicehub/kappa/components/button";
import { HoverCard } from "@dicehub/kappa/components/hover-card";
</script>
<template>
<HoverCard.Root disabled>
<HoverCard.Trigger as-child><Button disabled>Unavailable run</Button></HoverCard.Trigger>
<HoverCard.Content><h3>Unavailable run</h3><p>Validation must pass before this preview is available.</p></HoverCard.Content>
</HoverCard.Root>
</template>Accessibility
- Use a clear, focusable Trigger. Ark UI opens the card from pointer hover and keyboard focus, with the configured delay.
- Keep the preview supplementary. Required information and primary actions must have a non-hover path.
- Content is non-modal and does not trap focus. Links and controls inside it remain available while the pointer travels into the surface.
- Use
as-childwith one native interactive element. Do not nest a button or link inside another trigger. - Direction follows the inherited Ark UI locale. Provide an Ark UI LocaleProvider for right-to-left positioning and content.
- Disabled roots do not open. Do not use a disabled Trigger as the only way to discover essential information.
- Content motion stops under
prefers-reduced-motion; forced colors retain a visible boundary and arrow.
Markdown sibling
The rendered page has a sibling .md URL for copy and automation:/docs/components/hover-card.md.
API Reference
HoverCard.Root
| Prop | Type | Default | Description |
|---|---|---|---|
open / defaultOpen | boolean | false | Controlled or initial visibility. Pair open with update:open or v-model:open. |
openDelay | number | 600 | Milliseconds from pointer enter or focus until the card opens. This follows the installed Ark UI machine. |
closeDelay | number | 300 | Milliseconds from pointer leave until the card closes. Pointer movement into Content cancels the close. |
disabled | boolean | false | Prevents pointer and focus events from opening the card. |
positioning | HoverCardPositioningOptions | bottom, 8 px gutter | Ark UI placement, collision, offset, and strategy options. |
lazyMount / unmountOnExit | boolean | Ark UI | Control whether Content mounts on first open and unmounts after exit. |
triggerValue / defaultTriggerValue | string | null | null | Track the active value-bearing Trigger when one root owns multiple previews. |
id / ids | string / object | generated | Override the machine or individual part identifiers. |
HoverCard.Content
| Prop | Type | Default | Description |
|---|---|---|---|
teleport | boolean | true | Moves the positioner to teleportTo after mount without changing Ark UI state or relationships. |
teleportTo | string | Element | "body" | Vue Teleport target for the positioner. |
showArrow | boolean | true | Shows the Kappa Arrow and ArrowTip convenience parts. |
asChild | boolean | false | Merges content attributes into one child element through Ark UI. |
Parts
| Part | Element | Description |
|---|---|---|
HoverCard.Root | renderless | Owns open state, pointer/focus delays, active trigger value, outside interaction, and positioning. |
HoverCard.RootProvider | renderless | Connects parts to an external useHoverCard machine. |
HoverCard.Trigger | button | Pointer and keyboard focus target; asChild merges behavior onto a Kappa Button or link. |
HoverCard.Content | div | Interactive, portalled preview surface with a default positioner and arrow. |
HoverCard.Positioner | div | Public positioner for advanced manual composition; Content includes it by default. |
HoverCard.Arrow / ArrowTip | div | Positioned arrow wrapper and visual tip; Content renders both by default. |
HoverCard.Context | slot | Exposes reactive Ark UI state to a scoped slot. |
Events
| Event | Payload | Description |
|---|---|---|
update:open | boolean | Drives v-model:open. |
openChange | HoverCardOpenChangeDetails | Reports every visibility change. |
update:triggerValue | string | null | Drives v-model:triggerValue. |
triggerValueChange | HoverCardTriggerValueChangeDetails | Reports the active value-bearing trigger. |
focusOutside / interactOutside / pointerDownOutside | Ark outside event | Inspect or prevent outside interaction behavior. |
exitComplete | void | Fires after the closed-state motion completes. |
Exports
| Export | Description |
|---|---|
HoverCard | Compound API exposing Root, RootProvider, Trigger, Positioner, Content, Arrow, ArrowTip, and Context. |
HoverCardRoot / HoverCardContent … | Named unaugmented component exports. |
HoverCardProps / HoverCardContentProps | Public root, content, positioning, and part contracts. |
HoverCardOpenChangeDetails and outside-event types | Typed Ark UI event payloads. |
useHoverCard / useHoverCardContext | Ark UI hooks for external state and descendant access. |
hoverCardAnatomy | Ark UI part anatomy metadata. |
HOVER_CARD_DEFAULT_POSITIONING | Kappa's viewport-aware bottom placement. |