Social Hover Cards

Social and contact actions with a shared morphing card, direction-aware transitions, and interactive content.

Installation

Pro components require registry authentication. Add your Unlumen UI Pro key as UNLUMEN_LICENSE_KEY in your .env.local file and follow the setup guide.

File Structure

social-hover-cards.tsx

Usage

import { Github, MessageCircle, SendHorizontal } from "lucide-react";

import {
  SocialHoverCards,
  type SocialHoverCardItem,
} from "@/components/unlumen-ui/social-hover-cards";

const items: SocialHoverCardItem[] = [
  {
    value: "github",
    label: "GitHub",
    href: "https://github.com/your-account",
    icon: <Github />,
    content: (
      <div className="w-72 p-4">
        <p className="font-medium">@your-account</p>
        <p className="mt-1 text-sm text-muted-foreground">
          Building useful things in public.
        </p>
      </div>
    ),
  },
  {
    value: "message",
    label: "Message",
    icon: <MessageCircle />,
    content: (
      <div className="w-80 p-4">
        <p className="font-medium">Send a quick message</p>
        <form
          className="mt-3 flex rounded-xl border p-1.5 pl-3"
          onSubmit={(event) => event.preventDefault()}
        >
          <input
            aria-label="Message"
            placeholder="Write a message..."
            className="min-w-0 flex-1 bg-transparent text-sm outline-none"
          />
          <button type="submit" aria-label="Send message">
            <SendHorizontal className="size-4" />
          </button>
        </form>
      </div>
    ),
  },
];

export default function Example() {
  return <SocialHoverCards items={items} />;
}

API Reference

SocialHoverCards

PropTypeDefaultDescription
itemsSocialHoverCardItem[]-Social links and their preview content, rendered in the order provided.
value?string-Controlled value of the open card. Pass an empty string to close it.
defaultValue?string""Card opened on the first render in uncontrolled mode.
onValueChange?(value: string) => void-Called whenever the open card changes or closes.
cardOffset?number8Gap in pixels between the icon row and preview card.
iconSize?number24Icon width and height in pixels.
showLabels?booleanfalseDisplays each item label beside its icon.
closeDelay?number120Delay in milliseconds before closing after the pointer or focus leaves.
contentBlur?number8Blur in pixels used by incoming and outgoing content.
springStiffness?number420Spring stiffness used by the card position, dimensions, and content.
springDamping?number38Spring damping used by the card position, dimensions, and content.
cardClassName?string-Additional classes applied to the shared preview card.
linkClassName?string-Additional classes applied to every social link.
className?string-Additional classes applied to the root element.

SocialHoverCardItem

PropTypeDefaultDescription
valuestring-Unique value used to identify the card.
labelstring-Accessible name for the social link and its preview.
href?string-Optional destination opened when the item is activated. Items without an href render as buttons.
iconReact.ReactNode-Icon rendered inside the social link.
contentReact.ReactNode-Any React content rendered inside the shared morphing preview card.
target?React.HTMLAttributeAnchorTarget"_blank"Anchor target. Defaults to _blank; use _self for mailto links.
rel?string"noopener noreferrer"Anchor relationship value. Defaults to noopener noreferrer.

Notes

  • Mouse hover, keyboard focus, and touch are supported. On touch devices, the first tap opens the preview and the second follows the link.
  • Give each content node an explicit width such as w-72; the shared card measures that node and animates to its dimensions.
  • Reduced-motion preferences disable the directional travel and blur while preserving the card state change.
  • Items with an href render as links; items without one render as buttons, which is useful for interactive cards such as message forms.
  • The component does not import social icons or profile data. Everything visible in a card comes from the items prop.

Credits

Built by leo.

The interaction is adapted from Colin Lienard's open-source Contacts component, published under the MIT license.

Keep in mind

Most components on this site are inspired by or recreated from existing work across the web. I'm not here to take credit; just to learn, experiment, and sometimes push things a bit further. If something looks familiar and I forgot to mention you, reach out and I'll fix that right away.