rapidUI

Hover Card

Preview card shown when hovering or focusing a link.

Installation

pnpm dlx shadcn@latest add https://rdf.dev.360online.com/r/hover-card.json

Installs to @/components/ui/hover-card.

Manual installation

Install the dependencies:

pnpm add @base-ui/react@^1.8.0

Copy the source into your project:

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({
	className,
	side = 'bottom',
	sideOffset = 4,
	align = 'center',
	alignOffset = 4,
	...props
}: PreviewCardPrimitive.Popup.Props &
	Pick<PreviewCardPrimitive.Positioner.Props, 'align' | 'alignOffset' | 'side' | 'sideOffset'>) {
	return (
		<PreviewCardPrimitive.Portal data-slot="hover-card-portal">
			<PreviewCardPrimitive.Positioner
				align={align}
				alignOffset={alignOffset}
				side={side}
				sideOffset={sideOffset}
				className="isolate z-50"
			>
				<PreviewCardPrimitive.Popup
					data-slot="hover-card-content"
					className={cn(
						'z-50 w-64 origin-(--transform-origin) rounded-lg bg-popover p-2.5 text-sm text-popover-foreground shadow-md ring-1 ring-foreground/10 outline-hidden duration-100 data-[side=bottom]:slide-in-from-top-2 data-[side=inline-end]:slide-in-from-left-2 data-[side=inline-start]:slide-in-from-right-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}
				/>
			</PreviewCardPrimitive.Positioner>
		</PreviewCardPrimitive.Portal>
	)
}

export { HoverCard, HoverCardTrigger, HoverCardContent }

For sighted users to preview content available behind a link, such as a person, a case or a document. Built on Base UI PreviewCard, the card opens on hover or keyboard focus after a short delay.

Features

  • Opens on hover and focus
  • Configurable open and close delays (delay and closeDelay on HoverCardTrigger)
  • Pass the trigger element with render (e.g. render={<a href="…" />}); the trigger renders an <a> by default
  • Positioning on any side with alignment and offset
  • Rendered in a portal with enter and exit animations

Usage

import { Button } from '@/components/ui/button'
import { HoverCard, HoverCardContent, HoverCardTrigger } from '@/components/ui/hover-card'

export function OfficerPreview() {
  return (
    <HoverCard>
      <HoverCardTrigger delay={200} render={<Button variant="link" />}>@anna.lindqvist</HoverCardTrigger>
      <HoverCardContent>Case officer, Planning and Building Department.</HoverCardContent>
    </HoverCard>
  )
}

Examples

Default

An inline link to a case officer that previews their role and contact details.

Case Preview

An inline case link that previews status, registration date and number of documents.

Facility Preview

A button trigger that previews a library’s opening hours, opening above the trigger.

Sides

Cards opening on each side of the trigger.

Accessibility

  • Hover cards are ignored by screen readers; do not put essential information only in the card
  • The trigger should be a link or button so it can receive keyboard focus
  • Avoid interactive content that users must reach from the card
  • Use Popover instead when the content must be accessible on touch devices