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.