# animations-21st skill

Premium animated component patterns drawn from 21st.dev, Aceternity UI, and Magic UI.

## Animated grid background

```tsx
<div className="absolute inset-0 -z-10">
  <div
    className="absolute inset-0 bg-[linear-gradient(to_right,#80808012_1px,transparent_1px),linear-gradient(to_bottom,#80808012_1px,transparent_1px)] bg-[size:24px_24px]"
    style={{ maskImage: 'radial-gradient(ellipse 60% 50% at 50% 0%, black 70%, transparent 100%)' }}
  />
</div>
```

## Spotlight hero

```tsx
<div className="relative overflow-hidden">
  <div
    className="pointer-events-none absolute inset-0 -z-10"
    style={{
      background: 'radial-gradient(600px circle at 50% 0%, rgba(212,175,55,0.15), transparent 40%)'
    }}
  />
  {/* content */}
</div>
```

## Marquee (infinite scroll)

```tsx
<div className="group flex overflow-hidden [--gap:2rem] gap-[var(--gap)]">
  <div className="flex shrink-0 gap-[var(--gap)] animate-marquee group-hover:[animation-play-state:paused]">
    {items.map(i => <Card key={i} />)}
  </div>
  <div className="flex shrink-0 gap-[var(--gap)] animate-marquee" aria-hidden>
    {items.map(i => <Card key={i + '-dup'} />)}
  </div>
</div>
```

Tailwind config:
```js
animation: { marquee: 'marquee 30s linear infinite' },
keyframes: { marquee: { from: { transform: 'translateX(0)' }, to: { transform: 'translateX(calc(-100% - var(--gap)))' } } }
```

## Bento grid

```tsx
<div className="grid grid-cols-1 md:grid-cols-3 gap-4 auto-rows-[180px]">
  <div className="md:col-span-2 md:row-span-2 rounded-3xl bg-neutral-100 p-8">Large</div>
  <div className="rounded-3xl bg-neutral-100 p-8">Small</div>
  <div className="rounded-3xl bg-neutral-100 p-8">Small</div>
  <div className="md:col-span-2 rounded-3xl bg-neutral-100 p-8">Wide</div>
</div>
```

## Text reveal on scroll

```tsx
const words = "Your headline goes here".split(' ');
<p>
  {words.map((w, i) => (
    <motion.span
      key={i}
      initial={{ opacity: 0, y: 10 }}
      whileInView={{ opacity: 1, y: 0 }}
      viewport={{ once: true }}
      transition={{ duration: 0.5, delay: i * 0.05 }}
      className="inline-block mr-2"
    >
      {w}
    </motion.span>
  ))}
</p>
```

## Noise overlay

```tsx
<div
  className="pointer-events-none absolute inset-0 opacity-[0.03] mix-blend-overlay"
  style={{
    backgroundImage: `url("data:image/svg+xml,%3Csvg viewBox='0 0 200 200' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E")`
  }}
/>
```

## Cursor glow

```tsx
const [pos, setPos] = useState({ x: 0, y: 0 });
useEffect(() => {
  const onMove = (e: MouseEvent) => setPos({ x: e.clientX, y: e.clientY });
  window.addEventListener('mousemove', onMove);
  return () => window.removeEventListener('mousemove', onMove);
}, []);

<div
  className="pointer-events-none fixed -z-10 h-96 w-96 rounded-full"
  style={{
    left: pos.x - 192,
    top: pos.y - 192,
    background: 'radial-gradient(circle, rgba(212,175,55,0.1), transparent 70%)'
  }}
/>
```
