Inkbox

Component

Hover Card

A raised white preview card that opens after a short pause on a link or handle.

npx -y github:anwarlemu/inkbox-brand-cli#release add hover-card
Preview
Open

Usage

Use to preview what a link or an agent handle points to (the agent's addresses, its channels) for people with a pointer. Keep the same information reachable by clicking: hover cards do not open on touch.

Avoid

  • Actions that exist only inside the card
  • A card that opens instantly on hover
  • Long content

Exports: HoverCard, HoverCardContent, HoverCardTrigger. This component is a client component.

Dependencies: surface, radix-ui.

Example

examples/hover-card.tsx
import { EnvelopeSimpleIcon, PhoneIcon } from "@phosphor-icons/react/ssr";​import { HoverCard, HoverCardContent, HoverCardTrigger } from "@/components/ui/hover-card";​function AgentCard() {  return (    <div className="flex gap-3">      <span className="flex size-10 shrink-0 items-center justify-center rounded-control bg-avatar text-body-lg font-medium text-white">A</span>      <div className="grid min-w-0 gap-1">        <p className="text-body font-medium text-fg">@acme</p>        <p className="text-body text-fg-muted">Support agent for Acme. Created Jul 27, 2026.</p>        <p className="mt-1 flex items-center gap-2 text-body text-fg">          <EnvelopeSimpleIcon weight="fill" className="size-4.5 text-icon-secondary" /> acme@inkboxmail.com        </p>        <p className="flex items-center gap-2 text-body text-fg">          <PhoneIcon weight="fill" className="size-4.5 text-icon-secondary" /> +1 650 474 9720        </p>      </div>    </div>  );}​export function Preview() {  return (    <p className="text-body text-fg">      Messages to{" "}      <HoverCard>        <HoverCardTrigger href="#agent" className="text-rose underline-offset-4 hover:underline">          @acme        </HoverCardTrigger>        <HoverCardContent>          <AgentCard />        </HoverCardContent>      </HoverCard>{" "}      are answered within a minute.    </p>  );}​export function Open() {  return (    <div className="flex min-h-60 items-start justify-center">      <HoverCard defaultOpen>        <HoverCardTrigger href="#agent" className="text-rose underline-offset-4 hover:underline">          @acme        </HoverCardTrigger>        <HoverCardContent>          <AgentCard />        </HoverCardContent>      </HoverCard>    </div>  );}

Source

components/ui/hover-card.tsx
"use client";​import * as React from "react";import { HoverCard as HoverCardPrimitive } from "radix-ui";​import { usePortalContainer } from "@/lib/surface";import { cn } from "@/lib/utils";​// A preview on hover, extrapolated from the console's raised white panels (Figma 427:2715): white, 8px corners, the// floating shadow, 16px of padding, 14px ink. It waits before opening (so a passing pointer does not trigger it), then// grows out of its trigger from 96 percent with a fade.function HoverCard({ openDelay = 400, closeDelay = 150, ...props }: React.ComponentProps<typeof HoverCardPrimitive.Root>) {  return <HoverCardPrimitive.Root data-slot="hover-card" openDelay={openDelay} closeDelay={closeDelay} {...props} />;}​function HoverCardTrigger(props: React.ComponentProps<typeof HoverCardPrimitive.Trigger>) {  return <HoverCardPrimitive.Trigger data-slot="hover-card-trigger" {...props} />;}​function HoverCardContent({ className, align = "center", sideOffset = 6, ...props }: React.ComponentProps<typeof HoverCardPrimitive.Content>) {  const container = usePortalContainer();  return (    <HoverCardPrimitive.Portal container={container} data-slot="hover-card-portal">      <HoverCardPrimitive.Content        data-slot="hover-card-content"        align={align}        sideOffset={sideOffset}        className={cn(          "z-50 w-72 max-w-[calc(100vw-2rem)] origin-(--radix-hover-card-content-transform-origin) rounded-control bg-surface p-4 text-body leading-body text-fg shadow-floating outline-none data-[state=closed]:animate-pop-out data-[state=open]:animate-pop-in",          className,        )}        {...props}      />    </HoverCardPrimitive.Portal>  );}​export { HoverCard, HoverCardContent, HoverCardTrigger };

Reference: Extrapolated from the Inkbox console (Figma 427:2715): the raised white panels, the 8px corners and the avatar tile.