Overview

onCountdown(callback, duration, options?) creates a Countdown handle scoped to the component. Call start() (or restart()) to begin — the timer does not auto-start.

Supports pause / resume, optional onTick progress, and is stopped automatically on unmount. On SSR, returns a noop countdown that ignores control calls.

vs other timers

API
Control
Notes
onTimeout TimerHandle Fires once; pause/resume; auto-starts.
onInterval TimerHandle Repeats; pause/resume; auto-starts.
onCountdown Countdown Must start(); progress ticks; toast-friendly.

Pausable countdown with progress

Start a 4s countdown with onTick progress. Pause, resume, or restart. Stops automatically if the component unmounts.

import { html, atom, onCountdown, renderApp } from 'mates';

const Toast = () => {
const progress = atom(0);
const done = atom(false);

const t = onCountdown(() => done.set(true), 4000, {
onTick: ({ progress: p }) => progress.set(Math.round(p * 100)),
});
t.start();

return () => html`
<div class="m-col m-gap">
<div class="m-flex m-gap-sm m-items-center">
<button class="btn-ghost" @click=${() => t.pause()}>Pause</button>
<button class="btn-ghost" @click=${() => t.resume()}>Resume</button>
<button class="btn-primary" @click=${() => { done.set(false); progress.set(0); t.restart(); }}>Restart</button>
</div>
<div class="card card-body p-20 center">
${done() ? 'Done!' : 'Progress: ' + progress() + '%'}
</div>
</div>
`;
};

renderApp(Toast, document.getElementById('app'));