Skip to content
  1. Keyline UI
  2. Hover card
Keyline UIComponents
  • Get started
    • Installation
    • Theming
    • Modes
    • Configuration
    • Composition
  • Actions
    • Button
    • Button group
    • Split button
    • Toggle
    • Toggle group
    • Toolbar
    • Menu
    • Menubar
    • Context menu
  • Inputs
    • Field and form
    • Checkbox
    • Checkbox group
    • Radio group
    • Switch
    • Slider
    • Segmented
    • Select
    • Native select
    • Combobox
    • Multiselect
    • Number field
    • OTP field
    • Time field
    • Date picker and calendar
    • Date range
  • Data
    • Table
    • Chart
    • Stat and meter
    • Status and badge
    • Progress
    • Skeleton
    • Empty
    • Avatar
    • Kbd
    • Marker
  • Navigation
    • Tabs
    • Breadcrumb
    • Pagination
    • Nav
    • Navigation menu
    • Command menu
  • Overlays
    • Dialog
    • Alert dialog
    • Drawer
    • Sheet
    • Popover
    • Hover card
    • Tooltip
    • Toast
    • Notice
  • Layout
    • App shell
    • Sidebar
    • Panel
    • Resizable
    • Scroll area
    • Accordion
    • Collapsible
    • Carousel
    • Inspector
    • Item
    • Direction
  • Conversation
    • Message
    • Bubble
    • Message scroller
    • Attachment
    • Questionnaire
  • Blocks
    • Shipments

Hover card

A preview of what a link points to, so a reader can check without leaving the sentence. It opens after a pause on hover or on keyboard focus, and stays while the pointer crosses to it. The link still goes somewhere: the card only previews it.

Loading the live example…

"use client"

import { Avatar } from "@/components/keyline/ui/avatar"
import { HoverCard, HoverCardBody, HoverCardContent, HoverCardFacts, HoverCardHeader, HoverCardTrigger } from "@/components/keyline/ui/hover-card"
import { Status } from "@/components/keyline/ui/status"

const CLIENTS = {
  county: {
    name: "Lackawanna County",
    contact: "Procurement office",
    code: "C-0112",
    facts: [
      ["Rep", "Dwight Schrute"],
      ["Since", "2003"],
      ["Orders this year", "48"],
      ["Spend", "$61,240"],
    ],
    status: <Status kind="done">Paid up</Status>,
  },
  vance: {
    name: "Vance Refrigeration",
    contact: "Bob Vance",
    code: "C-0187",
    facts: [
      ["Rep", "Phyllis Vance"],
      ["Since", "2007"],
      ["Orders this year", "12"],
    ],
    status: <Status kind="attention">Invoice 31 days overdue</Status>,
  },
} as const

function Client({ id }: { id: keyof typeof CLIENTS }) {
  const c = CLIENTS[id]
  return (
    <HoverCard>
      <HoverCardTrigger href={`?client=${c.code}`} onClick={(e) => e.preventDefault()}>
        {c.name}
      </HoverCardTrigger>
      <HoverCardContent className="w-[min(320px,calc(100vw-24px))]">
        <HoverCardHeader media={<Avatar layout="cell" decorative name={c.contact} />} title={c.name} description={c.contact} code={c.code} />
        <HoverCardFacts facts={c.facts} />
        <HoverCardBody>{c.status}</HoverCardBody>
      </HoverCardContent>
    </HoverCard>
  )
}

export function ClientCards() {
  return (
    <p className="m-0 max-w-[60ch] text-[15px] leading-7">
      This week Dwight closed a renewal with <Client id="county" />, and Phyllis is still chasing <Client id="vance" /> for last
      month&apos;s invoice. Hover or focus a client for their account.
    </p>
  )
}

Installation

npx shadcn@latest add @keyline-ui/hover-card

Run it where your components.json is. The first time, map the @keyline-ui registry: one command, in Installation.

Usage

import { HoverCard, HoverCardBody, HoverCardContent, HoverCardFacts, HoverCardHeader, HoverCardTrigger } from "@/components/keyline/ui/hover-card"
<HoverCard>
  <HoverCardTrigger href="/clients/c-0112">Lackawanna County</HoverCardTrigger>
  <HoverCardContent>
    <HoverCardHeader media={<Avatar layout="cell" decorative name="…" />} title="Lackawanna County" code="C-0112" />
    <HoverCardFacts facts={[["Rep", "Dwight Schrute"], ["Since", "2003"]]} />
  </HoverCardContent>
</HoverCard>

Props

PropTypeDefaultDescription
hrefstringDefault —On HoverCardTrigger: where the link goes. The card never replaces it.
delay · closeDelaynumberDefault 600 · 300On HoverCardTrigger: milliseconds before it opens and closes.
side · alignBase UI side · alignDefault "bottom" · "start"On HoverCardContent.
HoverCardHeader{ media?, title, description?, code? }Default —A row of cells: a square media cell, the title, and a code cell such as an ID.
HoverCardFacts{ facts: [term, value][] }Default —Facts two to a row on shared seams; an odd last fact spans the row.
HoverCardBodydivDefault —Free content in its own row, such as a Status.

Touch screens have no hover, so the card never holds anything the linked page doesn't. Built on Base UI Preview Card.

Sheet 53 of 73PreviousPopoverNextTooltip
On this page