# Team Section 4

> Solace UI team section block variation 4.

A shadcn/ui block from the [@solaceui](https://www.solaceui.com) registry, listed on [shadcn.exchange](https://shadcn.exchange/r/solaceui/team-section-4).

- Page, with a live preview: https://shadcn.exchange/r/solaceui/team-section-4
- Screenshot: https://abzjhwgwpdpz7ua5.public.blob.vercel-storage.com/shots/solaceui/team-section-4-light-49feeb6b3d13a4d4.png
- Registry item: https://www.solaceui.com/r/team-section-4.json
- Listed: 2026-10-13, source last changed 2026-10-13

## Install

```bash
npx shadcn@latest add https://www.solaceui.com/r/team-section-4.json
```

Run it in a project that has shadcn/ui set up. It adds the files below and installs what they depend on.

## Dependencies

- npm packages: `lucide-react`, `motion`

## Files

### `src/registry/blocks/team-section/four/index.tsx`

```tsx
"use client";

import { useState } from "react";
import { motion, AnimatePresence } from "motion/react";
import Image from "next/image";
import { ArrowLeft, ArrowRight } from "lucide-react";
import { cn } from "@/lib/utils";

interface TeamMember {
  id: string;
  name: string;
  role: string;
  image: string;
}

const teamMembers: TeamMember[] = [
  {
    id: "1",
    name: "James Mitchell",
    role: "Product Manager",
    image: "https://assets.solaceui.com/solaceui-member-four.png",
  },
  {
    id: "2",
    name: "Sarah Jenkins",
    role: "Lead Designer",
    image: "https://assets.solaceui.com/solaceui-member-five.png",
  },
  {
    id: "3",
    name: "David Kim",
    role: "Founder and CEO",
    image: "https://assets.solaceui.com/solaceui-member-one.png",
  },
  {
    id: "4",
    name: "Alex Rivera",
    role: "Software Engineer",
    image: "https://assets.solaceui.com/solaceui-member-two.png",
  },
  {
    id: "5",
    name: "Dr. Helen Cho",
    role: "Research Director",
    image: "https://assets.solaceui.com/solaceui-member-three.png",
  },
];

export default function Team4() {
  const [activeIndex, setActiveIndex] = useState<number>(2);

  const handlePrev = () => {
    setActiveIndex((prev) => (prev - 1 + teamMembers.length) % teamMembers.length);
  };

  const handleNext = () => {
    setActiveIndex((prev) => (prev + 1) % teamMembers.length);
  };

  return (
    <section className="relative w-full py-24 bg-background overflow-hidden flex flex-col items-center justify-center">
      <div className="w-full max-w-6xl px-4 md:px-8">

        {/* Main Images & Floating text container */}
        <div className="relative w-full h-[400px] md:h-[550px] lg:h-[600px] mt-12">

          {/* Top Fade Overlay */}
          <div className="absolute top-0 left-0 right-0 h-28 bg-gradient-to-b from-background via-background/60 to-transparent pointer-events-none z-10" />

          {/* Bottom Fade Overlay */}
          <div className="absolute bottom-0 left-0 right-0 h-28 bg-gradient-to-t from-background via-background/60 to-transparent pointer-events-none z-10" />

          {/* Cards Flex Row */}
          <div className="flex w-full h-full gap-2 sm:gap-4 md:gap-1 items-stretch overflow-visible">
            {teamMembers.map((member, index) => {
              const isActive = index === activeIndex;

              return (
                <div
                  key={member.id}
                  onClick={() => setActiveIndex(index)}
                  className={cn(
                    "relative cursor-pointer transition-all duration-700 ease-out flex-1",
                    isActive ? "flex-[2] md:flex-[2.5]" : "flex-[0.8] md:flex-[1]"
                  )}
                >
                  {/* Floating active member text positioned above upper fade */}
                  <AnimatePresence mode="wait">
                    {isActive && (
                      <motion.div
                        layoutId="activeTeamText"
                        initial={{ opacity: 0, y: 10 }}
                        animate={{ opacity: 1, y: 0 }}
                        exit={{ opacity: 0, y: -10 }}
                        transition={{ duration: 0.5, ease: "easeOut" }}
                        className={cn(
                          "absolute bottom-[calc(100%+16px)] z-20 whitespace-nowrap pointer-events-none",
                          index >= 3 ? "right-0 text-right" : "left-0 text-left"
                        )}
                      >
                        <span className="font-sans font-semibold text-foreground text-md md:text-xl">
                          {member.name},
                        </span>
                        <span className="font-sans text-muted-foreground/60 dark:text-zinc-500 text-md md:text-xl ml-1.5">
                          {member.role}
                        </span>
                      </motion.div>
                    )}
                  </AnimatePresence>

                  {/* Individual member image card */}
                  <div className="w-full h-full rounded-lg overflow-hidden relative shadow-sm">
                    <Image
                      src={member.image}
                      alt={member.name}
                      fill
                      className={cn(
                        "object-cover object-center transition-all duration-700 ease-out",
                        isActive
                          ? "grayscale-0 scale-100 contrast-[1.05]"
                          : "grayscale contrast-[0.95] brightness-90 md:hover:brightness-95 md:hover:scale-[1.01]"
                      )}
                      sizes="(max-width: 768px) 30vw, 25vw"
                      priority={index === 2}
                      unoptimized
                    />
                  </div>
                </div>
              );
            })}
          </div>
        </div>

        {/* Navigation buttons at the bottom center */}
        <div className="flex justify-center items-center gap-2.5 mt-10">
          <button
            onClick={handlePrev}
            className="w-7 h-7 bg-zinc-950 dark:bg-zinc-50 hover:bg-zinc-800 dark:hover:bg-zinc-200 text-zinc-50 dark:text-zinc-950 flex items-center justify-center transition-colors focus:outline-none cursor-pointer"
            aria-label="Previous team member"
          >
            <ArrowLeft className="w-3.5 h-3.5" />
          </button>
          <button
            onClick={handleNext}
            className="w-7 h-7 bg-zinc-950 dark:bg-zinc-50 hover:bg-zinc-800 dark:hover:bg-zinc-200 text-zinc-50 dark:text-zinc-950 flex items-center justify-center transition-colors focus:outline-none cursor-pointer"
            aria-label="Next team member"
          >
            <ArrowRight className="w-3.5 h-3.5" />
          </button>
        </div>

      </div>
    </section>
  );
}
```
