ComponentsReveal
Tracking reveal
Letter spacing breathes open as it appears.
Installation
$ npx shadcn@latest add @textlab/tracking-revealNeeds @textlab in your components.json. Setup takes a minute.
Usage
usage.tsx
import { TrackingReveal } from "@/components/textlab/tracking-reveal/tracking-reveal";
<TrackingReveal as="h2" text="Quiet confidence" />Variants
opencloseProps
| Prop | Type | Default | Description |
|---|---|---|---|
| text* | string | – | The copy. |
| variant | "open" | "close" | "open" | open starts packed and breathes out; close starts wide and gathers in. |
| spread | number | 0.08 | Distance each letter travels per step from the center, in em. |
| as | ElementType | "span" | Rendered element. |
| trigger | "mount" | "inView" | "hover" | "manual" | "inView" | What starts the animation. manual follows `active`. |
| active | boolean | false | Drives trigger="manual". |
| once | boolean | true | In view: play once instead of on every entry. |
| delay | number | 0 | Seconds before the first part moves. |
| duration | number | 1.1 | Seconds each part takes. |
| ease | EaseName | [number, number, number, number] | "emphasized" | Easing token or cubic bezier. |
| reducedMotion | "user" | "always" | "never" | "user" | user follows the OS setting; always shows the still version. |
| className | string | – | Merged onto the root. |
| onComplete | () => void | – | Called when a one-shot animation finishes. |
When to use it
Reach for it
- Luxury or editorial titles where restraint matters.
- Short uppercase labels and wordmarks.
Skip it
- Long titles; the outer letters travel far.
- Body text.
Accessibility and motion
Accessibility
- Letters are aria-hidden; the title is read once.
- No reflow, so surrounding layout never moves.
Motion
- Every letter moves together; distance grows with its offset from the center.
- Uses the emphasized ease for a long, soft landing.
Reduced motion. Shows the text at its normal spacing.
Performance
- Transforms instead of letter-spacing, so no layout work per frame.