ComponentsNumbers
Countdown
Count down to a moment, second by second.
Installation
$ npx shadcn@latest add @textlab/countdownNeeds @textlab in your components.json. Setup takes a minute.
Usage
usage.tsx
import { Countdown } from "@/components/textlab/countdown/countdown";
<Countdown to="2026-12-31T23:59:59Z" variant="roll" />Variants
fliprollplainProps
| Prop | Type | Default | Description |
|---|---|---|---|
| to* | Date | string | number | – | The moment to count down to. |
| variant | "flip" | "roll" | "plain" | "flip" | Split-flap tiles, rolling digits, or a soft crossfade. |
| units | ("days" | "hours" | "minutes" | "seconds")[] | all four | Units to show, largest first. |
| labels | Partial<Record<Unit, string>> | null | English labels | Labels under each unit. null hides them. |
| onComplete | () => void | – | Called when a one-shot animation finishes. |
| as | ElementType | "div" | Rendered element. |
| reducedMotion | "user" | "always" | "never" | "user" | user follows the OS setting; always shows the still version. |
| className | string | – | Merged onto the root. |
When to use it
Reach for it
- Launches, sales and events with a fixed start time.
- Timers people glance at rather than read continuously.
Skip it
- Elapsed-time stopwatches; this only counts down.
- Precise timing below one second.
Accessibility and motion
Accessibility
- A visually hidden sentence reads the remaining time in words.
- It is not a live region, so it never interrupts every second.
Motion
- Ticks align to the wall clock, so every second changes on the beat.
- Seconds use the same flip or roll as the larger units.
Reduced motion. Digits change in place with no flip, roll or fade.
Performance
- One timer per countdown, scheduled for the next whole second.
- Only units that change animate.