
Compact team list with avatars, names, roles, and social links in a bordered layout with a hiring call-to-action.
@efferd
registry/blocks/team/2/team-section.tsx
import { GithubIcon } from "@/components/icons/github-icon";
import { LinkedinIcon } from "@/components/icons/linkedin-icon";
import { XIcon } from "@/components/icons/x-icon";
import {
Avatar,
AvatarFallback,
AvatarImage,
} from "@/components/ui/avatar";
import { Button } from "@/components/ui/button";
import { FullWidthDivider } from "@/components/full-width-divider";
type Social = {
label: "X" | "GitHub" | "LinkedIn";
href: string;
};
type TeamMember = {
name: string;
role: string;
image: string;
socials: Social[];
};
const socialIcons = {
X: XIcon,
GitHub: GithubIcon,
LinkedIn: LinkedinIcon,
} as const;
const team: TeamMember[] = [
{
name: "Shaban Haider",
role: "Founder & CEO",
image: "https://github.com/shabanhr.png",
socials: [
{ label: "X", href: "#" },
{ label: "GitHub", href: "#" },
{ label: "LinkedIn", href: "#" },
],
},
{
name: "Jordan Blake",
role: "Head of Product",
image:
"https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?auto=format&fit=crop&w=800&q=80",
socials: [
{ label: "X", href: "#" },
{ label: "GitHub", href: "#" },
],
},
{
name: "Priya Nair",
role: "Design Lead",
image:
"https://images.unsplash.com/photo-1573496359142-b8d87734a5a2?auto=format&fit=crop&w=800&q=80",
socials: [
{ label: "X", href: "#" },
{ label: "LinkedIn", href: "#" },
],
},
{
name: "Alex Rivera",
role: "Engineering",
image:
"https://images.unsplash.com/photo-1500648767791-00dcc994a43e?auto=format&fit=crop&w=800&q=80",
socials: [
{ label: "X", href: "#" },
{ label: "GitHub", href: "#" },
],
},
{
name: "Sam Okonkwo",
role: "Growth",
image:
"https://images.unsplash.com/photo-1580489944761-15a19d654956?auto=format&fit=crop&w=800&q=80",
socials: [
{ label: "X", href: "#" },
{ label: "LinkedIn", href: "#" },
],
},
{
name: "Leo Park",
role: "Developer Experience",
image:
"https://images.unsplash.com/photo-1472099645785-5658abf4ff4e?auto=format&fit=crop&w=800&q=80",
socials: [
{ label: "X", href: "#" },
{ label: "GitHub", href: "#" },
],
},
];
export function TeamSection() {
return (
<section
aria-labelledby="team-heading"
className="mx-auto flex h-screen w-full max-w-5xl flex-col justify-center border-x"
>
<div className="flex flex-col gap-2 px-4 py-8 md:px-6 md:py-12">
<h2
className="font-heading text-balance font-medium text-3xl md:text-4xl"
id="team-heading"
>
Meet the team
</h2>
<p className="max-w-lg text-pretty text-muted-foreground text-sm md:text-base">
The people who design, ship, and obsess over every Efferd block.
</p>
</div>
<div className="relative">
<FullWidthDivider position="top" />
<ul className="grid grid-cols-1 gap-px bg-border sm:grid-cols-2 lg:grid-cols-3">
{team.map((member) => (
<TeamMemberCard key={member.name} member={member} />
))}
</ul>
<FullWidthDivider position="bottom" />
</div>
<div className="relative flex flex-col items-start justify-between gap-4 px-4 py-8 md:flex-row md:items-center md:px-6">
<FullWidthDivider position="bottom" />
<div className="flex flex-col gap-1">
<p className="font-medium text-foreground">Want to join us?</p>
<p className="text-pretty text-muted-foreground text-sm">
We're always looking for people who care about craft.
</p>
</div>
<Button asChild variant="outline">
<a href="#careers">View openings</a>
</Button>
</div>
</section>
);
}
function TeamMemberCard({ member }: { member: TeamMember }) {
const { name, role, image, socials } = member;
return (
<li className="flex items-center gap-3 bg-background p-4 md:p-6">
<Avatar className="size-12 rounded-sm shadow-sm *:rounded-sm after:rounded-sm">
<AvatarImage alt={`${name}'s portrait`} src={image} />
<AvatarFallback>{getInitials(name)}</AvatarFallback>
</Avatar>
<div className="flex min-w-0 flex-col gap-0.5">
<h3 className="font-heading truncate font-medium text-foreground">{name}</h3>
<p className="text-muted-foreground text-sm">{role}</p>
</div>
<div className="ms-auto flex h-full shrink-0 items-end gap-0.5">
{socials.map((social) => {
const Icon = socialIcons[social.label];
return (
<Button
asChild
className="text-muted-foreground"
key={social.label}
size="icon-xs"
variant="ghost"
>
<a aria-label={`${name} on ${social.label}`} href={social.href}>
<Icon />
</a>
</Button>
);
})}
</div>
</li>
);
}
function getInitials(name: string) {
return name
.split(" ")
.map((part) => part[0])
.join("")
.slice(0, 2)
.toUpperCase();
}























