0.0.3

Timer

A pure vanilla JS implementation of Zag JS Timer Opens in a new window


Anatomy

The Timer component consists of the following data-part

root area item separator control action-trigger
:
:
:
<div class="timer timer-js" data-countdown="true" data-auto-start="true" data-interval="1000" data-days="1" data-hours="0" data-minutes="0" data-seconds="0">
                  <div data-part="root">
                  <div data-part="area">
                  <div data-part="item" data-type="days"></div>
                  <div data-part="separator">:</div>
                  <div data-part="item" data-type="hours"></div>
                  <div data-part="separator">:</div>
                  <div data-part="item" data-type="minutes"></div>
                  <div data-part="separator">:</div>
                  <div data-part="item" data-type="seconds"></div>
                  </div>
                  </div>
                  <div data-part="control">
                  <button class="button button--circle button--sm" data-part="action-trigger" data-action="start">
                  <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="button__icon">
                  <path stroke-linecap="round" stroke-linejoin="round" d="M5.25 5.653c0-.856.917-1.398 1.667-.986l11.54 6.347a1.125 1.125 0 0 1 0 1.972l-11.54 6.347a1.125 1.125 0 0 1-1.667-.986V5.653Z"></path>
                  </svg>
                  </button>
                  <button class="button button--circle button--sm" data-part="action-trigger" data-action="pause">
                  <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="button__icon">
                  <path stroke-linecap="round" stroke-linejoin="round" d="M15.75 5.25v13.5m-7.5-13.5v13.5"></path>
                  </svg>
                  </button>
                  <button class="button button--circle button--sm" data-part="action-trigger" data-action="resume">
                  <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="button__icon">
                  <path stroke-linecap="round" stroke-linejoin="round" d="M5.25 5.653c0-.856.917-1.398 1.667-.986l11.54 6.347a1.125 1.125 0 0 1 0 1.972l-11.54 6.347a1.125 1.125 0 0 1-1.667-.986V5.653Z"></path>
                  </svg>
                  </button>
                  <button class="button button--circle button--sm" data-part="action-trigger" data-action="reset">
                  <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="button__icon">
                  <path stroke-linecap="round" stroke-linejoin="round" d="M19.5 12c0-1.232-.046-2.453-.138-3.662a4.006 4.006 0 0 0-3.7-3.7 48.678 48.678 0 0 0-7.324 0 4.006 4.006 0 0 0-3.7 3.7c-.017.22-.032.441-.046.662M19.5 12l3-3m-3 3-3-3m-12 3c0 1.232.046 2.453.138 3.662a4.006 4.006 0 0 0 3.7 3.7 48.656 48.656 0 0 0 7.324 0 4.006 4.006 0 0 0 3.7-3.7c.017-.22.032-.441.046-.662M4.5 12l3 3m-3-3-3 3"></path>
                  </svg>
                  </button>
                  </div>
                  </div>

Data attributes

Each timer can be set with different settings with the following data-attribute.

:
:
:
<div class="timer timer-js" data-countdown="false" data-auto-start="true" data-interval="1000" data-days="0" data-hours="0" data-minutes="1" data-seconds="0" data-days-target="0" data-hours-target="1" data-minutes-target="0" data-seconds-target="0">
                  <div data-part="root">
                  <div data-part="area">
                  <div data-part="item" data-type="days"></div>
                  <div data-part="separator">:</div>
                  <div data-part="item" data-type="hours"></div>
                  <div data-part="separator">:</div>
                  <div data-part="item" data-type="minutes"></div>
                  <div data-part="separator">:</div>
                  <div data-part="item" data-type="seconds"></div>
                  </div>
                  </div>
                  <div data-part="control">
                  <button class="button button--circle button--sm" data-part="action-trigger" data-action="start">
                  <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="button__icon">
                  <path stroke-linecap="round" stroke-linejoin="round" d="M5.25 5.653c0-.856.917-1.398 1.667-.986l11.54 6.347a1.125 1.125 0 0 1 0 1.972l-11.54 6.347a1.125 1.125 0 0 1-1.667-.986V5.653Z"></path>
                  </svg>
                  </button>
                  <button class="button button--circle button--sm" data-part="action-trigger" data-action="pause">
                  <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="button__icon">
                  <path stroke-linecap="round" stroke-linejoin="round" d="M15.75 5.25v13.5m-7.5-13.5v13.5"></path>
                  </svg>
                  </button>
                  <button class="button button--circle button--sm" data-part="action-trigger" data-action="resume">
                  <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="button__icon">
                  <path stroke-linecap="round" stroke-linejoin="round" d="M5.25 5.653c0-.856.917-1.398 1.667-.986l11.54 6.347a1.125 1.125 0 0 1 0 1.972l-11.54 6.347a1.125 1.125 0 0 1-1.667-.986V5.653Z"></path>
                  </svg>
                  </button>
                  <button class="button button--circle button--sm" data-part="action-trigger" data-action="reset">
                  <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="button__icon">
                  <path stroke-linecap="round" stroke-linejoin="round" d="M19.5 12c0-1.232-.046-2.453-.138-3.662a4.006 4.006 0 0 0-3.7-3.7 48.678 48.678 0 0 0-7.324 0 4.006 4.006 0 0 0-3.7 3.7c-.017.22-.032.441-.046.662M19.5 12l3-3m-3 3-3-3m-12 3c0 1.232.046 2.453.138 3.662a4.006 4.006 0 0 0 3.7 3.7 48.656 48.656 0 0 0 7.324 0 4.006 4.006 0 0 0 3.7-3.7c.017-.22.032-.441.046-.662M4.5 12l3 3m-3-3-3 3"></path>
                  </svg>
                  </button>
                  </div>
                  </div>
Data attribute Type / Options Description
id string The unique id of the component. Default generated if none is provided
data-countdown boolean Whether the timer should countdown, decrementing the timer on each tick.
data-auto-start string Whether the timer should start automatically
data-interval number The interval in milliseconds to update the timer count.
data-days number The total duration of the timer in days.
data-hours number The total duration of the timer in hours.
data-minutes number The total duration of the timer in minutes.
data-seconds number The total duration of the timer in seconds.
data-days-target number The minimun count of the timer in days.
data-hours-target number The minimun count of the timer in hours.
data-minutes-target number The minimun count of the timer in minutes.
data-seconds-target number The minimun count of the timer in seconds.

Callbacks

Each Timer component can receive callbacks that can be used to respond to user interaction with custom behavior.

You must add a custom id for the timer and a event listener for your event name


                      document.getElementById("my-callback-timer")
                      ?.addEventListener("my-callback-timer-event", (event) => {
                        console.log("Received event:", (event as CustomEvent).detail);
                      });
                  
:
:
:
<div id="my-callback-timer" class="timer timer-js" data-countdown="true" data-auto-start="true" data-on-complete="my-callback-timer-event" data-days="0" data-hours="0" data-minutes="0" data-seconds="10">
                  <div data-part="root">
                  <div data-part="area">
                  <div data-part="item" data-type="days"></div>
                  <div data-part="separator">:</div>
                  <div data-part="item" data-type="hours"></div>
                  <div data-part="separator">:</div>
                  <div data-part="item" data-type="minutes"></div>
                  <div data-part="separator">:</div>
                  <div data-part="item" data-type="seconds"></div>
                  </div>
                  </div>
                  <div data-part="control">
                  <button class="button button--circle button--sm" data-part="action-trigger" data-action="start">
                  <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="button__icon">
                  <path stroke-linecap="round" stroke-linejoin="round" d="M5.25 5.653c0-.856.917-1.398 1.667-.986l11.54 6.347a1.125 1.125 0 0 1 0 1.972l-11.54 6.347a1.125 1.125 0 0 1-1.667-.986V5.653Z"></path>
                  </svg>
                  </button>
                  <button class="button button--circle button--sm" data-part="action-trigger" data-action="pause">
                  <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="button__icon">
                  <path stroke-linecap="round" stroke-linejoin="round" d="M15.75 5.25v13.5m-7.5-13.5v13.5"></path>
                  </svg>
                  </button>
                  <button class="button button--circle button--sm" data-part="action-trigger" data-action="resume">
                  <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="button__icon">
                  <path stroke-linecap="round" stroke-linejoin="round" d="M5.25 5.653c0-.856.917-1.398 1.667-.986l11.54 6.347a1.125 1.125 0 0 1 0 1.972l-11.54 6.347a1.125 1.125 0 0 1-1.667-.986V5.653Z"></path>
                  </svg>
                  </button>
                  <button class="button button--circle button--sm" data-part="action-trigger" data-action="reset">
                  <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="button__icon">
                  <path stroke-linecap="round" stroke-linejoin="round" d="M19.5 12c0-1.232-.046-2.453-.138-3.662a4.006 4.006 0 0 0-3.7-3.7 48.678 48.678 0 0 0-7.324 0 4.006 4.006 0 0 0-3.7 3.7c-.017.22-.032.441-.046.662M19.5 12l3-3m-3 3-3-3m-12 3c0 1.232.046 2.453.138 3.662a4.006 4.006 0 0 0 3.7 3.7 48.656 48.656 0 0 0 7.324 0 4.006 4.006 0 0 0 3.7-3.7c.017-.22.032-.441.046-.662M4.5 12l3 3m-3-3-3 3"></path>
                  </svg>
                  </button>
                  </div>
                  </div>

Open your browser's console to see the events received when the timer is copied


Custom (Tailwind)

If you are using Tailwind styling, you can customize each timer and its parts with Tailwind utilities

:
:
:
<div class="timer timer-js" data-countdown="true" data-auto-start="true" data-interval="1000" data-days="1" data-hours="0" data-minutes="0" data-seconds="0">
                  <div data-part="root">
                  <div data-part="area" class="bg-ui-brand rounded-full w-auto h-auto py-0 p-6">
                  <div data-part="item" data-type="days" class="text-contrast-brand"></div>
                  <div data-part="separator">:</div>
                  <div data-part="item" data-type="hours" class="text-contrast-brand"></div>
                  <div data-part="separator">:</div>
                  <div data-part="item" data-type="minutes" class="text-contrast-brand"></div>
                  <div data-part="separator">:</div>
                  <div data-part="item" data-type="seconds" class="text-contrast-alert"></div>
                  </div>
                  </div>
                  <div data-part="control">
                  <button class="button button--circle button--sm" data-part="action-trigger" data-action="start">
                  <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="button__icon">
                  <path stroke-linecap="round" stroke-linejoin="round" d="M5.25 5.653c0-.856.917-1.398 1.667-.986l11.54 6.347a1.125 1.125 0 0 1 0 1.972l-11.54 6.347a1.125 1.125 0 0 1-1.667-.986V5.653Z"></path>
                  </svg>
                  </button>
                  <button class="button button--circle button--sm" data-part="action-trigger" data-action="pause">
                  <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="button__icon">
                  <path stroke-linecap="round" stroke-linejoin="round" d="M15.75 5.25v13.5m-7.5-13.5v13.5"></path>
                  </svg>
                  </button>
                  <button class="button button--circle button--sm" data-part="action-trigger" data-action="resume">
                  <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="button__icon">
                  <path stroke-linecap="round" stroke-linejoin="round" d="M5.25 5.653c0-.856.917-1.398 1.667-.986l11.54 6.347a1.125 1.125 0 0 1 0 1.972l-11.54 6.347a1.125 1.125 0 0 1-1.667-.986V5.653Z"></path>
                  </svg>
                  </button>
                  <button class="button button--circle button--sm" data-part="action-trigger" data-action="reset">
                  <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="button__icon">
                  <path stroke-linecap="round" stroke-linejoin="round" d="M19.5 12c0-1.232-.046-2.453-.138-3.662a4.006 4.006 0 0 0-3.7-3.7 48.678 48.678 0 0 0-7.324 0 4.006 4.006 0 0 0-3.7 3.7c-.017.22-.032.441-.046.662M19.5 12l3-3m-3 3-3-3m-12 3c0 1.232.046 2.453.138 3.662a4.006 4.006 0 0 0 3.7 3.7 48.656 48.656 0 0 0 7.324 0 4.006 4.006 0 0 0 3.7-3.7c.017-.22.032-.441.046-.662M4.5 12l3 3m-3-3-3 3"></path>
                  </svg>
                  </button>
                  </div>
                  </div>

Templates

Timer components is available in the followng templates

Tabs Toggle Group