# <motion-reveal>

Viewport-triggered fade + translate reveal. Starts hidden, animates in
with a spring once the element intersects the viewport.

**Use it for:** headings, cards and images that should fade and rise into
place the first time they scroll into view.

**Avoid it for:** content in the first screen that people need at once.
For a list of items, use `motion-stagger`, which reveals children one after
another.

**Accessibility:** the content stays in the page while it is hidden, so
screen readers read it before it animates. Only opacity and transform
change, so the layout does not shift.

**Reduced motion:** the content shows at its final position at once, with
no animation.

**Common mistakes:** wrapping a whole page section in one reveal, so nothing
shows until 10% of it is in view; wrap each block instead, or lower
`threshold`. Putting a `motion-reveal` directly inside `motion-stagger`
animates the same element twice.

Docs: https://www.motion-components.dev/docs/reveal/motion-reveal/

## Install

```js
import 'motion-components/motion-reveal'
```

Or without a build step:

```html
<script type="module" src="https://cdn.jsdelivr.net/npm/motion-components@1/dist/motion-reveal.js/+esm"></script>
```

## Example

```html
<motion-reveal y="40" duration="0.8">
  <h2>Reveals when scrolled into view</h2>
</motion-reveal>
```

## Attributes

| Attribute | Type | Default | Description |
| --- | --- | --- | --- |
| `duration` | `number` | `0.6` | Spring duration of the reveal animation, in seconds. |
| `y` | `number` | `24` | Initial vertical offset in pixels; element rises to 0 on reveal. |
| `threshold` | `number` | `0.1` | IntersectionObserver threshold (0–1) at which the reveal triggers. |
| `once` | `boolean` | `true` | When `true`, only animate the first time the element enters view. Set `once="false"` to turn it off. |

## Properties

| Property | Type | Description |
| --- | --- | --- |
| `playState` | `'idle' \| 'running' \| 'paused' \| 'finished'` | Current state: `'idle'`, `'running'`, `'paused'` or `'finished'`. |
| `finished` | `Promise<void>` | Resolves when the current run settles. A new run replaces the promise. |

## Methods

| Method | Description |
| --- | --- |
| `replay()` | Re-runs the reveal animation from its hidden initial state. |
| `play()` | Starts the animation, or resumes it when paused. Resolves once the run settles. Under `prefers-reduced-motion: reduce` the final state is applied immediately without animating. |
| `pause()` | Holds the animation at its current position. No-op unless running. |
| `finish()` | Jumps to the final state and settles. Fires `motion-finish`. |
| `cancel()` | Reverts to the initial state and returns to idle. Fires `motion-cancel`. |

## Events

The `motion-*` events bubble and are composed.

| Event | Description |
| --- | --- |
| `motion-start` | When a run starts. |
| `motion-finish` | When a run finishes, or `finish()` jumps to the end. |
| `motion-cancel` | When `cancel()` stops a run and resets it. |

## Slots

| Slot | Description |
| --- | --- |
| (default) | The content to reveal on scroll-in. |
