# Hover Card

An accessible React hover card for Next.js and Tailwind CSS: a preview card for a link, like a profile on an @mention, built on Radix Hover Card.

Source: https://ui.fewtone.com/components/hover-card

## Installation

```bash
npx shadcn@latest add https://ui.fewtone.com/r/hover-card.json
```

## Usage

```tsx
import {
  HoverCard,
  HoverCardContent,
  HoverCardTrigger,
} from "@/components/ui/hover-card"

export function Mention() {
  return (
    <HoverCard>
      <HoverCardTrigger href="/people/maya">@maya</HoverCardTrigger>
      <HoverCardContent>
        <p className="text-sm font-medium">Maya Chen</p>
        <p className="text-sm text-muted-foreground">Design engineer.</p>
      </HoverCardContent>
    </HoverCard>
  )
}
```

## API reference

### HoverCard

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `open` | `boolean` | – | Whether it's open, when you control it. |
| `defaultOpen` | `boolean` | `false` | Whether it starts open. |
| `onOpenChange` | `(open: boolean) => void` | – | Called when it opens or closes. |
| `openDelay` | `number` | `300` | Milliseconds the pointer rests on the link, or focus stays on it, before the card opens. |
| `closeDelay` | `number` | `300` | Milliseconds before it closes once the pointer leaves, so it can move onto the card. |
| `skipDelayDuration` | `number` | `300` | Milliseconds after a card closes during which the next one, anywhere on the page, opens at once without the delay, gliding over from the last one instead of opening from its link. |

### HoverCardTrigger

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `href` | `string` | – | Where the link goes. |
| `asChild` | `boolean` | `false` | Render the single child (for example a Next.js Link) as the trigger. |

### HoverCardContent

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `side` | `"top" \| "right" \| "bottom" \| "left"` | `"bottom"` | The side of the link it opens on. It flips when there's no room. |
| `align` | `"start" \| "center" \| "end"` | `"center"` | How it lines up with the link along that side. |
| `sideOffset` | `number` | `4` | Gap between the link and the card, in px. |

**When to use it:** Use HoverCard to preview what a link points to, such as a person behind an @mention or a page behind a link, for sighted pointer and keyboard users. Never put anything essential only in the card: use Popover for content people interact with, and Tooltip for a short hint.
**Built on:** Radix Hover Card.
**npm packages (installed by the CLI):** motion@^14.0.0, radix-ui@^1.7.0.

## Examples

### Profiles on mentions

Rest the pointer on a name, or reach it with Tab, and a card shows who it is. Move to the next name and the card glides over to it, changing size to fit. Escape closes it.

```tsx
import { HoverCard, HoverCardContent, HoverCardTrigger } from "@/components/ui/hover-card";
import { CalendarIcon } from "lucide-react";
import { Fragment } from "react";

type Person = { handle: string; name: string; initials: string; bio: string; joined: string };

const people: Person[] = [
  {
    handle: "maya",
    name: "Maya Chen",
    initials: "MC",
    bio: "Design engineer. Motion, type and interfaces that work for everyone.",
    joined: "Joined March 2024",
  },
  {
    handle: "theo",
    name: "Theo Laurent",
    initials: "TL",
    bio: "Looks after the docs and the release notes.",
    joined: "Joined June 2024",
  },
  {
    handle: "ines",
    name: "Inés Romero",
    initials: "IR",
    bio: "Front-end developer at a small studio. Writes about CSS.",
    joined: "Joined January 2025",
  },
];

function Mention({ person }: { person: Person }) {
  return (
    <HoverCard>
      <HoverCardTrigger
        href={`https://example.com/${person.handle}`}
        className="font-medium text-foreground underline decoration-border underline-offset-4 transition-colors duration-(--duration-fast) ease-out hover:decoration-current outline-ring focus-visible:outline-(length:--focus-ring-width) focus-visible:outline-offset-(--focus-ring-offset)"
      >
        @{person.handle}
      </HoverCardTrigger>
      <HoverCardContent>
        <div className="flex gap-3">
          {/* Initials stand in for a photo */}
          <span
            aria-hidden
            className="flex size-10 shrink-0 items-center justify-center rounded-full bg-muted text-sm font-medium"
          >
            {person.initials}
          </span>
          <div className="grid gap-2">
            <div>
              <p className="text-sm font-medium">{person.name}</p>
              <p className="text-sm text-muted-foreground">@{person.handle}</p>
            </div>
            <p className="text-sm">{person.bio}</p>
            <p className="flex items-center gap-1.5 text-xs text-muted-foreground">
              <CalendarIcon aria-hidden className="size-(--size-icon-sm)" />
              {person.joined}
            </p>
          </div>
        </div>
      </HoverCardContent>
    </HoverCard>
  );
}

/** Rest on a name to see who it is, then move along: the next card opens at once */
export default function HoverCardProfile() {
  return (
    <p className="max-w-sm text-center text-sm text-muted-foreground">
      Reviewed by{" "}
      {people.map((person, index) => (
        <Fragment key={person.handle}>
          {index === 0 ? null : index === people.length - 1 ? " and " : ", "}
          <Mention person={person} />
        </Fragment>
      ))}
      .
    </p>
  );
}
```

## Related

- [Popover](https://ui.fewtone.com/components/popover.md): An accessible React popover for Next.js and Tailwind CSS: forms, settings and other rich content anchored to a button, built on Radix Popover.
- [Tooltip](https://ui.fewtone.com/components/tooltip.md): An accessible React tooltip for Next.js and Tailwind CSS: a short hint on hover and keyboard focus, fast across a toolbar, built on Radix Tooltip.
