{"slug":"timer","title":"Timer","description":"Using a countdown and stopwatch timer in your project.","contentType":"component","framework":"react","content":"The timer machine tracks elapsed or remaining time.\n\n## Resources\n\n\n[Latest version: v1.35.3](https://www.npmjs.com/package/@zag-js/timer)\n[Logic Visualizer](https://zag-visualizer.vercel.app/timer)\n[Source Code](https://github.com/chakra-ui/zag/tree/main/packages/machines/timer)\n\n\n\n**Features**\n\n- Countdown from a specified time\n- Use as stopwatch to record the time elapsed\n- Control the timer with start, pause, resume, reset, and restart actions\n- Set the tick interval for the timer\n\n## Installation\n\nInstall the timer package:\n\n```bash\nnpm install @zag-js/timer @zag-js/react\n# or\nyarn add @zag-js/timer @zag-js/react\n```\n\n## Anatomy\n\nCheck the timer anatomy and part names.\n\n> Each part includes a `data-part` attribute to help identify them in the DOM.\n\n\n\n## Usage\n\nImport the timer package:\n\n```jsx\nimport * as timer from \"@zag-js/timer\"\n```\n\nThese are the key exports:\n\n- `machine` - State machine logic.\n- `connect` - Maps machine state to JSX props and event handlers.\n- `parse` - Parses a date-time string or object into milliseconds.\n\nThen use the framework integration helpers:\n\n```jsx\nimport { normalizeProps, useMachine } from \"@zag-js/react\"\nimport * as timer from \"@zag-js/timer\"\n\nexport function Countdown() {\n  const service = useMachine(timer.machine, {\n    id: useId(),\n    countdown: true,\n    autoStart: true,\n    startMs: timer.parse({ days: 2, seconds: 10 }),\n  })\n\n  const api = timer.connect(service, normalizeProps)\n\n  return (\n    <div {...api.getRootProps()}>\n      <div {...api.getAreaProps()}>\n        <div {...api.getItemProps({ type: \"days\" })}>\n          {api.formattedTime.days}\n        </div>\n        <div {...api.getSeparatorProps()}>:</div>\n        <div {...api.getItemProps({ type: \"hours\" })}>\n          {api.formattedTime.hours}\n        </div>\n        <div {...api.getSeparatorProps()}>:</div>\n        <div {...api.getItemProps({ type: \"minutes\" })}>\n          {api.formattedTime.minutes}\n        </div>\n        <div {...api.getSeparatorProps()}>:</div>\n        <div {...api.getItemProps({ type: \"seconds\" })}>\n          {api.formattedTime.seconds}\n        </div>\n      </div>\n      <div {...api.getControlProps()}>\n        <button {...api.getActionTriggerProps({ action: \"start\" })}>\n          START\n        </button>\n        <button {...api.getActionTriggerProps({ action: \"pause\" })}>\n          PAUSE\n        </button>\n        <button {...api.getActionTriggerProps({ action: \"resume\" })}>\n          RESUME\n        </button>\n        <button {...api.getActionTriggerProps({ action: \"reset\" })}>\n          RESET\n        </button>\n      </div>\n    </div>\n  )\n}\n```\n\n### Setting the start value\n\nSet the `startMs` property to the timer machine's context to set the start time\nin milliseconds.\n\n```jsx\nconst service = useMachine(timer.machine, {\n  startMs: 1000 * 60 * 60, // 1 hour\n})\n```\n\nAlternatively, you can also use the `timer.parse` function to convert a date\ntime string or object into milliseconds\n\n```jsx\nconst service = useMachine(timer.machine, {\n  startMs: timer.parse(\"2021-01-01T12:00:00Z\"),\n  // startMs: timer.parse({ hours: 12, minutes: 0, seconds: 0 }),\n})\n```\n\n### Auto starting the timer\n\nSet the `autoStart` property to `true` in the timer machine's context to start\nthe timer automatically when the component mounts.\n\n```jsx\nconst service = useMachine(timer.machine, {\n  autoStart: true,\n})\n```\n\n### Usage as countdown timer\n\nTo use the timer as a countdown timer, set the `countdown` property to `true` in\nthe timer machine's context.\n\n```jsx\nconst service = useMachine(timer.machine, {\n  countdown: true,\n})\n```\n\n### Setting the target value\n\nTo set the target value of the countdown timer, pass the `targetMs` property in\nthe timer machine's context. The timer stops automatically when the `targetMs`\nis reached.\n\nWhen `targetMs` is set and `countdown=true`, the timer ticks down to zero from\nthe specified target time.\n\n```jsx\nconst service = useMachine(timer.machine, {\n  countdown: true,\n  targetMs: 1000 * 60 * 60, // 1 hour\n})\n```\n\nWhen `targetMs` is set and `countdown=false|undefined`, the timer ticks up to\nthe specified target time.\n\n```jsx\nconst service = useMachine(timer.machine, {\n  targetMs: 1000 * 60 * 60, // 1 hour\n})\n```\n\n### Setting the tick interval\n\nSet the `interval` property to the timer machine's context to set the tick\ninterval in milliseconds.\n\n```jsx\nconst service = useMachine(timer.machine, {\n  interval: 1000, // 1 second\n})\n```\n\n### Listening to tick events\n\nWhen the timer ticks, the `onTick` callback is invoked. You can listen to this\nevent and update your UI accordingly.\n\n```jsx\nconst service = useMachine(timer.machine, {\n  onTick(details) {\n    // details => { value: number, time, formattedTime }\n    console.log(details.formattedTime)\n  },\n})\n```\n\n### Listening for completion events\n\nWhen the timer reaches the target time, the `onComplete` callback is invoked.\n\n```jsx\nconst service = useMachine(timer.machine, {\n  countdown: true,\n  targetMs: 1000 * 60 * 60, // 1 hour\n  onComplete() {\n    console.log(\"Timer completed\")\n  },\n})\n```\n\n### Programmatic timer controls\n\nUse the connected API for timer actions.\n\n```jsx\napi.start()\napi.pause()\napi.resume()\napi.reset()\napi.restart()\n```\n\n## Methods and Properties\n\n### Machine Context\n\nThe timer machine exposes the following context properties:\n\n**`ids`**\nType: `Partial<{ root: string; area: string; }>`\nDescription: The ids of the timer parts\n\n**`countdown`**\nType: `boolean`\nDescription: Whether the timer should countdown, decrementing the timer on each tick.\n\n**`startMs`**\nType: `number`\nDescription: The total duration of the timer in milliseconds.\n\n**`targetMs`**\nType: `number`\nDescription: The minimum count of the timer in milliseconds.\n\n**`autoStart`**\nType: `boolean`\nDescription: Whether the timer should start automatically\n\n**`interval`**\nType: `number`\nDescription: The interval in milliseconds to update the timer count.\n\n**`onTick`**\nType: `(details: TickDetails) => void`\nDescription: Function invoked when the timer ticks\n\n**`onComplete`**\nType: `() => void`\nDescription: Function invoked when the timer is completed\n\n**`id`**\nType: `string`\nDescription: The unique identifier of the machine.\n\n**`getRootNode`**\nType: `() => ShadowRoot | Node | Document`\nDescription: A root node to correctly resolve document in custom environments. E.x.: Iframes, Electron.\n\n### Machine API\n\nThe timer `api` exposes the following methods:\n\n**`running`**\nType: `boolean`\nDescription: Whether the timer is running.\n\n**`paused`**\nType: `boolean`\nDescription: Whether the timer is paused.\n\n**`time`**\nType: `Time<number>`\nDescription: The formatted timer count value.\n\n**`formattedTime`**\nType: `Time<string>`\nDescription: The formatted time parts of the timer count.\n\n**`start`**\nType: `VoidFunction`\nDescription: Function to start the timer.\n\n**`pause`**\nType: `VoidFunction`\nDescription: Function to pause the timer.\n\n**`resume`**\nType: `VoidFunction`\nDescription: Function to resume the timer.\n\n**`reset`**\nType: `VoidFunction`\nDescription: Function to reset the timer.\n\n**`restart`**\nType: `VoidFunction`\nDescription: Function to restart the timer.\n\n**`progressPercent`**\nType: `number`\nDescription: The progress percentage of the timer.","package":"@zag-js/timer","editUrl":"https://github.com/chakra-ui/zag/edit/main/website/data/components/timer.mdx"}