caliper uidocs

Text loop

Free

One word in a sentence that cycles through a few options. The widest word reserves the space, it pauses on hover, focus, off screen and in a hidden tab, and a pause button stops it.

Installs components/ui/text-loop.tsxDepends on lucide-reactMotion honours reduced motion
pnpm dlx shadcn@latest add https://caliperui.site/r/text-loop.json

Close the books faster, with fewer errors, from anywhere

Ask about revenue, churn, refunds, pipeline in plain words.

When to use #

Use it for

  • A marketing headline with three or four audiences or outcomes.
  • An empty state that hints at what you can ask.

Skip it when

  • Information people need to read; every option must also make sense alone.
  • Product UI and controls; keep labels still.

Installation #

terminal
pnpm dlx shadcn@latest add https://caliperui.site/r/text-loop.json

Adds its 2 files to components/ui/, each with its own stylesheet, and installs their packages. No account needed. The first part also adds Caliper UI’s tokens; import them once as in Installation.

Usage #

This is the code behind the preview above.

example.tsx
import { TextLoop } from "@/components/ui/text-loop"

export function TextLoopDemo() {
  return (
    <div className="grid gap-6">
      <h2 className="text-3xl font-medium tracking-[-0.02em]">
        Close the books <TextLoop words={["faster", "with fewer errors", "from anywhere"]} reserve={false} className="text-muted-foreground" />
      </h2>
      <p className="text-sm text-muted-foreground">
        Ask about <TextLoop words={["revenue", "churn", "refunds", "pipeline"]} control={false} className="font-medium text-foreground" /> in plain words.
      </p>
    </div>
  );
}

API reference #

TextLoop

component
PropTypeDefaultDescription
words *readonly string[]—
intervalnumber2600Milliseconds each word stays.
controlbooleantrueShow the pause button. Required by the motion rules when the loop runs longer than five seconds.
reservebooleantrueKeep the widest word's width. Turn off only when nothing follows the word on its line.
classNamestring—

Accessibility #

It is built on native elements and keeps aria-hidden, aria-label and aria-pressed in step with state.

No custom key handling; Tab and the native activation keys do the work.

Motion #

It checks prefers-reduced-motion itself and settles immediately instead of travelling. Every state is still reachable.