Skip to content

Hover Card

A floating preview that opens on hover — profile peeks, link previews, glossary terms — with the neobrutalist borders-and-shadows treatment.

import {
  Avatar,
  AvatarFallback,

The hover card floats a panel of rich preview content over the page when the pointer rests on a trigger — no click required. Built on the Base UI Preview Card primitive and styled to the neobrutalist recipe: thick borders, hard shadows, and bold type.

Reach for it when:

  • Profile peeks — hover a @mention or avatar to show the bio, stats, and a follow button.
  • Link previews — surface a page's title and summary before the reader commits to the click.
  • Glossary terms — define jargon inline in docs without navigating away.

Installation

pnpm dlx shadcn@latest add https://neobrutalism.com/r/base/hover-card.json
npx shadcn@latest add https://neobrutalism.com/r/base/hover-card.json
yarn dlx shadcn@latest add https://neobrutalism.com/r/base/hover-card.json
bunx --bun shadcn@latest add https://neobrutalism.com/r/base/hover-card.json

Install the following dependencies:

pnpm add @base-ui/react
npm install @base-ui/react
yarn add @base-ui/react
bun add @base-ui/react

Copy and paste the following code into your project.

components/ui/hover-card.tsx
"use client"

import * as React from "react"
import { HoverCard as HoverCardPrimitive } from "radix-ui"

import { cn } from "@/lib/utils"

function HoverCard({
  ...props
}: React.ComponentProps<typeof HoverCardPrimitive.Root>) {
  return <HoverCardPrimitive.Root data-slot="hover-card" {...props} />
}

function HoverCardTrigger({
  ...props
}: React.ComponentProps<typeof HoverCardPrimitive.Trigger>) {
  return (
    <HoverCardPrimitive.Trigger data-slot="hover-card-trigger" {...props} />
  )
}

function HoverCardContent({
  className,
  align = "center",
  sideOffset = 4,
  ...props
}: React.ComponentProps<typeof HoverCardPrimitive.Content>) {
  return (
    <HoverCardPrimitive.Portal data-slot="hover-card-portal">
      <HoverCardPrimitive.Content
        data-slot="hover-card-content"
        align={align}
        sideOffset={sideOffset}
        className={cn(
          "z-50 w-64 origin-(--radix-hover-card-content-transform-origin) rounded border-2 bg-popover p-2.5 text-sm text-popover-foreground shadow-md outline-hidden duration-100 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95",
          className
        )}
        {...props}
      />
    </HoverCardPrimitive.Portal>
  )
}

export { HoverCard, HoverCardTrigger, HoverCardContent }

Update the import paths to match your project setup.

Usage

import {
  HoverCard,
  HoverCardContent,
  HoverCardTrigger,
} from "@/components/ui/hover-card"
<HoverCard>
  <HoverCardTrigger>Hover</HoverCardTrigger>
  <HoverCardContent>
    The React Framework – created and maintained by @vercel.
  </HoverCardContent>
</HoverCard>

Composition

Use the following composition to build a HoverCard:

HoverCard
├── HoverCardTrigger
└── HoverCardContent

Trigger Delays

Use delay and closeDelay on the trigger to control when the card opens and closes.

<HoverCard>
  <HoverCardTrigger delay={100} closeDelay={200}>
    Hover
  </HoverCardTrigger>
  <HoverCardContent>Content</HoverCardContent>
</HoverCard>

Positioning

Use the side and align props on HoverCardContent to control placement.

<HoverCard>
  <HoverCardTrigger>Hover</HoverCardTrigger>
  <HoverCardContent side="top" align="start">
    Content
  </HoverCardContent>
</HoverCard>

Examples

Basic

import {
  Avatar,
  AvatarFallback,

Sides

import { Button } from "@/components/ui/button"
import {
  HoverCard,

RTL

To enable RTL support in Neobrutalism.com, see the RTL configuration guide.

"use client"

import {

Accessibility

Hover cards have no dedicated WAI-ARIA pattern — the closest analogue is the Tooltip pattern. The Base UI primitive opens the card on keyboard focus of the trigger and dismisses it with Escape. Still, treat the content as supplemental for sighted users and keep the trigger a real link so the full content stays reachable at its destination.

Keyboard interactions:

KeyAction
Tab / Shift + TabMove focus to the trigger — focusing opens the card, leaving closes it
EscapeClose the card
EnterFollow the trigger link

API Reference

See the Base UI documentation for more information.