---
title: Reveal
description: Animation wrapper with viewport / click / manual triggers and 11 in/out presets
visibility: guest
draft: false
---

# Reveal

A thin Blade wrapper that animates its slot content into view using one of 11 presets. Drives the underlying `wirekitAnimate` Alpine helper. Honors `prefers-reduced-motion: reduce` (snaps to final state, no motion).

## Basic Usage

:::preview{title="Slide-up-in on scroll"}
<x-wirekit::reveal preset="slide-up-in" duration="slow" style="--wk-stagger-step: 0ms; animation-duration: 1200ms;">
    <x-wirekit::card>
        <x-wirekit::card.body>I slide into view on first viewport intersection. Click the replay button at the top-right of the preview to re-trigger the animation.</x-wirekit::card.body>
    </x-wirekit::card>
</x-wirekit::reveal>
:::

## All 11 Presets

Pick a preset from the matrix. Each has both an `-in` and `-out` variant; the Reveal component defaults to `-in` if you omit the suffix.

::: tip
The previews below run at `duration="slow"` (600 ms) so the motion is easy to follow. The component's runtime default is `duration="normal"` (300 ms) — set `duration="fast"` / `"normal"` / `"slow"` to pick the timing on your own page.
:::

:::preview{title="Fade"}
<x-wirekit::reveal preset="fade-in" duration="slow" style="--wk-stagger-step: 0ms">
    <x-wirekit::card><x-wirekit::card.body>fade-in</x-wirekit::card.body></x-wirekit::card>
</x-wirekit::reveal>
:::

:::preview{title="Slide-up"}
<x-wirekit::reveal preset="slide-up-in" duration="slow" style="--wk-stagger-step: 0ms">
    <x-wirekit::card><x-wirekit::card.body>slide-up-in</x-wirekit::card.body></x-wirekit::card>
</x-wirekit::reveal>
:::

:::preview{title="Scale"}
<x-wirekit::reveal preset="scale-in" duration="slow" style="--wk-stagger-step: 0ms">
    <x-wirekit::card><x-wirekit::card.body>scale-in</x-wirekit::card.body></x-wirekit::card>
</x-wirekit::reveal>
:::

:::preview{title="Zoom"}
<x-wirekit::reveal preset="zoom-in" duration="slow" style="--wk-stagger-step: 0ms">
    <x-wirekit::card><x-wirekit::card.body>zoom-in</x-wirekit::card.body></x-wirekit::card>
</x-wirekit::reveal>
:::

:::preview{title="Flip"}
<x-wirekit::reveal preset="flip-in" duration="slow" style="--wk-stagger-step: 0ms">
    <x-wirekit::card><x-wirekit::card.body>flip-in</x-wirekit::card.body></x-wirekit::card>
</x-wirekit::reveal>
:::

:::preview{title="Bounce"}
<x-wirekit::reveal preset="bounce-in" duration="slow" style="--wk-stagger-step: 0ms">
    <x-wirekit::card><x-wirekit::card.body>bounce-in</x-wirekit::card.body></x-wirekit::card>
</x-wirekit::reveal>
:::

:::preview{title="Spring"}
<x-wirekit::reveal preset="spring-in" duration="slow" style="--wk-stagger-step: 0ms">
    <x-wirekit::card><x-wirekit::card.body>spring-in</x-wirekit::card.body></x-wirekit::card>
</x-wirekit::reveal>
:::

## Preset Aliases

Four short-form aliases map to the canonical directional slide presets — handy when porting from `fade-up` / `fade-down` style conventions used in other UI libraries:

| Short form   | Canonical preset |
|--------------|------------------|
| `fade-up`    | `slide-up-in`    |
| `fade-down`  | `slide-down-in`  |
| `fade-left`  | `slide-left-in`  |
| `fade-right` | `slide-right-in` |

```blade
{{-- These two reveals render identically: --}}
<x-wirekit::reveal preset="fade-up">...</x-wirekit::reveal>
<x-wirekit::reveal preset="slide-up-in">...</x-wirekit::reveal>
```

The aliases are resolved at component-render time; the underlying Alpine helper still sees the canonical `slide-*-in` preset name.

## Triggers

The `trigger` prop controls when the animation fires:

| Trigger | Behavior |
|---------|----------|
| `viewport` (default) | Fires when 40% of the element scrolls into view (IntersectionObserver). Most common case. |
| `click` | Fires on click of the host element. |
| `manual` | Fires when developer dispatches `Alpine.$dispatch('wirekit:reveal')` from anywhere on the page. |

:::preview{title="Click trigger" replay="false"}
<x-wirekit::reveal preset="bounce-in" trigger="click" duration="slow" :once="false" style="--wk-stagger-step: 0ms; width: fit-content;">
    <x-wirekit::card><x-wirekit::card.body>Click me to bounce</x-wirekit::card.body></x-wirekit::card>
</x-wirekit::reveal>
:::

## Duration

Three duration tokens — `fast` (150ms), `normal` (300ms, default), `slow` (600ms). Override via the `duration` prop:

```blade
<x-wirekit::reveal preset="fade" duration="slow">…</x-wirekit::reveal>
```

## Delay

Hold the entrance for a beat before it begins. Useful for sequencing cards or letting a hero-section heading land before the supporting copy follows. Five tokens map to themeable CSS variables:

| Token | Default | Use for |
|-------|---------|---------|
| `none` | `0ms` | explicit zero (overrides config defaults) |
| `sm` | `75ms` | the rhythm step used by `<x-wirekit::feature-grid stagger>` |
| `md` | `150ms` | a single beat between two reveals |
| `lg` | `300ms` | hero → CTA pacing |
| `xl` | `500ms` | dramatic delayed lead-in |

```blade
<x-wirekit::reveal preset="slide-up" delay="md">…</x-wirekit::reveal>
```

Pass an integer for a one-off custom rhythm (raw milliseconds):

```blade
<x-wirekit::reveal preset="fade" :delay="125">…</x-wirekit::reveal>
```

The delay collapses to `0ms` under `prefers-reduced-motion: reduce` so users with the OS preference set never wait through the rhythm before the snap-to-final.

:::preview{title="Reveal with 300ms delay token"}
<x-wirekit::reveal preset="slide-up" delay="lg" duration="slow" style="--wk-stagger-step: 0ms">
    <x-wirekit::card><x-wirekit::card.body>I land 300ms after the page settles.</x-wirekit::card.body></x-wirekit::card>
</x-wirekit::reveal>
:::

## Direct Alpine helper

For non-Blade contexts or finer control, use the `wirekitAnimate` helper directly:

```blade
<div x-data="wirekitAnimate('slide-up-in', { trigger: 'click', once: false })" data-replayable="true">
    Click me to re-animate
</div>
```

The helper is registered automatically by the full WireKit JS bundle; for the core bundle, import `resources/js/components/animate.js` manually.

## Props

| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `preset` | string | `'fade-in'` | One of 22 keyframes (11 bases × in/out). Bases: `fade`, `slide-up`, `slide-down`, `slide-left`, `slide-right`, `scale`, `zoom`, `flip`, `rotate`, `bounce`, `spring`. Pass `'fade'` and the component appends `-in` automatically. |
| `trigger` | string | `'viewport'` | `viewport`, `click`, or `manual` |
| `duration` | string | `'normal'` | `fast` (150ms), `normal` (300ms), `slow` (600ms) |
| `delay` | string\|int\|null | `null` | Hold before the entrance begins. Token: `none`, `sm`, `md`, `lg`, `xl`. Or an integer in milliseconds. Honors `prefers-reduced-motion: reduce` (collapses to 0). |
| `once` | bool | `true` | If `false`, re-fires on every trigger |
| `threshold` | float | `0.4` | IntersectionObserver threshold (0..1) — only used when `trigger='viewport'` |
| `scope` | string | `null` | Scoped personalization name |

## Slots

| Slot | Description |
|------|-------------|
| default | Content to animate |

## Accessibility

- **Reduced motion**: when `prefers-reduced-motion: reduce` is set at the OS level, the global `@media` block in `wirekit.css` snaps `animation-duration` to `0.01ms` — element appears in final state immediately, no motion.
- **No focus stealing**: the helper does NOT `focus()` the element on reveal. Focus management stays in developer control.
- **Reveal-on-scroll does not auto-announce**: SR users hear the slot content normally as they navigate; the visual reveal is purely sighted-user enhancement.
- **Pass `aria-live` on the wrapper** if your slot content carries dynamic announcements:

```blade
<x-wirekit::reveal preset="slide-up" aria-live="polite">
    <p>{{ $statusMessage }}</p>
</x-wirekit::reveal>
```

- WCAG 2.3.3 (Animation from Interactions): all animations are opt-in via this component or the `wk-animate-*` utility classes. Developers who don't use them see no animations.

## Keyboard Interaction

This component is purely structural. Keyboard interaction is delegated to its slot content.

When `trigger="click"`, the host `<div>` becomes the click target — wrap interactive content (buttons, links) inside the slot rather than relying on the wrapper for activation.

## Pitfalls

- **Don't animate above-the-fold content with `viewport` trigger.** It's intersecting from page load, so there's no "scroll into view" event — the animation fires immediately with no perceived motion. Use `trigger="manual"` + dispatch on `DOMContentLoaded` if you want a hero-section reveal.
- **Don't combine with components that own their own transitions.** `<x-wirekit::modal>`, `<x-wirekit::drawer>`, `<x-wirekit::toast-region>`, `<x-wirekit::tooltip>`, `<x-wirekit::dropdown>`, `<x-wirekit::popover>` all have built-in entrance transitions; wrapping them in Reveal causes a double-motion conflict.
- **Don't use `preset="fade-out"` as a default.** Out-presets fade content TO opacity 0 — the element is invisible at the end. Use them only when you intend to remove the element after the animation (e.g. via Livewire wire:replace or x-show).

## Design Tokens

| Token | Default | Used for |
|-------|---------|----------|
| `--motion-wk-duration-fast` | `150ms` | `duration="fast"` |
| `--motion-wk-duration-normal` | `300ms` | `duration="normal"` (default) |
| `--motion-wk-duration-slow` | `600ms` | `duration="slow"` |
| `--motion-wk-easing-out` | `cubic-bezier(0.16, 1, 0.3, 1)` | Most presets |
| `--motion-wk-easing-in` | `cubic-bezier(0.7, 0, 0.84, 0)` | Bounce-out, spring-out |
| `--motion-wk-easing-spring` | `cubic-bezier(0.5, 1.5, 0.5, 1)` | Flip, rotate, bounce, spring |
| `--motion-wk-delay-none` | `0ms` | `delay="none"` |
| `--motion-wk-delay-sm` | `75ms` | `delay="sm"` |
| `--motion-wk-delay-md` | `150ms` | `delay="md"` |
| `--motion-wk-delay-lg` | `300ms` | `delay="lg"` |
| `--motion-wk-delay-xl` | `500ms` | `delay="xl"` |

## See Also

- [Animations reference](../animations.md) — full token table + preset gallery
- `<x-wirekit::stat animate>` — value count-up animation (separate plugin)
- WAI-ARIA APG: [Animation from Interactions](https://www.w3.org/WAI/WCAG21/Understanding/animation-from-interactions.html) (WCAG 2.3.3)
