77 / Feedback
Shimmering Text
Words with a light moving across them, for the wait between asking and the first token.
Checking the renewal window
"use client"
import { ShimmeringText } from "mischief-ui/shimmering-text"
export function ShimmeringTextDemo() {
return (
<div className="w-full max-w-sm space-y-3 text-sm">
<ShimmeringText>Reading the contract…</ShimmeringText>
<br />
<ShimmeringText duration={1.4} extent={0.5}>
Checking the renewal window
</ShimmeringText>
</div>
)
}Installation
Copy the source into your project, or keep it behind a package.
npx shadcn@latest add Tinkerers-Labs/mischief-ui/shimmering-textimport { ShimmeringText } from "mischief-ui/shimmering-text"Or paste it in yourself. The source imports the shared cn helper from @/lib/utils, so point that at your own copy.
"use client" import * as React from "react" import { cn } from "@/lib/utils" export type ShimmeringTextProps = React.HTMLAttributes<HTMLSpanElement> & { children: React.ReactNode /** Seconds for one pass of the sweep. */ duration?: number /** How wide the bright band is, as a fraction of the text. */ extent?: number /** Stops the sweep and leaves the words as they are. */ paused?: booleanUsage
export function Waiting() {
return <ShimmeringText>Reading the contract…</ShimmeringText>
}It is still text
The sweep is a background the words are clipped to, not an image of the words. They can be selected, translated, searched and read aloud exactly as if nothing were moving over them.
Where motion is unwelcome the clipping is dropped and the words keep their own colour. That is why the resting state is a colour rather than transparency: text that is transparent without its animation is text that has gone.
API
childrenReactNodeThe words.durationnumberSeconds for one pass. Defaults to 2.4.extentnumberHow wide the bright band is, nought to one. Defaults to 0.35.pausedbooleanStops the sweep and leaves the words as they are.Accessibility
The words are ordinary text throughout, so nothing about them is conditional on the animation. Under prefers-reduced-motion the sweep is not applied at all and the text renders in the muted foreground colour, which is the state it would have ended in anyway. It carries no live region of its own: what is being waited for belongs in the sentence, not in an announcement that repeats every time the light goes round.