Wensity Labs

Hover Card

Cards 11

About

A hover card that previews a user profile or link when you hover a name, with avatar, bio and actions. Great for mentions, author bylines and team directories.

Built with React and Tailwind. Copy the prompt and paste it into Claude Code, Cursor or Lovable: your agent adds Hover Card to your project and fits it to your theme.

Code

How Hover Card is used: the demo's code. The component's own source comes with a free account.

Usage.tsx

"use client";

import * as React from "react";
import { HoverCard, HoverCardTrigger, HoverCardContent, HoverCardTitle, HoverCardDescription } from "@/components/ui/hover-card";

import { clsx, type ClassValue } from "clsx";
import { twMerge } from "tailwind-merge";

function cn(...inputs: ClassValue[]) {
  return twMerge(clsx(inputs));
}

const primitivePreviewCardSurfaceFrameClass = cn(
  "relative isolate overflow-hidden rounded-2xl",
  "border",
);

const primitivePreviewCardSurfaceLightClass = cn(
  "border-black/[0.08] bg-[#f4f4f5]",
  "[box-shadow:0_1px_2px_rgba(0,0,0,.06),0_8px_24px_-12px_rgba(0,0,0,.08)]",
);

const primitivePreviewCardSurfaceClass = cn(
  primitivePreviewCardSurfaceFrameClass,
  primitivePreviewCardSurfaceLightClass,
  // Full static `dark:bg-[#0a0a0b]` kept for Tailwind content scan - same as
  // PRIMITIVE_PREVIEW_CANVAS_DARK_BG / PRIMITIVE_PREVIEW_CANVAS_DARK.
  "dark:border-white/[0.06] dark:bg-[#0a0a0b] dark:[box-shadow:0_1px_2px_rgba(0,0,0,.4),0_8px_24px_-12px_rgba(0,0,0,.6)]",
);

const wensityCardSurfaceClass = primitivePreviewCardSurfaceClass;

const inlineHoverTriggerClass = cn(
  "inline cursor-help appearance-none bg-transparent p-0 align-baseline",
  "text-[inherit] font-semibold leading-[inherit] text-[var(--foreground)] underline decoration-[var(--border)] decoration-1 underline-offset-[4px]",
  "transition-colors hover:decoration-[color:var(--border-strong,color-mix(in_srgb,var(--foreground)_16%,transparent))] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[color:var(--primitive-ring,color-mix(in_srgb,var(--foreground)_45%,transparent))]",
);

function InlineHoverTerm({
  children,
  title,
  description,
  meta,
  defaultOpen,
}: {
  defaultOpen?: boolean;
  children: React.ReactNode;
  title: string;
  description: string;
  meta?: string[];
}) {
  return (
    <HoverCard openDelay={220} closeDelay={140} defaultOpen={defaultOpen}>
      <HoverCardTrigger asChild>
        <button type="button" className={inlineHoverTriggerClass}>
          {children}
        </button>
      </HoverCardTrigger>
      <HoverCardContent width="md" className="text-left">
        <HoverCardTitle>{title}</HoverCardTitle>
        <HoverCardDescription className="mt-1.5">
          {description}
        </HoverCardDescription>
        {meta?.length ? (
          <div className="mt-3 flex flex-wrap items-center gap-x-3 gap-y-1 text-[10px] font-medium uppercase tracking-[0.08em] text-[var(--muted-foreground)]">
            {meta.map((item, index) => (
              <React.Fragment key={item}>
                {index > 0 ? (
                  <span className="size-1 rounded-full bg-[var(--border)]" aria-hidden="true" />
                ) : null}
                <span>{item}</span>
              </React.Fragment>
            ))}
          </div>
        ) : null}
      </HoverCardContent>
    </HoverCard>
  );
}

function ParagraphPreviewFrame({ children }: { children: React.ReactNode }) {
  return (
    <div className={cn(wensityCardSurfaceClass, "w-full max-w-xl p-6 sm:p-7")}>
      <div className="space-y-4 text-[13px] leading-7 text-[var(--muted-foreground)]">
        {children}
      </div>
    </div>
  );
}

export function HoverCardPreview() {
  return (
    <div className="flex min-h-[420px] w-full items-start justify-center px-6 pt-10 pb-40">
      <ParagraphPreviewFrame>
      <p>
        The release note keeps{" "}
        <InlineHoverTerm
          defaultOpen
          title="Registry parity"
          description="Every install surface resolves the same source artifact before the component is marked ready."
          meta={["source", "release gate"]}
        >
          registry parity
        </InlineHoverTerm>{" "}
        close to the sentence it affects, so reviewers do not lose context while scanning.
      </p>
      <p>
        Priya moved ownership to the{" "}
        <InlineHoverTerm
          title="Preview owner"
          description="Responsible for keeping the live demo, usage snippet, and generated metadata aligned."
          meta={["docs", "demo"]}
        >
          preview owner
        </InlineHoverTerm>{" "}
        before the{" "}
        <InlineHoverTerm
          title="Monday rollout"
          description="A narrow launch window for publishing the source object and refreshing the public registry mirror."
          meta={["publish", "mirror"]}
        >
          Monday rollout
        </InlineHoverTerm>
        .
      </p>
      </ParagraphPreviewFrame>
    </div>
  );
}

export default function Demo() {
  return <HoverCardPreview />;
}

Dependencies

More by Wensity Labs

View all
  • Sidebar

    Sidebar

    230
  • Calendar

    Calendar

    171
  • Button

    Button

    76
  • Color Picker

    Color Picker

    62
  • Image Comparison Slider

    Image Comparison Slider

    55
  • AI Prompt Input

    AI Prompt Input

    50
  • Navigation Menu

    Navigation Menu

    36
  • Text Morphing

    Text Morphing

    35

More in Cards

View all
  • Card

    Card

    70
  • Statistics Card 2

    Statistics Card 2

    263
  • Stats cards with links

    Stats cards with links

    39
  • Course Design Cards

    Course Design Cards

    1.1K
  • The Item one

    The Item one

    3
  • Card Studio

    Card Studio

    7
  • Statistics Card 7

    Statistics Card 7

    290
  • Dashboard with Collapsible Sidebar

    Dashboard with Collapsible Sidebar

    2.4K