suiss/ui
  • Docs
  • Components
  • Patterns
  • Interactions
  • Charts
  • Blocks
GitHubGet started
DocsComponentsPatternsInteractionsChartsBlocks
Components82
  • Overview
  • Accordion
  • Alert
  • Alert Dialog
  • Alert Sheet
  • Amount Input
  • Aspect Ratio
  • Attachment
  • Avatar
  • Badge
  • Bottom Bar
  • Breadcrumb
  • Bubble
  • Button
  • Button Group
  • Calendar
  • Card
  • Carousel
  • Chart
  • Checkbox
  • Chip
  • Collapsible
  • Combobox
  • Command
  • Context Menu
  • Dialog
  • Direction
  • Drawer
  • Dropdown Menu
  • Empty
  • FAB
  • Field
  • Fullscreen Menu
  • Haptics
  • Header
  • Hover Card
  • Icon
  • Input
  • Input Accessory Bar
  • Input Group
  • Input OTP
  • Item
  • Kbd
  • Keyboard Scroll View
  • Keypad
  • Label
  • Marker
  • Menubar
  • Message
  • Message Scroller
  • Native Select
  • Navigation Menu
  • Page Indicator
  • Pagination
  • Pin Pad
  • Popover
  • Progress
  • QR Scanner
  • Questionnaire
  • Radio Group
  • Resizable
  • Screen
  • Scroll Area
  • Select
  • Separator
  • Sheet
  • Sidebar
  • Signature Pad
  • Skeleton
  • Slider
  • Spinner
  • Switch
  • Tab Bar
  • Table
  • Tabs
  • Text
  • Textarea
  • Toast
  • Toggle
  • Toggle Group
  • Tooltip
  • Wheel Picker
  • Widget

suiss/ui · Component

Hover Card

A card that previews content behind a link when people hover over or focus it.

Hover Card is an open-source component from suiss/ui for React. The @esuiss/ui CLI copies its source into your project, so you own the code.

HoverCard wraps the hover card primitive of the chosen base. The HoverCard root manages the open state, HoverCardTrigger renders the link that opens it, and HoverCardContent renders the floating card in a portal, positioned next to the trigger.

Use a hover card for supplementary, non-essential previews, such as a profile summary behind a username. Because it only opens on hover or focus, do not put content there that people need to complete a task. For interactive content opened with a click, use a popover.

Installation

CLI

$ pnpm dlx shadcn@latest add @esuiss/hover-card

Works in any project with a components.json. See Installation for the one-line registry setup. Or use the suiss/ui CLI:

$ pnpm dlx @esuiss/ui@latest add hover-card

Manual

  1. Install the dependencies and add the cn helper:
$ pnpm add @base-ui/react
  1. Copy the source into components/ui/hover-card.tsx:
  1. Update the import paths to match your project.

Usage

import { HoverCard, HoverCardTrigger, HoverCardContent } 
<HoverCard
























The trigger renders an anchor, so give it an href. Position the card with the side, sideOffset, align and alignOffset props on HoverCardContent; by default it opens on the bottom, centered, with a 4 pixel offset. Set defaultOpen on the root to start open, or control it with open and onOpenChange.

Examples

Sides

Four hover cards opening on the top, right, bottom and left sides of their triggers.

API Reference

Anatomy3 parts
<HoverCard>
<HoverCardTrigger />
<HoverCardContent />
</HoverCard>
01

HoverCard

The root that manages the card's open state.

Also accepts the props of the primitive part it wraps.

02

HoverCardTrigger

The link that opens the card on hover or focus.

Also accepts the props of the primitive part it wraps.

03

HoverCardContent

The floating card, rendered in a portal and positioned relative to the trigger.

Also accepts the props of the primitive parts it wraps.

Accessibility

  • The trigger renders as a link and is reachable with Tab.
  • The card opens when the pointer rests on the trigger or when the trigger receives keyboard focus, and closes when the pointer leaves.
  • The card is a visual preview; make sure the same information is available elsewhere, for example on the linked page.

Notes

  • Styling hooks: data-slot values hover-card-trigger and hover-card-content. The root renders no element of its own.
  • HoverCardContent slides in from the side it opens on, and fades and zooms as it opens and closes.
  • The card is w-72 by default; override it with className.
  • Uses the popover and popover-foreground colors.
NextIconPreviousHeader

On this page

  1. 01Installation
    • CLI
    • Manual
  2. 02Usage
  3. 03Examples
    • Sides
  4. 04API Reference
    • HoverCard
    • HoverCardTrigger
    • HoverCardContent
  5. 05Accessibility
  6. 06Notes
from
"@/components/ui/hover-card"
>
<HoverCardTrigger
href="#"
className={buttonVariants({ variant: "link" })}
>
@nextjs
</HoverCardTrigger>
<HoverCardContent className="w-80">
<div className="flex gap-4">
<Avatar size="lg">
<AvatarImage src="https://github.com/vercel.png" alt="@nextjs" />
<AvatarFallback>NJ</AvatarFallback>
</Avatar>
<div className="flex flex-col gap-1">
<h4 className="text-sm font-semibold">@nextjs</h4>
<p className="text-sm">
The React framework, created and maintained by @vercel.
</p>
<div className="text-muted-foreground mt-1 flex items-center gap-1.5 text-xs">
<CalendarBlankIcon />
Joined December 2021
</div>
</div>
</div>
</HoverCardContent>
</HoverCard>
import { CalendarBlankIcon } from "@phosphor-icons/react"
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar"
import { buttonVariants } from "@/components/ui/button"
import {
  HoverCard,
  HoverCardContent,
  HoverCardTrigger,
} from "@/components/ui/hover-card"

export default function HoverCardDemo() {
  return (
    <HoverCard>
      <HoverCardTrigger
        href="#"
        className={buttonVariants({ variant: "link" })}
      >
        @nextjs
      </HoverCardTrigger>
      <HoverCardContent className="w-80">
        <div className="flex gap-4">
          <Avatar size="lg">
            <AvatarImage src="https://github.com/vercel.png" alt="@nextjs" />
            <AvatarFallback>NJ</AvatarFallback>
          </Avatar>
          <div className="flex flex-col gap-1">
            <h4 className="text-sm font-semibold">@nextjs</h4>
            <p className="text-sm">
              The React framework, created and maintained by @vercel.
            </p>
            <div className="text-muted-foreground mt-1 flex items-center gap-1.5 text-xs">
              <CalendarBlankIcon />
              Joined December 2021
            </div>
          </div>
        </div>
      </HoverCardContent>
    </HoverCard>
  )
}
components/ui/hover-card.tsx
"use client"

import { PreviewCard as PreviewCardPrimitive } from "@base-ui/react/preview-card"
import { cn } from "@/lib/utils"

function HoverCard({ ...props }: PreviewCardPrimitive.Root.Props) {
  return <PreviewCardPrimitive.Root data-slot="hover-card" {...props} />
}

function HoverCardTrigger({ ...props }: PreviewCardPrimitive.Trigger.Props) {
  return (
    <PreviewCardPrimitive.Trigger data-slot="hover-card-trigger" {...props} />
  )
}

function HoverCardContent({
import { buttonVariants } from "@/components/ui/button"
import {
  HoverCard,
  HoverCardContent,
  HoverCardTrigger,
} from "@/components/ui/hover-card"

export default function HoverCardSides() {
  return (
    <div className="flex flex-wrap items-center gap-3 p-24">
      {(["top", "right", "bottom", "left"] as const).map((side) => (
        <HoverCard key={side}>
          <HoverCardTrigger
            href="#"
            className={buttonVariants({ variant: "outline" })}
          >
            {side.charAt(0).toUpperCase() + side.slice(1)}
          </HoverCardTrigger>
          <HoverCardContent side={side} className="w-56">
            <p className="text-sm">
              This card opens on the {side} side of its trigger.
            </p>
          </HoverCardContent>
        </HoverCard>
      ))}
    </div>
  )
}