# Animated Content

> Wrapper that reveals its content on scroll with slides, blur, 3D tilts, soft wipes, staggered children and scroll-linked progress.

Animated Content reveals whatever you put inside it when it scrolls into view. It can slide, fade, scale, blur in, rotate, flip up in 3D or appear behind a soft wipe. Give it a `stagger` and each direct child animates in turn, which suits lists and grids. It can also play on mount, replay every time it scrolls in, follow the scroll position with `scrub`, or hide itself again after a while. Scroll the demo and try the presets in the panel.

<demo-animated-content>



</demo-animated-content>

## Installation

```bash
npx shadcn-vue@latest add "https://nxui.geoql.in/r/animated-content.json"
```

## Usage

```vue
<script setup lang="ts">
  import AnimatedContent from '~/components/ui/animated-content/AnimatedContent.vue';

  const features = ['Instant deploys', 'Preview builds', 'Built-in safety'];
</script>

<template>
  <!-- "Blur" preset, children staggered -->
  <AnimatedContent
    :distance="40"
    :blur="12"
    :duration="1"
    :stagger="0.08"
    class="grid grid-cols-3 gap-4"
  >
    <div v-for="feature in features" :key="feature">{{ feature }}</div>
  </AnimatedContent>
</template>
```

Eases use GSAP names (`power1`–`power4`, `expo`, `sine`, `circ`, `back(n)`, `elastic(a, p)`, `bounce`, `none`, each with `.in`, `.out` or `.inOut`) and run on a built-in tween, so GSAP is not needed.

## Props

<table>
<thead>
  <tr>
    <th>
      Prop
    </th>
    
    <th>
      Type
    </th>
    
    <th>
      Default
    </th>
    
    <th>
      Description
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <code>
        container
      </code>
    </td>
    
    <td>
      <code>
        string | HTMLElement | null
      </code>
    </td>
    
    <td>
      <code>
        null
      </code>
    </td>
    
    <td>
      Scroll container that drives the animation, as a selector or an element. Defaults to the page.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        distance
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        100
      </code>
    </td>
    
    <td>
      How far the content travels into place, in px.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        direction
      </code>
    </td>
    
    <td>
      <code>
        'vertical' | 'horizontal'
      </code>
    </td>
    
    <td>
      <code>
        'vertical'
      </code>
    </td>
    
    <td>
      Axis the content travels along.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        reverse
      </code>
    </td>
    
    <td>
      <code>
        boolean
      </code>
    </td>
    
    <td>
      <code>
        false
      </code>
    </td>
    
    <td>
      Comes in from the other side: from above, or from the left.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        duration
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        0.8
      </code>
    </td>
    
    <td>
      Length of the animation, in seconds.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        ease
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      <code>
        'power3.out'
      </code>
    </td>
    
    <td>
      GSAP-style ease, such as <code>
        'expo.out'
      </code>
      
      , <code>
        'back.out(1.6)'
      </code>
      
       or <code>
        'elastic.out(1, 0.5)'
      </code>
      
      .
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        initial-opacity
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        0
      </code>
    </td>
    
    <td>
      Opacity the content starts from.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        animate-opacity
      </code>
    </td>
    
    <td>
      <code>
        boolean
      </code>
    </td>
    
    <td>
      <code>
        true
      </code>
    </td>
    
    <td>
      Fades the content in. Turn off to keep it fully opaque while it moves.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        scale
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        1
      </code>
    </td>
    
    <td>
      Scale the content starts from.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        blur
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        0
      </code>
    </td>
    
    <td>
      Blur the content starts from, in px. It comes into focus as it lands.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        rotate
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        0
      </code>
    </td>
    
    <td>
      Rotation the content starts from, in degrees.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        tilt
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        0
      </code>
    </td>
    
    <td>
      Tips the content back in 3D, in degrees, so it flips up into place.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        wipe
      </code>
    </td>
    
    <td>
      <code>
        'none' | 'up' | 'down' | 'left' | 'right' | 'center'
      </code>
    </td>
    
    <td>
      <code>
        'none'
      </code>
    </td>
    
    <td>
      Reveals the content behind a soft moving edge instead of all at once.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        threshold
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        0.1
      </code>
    </td>
    
    <td>
      How far into the viewport the top of the content must be before it animates, from 0 to 1.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        delay
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        0
      </code>
    </td>
    
    <td>
      Wait before the animation starts, in seconds.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        stagger
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        0
      </code>
    </td>
    
    <td>
      Animates each direct child in turn, this many seconds apart.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        stagger-from
      </code>
    </td>
    
    <td>
      <code>
        'start' | 'end' | 'center' | 'edges' | 'random'
      </code>
    </td>
    
    <td>
      <code>
        'start'
      </code>
    </td>
    
    <td>
      Which child goes first when staggering.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        trigger
      </code>
    </td>
    
    <td>
      <code>
        'scroll' | 'mount'
      </code>
    </td>
    
    <td>
      <code>
        'scroll'
      </code>
    </td>
    
    <td>
      Animate when the content scrolls into view, or right away.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        once
      </code>
    </td>
    
    <td>
      <code>
        boolean
      </code>
    </td>
    
    <td>
      <code>
        true
      </code>
    </td>
    
    <td>
      Plays once. Turn off to replay on every scroll in and reverse when it scrolls back out.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        scrub
      </code>
    </td>
    
    <td>
      <code>
        boolean | number
      </code>
    </td>
    
    <td>
      <code>
        false
      </code>
    </td>
    
    <td>
      Ties the animation to the scroll position. A number smooths it, in seconds.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        disappear-after
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        0
      </code>
    </td>
    
    <td>
      Hides the content again this many seconds after it appears. 0 keeps it shown.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        disappear-duration
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        0.5
      </code>
    </td>
    
    <td>
      Length of the hide animation, in seconds.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        disappear-ease
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      <code>
        'power3.in'
      </code>
    </td>
    
    <td>
      Ease of the hide animation.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        class
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      <code>
        ''
      </code>
    </td>
    
    <td>
      Extra classes for the wrapper.
    </td>
  </tr>
</tbody>
</table>

## Events

<table>
<thead>
  <tr>
    <th>
      Event
    </th>
    
    <th>
      Description
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <code>
        start
      </code>
    </td>
    
    <td>
      The animation starts.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        complete
      </code>
    </td>
    
    <td>
      The animation finishes.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        disappearance-complete
      </code>
    </td>
    
    <td>
      The hide animation finishes.
    </td>
  </tr>
</tbody>
</table>

## Slots

<table>
<thead>
  <tr>
    <th>
      Slot
    </th>
    
    <th>
      Description
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <code>
        default
      </code>
    </td>
    
    <td>
      The content to animate. With <code>
        stagger
      </code>
      
      , each direct child animates alone.
    </td>
  </tr>
</tbody>
</table>

## Accessibility

- With `prefers-reduced-motion: reduce` the content is shown at once with no movement, and `complete` still fires.
- The wrapper adds no roles or focus stops. Content is hidden with `visibility: hidden` only until the component mounts.
- When the reveal lands, transform, filter and mask styles are cleared so the content behaves like normal static markup.
- Ported from [React Bits](https://reactbits.dev/animations/animated-content) by David Haz.
