Team Clippath
Team Clippath is a React and Tailwind CSS component from UI Layouts, licensed MIT. Copy it and paste it into your project.
UI Layouts
MIT
other
What it is
Team Clippath is a React and Tailwind CSS component from UI Layouts, licensed MIT. Copy it and paste it into your project.
How to use it
Open it in the catalogue, press copy, and paste it into your project. The prompt you copy carries the code and the rules that tell your agent to reproduce it without changing anything.
Five free copies a month. No card.
Needs
npm i motion
Licence
This component comes from UI Layouts and is redistributed under the MIT licence, which permits commercial use. The copyright notice travels with the code.
Team Clippath
'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>
)
}
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>
);
};