Countdown

Countdown displays a numeric value with smooth transition animation. Supports reactive values for live countdowns.

Basic Example

Static countdown values

await import('/components/data-display/countdown.js');
const { tags, $ } = Lightview;
const { div, span, Countdown } = tags;

const display = div({ style: 'display: flex; gap: 1.25rem' },
    Countdown({ value: 15, class: 'font-mono text-4xl' }),
    span({ class: 'text-4xl' }, ':'),
    Countdown({ value: 30, class: 'font-mono text-4xl' }),
    span({ class: 'text-4xl' }, ':'),
    Countdown({ value: 45, class: 'font-mono text-4xl' })
);

$('#example').content(display);
await import('/components/data-display/countdown.js');
const { $, tags } = Lightview;
const { Countdown, div, span } = tags;

const display = {
    tag: div,
    attributes: { style: 'display: flex; gap: 1.25rem' },
    children: [
        { tag: Countdown, attributes: { value: 15, class: 'font-mono text-4xl' } },
        { tag: span, attributes: { class: 'text-4xl' }, children: [':'] },
        { tag: Countdown, attributes: { value: 30, class: 'font-mono text-4xl' } },
        { tag: span, attributes: { class: 'text-4xl' }, children: [':'] },
        { tag: Countdown, attributes: { value: 45, class: 'font-mono text-4xl' } }
    ]
};

$('#example').content(display);
await import('/components/data-display/countdown.js');
const { $ } = Lightview;

const display = {
    div: {
        style: 'display: flex; gap: 1.25rem',
        children: [
            { Countdown: { value: 15, class: 'font-mono text-4xl' } },
            { span: { class: 'text-4xl', children: [':'] } },
            { Countdown: { value: 30, class: 'font-mono text-4xl' } },
            { span: { class: 'text-4xl', children: [':'] } },
            { Countdown: { value: 45, class: 'font-mono text-4xl' } }
        ]
    }
};

$('#example').content(display);

Live Timer

Reactive countdown with animated transitions

await import('/components/data-display/countdown.js');
await import('/components/actions/button.js');

const { signal, tags, $ } = Lightview;
const { div, Countdown, Button } = tags;

const seconds = signal(30);
const running = signal(false);
let interval = null;

const toggle = () => {
    if (running.value) {
        clearInterval(interval);
        running.value = false;
    } else {
        running.value = true;
        interval = setInterval(() => {
            if (seconds.value > 0) {
                seconds.value--;
            } else {
                clearInterval(interval);
                running.value = false;
            }
        }, 1000);
    }
};

const reset = () => {
    clearInterval(interval);
    running.value = false;
    seconds.value = 30;
};

const demo = div({ style: 'display: flex; flex-direction: column; align-items: center; gap: 1rem' },
    Countdown({ value: () => seconds.value, class: 'font-mono text-6xl' }),
    div({ style: 'display: flex; gap: 0.5rem' },
        Button({ 
            color: () => running.value ? 'error' : 'primary',
            onclick: toggle 
        }, () => running.value ? 'Pause' : 'Start'),
        Button({ onclick: reset }, 'Reset')
    )
);

$('#example').content(demo);
await import('/components/data-display/countdown.js');
await import('/components/actions/button.js');
const { signal, $, tags } = Lightview;
const { Countdown, div, Button } = tags;

const seconds = signal(30);
const running = signal(false);
let interval = null;

const toggle = () => {
    if (running.value) {
        clearInterval(interval);
        running.value = false;
    } else {
        running.value = true;
        interval = setInterval(() => {
            if (seconds.value > 0) {
                seconds.value--;
            } else {
                clearInterval(interval);
                running.value = false;
            }
        }, 1000);
    }
};

const reset = () => {
    clearInterval(interval);
    running.value = false;
    seconds.value = 30;
};

const demo = {
    tag: div,
    attributes: { style: 'display: flex; flex-direction: column; align-items: center; gap: 1rem' },
    children: [
        {
            tag: Countdown,
            attributes: { value: () => seconds.value, class: 'font-mono text-6xl' }
        },
        {
            tag: div,
            attributes: { style: 'display: flex; gap: 0.5rem' },
            children: [
                {
                    tag: Button,
                    attributes: { color: () => running.value ? 'error' : 'primary', onclick: toggle },
                    children: [() => running.value ? 'Pause' : 'Start']
                },
                { tag: Button, attributes: { onclick: reset }, children: ['Reset'] }
            ]
        }
    ]
};

$('#example').content(demo);
await import('/components/data-display/countdown.js');
await import('/components/actions/button.js');
const { signal, $ } = Lightview;

const seconds = signal(30);
const running = signal(false);
let interval = null;

const toggle = () => {
    if (running.value) {
        clearInterval(interval);
        running.value = false;
    } else {
        running.value = true;
        interval = setInterval(() => {
            if (seconds.value > 0) {
                seconds.value--;
            } else {
                clearInterval(interval);
                running.value = false;
            }
        }, 1000);
    }
};

const reset = () => {
    clearInterval(interval);
    running.value = false;
    seconds.value = 30;
};

const demo = {
    div: {
        style: 'display: flex; flex-direction: column; align-items: center; gap: 1rem',
        children: [
            { Countdown: { value: () => seconds.value, class: 'font-mono text-6xl' } },
            {
                div: {
                    style: 'display: flex; gap: 0.5rem',
                    children: [
                        { Button: { color: () => running.value ? 'error' : 'primary', onclick: toggle, children: [() => running.value ? 'Pause' : 'Start'] } },
                        { Button: { onclick: reset, children: ['Reset'] } }
                    ]
                }
            }
        ]
    }
};

$('#example').content(demo);

Props

Prop Type Default Description
value number | function 0 Countdown value (0-99, reactive)

With Labels

days
hours
min
sec