# Shimmer

> A band of light that sweeps across text for in-progress states, tinted from the text color and still under reduced motion.

Docs: https://hextaui.com/docs/shimmer
Markdown: https://hextaui.com/docs/shimmer.md

```tsx title="components/examples/shimmer/demo.tsx"
export function ShimmerDemo() {
  return (
    <p className="shimmer text-base text-muted-foreground">
      Thinking about your question…
    </p>
  )
}
```

## Installation

Shimmer is a Tailwind utility from shadcn's `tailwind.css`. The HextaUI theme already imports it, so if you've added the theme or any component, you have it.

```bash
npx shadcn@latest add https://hextaui.com/r/theme.json
```

Without the theme, install `shadcn` and import its CSS after Tailwind.

```bash
pnpm add shadcn
```

```css title="app/globals.css"
@import "tailwindcss";
@import "shadcn/tailwind.css";
```

## Usage

```tsx
<p className="shimmer text-muted-foreground">Generating response…</p>
```

Use it on short text that describes work in progress, like an assistant thinking, a file processing or a step that's running. The moving highlight says "still working" without a spinner taking up space beside the words.

## How it works

The text is painted with a gradient through `background-clip: text`, and a lighter band slides across it. The band is derived from the text's own color, so it suits muted, foreground or colored text without configuration, and it brightens in dark mode, where a lighter band reads better.

- Under reduced motion the gradient is removed entirely and the text renders in its normal color.
- In right-to-left layouts the sweep reverses, so it still travels in reading direction.
- The text stays real text: selectable, searchable and read normally by screen readers.

## Examples

### Options

Speed, band width, color and angle are each one class.

```tsx title="components/examples/shimmer/options.tsx"
export function ShimmerOptions() {
  return (
    <div className="flex flex-col items-start gap-4 text-sm">
      <p className="shimmer text-muted-foreground shimmer-duration-1000">
        Faster: shimmer-duration-1000
      </p>
      <p className="shimmer text-muted-foreground shimmer-spread-24">
        Wider band: shimmer-spread-24
      </p>
      <p className="shimmer text-foreground shimmer-color-info">
        Tinted: shimmer-color-info
      </p>
      <p className="shimmer text-muted-foreground shimmer-angle-45">
        Steeper: shimmer-angle-45
      </p>
    </div>
  )
}
```

### Status updates

Shimmer while a task runs, then sweep once with `shimmer-once` when it finishes. Changing the key restarts the sweep for each new step.

```tsx title="components/examples/shimmer/status.tsx"
"use client"

import * as React from "react"
import { cn } from "cn"

import { Button } from "@/components/ui/button"

const steps = ["Reading files…", "Planning changes…", "Writing code…"]

export function ShimmerStatus() {
  const [step, setStep] = React.useState<number | null>(null)

  React.useEffect(() => {
    if (step === null || step >= steps.length) {
      return
    }
    const timer = setTimeout(() => setStep(step + 1), 1600)
    return () => clearTimeout(timer)
  }, [step])

  const done = step !== null && step >= steps.length

  return (
    <div className="flex flex-col items-center gap-4">
      <p
        key={step ?? "idle"}
        role="status"
        className={cn(
          "h-5 text-sm text-muted-foreground",
          step !== null && "shimmer",
          done && "shimmer-duration-1200 shimmer-once"
        )}
      >
        {step === null ? "Ready" : done ? "Done." : steps[step]}
      </p>
      <Button variant="outline" size="sm" onClick={() => setStep(0)}>
        Run task
      </Button>
    </div>
  )
}
```

### Direction and breakpoints

```tsx
<p className="shimmer md:shimmer-none">Generating response…</p>
<p className="shimmer shimmer-reverse">Undoing…</p>
```

## Good to know

- Keep it to a line or two. A shimmering paragraph is tiring to read.
- Put the text in a `role="status"` region when it changes, so the new step is announced. The shimmer itself is decoration.
- For placeholder blocks rather than text, use [Skeleton](https://hextaui.com/docs/skeleton), which shimmers surfaces with the theme's `animate-shimmer`.

## API reference

| Class | Description |
| --- | --- |
| `shimmer` | Sweeps a highlight across the text, every 2s. |
| `shimmer-once` | Sweeps once instead of repeating. |
| `shimmer-reverse` | Sweeps in the opposite direction. |
| `shimmer-none` | Turns it off, for example at a breakpoint. |
| `shimmer-color-<color>` | Color of the highlight, from the theme or arbitrary. Takes an opacity modifier. |
| `shimmer-duration-<ms>` | Length of one sweep in milliseconds. |
| `shimmer-spread-<number>` | Width of the band on the spacing scale, or any length. Defaults to 3ch + 40px. |
| `shimmer-angle-<deg>` | Tilt of the band. Defaults to 20°. |

## Notes for AI assistants

- Install a component with the shadcn CLI: `npx shadcn@latest add https://hextaui.com/r/<name>.json`. It adds the source, the HextaUI theme tokens and any HextaUI components it depends on. `https://hextaui.com/r/all.json` installs every component.
- The code is then owned by the project, like shadcn/ui. There is no HextaUI npm package. HextaUI is MIT licensed and free for personal and commercial use.
- Behavior and accessibility come from Base UI (`@base-ui/react`). Compose with the `render` prop, not `asChild`.
- Styling uses Tailwind CSS v4 with theme tokens. Merge classes with `cn` from the `cn` package.
- Icons come from `@tabler/icons-react`.
- Import components from `@/components/ui/<name>`, hooks from `@/hooks/<name>` and utilities from `@/lib/<name>`.

Every HextaUI doc: https://hextaui.com/llms.txt
