HextaUI

Shimmer

Ein Lichtband, das für laufende Zustände über Text streicht, aus der Textfarbe getönt und bei reduzierter Bewegung statisch.

Thinking about your question…

export function ShimmerDemo() {
  return (
    <p className="shimmer text-base text-muted-foreground">
      Thinking about your question…
    </p>
  )
}

Shimmer ist eine Tailwind-Utility aus dem tailwind.css von shadcn. Das HextaUI-Theme importiert sie bereits, wenn du also das Theme oder eine Komponente hinzugefügt hast, hast du sie.

pnpm dlx shadcn@latest add https://hextaui.com/r/theme.json

Ohne das Theme installiere shadcn und importiere sein CSS nach Tailwind.

pnpm add shadcn
app/globals.css
@import "tailwindcss";
@import "shadcn/tailwind.css";
<p className="shimmer text-muted-foreground">Generating response…</p>

Nutze ihn für kurzen Text, der laufende Arbeit beschreibt, etwa einen denkenden Assistenten, eine Dateiverarbeitung oder einen laufenden Schritt. Das wandernde Highlight sagt „arbeitet noch“, ohne dass ein Spinner neben den Worten Platz belegt.

Der Text wird per background-clip: text mit einem Verlauf gemalt, und ein helleres Band gleitet darüber. Das Band wird aus der eigenen Farbe des Textes abgeleitet und passt daher ohne Konfiguration zu gedämpftem, Vordergrund- oder farbigem Text und wird im Dark Mode heller, wo ein helleres Band besser wirkt.

  • Bei reduzierter Bewegung wird der Verlauf ganz entfernt, und der Text erscheint in seiner normalen Farbe.
  • In rechts-nach-links-Layouts kehrt sich der Lauf um und verläuft weiterhin in Leserichtung.
  • Der Text bleibt echter Text: markierbar, durchsuchbar und von Screenreadern normal vorgelesen.

Optionen

Tempo, Bandbreite, Farbe und Winkel sind jeweils eine Klasse.

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>
  )
}

Statusmeldungen

Schimmere, solange eine Aufgabe läuft, und streiche beim Abschluss einmal mit shimmer-once darüber. Ein neuer Key startet den Durchlauf für jeden neuen Schritt neu.

"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>
  )
}
<p className="shimmer md:shimmer-none">Generating response…</p>
<p className="shimmer shimmer-reverse">Undoing…</p>
  • Halte es bei ein bis zwei Zeilen. Ein schimmernder Absatz ist anstrengend zu lesen.
  • Setze den Text in einen role="status"-Bereich, wenn er sich ändert, damit der neue Schritt angesagt wird. Der Shimmer selbst ist Dekoration.
  • Für Platzhalterblöcke statt Text nutze Skeleton, das Flächen mit dem animate-shimmer des Themes schimmern lässt.
KlasseBeschreibung
shimmerStreicht alle 2s ein Highlight über den Text.
shimmer-onceStreicht einmal, statt sich zu wiederholen.
shimmer-reverseStreicht in die Gegenrichtung.
shimmer-noneSchaltet ihn ab, zum Beispiel bei einem Breakpoint.
shimmer-color-<color>Farbe des Highlights, aus dem Theme oder beliebig. Nimmt einen Opacity-Modifier.
shimmer-duration-<ms>Dauer eines Durchlaufs in Millisekunden.
shimmer-spread-<number>Breite des Bands auf der Spacing-Skala oder eine beliebige Länge. Standard ist 3ch + 40px.
shimmer-angle-<deg>Neigung des Bands. Standard ist 20°.