## Focus Timer (S—070)

A focus timer whose ring (or 60 ticks) drains as time runs, with presets, start/pause and reset.

- URL: https://sundaeui.dev/components/focus-timer
- Category: UI components · Art direction: Refined
- Access: Sundae Pro (authenticated install)
- Stack: React 18+, TypeScript, plain CSS; dependencies: none
- Install: `npx shadcn@latest add https://sundaeui.dev/r/focus-timer.json`
- Tags: timer, clock, pomodoro, productivity, ring, countdown

A big mm:ss reading sits inside a ring that empties as the session runs; the colon blinks while it counts. Switch the face to sixty clock ticks that go out one by one.
Presets set the length, the main button reads Start, Pause, Resume or Again depending on state, and reset is one tap. Timing runs on requestAnimationFrame, so it pauses with the tab.

### Usage

```tsx
import { FocusTimer } from '@/components/sundae/focus-timer'

<FocusTimer minutes={25} presets={[5, 15, 25, 50]} onComplete={notify} />
```

### Props

- `minutes` (`number`, default `25`): Starting length.
- `presets` (`number[]`, default `[5, 15, 25]`): Quick lengths in minutes.
- `display` (`'ring' | 'ticks'`, default `'ring'`): Face style.
- `onComplete` (`() => void`): Called when the timer reaches zero.
- `autoStart` (`boolean`, default `false`): Start on mount.
- `speed` (`number`, default `1`): Seconds per real second. For demos.
- `fill` (`'dark' | 'light'`, default `'dark'`): Surface: dark or light.

### When to use

- Focus and pomodoro tools, workout rests, timed exams.
- Any short countdown the user starts themselves.

### When not to use

- Deadlines days away: show a date and a relative time.
- Server-driven countdowns that must match other clients: drive left from your server time.

### Accessibility

- The reading is role="timer" with a spoken label ("4 minutes 12 seconds left"); it does not announce every second.
- Start, pause, reset, preset changes and completion are announced once in a polite live region.
- Presets are toggle buttons (aria-pressed). Reduced motion stops the colon blink and ring easing.

### Keyboard

- Tab: Move between presets, start and reset
- Enter / Space: Pick a preset, start or pause, reset

### FAQ

**Does it keep running in a background tab?**
No, requestAnimationFrame pauses with the tab. For background timing, store the end time and compute the remainder on focus.

**Can it play a sound at the end?**
Yes, from onComplete. Browsers allow audio there because the timer was started by a click.

