Infinite Slider
motion-primitives/infinite-sliderFreeComponent
A slider component that loops infinitely through its content.
Install it
npx shadcn@latest add https://raw.githubusercontent.com/ibelick/motion-primitives/HEAD/public/c/infinite-slider.jsonSource
1'use client';2import { cn } from '@/lib/utils';3import { useMotionValue, animate, motion } from 'motion/react';4import { useState, useEffect } from 'react';5import useMeasure from 'react-use-measure';67export type InfiniteSliderProps = {8 children: React.ReactNode;9 gap?: number;10 speed?: number;11 speedOnHover?: number;12 direction?: 'horizontal' | 'vertical';13 reverse?: boolean;14 className?: string;15};1617export function InfiniteSlider({18 children,19 gap = 16,20 speed = 100,21 speedOnHover,22 direction = 'horizontal',23 reverse = false,24 className,25}: InfiniteSliderProps) {26 const [currentSpeed, setCurrentSpeed] = useState(speed);27 const [ref, { width, height }] = useMeasure();28 const translation = useMotionValue(0);29 const [isTransitioning, setIsTransitioning] = useState(false);30 const [key, setKey] = useState(0);3132 useEffect(() => {33 let controls;34 const size = direction === 'horizontal' ? width : height;35 const contentSize = size + gap;36 const from = reverse ? -contentSize / 2 : 0;37 const to = reverse ? 0 : -contentSize / 2;3839 const distanceToTravel = Math.abs(to - from);40 const duration = distanceToTravel / currentSpeed;4142 if (isTransitioning) {43 const remainingDistance = Math.abs(translation.get() - to);44 const transitionDuration = remainingDistance / currentSpeed;4546 controls = animate(translation, [translation.get(), to], {47 ease: 'linear',48 duration: transitionDuration,49 onComplete: () => {50 setIsTransitioning(false);51 setKey((prevKey) => prevKey + 1);52 },53 });54 } else {55 controls = animate(translation, [from, to], {56 ease: 'linear',57 duration: duration,58 repeat: Infinity,59 repeatType: 'loop',60 repeatDelay: 0,61 onRepeat: () => {62 translation.set(from);63 },64 });65 }6667 return controls?.stop;68 }, [69 key,70 translation,71 currentSpeed,72 width,73 height,74 gap,75 isTransitioning,76 direction,77 reverse,78 ]);7980 const hoverProps = speedOnHover81 ? {82 onHoverStart: () => {83 setIsTransitioning(true);84 setCurrentSpeed(speedOnHover);85 },86 onHoverEnd: () => {87 setIsTransitioning(true);88 setCurrentSpeed(speed);89 },90 }91 : {};9293 return (94 <div className={cn('overflow-hidden', className)}>95 <motion.div96 className='flex w-max'97 style={{98// … truncated
What it pulls in
npm packages
Files it writes
More from motion-primitives
All 33 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| Accordionaccordion | motion-primitives | Components | Free | 1 dep | |
| Animated Backgroundanimated-background | motion-primitives | Components | Free | 1 dep | |
| Animated Groupanimated-group | motion-primitives | Components | Free | 1 dep | |
| Animated Numberanimated-number | motion-primitives | Components | Free | 1 dep | |
| Border Trailborder-trail | motion-primitives | Components | Free | 1 dep | |
| Carouselcarousel | motion-primitives | Components | Free | 1 dep | |
| Cursorcursor | motion-primitives | Components | Free | 1 dep | |
| Dialogdialog | motion-primitives | Components | Free | 1 dep · 2 files |
