Todos os componentes

Scroll Animation Repeat

Scroll Animation Repeat é um componente de marquee para React e Tailwind CSS, da biblioteca UI Layouts, com licença MIT. Copia e cola no teu projeto.

UI Layouts MIT marquee

O que é

Scroll Animation Repeat é um componente de marquee 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.

Scroll Animation Repeat

./registry/components/scroll-animation/repeat-scroll.tsx
'use client';
import { ScrollAnimation } from '@/components/ui/scroll-animation';
import React from 'react';

function RepeatScroll() {
  return (
    <section>
      <div className='h-[500px] grid place-content-center'>
        <h1 className='text-6xl font-semibold text-center py-8'>Scroll Down 👇 </h1>
      </div>
      <div className='py-2'>
        <div className=' columns-3'>
          <ScrollAnimation direction='left' viewport={{ amount: 0.5, margin: '0px 0px 0px 0px' }}>
            <img
              src='https://images.unsplash.com/photo-1724690416947-3cdc197ffab1?q=80&w=600&auto=format&fit=crop'
              alt=''
              className='w-full mb-2'
            />
          </ScrollAnimation>
          <ScrollAnimation direction='left' viewport={{ amount: 0.5, margin: '0px 0px 0px 0px' }}>
            <img
              src='https://images.unsplash.com/photo-1695763594594-31505b18b58a?q=80&w=2072&auto=format&fit=crop'
              alt=''
              className='w-full mb-2'
            />
          </ScrollAnimation>
          <ScrollAnimation direction='left' viewport={{ amount: 0.5, margin: '0px 0px 0px 0px' }}>
            <img
              src='https://images.unsplash.com/photo-1724888861686-ad3f706ab067?q=80&w=1974&auto=format&fit=crop'
              alt=''
              className='w-full mb-2'
            />
          </ScrollAnimation>

          <ScrollAnimation viewport={{ amount: 0.5, margin: '0px 0px 0px 0px' }}>
            <img
              src='https://images.unsplash.com/photo-1724884564497-f5024b7e2f93?q=80&w=1974&auto=format&fit=crop'
              alt=''
              className='w-full mb-2'
            />
          </ScrollAnimation>
          <ScrollAnimation viewport={{ amount: 0.5, margin: '0px 0px 0px 0px' }}>
            <img
              src='https://images.unsplash.com/photo-1460999158988-6f0380f81f4d?q=80&w=2070&auto=format&fit=crop'
              alt=''
              className='w-full mb-2'
            />
          </ScrollAnimation>
          <ScrollAnimation viewport={{ amount: 0.5, margin: '0px 0px 0px 0px' }}>
            <img
              src='https://images.unsplash.com/photo-1478028928718-7bfdb1b32095?q=80&w=2070&auto=format&fit=crop'
              alt=''
              className='w-full mb-2'
            />
          </ScrollAnimation>
          <ScrollAnimation direction='right' viewport={{ amount: 0.5, margin: '0px 0px 0px 0px' }}>
            <img
              src='https://images.unsplash.com/photo-1460999158988-6f0380f81f4d?q=80&w=2070&auto=format&fit=crop'
              alt=''
              className='w-full mb-2'
            />
          </ScrollAnimation>
          <ScrollAnimation direction='right' viewport={{ amount: 0.5, margin: '0px 0px 0px 0px' }}>
            <img
              src='https://images.unsplash.com/photo-1478028928718-7bfdb1b32095?q=80&w=2070&auto=format&fit=crop'
              alt=''
              className='w-full mb-2'
            />
          </ScrollAnimation>
          <ScrollAnimation direction='right' viewport={{ amount: 0.5, margin: '0px 0px 0px 0px' }}>
            <img
              src='https://images.unsplash.com/photo-1460999158988-6f0380f81f4d?q=80&w=2070&auto=format&fit=crop'
              alt=''
              className='w-full mb-2'
            />
          </ScrollAnimation>
          <ScrollAnimation direction='right' viewport={{ amount: 0.5, margin: '0px 0px 0px 0px' }}>
            <img
              src='https://images.unsplash.com/photo-1478028928718-7bfdb1b32095?q=80&w=2070&auto=format&fit=crop'
              alt=''
              className='w-full mb-2'
            />
          </ScrollAnimation>
        </div>
      </div>
    </section>
  );
}

export default RepeatScroll;
./components/ui/scroll-animation.tsx
'use client';

import { cn } from '@/lib/utils';
import { HTMLMotionProps, motion } from 'motion/react';
import type React from 'react';

type Direction = 'up' | 'down' | 'left' | 'right';
type AsTag =
  | 'div'
  | 'span'
  | 'h1'
  | 'h2'
  | 'h3'
  | 'a'
  | 'p'
  | 'section'
  | 'figure'
  | 'button'
  | 'article';

const generateVariants = (direction: Direction) => {
  const axis = direction === 'left' || direction === 'right' ? 'x' : 'y';
  const value = direction === 'right' || direction === 'down' ? 20 : -20;

  return {
    hidden: { filter: 'blur(10px)', opacity: 0, [axis]: value },
    visible: {
      filter: 'blur(0px)',
      opacity: 1,
      [axis]: 0,
      transition: {
        duration: 0.7,
        ease: 'easeOut',
      },
    },
  };
};

const defaultViewport = {
  once: true,
  amount: 0.3,
  margin: '0px 0px -200px 0px',
};

interface ScrollElementProps {
  children: React.ReactNode;
  className?: string;
  variants?: {
    hidden?: any;
    visible?: any;
  };
  viewport?: {
    amount?: number;
    margin?: string;
    once?: boolean;
  };
  delay?: number;
  direction?: Direction;
  as?: AsTag;
  [key: string]: any; // Allow any additional props
}

export function ScrollAnimation({
  children,
  className,
  variants,
  viewport = defaultViewport,
  delay = 0,
  direction = 'down',
  as: Component = 'div',
  ...props
}: ScrollElementProps) {
  const baseVariants = variants || generateVariants(direction);
  const modifiedVariants = {
    hidden: baseVariants.hidden,
    visible: {
      ...baseVariants.visible,
      transition: {
        ...baseVariants.visible.transition,
        delay,
      },
    },
  };

  const MotionComponent = motion[Component] as typeof motion.div;

  return (
    <MotionComponent
      whileInView='visible'
      initial='hidden'
      variants={modifiedVariants}
      viewport={viewport as any}
      className={cn(className)}
      {...props}
    >
      {children}
    </MotionComponent>
  );
}

Componentes parecidos