Loading

Loading shows an animated indicator for loading states. Multiple types and sizes available.

Basic Example

Different loading types and sizes

await import('/components/data-display/loading.js');
const { tags, $ } = Lightview;
const { div, p, Loading } = tags;

const types = ['spinner', 'dots', 'ring', 'ball', 'bars', 'infinity'];

const loaders = div({ style: 'display: flex; flex-wrap: wrap; gap: 2rem;' },
    ...types.map(type => 
        div({ style: 'text-align: center;' },
            Loading({ type, size: 'lg' }),
            p({ style: 'font-size: 0.875rem; margin-top: 0.5rem; opacity: 0.5;' }, type)
        )
    )
);

$('#example').content(loaders);
await import('/components/data-display/loading.js');
const { $, tags } = Lightview;
const { Loading, div, p } = tags;

const types = ['spinner', 'dots', 'ring', 'ball', 'bars', 'infinity'];

const loaders = {
    tag: div,
    attributes: { style: 'display: flex; flex-wrap: wrap; gap: 2rem;' },
    children: types.map(type => ({
        tag: div,
        attributes: { style: 'text-align: center;' },
        children: [
            { tag: Loading, attributes: { type, size: 'lg' } },
            { tag: p, attributes: { style: 'font-size: 0.875rem; margin-top: 0.5rem; opacity: 0.5;' }, children: [type] }
        ]
    }))
};

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

const types = ['spinner', 'dots', 'ring', 'ball', 'bars', 'infinity'];

const loaders = {
    div: {
        style: 'display: flex; flex-wrap: wrap; gap: 2rem;',
        children: types.map(type => ({
            div: {
                style: 'text-align: center;',
                children: [
                    { Loading: { type, size: 'lg' } },
                    { p: { style: 'font-size: 0.875rem; margin-top: 0.5rem; opacity: 0.5;', children: [type] } }
                ]
            }
        }))
    }
};

$('#example').content(loaders);
<!-- Import the component (registers lv-loading) -->
<script type="module" src="/components/data-display/loading.js"></script>

<div style="display: flex; flex-wrap: wrap; gap: 2rem;">
    <div style="text-align: center;">
        <lv-loading type="spinner" size="lg"></lv-loading>
        <p style="font-size: 0.875rem; margin-top: 0.5rem; opacity: 0.5;">spinner</p>
    </div>
    <div style="text-align: center;">
        <lv-loading type="dots" size="lg"></lv-loading>
        <p style="font-size: 0.875rem; margin-top: 0.5rem; opacity: 0.5;">dots</p>
    </div>
    <div style="text-align: center;">
        <lv-loading type="ring" size="lg"></lv-loading>
        <p style="font-size: 0.875rem; margin-top: 0.5rem; opacity: 0.5;">ring</p>
    </div>
    <div style="text-align: center;">
        <lv-loading type="ball" size="lg"></lv-loading>
        <p style="font-size: 0.875rem; margin-top: 0.5rem; opacity: 0.5;">ball</p>
    </div>
    <div style="text-align: center;">
        <lv-loading type="bars" size="lg"></lv-loading>
        <p style="font-size: 0.875rem; margin-top: 0.5rem; opacity: 0.5;">bars</p>
    </div>
    <div style="text-align: center;">
        <lv-loading type="infinity" size="lg"></lv-loading>
        <p style="font-size: 0.875rem; margin-top: 0.5rem; opacity: 0.5;">infinity</p>
    </div>
</div>

Loading Button

Button with reactive loading state

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

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

const isLoading = signal(false);

const handleClick = async () => {
    isLoading.value = true;
    await new Promise(r => setTimeout(r, 2000));
    isLoading.value = false;
};

const demo = div({ style: 'display: flex; gap: 1rem; align-items: center;' },
    () => isLoading.value
        ? Button({ color: 'primary', disabled: true },
            Loading({ type: 'spinner', size: 'sm' }),
            span({}, ' Processing...')
        )
        : Button({ color: 'primary', onclick: handleClick }, 'Submit'),
    span({ style: 'font-size: 0.875rem; opacity: 0.7;' },
        () => isLoading.value ? 'Please wait...' : 'Click the button'
    )
);

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

const isLoading = signal(false);

const handleClick = async () => {
    isLoading.value = true;
    await new Promise(r => setTimeout(r, 2000));
    isLoading.value = false;
};

const demo = {
    tag: div,
    attributes: { style: 'display: flex; gap: 1rem; align-items: center;' },
    children: [
        () => isLoading.value
            ? {
                tag: Button,
                attributes: { color: 'primary', disabled: true },
                children: [
                    { tag: Loading, attributes: { type: 'spinner', size: 'sm' } },
                    { tag: span, children: [' Processing...'] }
                ]
            }
            : {
                tag: Button,
                attributes: { color: 'primary', onclick: handleClick },
                children: ['Submit']
            },
        {
            tag: span,
            attributes: { style: 'font-size: 0.875rem; opacity: 0.7;' },
            children: [() => isLoading.value ? 'Please wait...' : 'Click the button']
        }
    ]
};

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

const isLoading = signal(false);

const handleClick = async () => {
    isLoading.value = true;
    await new Promise(r => setTimeout(r, 2000));
    isLoading.value = false;
};

const demo = {
    div: {
        style: 'display: flex; gap: 1rem; align-items: center',
        children: [
            () => isLoading.value
                ? {
                    Button: {
                        color: 'primary',
                        disabled: true,
                        children: [
                            { Loading: { type: 'spinner', size: 'sm' } },
                            { span: { children: [' Processing...'] } }
                        ]
                    }
                }
                : {
                    Button: { color: 'primary', onclick: handleClick, children: ['Submit'] }
                },
            {
                span: {
                    style: 'font-size: 0.875rem; opacity: 0.7;',
                    children: [() => isLoading.value ? 'Please wait...' : 'Click the button']
                }
            }
        ]
    }
};

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

Props

Prop Type Default Description
type string 'spinner' 'spinner' | 'dots' | 'ring' | 'ball' | 'bars' | 'infinity'
size string 'md' 'xs' | 'sm' | 'md' | 'lg'
color string - Color utility class e.g. 'text-primary'

Loading Gallery

Live examples using <lv-loading> custom elements.

All Types

spinner

dots

ring

ball

bars

infinity

All Sizes

xs

sm

md

lg

With Colors