Skip to main content
WireKit
Copy for LLM

Shimmer

An animated highlight sweep that runs across the letterforms of live text — the "Generating response…" / "Thinking…" affordance you see while an AI assistant streams or a long task runs. Unlike Skeleton, which shimmers a gray placeholder block, Shimmer clips the gradient to the real copy via background-clip: text, so the words themselves shimmer.

The text stays in the DOM and is read by screen readers — the shimmer is purely decorative and is disabled under reduced-motion, forced-colors, and reduced-transparency.

Basic Usage

A shimmering status line
Generating response…

Settled state (active)

The active prop is what makes this Livewire-native: bind it to a component property so the shimmer runs only while work is in flight and settles to plain text when done — no conditional markup, no JavaScript.

Active vs. settled
Streaming the answer… Here is the finished answer.

Duration

duration accepts any CSS time value and overrides the --shimmer-wk-duration token for that instance — slower reads as calmer, faster as more urgent.

Custom shimmer speeds
Deliberating… Working fast…

In context

Because the wrapper defaults to an inline <span>, a shimmer sits inside a heading, a row, or next to a Spinner.

Shimmer alongside a spinner
Loading Assistant is thinking…

Livewire

Drive active straight from a component property so the effect mirrors the real streaming state:

{{-- 1. `$streaming` is true only while the assistant streams tokens --}}
<x-wirekit::shimmer :active="$streaming">
    {{ $partialResponse ?: 'Generating response…' }}
</x-wirekit::shimmer>
// 2. Flip $streaming around the streamed call — the shimmer follows it
public bool $streaming = false;

public function ask(): void
{
    $this->streaming = true;
    $this->stream(to: 'partialResponse', content: '…');  // wire:stream
    $this->streaming = false;
}

Props

Prop Type Default Description
active bool true When false the slot renders as plain inherited-color text (no shimmer). Bind to a Livewire property to gate the effect on streaming state.
as string 'span' Wrapper tag: span, div, p, strong, em.
duration string|null null Any CSS <time>; overrides --shimmer-wk-duration for this instance.
scope string|null null Scoped personalization name.

Accessibility

  • The shimmering text is real text — it stays in the DOM and is announced by screen readers. The shimmer is decorative only.
  • Under prefers-reduced-motion: reduce the sweep animation is removed.
  • Under forced-colors: active (Windows High Contrast) the transparent glyph fill is restored to a solid, system-colored glyph so the text never vanishes.
  • Under prefers-reduced-transparency: reduce the transparent fill is likewise restored to solid inherited-color text.
  • For a streaming region, pair the shimmer with an aria-live="polite" container and announce the settled text once — not every token.

Keyboard Interaction

This component is purely presentational and does not respond to keyboard input.

Pitfalls

  • Don't shimmer text the user must read carefully. The effect is for transient status ("Generating…"), not for body copy that lingers.
  • Turn it off when done. Bind active to the real loading state so settled content renders as ordinary, high-contrast text.
  • Keep runs short. A shimmer on a long paragraph draws the eye away from the content — reserve it for a status line.

Design Tokens

Element Token
Travel duration --shimmer-wk-duration (default 2s)
Highlight band half-width --shimmer-wk-band (default 3ch)
Band tilt --shimmer-wk-angle (default 105deg)
Base glyph color --color-wk-text-muted
Highlight band color --color-wk-text

The gradient is clipped to the text via background-clip: text, which is in the supported-browser baseline (Chrome/Edge 111, Safari 16.4, Firefox 128).

Further Reading

Was this page helpful?

Voting requires cookies or local storage. What we store