09 / 21
All 21 in 21 Tailwind CSS Tooltips
- 01Tailwind Schematic Hotspot Tooltip with Pulsing CAD Callouts
- 02Tailwind Keyboard Shortcut Tooltip with Animated 3D Keycaps
- 03Tailwind IDE Function Signature Tooltip with Typed Docs Popover
- 04Tailwind Editorial Footnote Tooltip with Torn-Paper Sidenote
- 05Tailwind Profile Hover Card Tooltip with Staggered Reveal
- 06Tailwind RPG Inventory Tooltip with Rarity-Tinted Item Cards
- 07Tailwind Glossary Word Tooltip with Dictionary Definition Card
- 08Tailwind Service Status Tooltip with 30-Day Uptime History
- 09Tailwind Team Avatar Hover Card with Presence and Quick Actions
- 10Tailwind Keyboard Shortcut Reference Tooltip with When-To-Use Card
- 11Tailwind Data Table Cell Tooltip with Segment Breakdown Bars
- 12Tailwind Content Tag Tooltip with Topic Detail and Popularity Bar
- 13Tailwind Airport Departures Board Tooltip with Flight Detail Card
- 14Tailwind Recipe Ingredient Tooltip with Nutrition and Substitutions
- 15Tailwind Constellation Star Chart Tooltip with Astronomical Data
- 16Tailwind Periodic Table Element Tooltip with Category Colour Coding
- 17Tailwind Photo Grid EXIF Tooltip with Camera Settings Card
- 18Tailwind Org Chart Node Tooltip with Reporting-Line Detail Card
- 19Tailwind Company Timeline Tooltip with Alternating Event Cards
- 20Tailwind Icon Toolbar Tooltip with Pure-CSS Arrow Pill
- 21Tailwind Form Field Help Tooltip with Side-Anchored Hint Pill
Tailwind Team Avatar Hover Card with Presence and Quick Actions
Initials avatars that lift on hover and pop a compact profile: gradient hero band, ringed portrait, role, presence, bio, three stats and two actions. The port's honest finding is that per-person gradients are data, so they stay inline as bg-linear-to-br from-[#6028a0] to-[#9060d0] while the card shell — identical four times — moves into one @apply class.
Untitled UI Pro: 5,000+ React + Tailwind CSS v4 components · from $349 one-time
Untitled UI React · Affiliate link
The code
<section class="ttp-09 w-full min-h-svh flex items-end justify-center bg-white px-7 pt-[300px] pb-10 font-ttp09-sans">
<div class="flex flex-wrap justify-center gap-3.5">
<div class="group relative">
<button type="button" aria-label="Sarah Lindqvist, CEO" aria-describedby="ttp09-p1" class="ttp09-circle bg-linear-to-br from-[#6028a0] to-[#9060d0]">SL</button>
<div id="ttp09-p1" role="tooltip" class="ttp09-card">
<div class="relative h-14 bg-linear-to-br from-[#4a1880] to-[#8050c0]"><div class="ttp09-photo bg-linear-to-br from-[#6028a0] to-[#9060d0]">SL</div></div>
<div class="px-3.5 pt-5 pb-3">
<div class="text-sm font-semibold text-ttp09-ink">Sarah Lindqvist</div>
<div class="mt-0.5 text-[10.5px] text-ttp09-muted">CEO · Executive</div>
<div class="mt-1.5 flex items-center gap-1.25 text-[10.5px] text-ttp09-muted"><span class="h-1.5 w-1.5 rounded-full bg-ttp09-online"></span>Active now</div>
<div class="mt-2 text-[11.5px] leading-[1.5] text-ttp09-body">Former Stripe PM. Building the next layer of financial infrastructure for SMBs.</div>
<div class="mt-3 grid grid-cols-3 border-t border-ttp09-rule pt-2.75 text-center">
<div><div class="text-[15px] font-bold text-ttp09-ink">214</div><div class="mt-px text-[8.5px] uppercase tracking-[0.08em] text-ttp09-muted">Team</div></div>
<div><div class="text-[15px] font-bold text-ttp09-ink">8yr</div><div class="mt-px text-[8.5px] uppercase tracking-[0.08em] text-ttp09-muted">Tenure</div></div>
<div><div class="text-[15px] font-bold text-ttp09-ink">$1.2B</div><div class="mt-px text-[8.5px] uppercase tracking-[0.08em] text-ttp09-muted">Valuation</div></div>
</div>
</div>
<div class="flex gap-1.5 border-t border-ttp09-rule px-3.5 py-2.25">
<button type="button" class="ttp09-btn">Message</button>
<button type="button" class="ttp09-btn ttp09-btn-prim">View Profile</button>
</div>
</div>
</div>
<div class="group relative">
<button type="button" aria-label="Marcus Webb, CTO" aria-describedby="ttp09-p2" class="ttp09-circle bg-linear-to-br from-[#204080] to-[#4070c0]">MW</button>
<div id="ttp09-p2" role="tooltip" class="ttp09-card">
<div class="relative h-14 bg-linear-to-br from-[#102060] to-[#3060a0]"><div class="ttp09-photo bg-linear-to-br from-[#204080] to-[#4070c0]">MW</div></div>
<div class="px-3.5 pt-5 pb-3">
<div class="text-sm font-semibold text-ttp09-ink">Marcus Webb</div>
<div class="mt-0.5 text-[10.5px] text-ttp09-muted">CTO · Engineering</div>
<div class="mt-1.5 flex items-center gap-1.25 text-[10.5px] text-ttp09-muted"><span class="h-1.5 w-1.5 rounded-full bg-ttp09-online"></span>Active now</div>
<div class="mt-2 text-[11.5px] leading-[1.5] text-ttp09-body">Ex-Google infra. Obsessed with distributed systems and making things fast at scale.</div>
<div class="mt-3 grid grid-cols-3 border-t border-ttp09-rule pt-2.75 text-center">
<div><div class="text-[15px] font-bold text-ttp09-ink">96</div><div class="mt-px text-[8.5px] uppercase tracking-[0.08em] text-ttp09-muted">Team</div></div>
<div><div class="text-[15px] font-bold text-ttp09-ink">5yr</div><div class="mt-px text-[8.5px] uppercase tracking-[0.08em] text-ttp09-muted">Tenure</div></div>
<div><div class="text-[15px] font-bold text-ttp09-ink">340</div><div class="mt-px text-[8.5px] uppercase tracking-[0.08em] text-ttp09-muted">PRs</div></div>
</div>
</div>
<div class="flex gap-1.5 border-t border-ttp09-rule px-3.5 py-2.25">
<button type="button" class="ttp09-btn">Message</button>
<button type="button" class="ttp09-btn ttp09-btn-prim">View Profile</button>
</div>
</div>
</div>
<div class="group relative">
<button type="button" aria-label="Elena Russo, CMO" aria-describedby="ttp09-p3" class="ttp09-circle bg-linear-to-br from-[#0a6050] to-[#1aa080]">ER</button>
<div id="ttp09-p3" role="tooltip" class="ttp09-card">
<div class="relative h-14 bg-linear-to-br from-[#054030] to-[#108060]"><div class="ttp09-photo bg-linear-to-br from-[#0a6050] to-[#1aa080]">ER</div></div>
<div class="px-3.5 pt-5 pb-3">
<div class="text-sm font-semibold text-ttp09-ink">Elena Russo</div>
<div class="mt-0.5 text-[10.5px] text-ttp09-muted">CMO · Marketing</div>
<div class="mt-1.5 flex items-center gap-1.25 text-[10.5px] text-ttp09-muted"><span class="h-1.5 w-1.5 rounded-full bg-ttp09-away"></span>Away · 2h ago</div>
<div class="mt-2 text-[11.5px] leading-[1.5] text-ttp09-body">Brand strategist. Grew Notion's Europe presence 3×. London-based, GMT+1.</div>
<div class="mt-3 grid grid-cols-3 border-t border-ttp09-rule pt-2.75 text-center">
<div><div class="text-[15px] font-bold text-ttp09-ink">68</div><div class="mt-px text-[8.5px] uppercase tracking-[0.08em] text-ttp09-muted">Team</div></div>
<div><div class="text-[15px] font-bold text-ttp09-ink">3yr</div><div class="mt-px text-[8.5px] uppercase tracking-[0.08em] text-ttp09-muted">Tenure</div></div>
<div><div class="text-[15px] font-bold text-ttp09-ink">+84%</div><div class="mt-px text-[8.5px] uppercase tracking-[0.08em] text-ttp09-muted">YoY</div></div>
</div>
</div>
<div class="flex gap-1.5 border-t border-ttp09-rule px-3.5 py-2.25">
<button type="button" class="ttp09-btn">Message</button>
<button type="button" class="ttp09-btn ttp09-btn-prim">View Profile</button>
</div>
</div>
</div>
<div class="group relative">
<button type="button" aria-label="Aisha Patel, Growth Lead" aria-describedby="ttp09-p4" class="ttp09-circle bg-linear-to-br from-[#802050] to-[#c04080]">AP</button>
<div id="ttp09-p4" role="tooltip" class="ttp09-card">
<div class="relative h-14 bg-linear-to-br from-[#601030] to-[#a03060]"><div class="ttp09-photo bg-linear-to-br from-[#802050] to-[#c04080]">AP</div></div>
<div class="px-3.5 pt-5 pb-3">
<div class="text-sm font-semibold text-ttp09-ink">Aisha Patel</div>
<div class="mt-0.5 text-[10.5px] text-ttp09-muted">Growth Lead · Marketing</div>
<div class="mt-1.5 flex items-center gap-1.25 text-[10.5px] text-ttp09-muted"><span class="h-1.5 w-1.5 rounded-full bg-ttp09-offline"></span>Offline</div>
<div class="mt-2 text-[11.5px] leading-[1.5] text-ttp09-body">Data-driven growth. 0 → 100k users in 18 months. Runs the acquisition engine.</div>
<div class="mt-3 grid grid-cols-3 border-t border-ttp09-rule pt-2.75 text-center">
<div><div class="text-[15px] font-bold text-ttp09-ink">6</div><div class="mt-px text-[8.5px] uppercase tracking-[0.08em] text-ttp09-muted">Team</div></div>
<div><div class="text-[15px] font-bold text-ttp09-ink">1yr</div><div class="mt-px text-[8.5px] uppercase tracking-[0.08em] text-ttp09-muted">Tenure</div></div>
<div><div class="text-[15px] font-bold text-ttp09-ink">$1.2M</div><div class="mt-px text-[8.5px] uppercase tracking-[0.08em] text-ttp09-muted">Budget</div></div>
</div>
</div>
<div class="flex gap-1.5 border-t border-ttp09-rule px-3.5 py-2.25">
<button type="button" class="ttp09-btn">Message</button>
<button type="button" class="ttp09-btn ttp09-btn-prim">View Profile</button>
</div>
</div>
</div>
</div>
</section><section class="ttp-09 w-full min-h-svh flex items-end justify-center bg-white px-7 pt-[300px] pb-10 font-ttp09-sans">
<div class="flex flex-wrap justify-center gap-3.5">
<div class="group relative">
<button type="button" aria-label="Sarah Lindqvist, CEO" aria-describedby="ttp09-p1" class="ttp09-circle bg-linear-to-br from-[#6028a0] to-[#9060d0]">SL</button>
<div id="ttp09-p1" role="tooltip" class="ttp09-card">
<div class="relative h-14 bg-linear-to-br from-[#4a1880] to-[#8050c0]"><div class="ttp09-photo bg-linear-to-br from-[#6028a0] to-[#9060d0]">SL</div></div>
<div class="px-3.5 pt-5 pb-3">
<div class="text-sm font-semibold text-ttp09-ink">Sarah Lindqvist</div>
<div class="mt-0.5 text-[10.5px] text-ttp09-muted">CEO · Executive</div>
<div class="mt-1.5 flex items-center gap-1.25 text-[10.5px] text-ttp09-muted"><span class="h-1.5 w-1.5 rounded-full bg-ttp09-online"></span>Active now</div>
<div class="mt-2 text-[11.5px] leading-[1.5] text-ttp09-body">Former Stripe PM. Building the next layer of financial infrastructure for SMBs.</div>
<div class="mt-3 grid grid-cols-3 border-t border-ttp09-rule pt-2.75 text-center">
<div><div class="text-[15px] font-bold text-ttp09-ink">214</div><div class="mt-px text-[8.5px] uppercase tracking-[0.08em] text-ttp09-muted">Team</div></div>
<div><div class="text-[15px] font-bold text-ttp09-ink">8yr</div><div class="mt-px text-[8.5px] uppercase tracking-[0.08em] text-ttp09-muted">Tenure</div></div>
<div><div class="text-[15px] font-bold text-ttp09-ink">$1.2B</div><div class="mt-px text-[8.5px] uppercase tracking-[0.08em] text-ttp09-muted">Valuation</div></div>
</div>
</div>
<div class="flex gap-1.5 border-t border-ttp09-rule px-3.5 py-2.25">
<button type="button" class="ttp09-btn">Message</button>
<button type="button" class="ttp09-btn ttp09-btn-prim">View Profile</button>
</div>
</div>
</div>
<div class="group relative">
<button type="button" aria-label="Marcus Webb, CTO" aria-describedby="ttp09-p2" class="ttp09-circle bg-linear-to-br from-[#204080] to-[#4070c0]">MW</button>
<div id="ttp09-p2" role="tooltip" class="ttp09-card">
<div class="relative h-14 bg-linear-to-br from-[#102060] to-[#3060a0]"><div class="ttp09-photo bg-linear-to-br from-[#204080] to-[#4070c0]">MW</div></div>
<div class="px-3.5 pt-5 pb-3">
<div class="text-sm font-semibold text-ttp09-ink">Marcus Webb</div>
<div class="mt-0.5 text-[10.5px] text-ttp09-muted">CTO · Engineering</div>
<div class="mt-1.5 flex items-center gap-1.25 text-[10.5px] text-ttp09-muted"><span class="h-1.5 w-1.5 rounded-full bg-ttp09-online"></span>Active now</div>
<div class="mt-2 text-[11.5px] leading-[1.5] text-ttp09-body">Ex-Google infra. Obsessed with distributed systems and making things fast at scale.</div>
<div class="mt-3 grid grid-cols-3 border-t border-ttp09-rule pt-2.75 text-center">
<div><div class="text-[15px] font-bold text-ttp09-ink">96</div><div class="mt-px text-[8.5px] uppercase tracking-[0.08em] text-ttp09-muted">Team</div></div>
<div><div class="text-[15px] font-bold text-ttp09-ink">5yr</div><div class="mt-px text-[8.5px] uppercase tracking-[0.08em] text-ttp09-muted">Tenure</div></div>
<div><div class="text-[15px] font-bold text-ttp09-ink">340</div><div class="mt-px text-[8.5px] uppercase tracking-[0.08em] text-ttp09-muted">PRs</div></div>
</div>
</div>
<div class="flex gap-1.5 border-t border-ttp09-rule px-3.5 py-2.25">
<button type="button" class="ttp09-btn">Message</button>
<button type="button" class="ttp09-btn ttp09-btn-prim">View Profile</button>
</div>
</div>
</div>
<div class="group relative">
<button type="button" aria-label="Elena Russo, CMO" aria-describedby="ttp09-p3" class="ttp09-circle bg-linear-to-br from-[#0a6050] to-[#1aa080]">ER</button>
<div id="ttp09-p3" role="tooltip" class="ttp09-card">
<div class="relative h-14 bg-linear-to-br from-[#054030] to-[#108060]"><div class="ttp09-photo bg-linear-to-br from-[#0a6050] to-[#1aa080]">ER</div></div>
<div class="px-3.5 pt-5 pb-3">
<div class="text-sm font-semibold text-ttp09-ink">Elena Russo</div>
<div class="mt-0.5 text-[10.5px] text-ttp09-muted">CMO · Marketing</div>
<div class="mt-1.5 flex items-center gap-1.25 text-[10.5px] text-ttp09-muted"><span class="h-1.5 w-1.5 rounded-full bg-ttp09-away"></span>Away · 2h ago</div>
<div class="mt-2 text-[11.5px] leading-[1.5] text-ttp09-body">Brand strategist. Grew Notion's Europe presence 3×. London-based, GMT+1.</div>
<div class="mt-3 grid grid-cols-3 border-t border-ttp09-rule pt-2.75 text-center">
<div><div class="text-[15px] font-bold text-ttp09-ink">68</div><div class="mt-px text-[8.5px] uppercase tracking-[0.08em] text-ttp09-muted">Team</div></div>
<div><div class="text-[15px] font-bold text-ttp09-ink">3yr</div><div class="mt-px text-[8.5px] uppercase tracking-[0.08em] text-ttp09-muted">Tenure</div></div>
<div><div class="text-[15px] font-bold text-ttp09-ink">+84%</div><div class="mt-px text-[8.5px] uppercase tracking-[0.08em] text-ttp09-muted">YoY</div></div>
</div>
</div>
<div class="flex gap-1.5 border-t border-ttp09-rule px-3.5 py-2.25">
<button type="button" class="ttp09-btn">Message</button>
<button type="button" class="ttp09-btn ttp09-btn-prim">View Profile</button>
</div>
</div>
</div>
<div class="group relative">
<button type="button" aria-label="Aisha Patel, Growth Lead" aria-describedby="ttp09-p4" class="ttp09-circle bg-linear-to-br from-[#802050] to-[#c04080]">AP</button>
<div id="ttp09-p4" role="tooltip" class="ttp09-card">
<div class="relative h-14 bg-linear-to-br from-[#601030] to-[#a03060]"><div class="ttp09-photo bg-linear-to-br from-[#802050] to-[#c04080]">AP</div></div>
<div class="px-3.5 pt-5 pb-3">
<div class="text-sm font-semibold text-ttp09-ink">Aisha Patel</div>
<div class="mt-0.5 text-[10.5px] text-ttp09-muted">Growth Lead · Marketing</div>
<div class="mt-1.5 flex items-center gap-1.25 text-[10.5px] text-ttp09-muted"><span class="h-1.5 w-1.5 rounded-full bg-ttp09-offline"></span>Offline</div>
<div class="mt-2 text-[11.5px] leading-[1.5] text-ttp09-body">Data-driven growth. 0 → 100k users in 18 months. Runs the acquisition engine.</div>
<div class="mt-3 grid grid-cols-3 border-t border-ttp09-rule pt-2.75 text-center">
<div><div class="text-[15px] font-bold text-ttp09-ink">6</div><div class="mt-px text-[8.5px] uppercase tracking-[0.08em] text-ttp09-muted">Team</div></div>
<div><div class="text-[15px] font-bold text-ttp09-ink">1yr</div><div class="mt-px text-[8.5px] uppercase tracking-[0.08em] text-ttp09-muted">Tenure</div></div>
<div><div class="text-[15px] font-bold text-ttp09-ink">$1.2M</div><div class="mt-px text-[8.5px] uppercase tracking-[0.08em] text-ttp09-muted">Budget</div></div>
</div>
</div>
<div class="flex gap-1.5 border-t border-ttp09-rule px-3.5 py-2.25">
<button type="button" class="ttp09-btn">Message</button>
<button type="button" class="ttp09-btn ttp09-btn-prim">View Profile</button>
</div>
</div>
</div>
</div>
</section>@import "tailwindcss";
@theme {
--color-ttp09-ink: #111111;
--color-ttp09-ink: oklch(0.18 0 0);
--color-ttp09-body: #4d4d4d;
--color-ttp09-body: oklch(0.42 0 0);
--color-ttp09-muted: #6b6b6b;
--color-ttp09-muted: oklch(0.52 0 0);
--color-ttp09-rule: #ededed;
--color-ttp09-rule: oklch(0.93 0 0);
--color-ttp09-online: #16a34a;
--color-ttp09-online: oklch(0.6 0.16 150);
--color-ttp09-away: #d97706;
--color-ttp09-away: oklch(0.65 0.15 62);
--color-ttp09-offline: #64748b;
--color-ttp09-offline: oklch(0.55 0.03 255);
--font-ttp09-sans: 'Inter', system-ui, sans-serif;
}
.ttp-09 {
width: 100%;
min-height: 100svh;
}
/* Four identical card shells, two identical action buttons, four
identical avatar circles. The per-person gradients stay inline in
the markup, because those are data, not shape. */
.ttp-09 .ttp09-circle {
@apply flex h-12 w-12 cursor-help items-center justify-center rounded-full border-0 p-0 text-[13px] font-semibold tracking-[0.03em] text-white transition-[transform,box-shadow] duration-150 group-hover:scale-110 group-hover:-translate-y-[3px] group-hover:shadow-[0_8px_20px_rgba(0,0,0,0.18)] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ttp09-ink;
}
.ttp-09 .ttp09-card {
@apply pointer-events-none invisible absolute bottom-[calc(100%+12px)] left-1/2 z-30 w-60 max-w-[calc(100vw-48px)] -translate-x-1/2 translate-y-1 overflow-hidden rounded-xl border border-black/7 bg-white text-left opacity-0 shadow-[0_12px_36px_rgba(0,0,0,0.12),0_2px_8px_rgba(0,0,0,0.06)] transition-[opacity,translate,visibility] duration-250 ease-[cubic-bezier(0.22,1,0.36,1)] group-hover:visible group-hover:translate-y-0 group-hover:opacity-100 group-hover:pointer-events-auto group-focus-within:visible group-focus-within:translate-y-0 group-focus-within:opacity-100 group-focus-within:pointer-events-auto;
}
.ttp-09 .ttp09-photo {
@apply absolute -bottom-3.5 left-3.5 flex h-12 w-12 items-center justify-center rounded-full border-3 border-white text-sm font-bold text-white shadow-[0_2px_8px_rgba(0,0,0,0.14)];
}
.ttp-09 .ttp09-btn {
@apply flex-1 cursor-pointer rounded-md border border-ttp09-rule bg-ttp09-rule/40 py-1.5 text-center text-[11px] font-medium text-ttp09-body transition-colors hover:bg-ttp09-rule focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ttp09-ink;
}
.ttp-09 .ttp09-btn-prim {
@apply border-ttp09-ink bg-ttp09-ink text-white hover:bg-black;
}@import "tailwindcss";
@theme {
--color-ttp09-ink: #111111;
--color-ttp09-ink: oklch(0.18 0 0);
--color-ttp09-body: #4d4d4d;
--color-ttp09-body: oklch(0.42 0 0);
--color-ttp09-muted: #6b6b6b;
--color-ttp09-muted: oklch(0.52 0 0);
--color-ttp09-rule: #ededed;
--color-ttp09-rule: oklch(0.93 0 0);
--color-ttp09-online: #16a34a;
--color-ttp09-online: oklch(0.6 0.16 150);
--color-ttp09-away: #d97706;
--color-ttp09-away: oklch(0.65 0.15 62);
--color-ttp09-offline: #64748b;
--color-ttp09-offline: oklch(0.55 0.03 255);
--font-ttp09-sans: 'Inter', system-ui, sans-serif;
}
.ttp-09 {
width: 100%;
min-height: 100svh;
}
/* Four identical card shells, two identical action buttons, four
identical avatar circles. The per-person gradients stay inline in
the markup, because those are data, not shape. */
.ttp-09 .ttp09-circle {
@apply flex h-12 w-12 cursor-help items-center justify-center rounded-full border-0 p-0 text-[13px] font-semibold tracking-[0.03em] text-white transition-[transform,box-shadow] duration-150 group-hover:scale-110 group-hover:-translate-y-[3px] group-hover:shadow-[0_8px_20px_rgba(0,0,0,0.18)] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ttp09-ink;
}
.ttp-09 .ttp09-card {
@apply pointer-events-none invisible absolute bottom-[calc(100%+12px)] left-1/2 z-30 w-60 max-w-[calc(100vw-48px)] -translate-x-1/2 translate-y-1 overflow-hidden rounded-xl border border-black/7 bg-white text-left opacity-0 shadow-[0_12px_36px_rgba(0,0,0,0.12),0_2px_8px_rgba(0,0,0,0.06)] transition-[opacity,translate,visibility] duration-250 ease-[cubic-bezier(0.22,1,0.36,1)] group-hover:visible group-hover:translate-y-0 group-hover:opacity-100 group-hover:pointer-events-auto group-focus-within:visible group-focus-within:translate-y-0 group-focus-within:opacity-100 group-focus-within:pointer-events-auto;
}
.ttp-09 .ttp09-photo {
@apply absolute -bottom-3.5 left-3.5 flex h-12 w-12 items-center justify-center rounded-full border-3 border-white text-sm font-bold text-white shadow-[0_2px_8px_rgba(0,0,0,0.14)];
}
.ttp-09 .ttp09-btn {
@apply flex-1 cursor-pointer rounded-md border border-ttp09-rule bg-ttp09-rule/40 py-1.5 text-center text-[11px] font-medium text-ttp09-body transition-colors hover:bg-ttp09-rule focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ttp09-ink;
}
.ttp-09 .ttp09-btn-prim {
@apply border-ttp09-ink bg-ttp09-ink text-white hover:bg-black;
}Setup — do this once per project
Skip this if your project already runs Tailwind v4.
<script src="https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4"></script>
<script src="https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4"></script>Compiles in the browser — perfect for a CodePen or a quick test, not for production.
npm install tailwindcss @tailwindcss/vite
npm install tailwindcss @tailwindcss/vite// vite.config.js ("type": "module" in package.json)
import { defineConfig } from 'vite'
import tailwindcss from '@tailwindcss/vite'
export default defineConfig({
plugins: [tailwindcss()],
})// vite.config.js ("type": "module" in package.json)
import { defineConfig } from 'vite'
import tailwindcss from '@tailwindcss/vite'
export default defineConfig({
plugins: [tailwindcss()],
})Any v4 setup works — Vite, PostCSS or the CLI. Nothing in this demo is bundler-specific.
@import "tailwindcss";
@theme {
--color-ttp09-ink: #111111;
--color-ttp09-ink: oklch(0.18 0 0);
--color-ttp09-body: #4d4d4d;
--color-ttp09-body: oklch(0.42 0 0);
--color-ttp09-muted: #6b6b6b;
--color-ttp09-muted: oklch(0.52 0 0);
--color-ttp09-rule: #ededed;
--color-ttp09-rule: oklch(0.93 0 0);
--color-ttp09-online: #16a34a;
--color-ttp09-online: oklch(0.6 0.16 150);
--color-ttp09-away: #d97706;
--color-ttp09-away: oklch(0.65 0.15 62);
--color-ttp09-offline: #64748b;
--color-ttp09-offline: oklch(0.55 0.03 255);
--font-ttp09-sans: 'Inter', system-ui, sans-serif;
}
.ttp-09 {
width: 100%;
min-height: 100svh;
}
/* Four identical card shells, two identical action buttons, four
identical avatar circles. The per-person gradients stay inline in
the markup, because those are data, not shape. */
.ttp-09 .ttp09-circle {
@apply flex h-12 w-12 cursor-help items-center justify-center rounded-full border-0 p-0 text-[13px] font-semibold tracking-[0.03em] text-white transition-[transform,box-shadow] duration-150 group-hover:scale-110 group-hover:-translate-y-[3px] group-hover:shadow-[0_8px_20px_rgba(0,0,0,0.18)] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ttp09-ink;
}
.ttp-09 .ttp09-card {
@apply pointer-events-none invisible absolute bottom-[calc(100%+12px)] left-1/2 z-30 w-60 max-w-[calc(100vw-48px)] -translate-x-1/2 translate-y-1 overflow-hidden rounded-xl border border-black/7 bg-white text-left opacity-0 shadow-[0_12px_36px_rgba(0,0,0,0.12),0_2px_8px_rgba(0,0,0,0.06)] transition-[opacity,translate,visibility] duration-250 ease-[cubic-bezier(0.22,1,0.36,1)] group-hover:visible group-hover:translate-y-0 group-hover:opacity-100 group-hover:pointer-events-auto group-focus-within:visible group-focus-within:translate-y-0 group-focus-within:opacity-100 group-focus-within:pointer-events-auto;
}
.ttp-09 .ttp09-photo {
@apply absolute -bottom-3.5 left-3.5 flex h-12 w-12 items-center justify-center rounded-full border-3 border-white text-sm font-bold text-white shadow-[0_2px_8px_rgba(0,0,0,0.14)];
}
.ttp-09 .ttp09-btn {
@apply flex-1 cursor-pointer rounded-md border border-ttp09-rule bg-ttp09-rule/40 py-1.5 text-center text-[11px] font-medium text-ttp09-body transition-colors hover:bg-ttp09-rule focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ttp09-ink;
}
.ttp-09 .ttp09-btn-prim {
@apply border-ttp09-ink bg-ttp09-ink text-white hover:bg-black;
}@import "tailwindcss";
@theme {
--color-ttp09-ink: #111111;
--color-ttp09-ink: oklch(0.18 0 0);
--color-ttp09-body: #4d4d4d;
--color-ttp09-body: oklch(0.42 0 0);
--color-ttp09-muted: #6b6b6b;
--color-ttp09-muted: oklch(0.52 0 0);
--color-ttp09-rule: #ededed;
--color-ttp09-rule: oklch(0.93 0 0);
--color-ttp09-online: #16a34a;
--color-ttp09-online: oklch(0.6 0.16 150);
--color-ttp09-away: #d97706;
--color-ttp09-away: oklch(0.65 0.15 62);
--color-ttp09-offline: #64748b;
--color-ttp09-offline: oklch(0.55 0.03 255);
--font-ttp09-sans: 'Inter', system-ui, sans-serif;
}
.ttp-09 {
width: 100%;
min-height: 100svh;
}
/* Four identical card shells, two identical action buttons, four
identical avatar circles. The per-person gradients stay inline in
the markup, because those are data, not shape. */
.ttp-09 .ttp09-circle {
@apply flex h-12 w-12 cursor-help items-center justify-center rounded-full border-0 p-0 text-[13px] font-semibold tracking-[0.03em] text-white transition-[transform,box-shadow] duration-150 group-hover:scale-110 group-hover:-translate-y-[3px] group-hover:shadow-[0_8px_20px_rgba(0,0,0,0.18)] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ttp09-ink;
}
.ttp-09 .ttp09-card {
@apply pointer-events-none invisible absolute bottom-[calc(100%+12px)] left-1/2 z-30 w-60 max-w-[calc(100vw-48px)] -translate-x-1/2 translate-y-1 overflow-hidden rounded-xl border border-black/7 bg-white text-left opacity-0 shadow-[0_12px_36px_rgba(0,0,0,0.12),0_2px_8px_rgba(0,0,0,0.06)] transition-[opacity,translate,visibility] duration-250 ease-[cubic-bezier(0.22,1,0.36,1)] group-hover:visible group-hover:translate-y-0 group-hover:opacity-100 group-hover:pointer-events-auto group-focus-within:visible group-focus-within:translate-y-0 group-focus-within:opacity-100 group-focus-within:pointer-events-auto;
}
.ttp-09 .ttp09-photo {
@apply absolute -bottom-3.5 left-3.5 flex h-12 w-12 items-center justify-center rounded-full border-3 border-white text-sm font-bold text-white shadow-[0_2px_8px_rgba(0,0,0,0.14)];
}
.ttp-09 .ttp09-btn {
@apply flex-1 cursor-pointer rounded-md border border-ttp09-rule bg-ttp09-rule/40 py-1.5 text-center text-[11px] font-medium text-ttp09-body transition-colors hover:bg-ttp09-rule focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ttp09-ink;
}
.ttp-09 .ttp09-btn-prim {
@apply border-ttp09-ink bg-ttp09-ink text-white hover:bg-black;
}<link rel="preconnect" href="https://fonts.googleapis.com"> <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap">What changed in the port
Which parts became utilities, which stayed CSS, and why.
- The rule this demo teaches: shape repeats, data does not. Four identical shells went to
@apply; sixteen per-person gradient stops stayed inline where an editor can change a person's colour without opening the stylesheet. - Because the card holds real buttons,
group-hover:pointer-events-autohas to appear alongside the reveal — the one line that separates a tooltip from a menu. - UI change from the CSS original: triggers and actions are real
<button>elements witharia-label/aria-describedbyand agroup-focus-within:reveal; the role, presence and stat-label greys (#888,#bbb) were darkened to a 0.52-lightness token, the presence green and amber darkened for AA on white, and stat labels went 8px → 8.5px.
Here's a working CSS demo from CodeFronts. Use it as-is or adapt to your framework. All classes are scoped under a unique prefix so the code won't collide with your existing styles. MIT licensed.
Demo: Tailwind Team Avatar Hover Card with Presence and Quick Actions
Source: https://codefronts.com/snippets/tailwind-css-tooltips/tailwind-team-avatar-hover-card-presence-quick-actions/
Initials avatars that lift on hover and pop a compact profile: gradient hero band, ringed portrait, role, presence, bio, three stats and two actions. The port's honest finding is that per-person gradients are data, so they stay inline as bg-linear-to-br from-[#6028a0] to-[#9060d0] while the card shell — identical four times — moves into one @apply class.
## HTML
```html
<section class="ttp-09 w-full min-h-svh flex items-end justify-center bg-white px-7 pt-[300px] pb-10 font-ttp09-sans">
<div class="flex flex-wrap justify-center gap-3.5">
<div class="group relative">
<button type="button" aria-label="Sarah Lindqvist, CEO" aria-describedby="ttp09-p1" class="ttp09-circle bg-linear-to-br from-[#6028a0] to-[#9060d0]">SL</button>
<div id="ttp09-p1" role="tooltip" class="ttp09-card">
<div class="relative h-14 bg-linear-to-br from-[#4a1880] to-[#8050c0]"><div class="ttp09-photo bg-linear-to-br from-[#6028a0] to-[#9060d0]">SL</div></div>
<div class="px-3.5 pt-5 pb-3">
<div class="text-sm font-semibold text-ttp09-ink">Sarah Lindqvist</div>
<div class="mt-0.5 text-[10.5px] text-ttp09-muted">CEO · Executive</div>
<div class="mt-1.5 flex items-center gap-1.25 text-[10.5px] text-ttp09-muted"><span class="h-1.5 w-1.5 rounded-full bg-ttp09-online"></span>Active now</div>
<div class="mt-2 text-[11.5px] leading-[1.5] text-ttp09-body">Former Stripe PM. Building the next layer of financial infrastructure for SMBs.</div>
<div class="mt-3 grid grid-cols-3 border-t border-ttp09-rule pt-2.75 text-center">
<div><div class="text-[15px] font-bold text-ttp09-ink">214</div><div class="mt-px text-[8.5px] uppercase tracking-[0.08em] text-ttp09-muted">Team</div></div>
<div><div class="text-[15px] font-bold text-ttp09-ink">8yr</div><div class="mt-px text-[8.5px] uppercase tracking-[0.08em] text-ttp09-muted">Tenure</div></div>
<div><div class="text-[15px] font-bold text-ttp09-ink">$1.2B</div><div class="mt-px text-[8.5px] uppercase tracking-[0.08em] text-ttp09-muted">Valuation</div></div>
</div>
</div>
<div class="flex gap-1.5 border-t border-ttp09-rule px-3.5 py-2.25">
<button type="button" class="ttp09-btn">Message</button>
<button type="button" class="ttp09-btn ttp09-btn-prim">View Profile</button>
</div>
</div>
</div>
<div class="group relative">
<button type="button" aria-label="Marcus Webb, CTO" aria-describedby="ttp09-p2" class="ttp09-circle bg-linear-to-br from-[#204080] to-[#4070c0]">MW</button>
<div id="ttp09-p2" role="tooltip" class="ttp09-card">
<div class="relative h-14 bg-linear-to-br from-[#102060] to-[#3060a0]"><div class="ttp09-photo bg-linear-to-br from-[#204080] to-[#4070c0]">MW</div></div>
<div class="px-3.5 pt-5 pb-3">
<div class="text-sm font-semibold text-ttp09-ink">Marcus Webb</div>
<div class="mt-0.5 text-[10.5px] text-ttp09-muted">CTO · Engineering</div>
<div class="mt-1.5 flex items-center gap-1.25 text-[10.5px] text-ttp09-muted"><span class="h-1.5 w-1.5 rounded-full bg-ttp09-online"></span>Active now</div>
<div class="mt-2 text-[11.5px] leading-[1.5] text-ttp09-body">Ex-Google infra. Obsessed with distributed systems and making things fast at scale.</div>
<div class="mt-3 grid grid-cols-3 border-t border-ttp09-rule pt-2.75 text-center">
<div><div class="text-[15px] font-bold text-ttp09-ink">96</div><div class="mt-px text-[8.5px] uppercase tracking-[0.08em] text-ttp09-muted">Team</div></div>
<div><div class="text-[15px] font-bold text-ttp09-ink">5yr</div><div class="mt-px text-[8.5px] uppercase tracking-[0.08em] text-ttp09-muted">Tenure</div></div>
<div><div class="text-[15px] font-bold text-ttp09-ink">340</div><div class="mt-px text-[8.5px] uppercase tracking-[0.08em] text-ttp09-muted">PRs</div></div>
</div>
</div>
<div class="flex gap-1.5 border-t border-ttp09-rule px-3.5 py-2.25">
<button type="button" class="ttp09-btn">Message</button>
<button type="button" class="ttp09-btn ttp09-btn-prim">View Profile</button>
</div>
</div>
</div>
<div class="group relative">
<button type="button" aria-label="Elena Russo, CMO" aria-describedby="ttp09-p3" class="ttp09-circle bg-linear-to-br from-[#0a6050] to-[#1aa080]">ER</button>
<div id="ttp09-p3" role="tooltip" class="ttp09-card">
<div class="relative h-14 bg-linear-to-br from-[#054030] to-[#108060]"><div class="ttp09-photo bg-linear-to-br from-[#0a6050] to-[#1aa080]">ER</div></div>
<div class="px-3.5 pt-5 pb-3">
<div class="text-sm font-semibold text-ttp09-ink">Elena Russo</div>
<div class="mt-0.5 text-[10.5px] text-ttp09-muted">CMO · Marketing</div>
<div class="mt-1.5 flex items-center gap-1.25 text-[10.5px] text-ttp09-muted"><span class="h-1.5 w-1.5 rounded-full bg-ttp09-away"></span>Away · 2h ago</div>
<div class="mt-2 text-[11.5px] leading-[1.5] text-ttp09-body">Brand strategist. Grew Notion's Europe presence 3×. London-based, GMT+1.</div>
<div class="mt-3 grid grid-cols-3 border-t border-ttp09-rule pt-2.75 text-center">
<div><div class="text-[15px] font-bold text-ttp09-ink">68</div><div class="mt-px text-[8.5px] uppercase tracking-[0.08em] text-ttp09-muted">Team</div></div>
<div><div class="text-[15px] font-bold text-ttp09-ink">3yr</div><div class="mt-px text-[8.5px] uppercase tracking-[0.08em] text-ttp09-muted">Tenure</div></div>
<div><div class="text-[15px] font-bold text-ttp09-ink">+84%</div><div class="mt-px text-[8.5px] uppercase tracking-[0.08em] text-ttp09-muted">YoY</div></div>
</div>
</div>
<div class="flex gap-1.5 border-t border-ttp09-rule px-3.5 py-2.25">
<button type="button" class="ttp09-btn">Message</button>
<button type="button" class="ttp09-btn ttp09-btn-prim">View Profile</button>
</div>
</div>
</div>
<div class="group relative">
<button type="button" aria-label="Aisha Patel, Growth Lead" aria-describedby="ttp09-p4" class="ttp09-circle bg-linear-to-br from-[#802050] to-[#c04080]">AP</button>
<div id="ttp09-p4" role="tooltip" class="ttp09-card">
<div class="relative h-14 bg-linear-to-br from-[#601030] to-[#a03060]"><div class="ttp09-photo bg-linear-to-br from-[#802050] to-[#c04080]">AP</div></div>
<div class="px-3.5 pt-5 pb-3">
<div class="text-sm font-semibold text-ttp09-ink">Aisha Patel</div>
<div class="mt-0.5 text-[10.5px] text-ttp09-muted">Growth Lead · Marketing</div>
<div class="mt-1.5 flex items-center gap-1.25 text-[10.5px] text-ttp09-muted"><span class="h-1.5 w-1.5 rounded-full bg-ttp09-offline"></span>Offline</div>
<div class="mt-2 text-[11.5px] leading-[1.5] text-ttp09-body">Data-driven growth. 0 → 100k users in 18 months. Runs the acquisition engine.</div>
<div class="mt-3 grid grid-cols-3 border-t border-ttp09-rule pt-2.75 text-center">
<div><div class="text-[15px] font-bold text-ttp09-ink">6</div><div class="mt-px text-[8.5px] uppercase tracking-[0.08em] text-ttp09-muted">Team</div></div>
<div><div class="text-[15px] font-bold text-ttp09-ink">1yr</div><div class="mt-px text-[8.5px] uppercase tracking-[0.08em] text-ttp09-muted">Tenure</div></div>
<div><div class="text-[15px] font-bold text-ttp09-ink">$1.2M</div><div class="mt-px text-[8.5px] uppercase tracking-[0.08em] text-ttp09-muted">Budget</div></div>
</div>
</div>
<div class="flex gap-1.5 border-t border-ttp09-rule px-3.5 py-2.25">
<button type="button" class="ttp09-btn">Message</button>
<button type="button" class="ttp09-btn ttp09-btn-prim">View Profile</button>
</div>
</div>
</div>
</div>
</section>
```
## CSS
```css
@import "tailwindcss";
@theme {
--color-ttp09-ink: #111111;
--color-ttp09-ink: oklch(0.18 0 0);
--color-ttp09-body: #4d4d4d;
--color-ttp09-body: oklch(0.42 0 0);
--color-ttp09-muted: #6b6b6b;
--color-ttp09-muted: oklch(0.52 0 0);
--color-ttp09-rule: #ededed;
--color-ttp09-rule: oklch(0.93 0 0);
--color-ttp09-online: #16a34a;
--color-ttp09-online: oklch(0.6 0.16 150);
--color-ttp09-away: #d97706;
--color-ttp09-away: oklch(0.65 0.15 62);
--color-ttp09-offline: #64748b;
--color-ttp09-offline: oklch(0.55 0.03 255);
--font-ttp09-sans: 'Inter', system-ui, sans-serif;
}
.ttp-09 {
width: 100%;
min-height: 100svh;
}
/* Four identical card shells, two identical action buttons, four
identical avatar circles. The per-person gradients stay inline in
the markup, because those are data, not shape. */
.ttp-09 .ttp09-circle {
@apply flex h-12 w-12 cursor-help items-center justify-center rounded-full border-0 p-0 text-[13px] font-semibold tracking-[0.03em] text-white transition-[transform,box-shadow] duration-150 group-hover:scale-110 group-hover:-translate-y-[3px] group-hover:shadow-[0_8px_20px_rgba(0,0,0,0.18)] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ttp09-ink;
}
.ttp-09 .ttp09-card {
@apply pointer-events-none invisible absolute bottom-[calc(100%+12px)] left-1/2 z-30 w-60 max-w-[calc(100vw-48px)] -translate-x-1/2 translate-y-1 overflow-hidden rounded-xl border border-black/7 bg-white text-left opacity-0 shadow-[0_12px_36px_rgba(0,0,0,0.12),0_2px_8px_rgba(0,0,0,0.06)] transition-[opacity,translate,visibility] duration-250 ease-[cubic-bezier(0.22,1,0.36,1)] group-hover:visible group-hover:translate-y-0 group-hover:opacity-100 group-hover:pointer-events-auto group-focus-within:visible group-focus-within:translate-y-0 group-focus-within:opacity-100 group-focus-within:pointer-events-auto;
}
.ttp-09 .ttp09-photo {
@apply absolute -bottom-3.5 left-3.5 flex h-12 w-12 items-center justify-center rounded-full border-3 border-white text-sm font-bold text-white shadow-[0_2px_8px_rgba(0,0,0,0.14)];
}
.ttp-09 .ttp09-btn {
@apply flex-1 cursor-pointer rounded-md border border-ttp09-rule bg-ttp09-rule/40 py-1.5 text-center text-[11px] font-medium text-ttp09-body transition-colors hover:bg-ttp09-rule focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ttp09-ink;
}
.ttp-09 .ttp09-btn-prim {
@apply border-ttp09-ink bg-ttp09-ink text-white hover:bg-black;
}
```Here's a working CSS demo from CodeFronts. Use it as-is or adapt to your framework. All classes are scoped under a unique prefix so the code won't collide with your existing styles. MIT licensed.
Demo: Tailwind Team Avatar Hover Card with Presence and Quick Actions
Source: https://codefronts.com/snippets/tailwind-css-tooltips/tailwind-team-avatar-hover-card-presence-quick-actions/
Initials avatars that lift on hover and pop a compact profile: gradient hero band, ringed portrait, role, presence, bio, three stats and two actions. The port's honest finding is that per-person gradients are data, so they stay inline as bg-linear-to-br from-[#6028a0] to-[#9060d0] while the card shell — identical four times — moves into one @apply class.
## HTML
```html
<section class="ttp-09 w-full min-h-svh flex items-end justify-center bg-white px-7 pt-[300px] pb-10 font-ttp09-sans">
<div class="flex flex-wrap justify-center gap-3.5">
<div class="group relative">
<button type="button" aria-label="Sarah Lindqvist, CEO" aria-describedby="ttp09-p1" class="ttp09-circle bg-linear-to-br from-[#6028a0] to-[#9060d0]">SL</button>
<div id="ttp09-p1" role="tooltip" class="ttp09-card">
<div class="relative h-14 bg-linear-to-br from-[#4a1880] to-[#8050c0]"><div class="ttp09-photo bg-linear-to-br from-[#6028a0] to-[#9060d0]">SL</div></div>
<div class="px-3.5 pt-5 pb-3">
<div class="text-sm font-semibold text-ttp09-ink">Sarah Lindqvist</div>
<div class="mt-0.5 text-[10.5px] text-ttp09-muted">CEO · Executive</div>
<div class="mt-1.5 flex items-center gap-1.25 text-[10.5px] text-ttp09-muted"><span class="h-1.5 w-1.5 rounded-full bg-ttp09-online"></span>Active now</div>
<div class="mt-2 text-[11.5px] leading-[1.5] text-ttp09-body">Former Stripe PM. Building the next layer of financial infrastructure for SMBs.</div>
<div class="mt-3 grid grid-cols-3 border-t border-ttp09-rule pt-2.75 text-center">
<div><div class="text-[15px] font-bold text-ttp09-ink">214</div><div class="mt-px text-[8.5px] uppercase tracking-[0.08em] text-ttp09-muted">Team</div></div>
<div><div class="text-[15px] font-bold text-ttp09-ink">8yr</div><div class="mt-px text-[8.5px] uppercase tracking-[0.08em] text-ttp09-muted">Tenure</div></div>
<div><div class="text-[15px] font-bold text-ttp09-ink">$1.2B</div><div class="mt-px text-[8.5px] uppercase tracking-[0.08em] text-ttp09-muted">Valuation</div></div>
</div>
</div>
<div class="flex gap-1.5 border-t border-ttp09-rule px-3.5 py-2.25">
<button type="button" class="ttp09-btn">Message</button>
<button type="button" class="ttp09-btn ttp09-btn-prim">View Profile</button>
</div>
</div>
</div>
<div class="group relative">
<button type="button" aria-label="Marcus Webb, CTO" aria-describedby="ttp09-p2" class="ttp09-circle bg-linear-to-br from-[#204080] to-[#4070c0]">MW</button>
<div id="ttp09-p2" role="tooltip" class="ttp09-card">
<div class="relative h-14 bg-linear-to-br from-[#102060] to-[#3060a0]"><div class="ttp09-photo bg-linear-to-br from-[#204080] to-[#4070c0]">MW</div></div>
<div class="px-3.5 pt-5 pb-3">
<div class="text-sm font-semibold text-ttp09-ink">Marcus Webb</div>
<div class="mt-0.5 text-[10.5px] text-ttp09-muted">CTO · Engineering</div>
<div class="mt-1.5 flex items-center gap-1.25 text-[10.5px] text-ttp09-muted"><span class="h-1.5 w-1.5 rounded-full bg-ttp09-online"></span>Active now</div>
<div class="mt-2 text-[11.5px] leading-[1.5] text-ttp09-body">Ex-Google infra. Obsessed with distributed systems and making things fast at scale.</div>
<div class="mt-3 grid grid-cols-3 border-t border-ttp09-rule pt-2.75 text-center">
<div><div class="text-[15px] font-bold text-ttp09-ink">96</div><div class="mt-px text-[8.5px] uppercase tracking-[0.08em] text-ttp09-muted">Team</div></div>
<div><div class="text-[15px] font-bold text-ttp09-ink">5yr</div><div class="mt-px text-[8.5px] uppercase tracking-[0.08em] text-ttp09-muted">Tenure</div></div>
<div><div class="text-[15px] font-bold text-ttp09-ink">340</div><div class="mt-px text-[8.5px] uppercase tracking-[0.08em] text-ttp09-muted">PRs</div></div>
</div>
</div>
<div class="flex gap-1.5 border-t border-ttp09-rule px-3.5 py-2.25">
<button type="button" class="ttp09-btn">Message</button>
<button type="button" class="ttp09-btn ttp09-btn-prim">View Profile</button>
</div>
</div>
</div>
<div class="group relative">
<button type="button" aria-label="Elena Russo, CMO" aria-describedby="ttp09-p3" class="ttp09-circle bg-linear-to-br from-[#0a6050] to-[#1aa080]">ER</button>
<div id="ttp09-p3" role="tooltip" class="ttp09-card">
<div class="relative h-14 bg-linear-to-br from-[#054030] to-[#108060]"><div class="ttp09-photo bg-linear-to-br from-[#0a6050] to-[#1aa080]">ER</div></div>
<div class="px-3.5 pt-5 pb-3">
<div class="text-sm font-semibold text-ttp09-ink">Elena Russo</div>
<div class="mt-0.5 text-[10.5px] text-ttp09-muted">CMO · Marketing</div>
<div class="mt-1.5 flex items-center gap-1.25 text-[10.5px] text-ttp09-muted"><span class="h-1.5 w-1.5 rounded-full bg-ttp09-away"></span>Away · 2h ago</div>
<div class="mt-2 text-[11.5px] leading-[1.5] text-ttp09-body">Brand strategist. Grew Notion's Europe presence 3×. London-based, GMT+1.</div>
<div class="mt-3 grid grid-cols-3 border-t border-ttp09-rule pt-2.75 text-center">
<div><div class="text-[15px] font-bold text-ttp09-ink">68</div><div class="mt-px text-[8.5px] uppercase tracking-[0.08em] text-ttp09-muted">Team</div></div>
<div><div class="text-[15px] font-bold text-ttp09-ink">3yr</div><div class="mt-px text-[8.5px] uppercase tracking-[0.08em] text-ttp09-muted">Tenure</div></div>
<div><div class="text-[15px] font-bold text-ttp09-ink">+84%</div><div class="mt-px text-[8.5px] uppercase tracking-[0.08em] text-ttp09-muted">YoY</div></div>
</div>
</div>
<div class="flex gap-1.5 border-t border-ttp09-rule px-3.5 py-2.25">
<button type="button" class="ttp09-btn">Message</button>
<button type="button" class="ttp09-btn ttp09-btn-prim">View Profile</button>
</div>
</div>
</div>
<div class="group relative">
<button type="button" aria-label="Aisha Patel, Growth Lead" aria-describedby="ttp09-p4" class="ttp09-circle bg-linear-to-br from-[#802050] to-[#c04080]">AP</button>
<div id="ttp09-p4" role="tooltip" class="ttp09-card">
<div class="relative h-14 bg-linear-to-br from-[#601030] to-[#a03060]"><div class="ttp09-photo bg-linear-to-br from-[#802050] to-[#c04080]">AP</div></div>
<div class="px-3.5 pt-5 pb-3">
<div class="text-sm font-semibold text-ttp09-ink">Aisha Patel</div>
<div class="mt-0.5 text-[10.5px] text-ttp09-muted">Growth Lead · Marketing</div>
<div class="mt-1.5 flex items-center gap-1.25 text-[10.5px] text-ttp09-muted"><span class="h-1.5 w-1.5 rounded-full bg-ttp09-offline"></span>Offline</div>
<div class="mt-2 text-[11.5px] leading-[1.5] text-ttp09-body">Data-driven growth. 0 → 100k users in 18 months. Runs the acquisition engine.</div>
<div class="mt-3 grid grid-cols-3 border-t border-ttp09-rule pt-2.75 text-center">
<div><div class="text-[15px] font-bold text-ttp09-ink">6</div><div class="mt-px text-[8.5px] uppercase tracking-[0.08em] text-ttp09-muted">Team</div></div>
<div><div class="text-[15px] font-bold text-ttp09-ink">1yr</div><div class="mt-px text-[8.5px] uppercase tracking-[0.08em] text-ttp09-muted">Tenure</div></div>
<div><div class="text-[15px] font-bold text-ttp09-ink">$1.2M</div><div class="mt-px text-[8.5px] uppercase tracking-[0.08em] text-ttp09-muted">Budget</div></div>
</div>
</div>
<div class="flex gap-1.5 border-t border-ttp09-rule px-3.5 py-2.25">
<button type="button" class="ttp09-btn">Message</button>
<button type="button" class="ttp09-btn ttp09-btn-prim">View Profile</button>
</div>
</div>
</div>
</div>
</section>
```
## CSS
```css
@import "tailwindcss";
@theme {
--color-ttp09-ink: #111111;
--color-ttp09-ink: oklch(0.18 0 0);
--color-ttp09-body: #4d4d4d;
--color-ttp09-body: oklch(0.42 0 0);
--color-ttp09-muted: #6b6b6b;
--color-ttp09-muted: oklch(0.52 0 0);
--color-ttp09-rule: #ededed;
--color-ttp09-rule: oklch(0.93 0 0);
--color-ttp09-online: #16a34a;
--color-ttp09-online: oklch(0.6 0.16 150);
--color-ttp09-away: #d97706;
--color-ttp09-away: oklch(0.65 0.15 62);
--color-ttp09-offline: #64748b;
--color-ttp09-offline: oklch(0.55 0.03 255);
--font-ttp09-sans: 'Inter', system-ui, sans-serif;
}
.ttp-09 {
width: 100%;
min-height: 100svh;
}
/* Four identical card shells, two identical action buttons, four
identical avatar circles. The per-person gradients stay inline in
the markup, because those are data, not shape. */
.ttp-09 .ttp09-circle {
@apply flex h-12 w-12 cursor-help items-center justify-center rounded-full border-0 p-0 text-[13px] font-semibold tracking-[0.03em] text-white transition-[transform,box-shadow] duration-150 group-hover:scale-110 group-hover:-translate-y-[3px] group-hover:shadow-[0_8px_20px_rgba(0,0,0,0.18)] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ttp09-ink;
}
.ttp-09 .ttp09-card {
@apply pointer-events-none invisible absolute bottom-[calc(100%+12px)] left-1/2 z-30 w-60 max-w-[calc(100vw-48px)] -translate-x-1/2 translate-y-1 overflow-hidden rounded-xl border border-black/7 bg-white text-left opacity-0 shadow-[0_12px_36px_rgba(0,0,0,0.12),0_2px_8px_rgba(0,0,0,0.06)] transition-[opacity,translate,visibility] duration-250 ease-[cubic-bezier(0.22,1,0.36,1)] group-hover:visible group-hover:translate-y-0 group-hover:opacity-100 group-hover:pointer-events-auto group-focus-within:visible group-focus-within:translate-y-0 group-focus-within:opacity-100 group-focus-within:pointer-events-auto;
}
.ttp-09 .ttp09-photo {
@apply absolute -bottom-3.5 left-3.5 flex h-12 w-12 items-center justify-center rounded-full border-3 border-white text-sm font-bold text-white shadow-[0_2px_8px_rgba(0,0,0,0.14)];
}
.ttp-09 .ttp09-btn {
@apply flex-1 cursor-pointer rounded-md border border-ttp09-rule bg-ttp09-rule/40 py-1.5 text-center text-[11px] font-medium text-ttp09-body transition-colors hover:bg-ttp09-rule focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ttp09-ink;
}
.ttp-09 .ttp09-btn-prim {
@apply border-ttp09-ink bg-ttp09-ink text-white hover:bg-black;
}
```How this works
Actions changed the accessibility maths. A read-only tooltip can be pointer-events-none; this card has Message and View Profile buttons, so it must be reachable. The card therefore turns pointer events back ON when shown and answers group-focus-within:, which is what SC 1.4.13 means by hoverable and persistent.
The shell is one class, the people are markup. Four identical 240px cards with the same radius, border, shadow and transition — that repetition is noise, so it lives in .ttp09-card. Names, gradients, bios and stats stay where a content editor can find them.
Presence is a dot plus a word — "Active now", "Away · 2h ago", "Offline" — never colour alone.
Make it yours
- Person colour: the two gradient stops on the circle and hero. Everything else is neutral by design.
- Lift:
group-hover:scale-110plus 3px. Halve it for an enterprise directory. - Actions: the footer is a flex row — add a third button and the widths resolve themselves.
Gotchas — read before shipping
- A card containing buttons must not keep
pointer-events-noneonce shown, or the actions are unreachable by mouse. - Avatar initials need a real accessible name: the trigger carries
aria-label, since two letters are not a name. - 240px cards centred on a 48px avatar overflow at the row edges; the port clamps with
max-w-[calc(100vw-48px)].
Browser support
| Chrome | Safari | Firefox | Edge |
|---|---|---|---|
| 111+ | 16.4+ | 128+ | 111+ |
gradients, grid and :focus-within are Baseline; the floor quoted is Tailwind v4's own generated sheet.