Team Grid

Team cards with social links that slide up on hover.

AC

Ava Chen

CEO & Co-founder

LP

Liam Patel

CTO & Co-founder

NK

Noah Kim

Head of Design

MR

Mia Rossi

Lead Engineer

Installation

  1. Install the dependencies

    $ npm i motion lucide-react
  2. Copy the source into components/ui/team-grid.tsx

    components/ui/team-grid.tsx
    "use client";
    
    import { motion } from "motion/react";
    import { Github, Linkedin, Twitter } from "lucide-react";
    
    type Member = { name: string; role: string; color: string };
    
    const defaultTeam: Member[] = [
      { name: "Ava Chen", role: "CEO & Co-founder", color: "from-blue-400 to-indigo-600" },
      { name: "Liam Patel", role: "CTO & Co-founder", color: "from-violet-400 to-fuchsia-600" },
      { name: "Noah Kim", role: "Head of Design", color: "from-emerald-400 to-teal-600" },
      { name: "Mia Rossi", role: "Lead Engineer", color: "from-amber-400 to-orange-600" },
    ];
    
    export function TeamGrid({ team = defaultTeam }: { team?: Member[] }) {
      return (
        <div className="grid gap-5 sm:grid-cols-2 lg:grid-cols-4">
          {team.map((m, i) => (
            <motion.div
              key={m.name}
              initial={{ opacity: 0, y: 20 }}
              whileInView={{ opacity: 1, y: 0 }}
              viewport={{ once: true }}
              transition={{ delay: i * 0.08, duration: 0.5 }}
              className="group text-center"
            >
              <div className={`relative mx-auto aspect-square overflow-hidden rounded-3xl bg-gradient-to-br ${m.color}`}>
                <span className="absolute inset-0 grid place-items-center text-5xl font-semibold text-white/90 transition-transform duration-500 group-hover:scale-110">
                  {m.name.split(" ").map((n) => n[0]).join("")}
                </span>
                <div className="absolute inset-x-0 bottom-0 flex translate-y-full justify-center gap-2 bg-gradient-to-t from-black/40 to-transparent p-4 transition-transform duration-300 group-hover:translate-y-0">
                  {[Twitter, Linkedin, Github].map((Icon, k) => (
                    <a key={k} href="#" aria-label={`${m.name} profile`} className="grid size-9 place-items-center rounded-full bg-white/90 text-zinc-800 transition hover:bg-white">
                      <Icon className="size-4" />
                    </a>
                  ))}
                </div>
              </div>
              <p className="mt-4 font-semibold text-zinc-900">{m.name}</p>
              <p className="text-sm text-zinc-500">{m.role}</p>
            </motion.div>
          ))}
        </div>
      );
    }
    
    export default function Demo() {
      return (
        <div className="w-full max-w-4xl">
          <TeamGrid />
        </div>
      );
    }
    
  3. Use it

    The file exports the component and a Demo showing typical usage. Import whichever you need.