MC Hover Card
A card that appears on hover with additional information.
Overview
The mc-hover-card is a lightweight, hover-triggered card component in the MicroClub UI library. Built on the @base-ui/react preview-card primitive, it delivers accessible hover interactions with a flexible card layout and image/content support.
This component is designed for seamless integration into your codebase, with customizable alignment, offset, and content props.
Preview
import { McHoverCard, McHoverCardContent, McHoverCardTrigger } from '../ui/mc-hover-card';export default function McHoverCardDemo() { return ( <div> <McHoverCard> <McHoverCardTrigger> <button type="button" className="cursor-pointer rounded-full"> hover me </button> </McHoverCardTrigger> <McHoverCardContent textAlign="start" title="John Doe" subtitle="Software Engineer" description="John is a software engineer with 5 years of experience in web development. He loves working with React and TypeScript." /> </McHoverCard> </div> );}Add to Your Project
Deploy the mc-hover-card directly to your components/ui directory:
npx mcoli-ui@latest add mc-hover-card
pnpm dlx mcoli-ui@latest add mc-hover-card
yarn dlx mcoli-ui@latest add mc-hover-card
bunx mcoli-ui@latest add mc-hover-card
Manual Setup
If you prefer manual control:
Install the core dependencies
npm install @base-ui/react
pnpm add @base-ui/react
yarn add @base-ui/react
bun add @base-ui/react
Copy the source code
'use client';import { PreviewCard as PreviewCardPrimitive } from '@base-ui/react/preview-card';import { cn } from '@/lib/utils';function McHoverCard({ ...props }: PreviewCardPrimitive.Root.Props) { return <PreviewCardPrimitive.Root data-slot="hover-card" {...props} />;}function McHoverCardTrigger({ ...props }: PreviewCardPrimitive.Trigger.Props) { return <PreviewCardPrimitive.Trigger data-slot="hover-card-trigger" {...props} />;}function McHoverCardContent({ className, side = 'bottom', sideOffset = 4, align = 'center', alignOffset = 4, textAlign = 'start', imageSrc = null, imageposition = 'top', title, subtitle, description, ...props}: PreviewCardPrimitive.Popup.Props & Pick<PreviewCardPrimitive.Positioner.Props, 'align' | 'alignOffset' | 'side' | 'sideOffset'> & { textAlign?: 'start' | 'center'; imageSrc?: string | null; imageposition?: 'top' | 'bottom'; title?: string; subtitle?: string; description?: string; }) { return ( <PreviewCardPrimitive.Portal data-slot="hover-card-portal"> <PreviewCardPrimitive.Positioner align={align} alignOffset={alignOffset} side={side} sideOffset={sideOffset} className="isolate z-50 w-76 origin-(--transform-origin) rounded-lg bg-card p-4 text-sm text-popover-foreground shadow-md ring-inset ring-1 ring-border flex flex-col " > <div className={`${imageposition === 'top' ? 'flex-col' : 'flex-col-reverse'} flex gap-4`}> {imageSrc && <img src={imageSrc} alt="Profile" className={`w-full `} />} <div className={`${textAlign === 'start' ? 'items-start' : 'items-center'} flex flex-col gap-2`} > {title && <h4 className="font-semibold text-card-foreground">{title}</h4>} <div className={`${textAlign === 'start' ? 'items-start' : 'text-center'} flex flex-col`} > {subtitle && <p className=" font-regular text-card-foreground">{subtitle}</p>} {description && <p className="font-regular text-card-foreground">{description}</p>} </div> </div> </div> <PreviewCardPrimitive.Popup data-slot="hover-card-content" className={cn( ' 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 gap-4', className )} {...props} /> </PreviewCardPrimitive.Positioner> </PreviewCardPrimitive.Portal> );}export { McHoverCard, McHoverCardTrigger, McHoverCardContent };Adjust import paths
Ensure your @/lib/utils or equivalent classname helper is correctly imported.
Usage
import { McHoverCard, McHoverCardTrigger, McHoverCardContent } from '@/components/ui/mc-hover-card';
export default function Example() {
return (
<McHoverCard>
<McHoverCardTrigger>
<button type="button">Hover me</button>
</McHoverCardTrigger>
<McHoverCardContent
title="John Doe"
subtitle="Software Engineer"
description="John is a software engineer with 5 years of experience in web development. He loves working with React and TypeScript."
imageSrc="https://cdn-imgix.headout.com/media/images/c9db3cea62133b6a6bb70597326b4a34-388-dubai-img-worlds-of-adventure-tickets-01.jpg?auto=compress%2Cformat&w=1222.3999999999999&h=687.6&q=90&ar=16%3A9&crop=faces&fit=crop"
/>
</McHoverCard>
);
}Examples
Image Top
<McHoverCard>
<McHoverCardTrigger>
<button type="button">Hover me</button>
</McHoverCardTrigger>
<McHoverCardContent
textAlign="start"
imageSrc="https://cdn-imgix.headout.com/media/images/c9db3cea62133b6a6bb70597326b4a34-388-dubai-img-worlds-of-adventure-tickets-01.jpg?auto=compress%2Cformat&w=1222.3999999999999&h=687.6&q=90&ar=16%3A9&crop=faces&fit=crop"
title="John Doe"
subtitle="Software Engineer"
description="John is a software engineer with 5 years of experience in web development. He loves working with React and TypeScript."
/>
</McHoverCard>Bottom Image
<McHoverCard>
<McHoverCardTrigger>
<button type="button">Hover me</button>
</McHoverCardTrigger>
<McHoverCardContent
imageposition="bottom"
textAlign="center"
title="Profile"
subtitle="Designer"
description="A bold hover card with the image placed below the content and centered text alignment."
/>
</McHoverCard>Side Placement
<McHoverCard>
<McHoverCardTrigger>
<button type="button">Hover me</button>
</McHoverCardTrigger>
<McHoverCardContent side="right" sideOffset={8} align="start" alignOffset={8}>
<div className="space-y-2">
<h4 className="font-semibold">Details</h4>
<p className="text-sm">
Use `side`, `sideOffset`, `align`, and `alignOffset` to control the hover card position.
</p>
</div>
</McHoverCardContent>
</McHoverCard>API Reference
Props
| Prop | Type | Default | Description |
|---|---|---|---|
title | string | undefined | Main heading displayed inside the hover card |
subtitle | string | undefined | Secondary line of text below the title |
description | string | undefined | Body text shown inside the card |
imageSrc | string | null | null | Optional image URL shown above or below the content |
imageposition | "top" | "bottom" | "top" | Position of the image relative to the text content |
textAlign | "start" | "center" | "start" | Text alignment for title, subtitle, and description |
side | "top" | "right" | "bottom" | "left" | "inline-start" | "inline-end" | "bottom" | Side where the hover card appears |
sideOffset | number | 4 | Offset distance from the trigger on the specified side |
align | "start" | "center" | "end" | "center" | Alignment of the hover card relative to the trigger |
alignOffset | number | 4 | Offset distance along the alignment axis |
className | string | undefined | Additional CSS classes passed to the hover card content |
All other props from @base-ui/react/preview-card are supported.