Skip to content
Kappa
Hover Card
@dicehub/kappav0.4.2

Hover Card

Previews linked or interactive context without leaving the current workflow.

<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

Typical part hierarchy
HoverCard.Root
├── HoverCard.Trigger
└── HoverCard.Content
    ├── Positioner + Teleport (automatic)
    ├── HoverCard.Arrow
    │   └── HoverCard.ArrowTip
    └── interactive preview content

Kappa 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.

  • HoverCard and HoverCard.Root are the same root component.
  • Content defaults to a body Teleport. 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 RootProvider and useHoverCard when 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-child with 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

PropTypeDefaultDescription
open / defaultOpenbooleanfalseControlled or initial visibility. Pair open with update:open or v-model:open.
openDelaynumber600Milliseconds from pointer enter or focus until the card opens. This follows the installed Ark UI machine.
closeDelaynumber300Milliseconds from pointer leave until the card closes. Pointer movement into Content cancels the close.
disabledbooleanfalsePrevents pointer and focus events from opening the card.
positioningHoverCardPositioningOptionsbottom, 8 px gutterArk UI placement, collision, offset, and strategy options.
lazyMount / unmountOnExitbooleanArk UIControl whether Content mounts on first open and unmounts after exit.
triggerValue / defaultTriggerValuestring | nullnullTrack the active value-bearing Trigger when one root owns multiple previews.
id / idsstring / objectgeneratedOverride the machine or individual part identifiers.

HoverCard.Content

PropTypeDefaultDescription
teleportbooleantrueMoves the positioner to teleportTo after mount without changing Ark UI state or relationships.
teleportTostring | Element"body"Vue Teleport target for the positioner.
showArrowbooleantrueShows the Kappa Arrow and ArrowTip convenience parts.
asChildbooleanfalseMerges content attributes into one child element through Ark UI.

Parts

PartElementDescription
HoverCard.RootrenderlessOwns open state, pointer/focus delays, active trigger value, outside interaction, and positioning.
HoverCard.RootProviderrenderlessConnects parts to an external useHoverCard machine.
HoverCard.TriggerbuttonPointer and keyboard focus target; asChild merges behavior onto a Kappa Button or link.
HoverCard.ContentdivInteractive, portalled preview surface with a default positioner and arrow.
HoverCard.PositionerdivPublic positioner for advanced manual composition; Content includes it by default.
HoverCard.Arrow / ArrowTipdivPositioned arrow wrapper and visual tip; Content renders both by default.
HoverCard.ContextslotExposes reactive Ark UI state to a scoped slot.

Events

EventPayloadDescription
update:openbooleanDrives v-model:open.
openChangeHoverCardOpenChangeDetailsReports every visibility change.
update:triggerValuestring | nullDrives v-model:triggerValue.
triggerValueChangeHoverCardTriggerValueChangeDetailsReports the active value-bearing trigger.
focusOutside / interactOutside / pointerDownOutsideArk outside eventInspect or prevent outside interaction behavior.
exitCompletevoidFires after the closed-state motion completes.

Exports

ExportDescription
HoverCardCompound API exposing Root, RootProvider, Trigger, Positioner, Content, Arrow, ArrowTip, and Context.
HoverCardRoot / HoverCardContent …Named unaugmented component exports.
HoverCardProps / HoverCardContentPropsPublic root, content, positioning, and part contracts.
HoverCardOpenChangeDetails and outside-event typesTyped Ark UI event payloads.
useHoverCard / useHoverCardContextArk UI hooks for external state and descendant access.
hoverCardAnatomyArk UI part anatomy metadata.
HOVER_CARD_DEFAULT_POSITIONINGKappa's viewport-aware bottom placement.