shadcn.io is not affiliated with official shadcn/ui
Countdown Text counts down to a moment, live: as each second runs out, the digits that change drop into their windows from above while the old ones fall away, so only what changed moves. It writes the time left with its units (3d 04h 05m 09s), in short or long words, or as a digital readout, and stops at zero, where it calls onComplete once.
Use it for a launch page, the end of a sale, an event lobby, or a wait before something can be done again. For the time of day, use Clock Text; for "in 5 minutes" or "5 minutes ago", Relative Time Text. A small timer wakes as each whole second runs out and the digits move with CSS keyframe animations the install adds to your stylesheet, with no animation library; with reduced motion the digits change in place.
Installation
Usage
import { CountdownText } from "@/components/ui/countdown-text";<CountdownText target="2027-01-01T00:00:00Z" />Demos
Format
format is how the time left is written: narrow, the default, short or long words, or a digital readout. The days and the hours show only while there are any, so the last hour reads 59m 59s. Units and the words between them come from Intl in locale, en-US by default.
Complete
onComplete is called once, when the countdown reaches zero: here, the button to ask for another code comes back. target can be a Date, a timestamp, or a date string.
Accessibility
It renders a <time> element whose dateTime is the time left as a duration (P3DT4H5M9S). Screen readers read the time left in words (3 days, 4 hours, 5 minutes, 9 seconds) from a visually hidden copy, whatever the format; the moving digits are hidden from them. It doesn't announce each second, which would be noise; to mark it as a running timer, put it in an element with role="timer", and announce the end yourself from onComplete if it matters. With reduced motion the digits change in place.
FAQ
Why is it blank for a moment when the page loads?
The time left depends on the visitor's clock, which the server can't know, so it renders an invisible placeholder as wide as a countdown with every unit, and the browser fills in the time as soon as the page runs. The server and the browser render the same markup.
What can I pass as the target?
A Date, a timestamp in milliseconds, or a date string such as "2027-01-01T00:00:00Z". Give the string a time zone (the Z, or an offset) so everyone counts down to the same moment.
When is onComplete called?
Once, as the countdown reaches zero, and at once when the page opens after target has passed. The countdown then stays at zero and its timer stops.
Does it round the seconds up or down?
Up, as a countdown should: with half a second left it still reads one second, and it reads zero only at the target itself.
API Reference
CountdownText
<time> data-slot="countdown-text"
targetDate | number | string
The moment it counts down to: a Date, a timestamp in milliseconds or
a date string ("2027-01-01T00:00:00Z").
- Type
Date | number | string
format?Format
How it's written: each number with its unit, narrow (3d 04h 05m 09s),
short or long, or a digital readout (03:04:05:09).
- Default
"narrow"
locale?string
The locale it's written in (its digits, units and the joins between them). Fixed by default, so the server and the browser write it the same way.
- Default
"en-US"
onComplete?() → void
Called once, when the countdown reaches zero (at once if target has passed).
- Returns
void
render?ReactElement | ((props: object, state: object) => ReactElement)
Replace the host element or compose it with another component.
- Type
ReactElement | ((props: object, state: object) => ReactElement)
className?string
Merged with the part's classes.
--countdown-text-durationstring
A digit's drop into its window (400ms).
Related
- Pro
Clock Text
NumbersShow the time of day
- Pro
Relative Time Text
NumbersSay it as in 5 minutes
- Pro
Timecode Text
NumbersA timecode running hours to frames
Sliding Number
NumbersDigits that roll to any value
- Pro
LCD Text
DecorativeDigits that look like hardware
- Pro
Progress Text
NumbersHow far a goal has got