# Countdown

Countdown is a neobrutalist React component from Cruise UI. Days, hours, minutes and seconds in boxes, or one compact line; red in the last minute.

Install (with the @cruiseui registry in components.json, see Installation):

```bash
npx shadcn@latest add @cruiseui/countdown
```

Import: `import { CruiseCountdown } from "@/components/cruise/countdown";`

## When to use

Sales ending, events starting, game rounds.

## When not to

Fake urgency on things that don't end.

## Example (React)

```tsx
import { CruiseCountdown } from "@/components/cruise/countdown";

export default function CountdownExample() {
  // Use target={new Date("2026-12-24T23:59:59")} for a fixed date.
  return (
    <div className="flex flex-col gap-6">
      <CruiseCountdown duration={(2 * 86400 + 5 * 3600 + 14 * 60) * 1000} label="Sale ends in" />
      <div className="flex flex-wrap items-center gap-3">
        <span>Offer ends in</span>
        <CruiseCountdown duration={75 * 1000} compact label="Offer ends in" />
      </div>
    </div>
  );
}
```

## HTML

Needs theme.css (https://cruiseui.dev/theme.css).

```html
<div role="timer" aria-label="Sale ends in">
  <div class="countdown" aria-hidden="true">
    <span class="countdown-unit"><span class="countdown-number">02</span><span class="countdown-label">Days</span></span>
    <span class="countdown-unit"><span class="countdown-number">05</span><span class="countdown-label">Hours</span></span>
    <span class="countdown-unit"><span class="countdown-number">14</span><span class="countdown-label">Min</span></span>
    <span class="countdown-unit"><span class="countdown-number">09</span><span class="countdown-label">Sec</span></span>
  </div>
  <span class="visually-hidden" aria-live="polite">2 days, 5 hours, 14 minutes left.</span>
</div>
```

## Props: CruiseCountdown

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `target?` | `string \| number \| Date` | — | When it ends: a Date, an ISO string or a timestamp. |
| `duration?` | `number` | — | Or: how long from when it appears, in milliseconds (e.g. a 90-second round). |
| `onComplete?` | `(() => void)` | — | — |
| `compact?` | `boolean` | `false` | One line, "02:14:09", instead of boxes. |
| `urgent?` | `boolean` | `true` | Turn --danger in the last minute. |
| `showDays?` | `boolean` | — | Show the days box (default: when there's at least a day left). |
| `label?` | `string` | `"Time left"` | — |
| `className?` | `string` | — | — |

## Accessibility

- role="timer" with a label; the ticking digits are hidden from screen readers.
- It's announced each minute and each of the last 10 seconds, not every second.
- Tabular numbers, so the layout never shifts.
