Todos os componentes

Team Clippath

Team Clippath é um componente para React e Tailwind CSS, da biblioteca UI Layouts, com licença MIT. Copia e cola no teu projeto.

UI Layouts MIT other

O que é

Team Clippath é um componente para React e Tailwind CSS, da biblioteca UI Layouts, com licença MIT. Copia e cola no teu projeto.

Como usar

Abre o componente no catálogo, carrega em copiar, e cola no teu projeto. O prompt copiado leva o código e as regras para o teu agente o reproduzir sem alterar nada.

Abrir no catálogo

Cinco cópias grátis por mês. Sem cartão.

Precisa de

npm i motion

Licença

Este componente vem de UI Layouts e é redistribuído sob a licença MIT, que permite uso comercial. O aviso de copyright viaja com o código.

Team Clippath

../../packages/blocks/src/team-section/team-clippath.tsx
'use client'
import React, { useState } from 'react'
import { motion, AnimatePresence } from 'motion/react'
import { TimelineAnimation } from '@/components/ui/timeline-animation'

const items = [
  {
    id: '1',
    url: 'https://images.unsplash.com/photo-1535713875002-d1d0cf377fde?q=80&w=880&auto=format&fit=crop',

    title: 'Adrian Paul',
    description: 'COO & Co-Founder',
    tags: ['Floral', 'Highlands', 'Wildflowers', 'Colorful', 'Resilience'],
  },
  {
    id: '2',
    url: 'https://images.unsplash.com/photo-1623366302587-b38b1ddaefd9?q=80&w=1025&auto=format&fit=crop',

    title: 'Flualy Cual',
    description: 'Founder & CEO',
    tags: ['Twilight', 'Peaks', 'Silhouette', 'Evening Sky', 'Peaceful'],
  },
  {
    id: '3',
    url: 'https://images.unsplash.com/photo-1569292316763-0b667e9e960c?q=80&w=687&auto=format&fit=crop',

    title: 'Naymur Rahman',
    description: 'CTO & Co-Founder',
    tags: ['Rocky', 'Ridges', 'Contrast', 'Adventure', 'Clouds'],
  },
  {
    id: '4',
    url: 'https://images.unsplash.com/flagged/photo-1573603867003-89f5fd7a7576?q=80&w=746&auto=format&fit=crop',

    title: 'John Doe',
    description: 'Lead Designer',
    tags: ['Creative', 'Vision', 'Design', 'Innovation', 'Artistic'],
  },
]

export function TeamClipPath() {
  const timelineRef = React.useRef<HTMLDivElement>(null)
  const [hoveredId, setHoveredId] = useState(null)

  return (
    <section
      className="py-20 bg-neutral-100 min-h-screen relative"
      ref={timelineRef}
    >
      <div className="max-w-7xl mx-auto px-4">
        <TimelineAnimation
          as="h1"
          animationNum={0}
          timelineRef={timelineRef}
          className="text-5xl font-semibold text-neutral-900 mb-4 text-center"
        >
          Meet Our Team
        </TimelineAnimation>
        <TimelineAnimation
          as="p"
          animationNum={1}
          timelineRef={timelineRef}
          className="text-neutral-600 mb-2 text-center"
        >
          We lead with care — our core value — and a shared passion for
          connecting the world.
        </TimelineAnimation>
        <div className="flex gap-6 justify-center items-center h-[420px]">
          {items.map((item) => {
            const isHovered = hoveredId === item.id
            const isOtherHovered = hoveredId !== null && hoveredId !== item.id

            return (
              <motion.div
                key={item.id}
                className="relative cursor-pointer h-full"
                style={{ overflow: 'hidden' }}
                // @ts-ignore
                onMouseEnter={() => setHoveredId(item.id)}
                onMouseLeave={() => setHoveredId(null)}
                initial={{
                  width: '300px',
                  clipPath: 'circle(72.3% at 50% 50%)',
                }}
                animate={{
                  width: isHovered
                    ? '600px'
                    : isOtherHovered
                      ? '150px'
                      : '200px',
                  clipPath: isHovered
                    ? 'circle(72.3% at 50% 50%)'
                    : 'circle(50% at 50% 50%)',
                  filter: isOtherHovered ? 'blur(4px)' : 'blur(0px)',
                  opacity: isOtherHovered ? 0.6 : 1,
                }}
                transition={{
                  width: {
                    duration: 0.5,
                    ease: [0.5, 0.85, 0.25, 1.15],
                  },
                  filter: {
                    duration: 0.4,
                    ease: 'easeInOut',
                  },
                  opacity: {
                    duration: 0.4,
                    ease: 'easeInOut',
                  },
                }}
              >
                {/* Image Background */}
                <div className="absolute inset-0">
                  <img
                    src={item.url}
                    alt={item.title}
                    className="w-full h-full object-cover"
                  />
                  <div className="absolute inset-0 bg-linear-to-t from-black/70 via-black/20 to-transparent" />
                </div>

                {/* Content */}
                <div className="absolute inset-0 p-6 flex flex-col justify-end text-white z-10">
                  <motion.h2
                    className="text-2xl font-semibold mb-2 whitespace-nowrap overflow-hidden"
                    initial={{ opacity: 0, y: 20 }}
                    animate={{
                      opacity: isHovered ? 1 : 0,
                      y: isHovered ? 0 : 20,
                    }}
                    transition={{
                      duration: 0.3,
                      delay: isHovered ? 0.2 : 0,
                      ease: [0.5, 0.85, 0.25, 1.8],
                    }}
                  >
                    {item.title}
                  </motion.h2>

                  <motion.p
                    className="text-lg opacity-90 mb-4 whitespace-nowrap overflow-hidden"
                    initial={{ opacity: 0, y: 20 }}
                    animate={{
                      opacity: isHovered ? 1 : 0,
                      y: isHovered ? 0 : 20,
                    }}
                    transition={{
                      duration: 0.3,
                      delay: isHovered ? 0.3 : 0,
                      ease: [0.5, 0.85, 0.25, 1.8],
                    }}
                  >
                    {item.description}
                  </motion.p>

                  <motion.div
                    className="flex flex-wrap gap-2"
                    initial={{ opacity: 0, y: 20 }}
                    animate={{
                      opacity: isHovered ? 1 : 0,
                      y: isHovered ? 0 : 20,
                    }}
                    transition={{
                      duration: 0.3,
                      delay: isHovered ? 0.4 : 0,
                      ease: [0.5, 0.85, 0.25, 1.8],
                    }}
                  >
                    {item.tags.map((tag, idx) => (
                      <span
                        key={idx}
                        className="px-3 py-1 bg-white/20 backdrop-blur-sm rounded-full text-sm"
                      >
                        {tag}
                      </span>
                    ))}
                  </motion.div>
                </div>
              </motion.div>
            )
          })}
        </div>
      </div>
    </section>
  )
}
./components/ui/timeline-animation.tsx
import type { Variants } from 'motion/react';
import { type HTMLMotionProps, motion, useInView } from 'motion/react';
import type React from 'react';

type TimelineContentProps<T extends keyof HTMLElementTagNameMap> = {
  children?: React.ReactNode;
  animationNum: number;
  className?: string;
  timelineRef: React.RefObject<HTMLElement | null>;
  as?: T;
  customVariants?: Variants;
  once?: boolean;
} & HTMLMotionProps<T>;

export const TimelineAnimation = <T extends keyof HTMLElementTagNameMap = 'div'>({
  children,
  animationNum,
  timelineRef,
  className,
  as,
  customVariants,
  once = true,
  ...props
}: TimelineContentProps<T>) => {
  const defaultSequenceVariants = {
    visible: (i: number) => ({
      filter: 'blur(0px)',
      y: 0,
      opacity: 1,
      transition: {
        delay: i * 0.5,
        duration: 0.5,
      },
    }),
    hidden: {
      filter: 'blur(20px)',
      y: 0,
      opacity: 0,
    },
  };

  const sequenceVariants = customVariants || defaultSequenceVariants;

  const isInView = useInView(timelineRef, {
    once,
  });

  const MotionComponent = motion[as || 'div'] as React.ElementType;

  return (
    <MotionComponent
      initial='hidden'
      animate={isInView ? 'visible' : 'hidden'}
      custom={animationNum}
      variants={sequenceVariants}
      className={className}
      {...props}
    >
      {children}
    </MotionComponent>
  );
};

Componentes parecidos