HextaUI

Shimmer

Una banda de luz que barre el texto en estados en curso, teñida a partir del color del texto y estática con movimiento reducido.

Thinking about your question…

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

Shimmer es una utilidad de Tailwind del tailwind.css de shadcn. El tema de HextaUI ya lo importa, así que si has añadido el tema o cualquier componente, ya lo tienes.

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

Sin el tema, instala shadcn e importa su CSS después de Tailwind.

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

Úsalo en textos cortos que describan trabajo en curso, como un asistente pensando, un archivo procesándose o un paso en ejecución. El resaltado en movimiento dice "sigo trabajando" sin que un spinner ocupe espacio junto a las palabras.

El texto se pinta con un degradado mediante background-clip: text, y una banda más clara se desliza sobre él. La banda se deriva del propio color del texto, así que encaja con texto atenuado, de primer plano o de color sin configuración, y se ilumina en modo oscuro, donde una banda más clara se lee mejor.

  • Con movimiento reducido el degradado se elimina por completo y el texto se renderiza con su color normal.
  • En diseños de derecha a izquierda el barrido se invierte, así que sigue recorriendo en la dirección de lectura.
  • El texto sigue siendo texto real: seleccionable, buscable y leído con normalidad por los lectores de pantalla.

Opciones

La velocidad, el ancho de la banda, el color y el ángulo son una clase cada uno.

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

Actualizaciones de estado

Aplica shimmer mientras se ejecuta una tarea y haz un barrido único con shimmer-once cuando termine. Cambiar la key reinicia el barrido en cada nuevo paso.

"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>
  • Mantenlo en una o dos líneas. Un párrafo con brillo cansa al leerlo.
  • Pon el texto en una región role="status" cuando cambie, para que se anuncie el nuevo paso. El brillo en sí es decorativo.
  • Para bloques de marcador de posición en lugar de texto, usa Skeleton, que hace brillar las superficies con el animate-shimmer del tema.
ClaseDescripción
shimmerBarre el texto con un resaltado, cada 2s.
shimmer-onceBarre una sola vez en lugar de repetirse.
shimmer-reverseBarre en la dirección opuesta.
shimmer-noneLo desactiva, por ejemplo en un breakpoint.
shimmer-color-<color>Color del resaltado, del tema o arbitrario. Acepta un modificador de opacidad.
shimmer-duration-<ms>Duración de un barrido en milisegundos.
shimmer-spread-<number>Ancho de la banda en la escala de espaciado, o cualquier longitud. Por defecto es 3ch + 40px.
shimmer-angle-<deg>Inclinación de la banda. Por defecto es 20°.