Skip to main content
Gremorie

Shimmer

Animated text shimmer effect that slides a gradient across the characters - the universal "the model is working" cue.

Overview

Shimmer is the streaming text affordance. It wraps a string in a motion element that animates a horizontal gradient across the characters, giving the model's output a subtle "loading" wash without spinners. It is the same primitive used internally by Reasoning, Plan, and Suggestion when they need to indicate streaming.

Use it for ephemeral status text - "Thinking...", "Generating response...", "Loading..." - in spots where a spinner would feel clunky.

Preview

Buscando referencias nos docs...

Installation

bash npx gremorie@latest add rx-shimmer
bash pnpm dlx gremorie@latest add rx-shimmer
bash yarn dlx gremorie@latest add rx-shimmer
bash bunx --bun gremorie@latest add rx-shimmer

Usage

import { Shimmer } from "@gremorie/rx-ai";

export function Example() {
  return <Shimmer>Thinking...</Shimmer>;
}
import { Component } from "@angular/core";
import { Shimmer } from "@gremorie/ng-ai";

@Component({
selector: "app-example",
standalone: true,
imports: [Shimmer],
template: `<span ngShimmer>Thinking...</span>`,
})
export class ExampleComponent {}

The Angular version is a directive ([ngShimmer]) rather than a component. Apply it to any element with text content; the spread auto-scales with character count, mirroring the React implementation.

API

<Shimmer>

PropTypeDefaultDescription
childrenstring-Required. The text to shimmer. String is required so the spread can scale with character count.
asElementType"p"Override the rendered element (e.g. "span" to inline inside a sentence).
classNamestring-Extra classes.
durationnumber2Seconds per cycle. Lower = faster shimmer.
spreadnumber2Multiplier on the gradient spread (per character). Lower = tighter wash.

Memoized with React.memo.

Composition

Shimmer is a single primitive. Drop it anywhere a string would go; it picks up the surrounding font and color automatically.

Variations

Loading hint

The 90% case: a short status string.

<Shimmer>Generating response...</Shimmer>

Inline inside a sentence

Render as span to shimmer a single word inside a normal paragraph.

<p>
  The assistant is <Shimmer as="span">thinking</Shimmer> about your request.
</p>

Faster, tighter shimmer

For shorter labels where the default 2s feels slow.

<Shimmer duration={1} spread={1}>
  Reasoning
</Shimmer>

Reasoning trigger override

A common use - inject Shimmer into ReasoningTrigger via getThinkingMessage to localize or rebrand the label.

<Reasoning isStreaming>
  <ReasoningTrigger
    getThinkingMessage={(streaming) =>
      streaming ? <Shimmer>Pensando...</Shimmer> : null
    }
  />
  <ReasoningContent>{thinking}</ReasoningContent>
</Reasoning>

Accessibility

  • Keyboard: no interaction - Shimmer is a static text element.
  • ARIA: the text content is preserved in the DOM (no obfuscation), so screen readers announce it normally.
  • Screen readers: keep the label semantically meaningful ("Thinking", "Loading", "Generating response"). Avoid decorative-only strings.
  • Reduced motion: the animation uses Framer Motion. Honour prefers-reduced-motion: reduce by either swapping the shimmer for a static label at the call site, or wrapping with a media-query check.
  • Reasoning - uses Shimmer internally while streaming
  • Plan - uses Shimmer on title and description while streaming
  • Suggestion - quick-replies that often pair with a shimmering label

On this page