Components / Feedback

Countdown

A launch countdown with rolling digits that morphs into a live state at zero.

Install

npx shadcn@latest add https://irisui.dev/r/countdown.json
import { Countdown } from "@/components/iris/countdown/countdown";
Registry item countdownBrings in foundationRegistry JSON

Preview

Countdown

A countdown to a fixed moment with rolling digits that morphs into a live label when it reaches zero.

When to use

  • Launches, live events, webinars, and sale deadlines people wait for.
  • Compact inline timers in banners and table cells (variant: "compact").
  • Not for elapsed time or task progress: use Progress. For a whole promotional bar with a countdown inside, use AnnouncementBar.

Usage

import { Countdown } from "@/components/iris/countdown/countdown";

h(Countdown, { target: "2026-11-04T07:00:00Z", label: "Series A · wave 1 embargo lifts in" });

h(Countdown, {
  target: "2026-11-04 09:00",
  timeZone: "America/Los_Angeles",
  variant: "compact",
  units: ["hours", "minutes", "seconds"],
  completeLabel: "Starting now",
  onComplete: () => refresh(),
});

Props

Prop Type Default Description
target Date | number | string — Required. Epoch ms, a Date, or an ISO string. A string without an offset is wall time in timeZone (UTC if none), never the visitor's zone.
timeZone string — IANA zone for offset-less target strings; daylight saving is resolved for the target date.
units ("days" | "hours" | "minutes" | "seconds")[] all four Units to show; the largest absorbs the rest (hours can pass 24 without days).
variant "large" | "compact" "large" Display digits with unit names, or one pill-shaped line.
completeLabel ReactNode "Live now" Shown once the target passes.
onComplete () => void — Fires once when zero is reached while mounted, even in a hidden tab.
label string "Time remaining" Accessible name of the timer.
clock () => number Date.now Clock source; pass a server-synced clock if device time is untrusted.
className, ref Root class and ref.

Notes

  • role="timer"; a spoken summary is kept in a visually hidden element rather than announcing every tick.
  • The large variant is a CSS size container and sizes its digits to the available width, so give its parent a definite width (it collapses inside a shrink-to-fit flex item).
  • Ticks only while on screen and the tab is visible, re-reading the clock on return so nothing drifts. Reduced motion swaps rolling digits for fades.
  • Reads --font-display, --tracking-display, --ink-3, --surface, --line, --green.