ComponentsInfinite Slider
Infinite Slider
Terminal
npm i clsx tailwind-merge
utils/cn.ts
import { type ClassValue, clsx } from "clsx";
import { twMerge } from "tailwind-merge";
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs));
}
InfiniteSlider.tsx
import { cn } from "@/utils/cn";
export function InfiniteSliderExample() {
return (
<InfiniteSlider pauseOnHover>
<img
src="https://i.imgur.com/NfGQgBk.png"
className="aspect-square w-[120px] rounded-[4px]"
alt="01's image"
/>
<img
src="https://i.imgur.com/EeC1h3b.jpeg"
className="aspect-square w-[120px] rounded-[4px]"
alt="02's image"
/>
<img
src="https://i.imgur.com/4VCS3zG.jpeg"
className="aspect-square w-[120px] rounded-[4px]"
alt="03's image"
/>
<img
src="https://i.imgur.com/yWunBhl.jpeg"
className="aspect-square w-[120px] rounded-[4px]"
alt="04's image"
/>
<img
src="https://i.imgur.com/dfDyDad.jpeg"
className="aspect-square w-[120px] rounded-[4px]"
alt="05's image"
/>
<img
src="https://i.imgur.com/7N3FxDW.jpeg"
className="aspect-square w-[120px] rounded-[4px]"
alt="06's image"
/>
</InfiniteSlider>
);
}
type InfiniteSliderProps = {
children: React.ReactNode;
className?: string;
pauseOnHover?: boolean;
};
function InfiniteSlider({
children,
className,
pauseOnHover,
}: InfiniteSliderProps) {
return (
<div
data-id="slider"
className={cn("group relative flex gap-10 overflow-hidden", className)}
>
<div className="absolute left-0 w-1/12 h-full bg-gradient-to-r from-background to-transparent z-10" />
{Array.from({ length: 15 }).map((_, i) => (
<div
key={i}
className={cn(
"flex shrink-0 animate-infinite-slider justify-around gap-10 [--gap:1rem]",
pauseOnHover && "group-hover:[animation-play-state:paused]"
)}
data-id={`slider-child-${i + 1}`}
>
{children}
</div>
))}
<div className="absolute right-0 w-1/12 h-full bg-gradient-to-l from-background to-transparent z-10" />
</div>
);
}
tailwind.config.ts
{
"animation": {
"infinite-slider": "infinite-slider 40s linear infinite"
},
"keyframes": {
"infinite-slider": {
"from": {
"transform": "translateX(0)"
},
"to": {
"transform": "translateX(calc(-100% - var(--gap)))"
}
}
}
}