Retour au catalogue
Team Bento
Grille bento avec tailles variees pour presenter l'equipe de maniere dynamique.
teammedium Both Responsive a11y
boldeditorialagencyportfoliomasonry
Theme
"use client";
import { motion } from "framer-motion";
interface TeamMember {
name: string;
role: string;
imageUrl: string;
bio: string;
}
interface TeamBentoProps {
title?: string;
subtitle?: string;
members?: TeamMember[];
}
const EASE = [0.16, 1, 0.3, 1] as const;
export default function TeamBento({
title = "Notre equipe",
subtitle = "Equipe",
members = [],
}: TeamBentoProps) {
const getSpanClass = (i: number): string => {
const patterns = [
"col-span-2 row-span-2",
"col-span-1 row-span-1",
"col-span-1 row-span-1",
"col-span-1 row-span-2",
"col-span-1 row-span-1",
"col-span-2 row-span-1",
];
return patterns[i % patterns.length];
};
return (
<section
style={{
paddingTop: "var(--section-padding-y)",
paddingBottom: "var(--section-padding-y)",
background: "var(--color-background)",
}}
>
<div
className="mx-auto"
style={{
maxWidth: "var(--container-max-width)",
paddingLeft: "var(--container-padding-x)",
paddingRight: "var(--container-padding-x)",
}}
>
<motion.div
initial={{ opacity: 0, y: 16 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true }}
transition={{ duration: 0.5, ease: EASE }}
className="text-center mb-14"
>
<p className="text-xs font-semibold uppercase tracking-widest mb-2" style={{ color: "var(--color-accent)" }}>
{subtitle}
</p>
<h2 className="text-2xl md:text-3xl font-bold tracking-tight" style={{ color: "var(--color-foreground)" }}>
{title}
</h2>
</motion.div>
<div className="grid grid-cols-2 md:grid-cols-3 auto-rows-[180px] gap-4">
{members.map((member, i) => (
<motion.div
key={member.name}
initial={{ opacity: 0, scale: 0.95 }}
whileInView={{ opacity: 1, scale: 1 }}
viewport={{ once: true }}
transition={{ duration: 0.45, delay: i * 0.06, ease: EASE }}
className={`${getSpanClass(i)} group relative overflow-hidden rounded-xl`}
style={{ borderRadius: "var(--radius-lg)" }}
>
<img
src={member.imageUrl}
alt={member.name}
className="w-full h-full object-cover transition-transform duration-500 group-hover:scale-105"
/>
<div
className="absolute inset-0 flex flex-col justify-end p-4"
style={{
background: "linear-gradient(to top, rgba(0,0,0,0.7) 0%, transparent 60%)",
}}
>
<h3 className="text-sm font-semibold text-white">{member.name}</h3>
<p className="text-xs text-white/70">{member.role}</p>
</div>
</motion.div>
))}
</div>
</div>
</section>
);
}