Skip to main content
Gremorie
Chatbot

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...

'use client';import { Shimmer } from '@gremorie/rx-ai';export function ShimmerPreview() {  return <Shimmer>Buscando referencias nos docs...</Shimmer>;}

Anatomy

Shimmer   animated gradient sweep over text — leaf primitive (no subcomponents)

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>;
}
npx gremorie@latest add ng-shimmer

Prerequisite

Angular components emit Tailwind utility classes and ship no compiled CSS. Without the setup below in src/styles.css the component mounts but renders completely unstyled. Requires Tailwind CSS v4.

@import 'tailwindcss';@import '@gremorie/tokens/theme.css';/* Required. Tailwind v4 skips node_modules by default, so without this line   the components' utility classes never reach your compiled CSS and every   Gremorie component renders unstyled. */@source '../node_modules/@gremorie';

The @source line is required: Tailwind v4 skips node_modules by default. Adjust the relative path if your stylesheet is not at src/styles.css. Full setup in Installation.

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