Peer Stack
PeerStack is a high-density social proof component designed for modern dashboards. It visualizes active contributors or team members with orchestrated Framer Motion animations, magnetic status indicators, and context-aware tooltips. Engineered to stay sharp on any background with a built-in ring system and sub-pixel anti-aliasing.
Live Preview

+12
Dependencies
npm install
framer-motionCode
"use client";
import React, { useState } from "react";
import { motion, AnimatePresence } from "framer-motion";
const data = [
{
name: "Mritunjay",
role: "Lead Developer",
img: "https://res.cloudinary.com/dmqwpwo6c/image/upload/v1776147234/myimg2_rfavkf.jpg",
status: "Active",
commits: 142,
color: "text-emerald-500",
},
{
name: "Sarah",
role: "UI Engineer",
img: "https://api.dicebear.com/7.x/avataaars/svg?seed=Liliana",
status: "Active",
commits: 89,
color: "text-amber-500",
},
{
name: "Alex",
role: "Core Contributor",
img: "https://api.dicebear.com/7.x/avataaars/svg?seed=Robert",
status: "Idle",
commits: 54,
color: "text-zinc-400",
},
];
export default function PeerStack({ USERS = data }) {
const [hoveredUser, setHoveredUser] = useState<string | null>(null);
return (
<div className="flex items-center gap-4">
<div className="flex -space-x-4">
{USERS.map((u) => (
<div
key={u.name}
className="relative"
onMouseEnter={() => setHoveredUser(u.name)}
onMouseLeave={() => setHoveredUser(null)}
>
{/* 1. TOOLTIP */}
<AnimatePresence>
{hoveredUser === u.name && (
<motion.div
initial={{ opacity: 0, y: 10, scale: 0.9 }}
animate={{ opacity: 1, y: -45, scale: 1 }}
exit={{ opacity: 0, y: 10, scale: 0.9 }}
className={`absolute left-1/2 -translate-x-1/2 px-2 py-1 bg-zinc-900 dark:bg-white ${u.color} text-[10px] font-mono rounded pointer-events-none whitespace-nowrap`}
>
{u.name} <span className="opacity-50">[{u.role}]</span>
<div className="absolute -bottom-1 left-1/2 -translate-x-1/2 w-2 h-2 bg-inherit rotate-45" />
</motion.div>
)}
</AnimatePresence>
{/* 2. AVATAR */}
<motion.div
key={u.name}
whileHover="hover" // This triggers the "hover" variant in all children
className="relative"
>
<motion.img
variants={{
hover: { scale: 1.1, zIndex: 50 },
}}
whileTap={{ scale: 0.9 }}
src={u.img}
className="w-14 h-14 relative rounded-full border-3 object-cover border-white dark:border-zinc-950 bg-zinc-100 dark:bg-zinc-800 cursor-default ring-1 ring-zinc-200 dark:ring-zinc-800"
alt={u.name}
/>
<motion.div
variants={{
hover: { scale: 1.4, x: -2, y: -2 }, // Scale up and adjust position slightly on hover
}}
transition={{ type: "spring", stiffness: 300, damping: 20 }}
className={`absolute w-2 h-2 ${
u.status === "Active"
? "bg-green-500"
: u.status === "Idle"
? "bg-amber-500"
: "bg-red-500"
} top-0 left-2 rounded-full ring-1 ring-zinc-200 dark:ring-zinc-800 z-50 shadow-sm`}
/>
</motion.div>
</div>
))}
{/* 3. THE "+X" INDICATOR */}
<motion.div
whileHover={{ y: -4 }}
className="w-14 h-14 z-5 rounded-full bg-zinc-100 dark:bg-zinc-900 border-[3px] border-white dark:border-[#050505] flex items-center justify-center ring-1 ring-zinc-200 dark:ring-zinc-800"
>
<span className="text-[10px] font-black text-zinc-500 dark:text-zinc-400 font-mono">
+12
</span>
</motion.div>
</div>
</div>
);
}
Props
| Prop | Type | Default | Description |
|---|---|---|---|
| USERS | UserObject[] | data | Array of user entities to be rendered in the stack. |
| name | string | - | Unique identifier and primary label for the tooltip. |
| role | string | - | Professional designation displayed within the tooltip brackets. |
| img | string | - | Source URL for the avatar image; rendered with object-cover. |
| status | 'Active' | 'Idle' | 'Offline' | Active | Controls the background color of the animated status indicator. |
| commits | number | 0 | Optional metric for displaying activity depth or contribution weight. |
| color | string | text-emerald-500 | Tailwind CSS class for the name highlight color in the tooltip. |