All components (204)
Countdown
Dates and time · Countdown · .amset-count
What it is and when to use it
A countdown in seconds: "Resend the code in 29 s", "1:30" from one minute on and "1:02:05" from one hour on, with the digits of the language. For what runs out: resending a code, the end of a reservation, a saved cart.
When to use it
- A short wait that the person has to see counting down.
labelsays what the countdown is for ("Resend the code") andtextchanges the sentence shown while it runs.endContentfor what appears on reaching zero (normally the button that can now be pressed),finalAnnouncementfor what is said then, andonFinishto find out from code.active={false}to stop it where it is (when set back totrueit continues from there); whensecondschanges it starts over.tonefor when time is pressing:warningon a reservation that is about to expire.
When not to
- Warning that the session is about to expire, with the exits at hand:
IdleWarning. - A date that has already passed or is yet to come ("3 minutes ago"):
RelativeTime.
Keyboard: it is not interactive and does not enter the Tab order; what is placed in endContent does.
Accessibility: the number is seen changing every second, but it is not announced every second, which would drown out anything else the screen reader was reading. A hidden status region says it when the seconds left are a multiple of announceEvery (10 by default), and in words: "Resend the code in 1 minute and 30 seconds", because "1:30" read aloud sounds like a time of day. On reaching zero the same region says finalAnnouncement ("Resend the code: the countdown has finished", by default) and endContent is rendered in place of the countdown. The region is there from the start: one that was born already containing the text might not be read.
Clock: it counts against the real time, not by subtracting one per tick. A background tab receives its timers late (as rarely as once per minute); when you come back, the countdown shows what is really left.
Sizes: font of 12, 13 or 14 px, and it reserves the height of a control of its size (30, 36 or 44 px), so that on reaching zero the endContent button takes the same place and nothing jumps. Give it a button of the same size.
Variants (variant):
roll(default): each digit sits in its own window and only the ones that change roll; the outgoing one goes down and the new one comes in from above, like a drum. From 1:30 to 1:29 two digits move, not the whole number.ring: a ring that empties continuously, with no second-by-second jumps, with the number inside andlabelbeside it. It is a single CSS animation that lasts the whole countdown and is driven by the browser's clock; withactive={false}it stops where it is.textis not used there.text: the whole number changes at once with a short fade, the look it had before.
Motion: the digits roll at the theme's slow duration and endContent enters with a fade. With reduced motion the digits change without rolling, but the ring keeps emptying at its own pace: it is what remains, not decoration.
Fine-tuning: --amset-count-font, -height (the one it reserves; auto if it goes inside a sentence), -slot, -color (the text), -number-color and -number-weight. In ring, --amset-count-ring (the side: 44, 56 or 72 px depending on the size) and --amset-count-ring-track (the color of what has already been used up); the arc takes the color of the number.
Context: it goes inside LocaleProvider (or AmsetProvider), which decides how the digits are written.
What it looks like
{/* Por defecto (roll): ruedan solo las cifras que cambian */}
<Countdown label="The offer ends" seconds={3600} />
{/* Un anillo que se vacia sin saltos, con el numero dentro */}
<Countdown label="Your reservation expires" seconds={90} variant="ring" tone="warning" />Props
Import it with import { Countdown } from '@amset/ui'. Required props are marked.
| Prop | Type | What it does |
|---|---|---|
labelrequired | string | What the countdown is for: "Resend the code". Required. |
secondsrequired | number | — |
active | boolean | Starts on its own. With `false` it stays stopped where it is and resumes from there when it goes back to `true`. |
announceEvery | number | How many seconds between announcements. Announcing every second is pure noise for whoever uses a screen reader. |
className | string | Merged with the library classes; it does not replace them. |
endContent | ReactNode | What is shown on reaching zero, instead of the count: normally a button. |
finalAnnouncement | string | What is announced on reaching zero. By default: "Resend the code: the countdown has finished". |
onFinish | () => void | — |
size | "sm" | "md" | "lg" | Font and reserved height: that of an `sm`, `md` or `lg` control (30, 36 or 44 px). |
text | (remaining: ReactNode, seconds: number) => ReactNode | What is shown while it runs. By default: "Resend the code in 0:29". It receives the number already written, in its own element (the one that moves on change), and the seconds left in case the bare figure is needed. |
tone | "neutral" | "accent" | "secondary" | "tertiary" | "info" | "success" | "warning" | "error" | The color of the text and the number. `neutral` by default; `warning` or `error` when something that matters is running out. |
variant | CountdownVariant | How it looks: `roll` (the default, the digits roll), `ring` (a ring that empties, with the number inside and `label` beside it; `text` is not used there) or `text` (the whole number jumps, as before). |
It also accepts the attributes of the element it renders: className, style, data-*, aria-* and its events.
CSS variables
These CSS variables are how you adapt it. Declare them on the component's selector, not on :root: the stylesheet redeclares them in the rule itself, and a declaration on the same element always wins.
| Variable | Default |
|---|---|
--amset-count-color | var(--amset-ink-2) |
--amset-count-number-color | var(--amset-ink) |
--amset-count-number-weight | var(--amset-weight-medium) |
--amset-count-font | var(--amset-text-sm) |
--amset-count-height | var(--amset-height-control) |
--amset-count-slot | var(--amset-space-2) |
How to change it
.amset-count {
--amset-count-color: ...;
--amset-count-number-color: ...;
}In the test bench
Every state and variant, to try one at a time, on its page at ui.amset.tech:
