New

AvatarStack

Overlapping avatar group with overflow count and hover expansion

Data Displayavatarstackgroupusers

Dependencies

shadcn/ui components needed:

npx shadcn@latest add cardnpx shadcn@latest add avatar

How to use this component

Copy the code below into your project. Make sure you have the required shadcn/ui dependencies installed. Then import and use the component in your pages or layouts.

Code

1"use client"
2
3import * as React from "react"
4import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"
5import { Avatar, AvatarFallback } from "@/components/ui/avatar"
6import { cn } from "@/lib/utils"
7
8interface AvatarStackProps {
9 className?: string
10 size?: "sm" | "md" | "lg"
11}
12
13interface TeamMember {
14 name: string
15 initials: string
16 color: string
17}
18
19const members: TeamMember[] = [
20 { name: "Sarah Chen", initials: "SC", color: "bg-blue-500" },
21 { name: "Alex Rivera", initials: "AR", color: "bg-violet-500" },
22 { name: "Jordan Lee", initials: "JL", color: "bg-emerald-500" },
23 { name: "Morgan Smith", initials: "MS", color: "bg-amber-500" },
24 { name: "Taylor Kim", initials: "TK", color: "bg-rose-500" },
25 { name: "Casey Brown", initials: "CB", color: "bg-cyan-500" },
26 { name: "Drew Wilson", initials: "DW", color: "bg-pink-500" },
27]
28
29const sizeClasses = {
30 sm: "w-7 h-7 text-xs",
31 md: "w-10 h-10 text-sm",
32 lg: "w-12 h-12 text-base",
33}
34
35export function AvatarStack({ className, size = "md" }: AvatarStackProps) {
36 const visibleCount = 5
37 const overflowCount = members.length - visibleCount
38
39 return (
40 <Card className={cn("w-full max-w-sm", className)}>
41 <CardHeader>
42 <CardTitle>Team Members</CardTitle>
43 </CardHeader>
44 <CardContent>
45 <div className="flex flex-col items-center gap-4">
46 <div className="group flex items-center">
47 {members.slice(0, visibleCount).map((member, i) => (
48 <Avatar
49 key={member.id || member.name}
50 className={cn(
51 "ring-2 ring-background transition-all duration-300",
52 sizeClasses[size],
53 i === 0 ? "ml-0" : "-ml-3",
54 "group-hover:ml-0 group-hover:translate-x-0"
55 )}
56 style={{ zIndex: visibleCount - i }}
57 >
58 <AvatarFallback className={cn("text-white font-medium", member.color)}>
59 {member.initials}
60 </AvatarFallback>
61 </Avatar>
62 ))}
63 {overflowCount > 0 && (
64 <div
65 className={cn(
66 "flex items-center justify-center rounded-full bg-muted ring-2 ring-background font-medium text-muted-foreground transition-all duration-300",
67 sizeClasses[size],
68 "-ml-3 group-hover:ml-0"
69 )}
70 style={{ zIndex: 0 }}
71 >
72 +{overflowCount}
73 </div>
74 )}
75 </div>
76 <div className="flex flex-wrap justify-center gap-2 text-xs text-muted-foreground">
77 {members.slice(0, 4).map((member) => (
78 <span key={member.name}>{member.name}</span>
79 ))}
80 <span>and {overflowCount + 1} more</span>
81 </div>
82 </div>
83 </CardContent>
84 </Card>
85 )
86}

Related Data Display Components

Command Palette

Search for a command to run...