Skip to main content
WireKit
Copy for LLM

Replay Button

Re-runs (or resets) a demo by replacing the wrapping element's inner HTML with a saved snapshot, then calling Alpine.initTree() so every Alpine scope re-binds. Pairs with the data-replayable="true" attribute emitted by any WireKit preview that can be re-run or reset — animation-capable components (<x-wirekit::reveal>, <x-wirekit::stat animate>, animated card / hero / cta / feature / footer, chart) and state-mutating components whose demo is "used up" by interaction (a dismissible <x-wirekit::badge> or <x-wirekit::alert>).

Why this component exists: it primarily powers WireKit's own documentation site — docs.wirekit.app wraps every re-runnable example in the replay pattern and renders a ↻ Replay control on top. Since it ships in the package regardless, it doubles as a ready-made building block for your own app: wire it up to re-run an animation, reset an interactive demo to its starting state, or restore a dismissed badge or alert. Combine it with the data-replayable contract below and use it however fits your UI.

How it works

The pattern requires three pieces:

  1. A wrapper element carrying data-replay-target and data-replay-source="<encoded snapshot>".
  2. Inside that wrapper: the actual demo (<x-wirekit::reveal>, <x-wirekit::stat animate>, etc.) which emits data-replayable="true".
  3. The <x-wirekit::replay-button> itself, anywhere in the same DOM tree.

On click, the button walks closest('[data-replay-target]') from itself, replaces that element's innerHTML with the snapshot, then calls Alpine.initTree(root) to re-mount.

The docs site auto-injects this pattern around every :::preview block whose source matches a data-replayable shape, so developers reading the docs see a "↻ Replay" button on every re-runnable or resettable example — an animated demo, or a dismissible badge / alert whose chips can be restored after they are dismissed.

Usage

The simplest shape — drop an animated demo into a :::preview block and the docs site auto-wires the replay-target wrapper around it:

Replay-aware reveal animation
Hello!

For developers wiring the pattern manually in their own app (outside the docs auto-injection), the full shape is:

<div data-replay-target
     data-replay-source="{{ e('<x-wirekit::reveal preset=\'fade\'>Hello!</x-wirekit::reveal>') }}">
    <x-wirekit::reveal preset="fade">Hello!</x-wirekit::reveal>
</div>
<x-wirekit::replay-button />

The data-replay-source attribute MUST hold an HTML-escaped snapshot of the inner markup — the click handler decodes it and assigns it to innerHTML before re-running Alpine.initTree(). Use e(...) or Blade's {{ }} echo to escape angle brackets and quotes, otherwise the browser parses the snapshot prematurely and the replay restores broken HTML.

The button picks up the closest data-replay-target ancestor automatically. To target a specific selector instead, pass target="…":

<x-wirekit::replay-button target="[data-demo-root]" />

Customizing the icon

Pass slot content to override the default circular-arrow glyph:

<x-wirekit::replay-button>
    <x-wirekit::icon name="refresh" size="sm" />
    Replay
</x-wirekit::replay-button>

Style hooks

Single BEM root: wk-replay-button. Override via your app.css:

.wk-replay-button {
    color: var(--color-wk-text-subtle);
    transition: color var(--motion-wk-duration-md);
}

.wk-replay-button:hover {
    color: var(--color-wk-text);
}

Props

Prop Type Default Notes
label string 'Replay' Becomes aria-label on the rendered <button>.
target string|null null Optional CSS selector; when set, the click handler walks $el.closest(selector) instead of [data-replay-target].

Accessibility

  • Default aria-label="Replay" (overridable via the label prop).
  • Renders as a real <button type="button"> so keyboard activation (Space / Enter) works without extra wiring.
  • Dispatches wirekit:replayed (bubbling) on the data-replay-target root after re-mount; listeners can hook into the event for analytics / focus management.

Keyboard Interaction

Key Action
Tab Move focus to / away from the button (native browser tab order).
Space Activate the replay (re-mount the demo).
Enter Activate the replay (re-mount the demo).

Focus stays on the button after activation so a keyboard user can replay multiple times without needing to re-tab. The dispatched wirekit:replayed event fires after the inner DOM is replaced; developers can listen to it and shift focus elsewhere if the demo's first interactive element should receive focus instead.

Was this page helpful?

Voting requires cookies or local storage. What we store