Button

Buttons allow the user to take actions or make choices. Available in multiple variants, colors, and sizes with reactive state support.

Basic Usage

Standard buttons with default styling.

await import('/components/actions/button.js');
const { tags, $ } = Lightview;
const { div, Button } = tags;

const buttons = div({ style: 'display: flex; gap: 0.5rem;' },
    Button({}, 'Default'),
    Button({ color: 'primary' }, 'Primary'),
    Button({ color: 'secondary' }, 'Secondary')
);

$('#example').content(buttons);
await import('/components/actions/button.js');
const { $, tags } = Lightview;
const { div, Button } = tags;

const buttons = {
    tag: div,
    attributes: { style: 'display: flex; gap: 0.5rem;' },
    children: [
        { tag: Button, children: ['Default'] },
        { tag: Button, attributes: { color: 'primary' }, children: ['Primary'] },
        { tag: Button, attributes: { color: 'secondary' }, children: ['Secondary'] }
    ]
};

$('#example').content(buttons);
// Object DOM syntax now requires lightview-x.js
await import('/components/actions/button.js');
const { $ } = Lightview;

const buttons = {
    div: {
        style: 'display: flex; gap: 0.5rem;',
        children: [
            { Button: { children: ['Default'] } },
            { Button: { color: 'primary', children: ['Primary'] } },
            { Button: { color: 'secondary', children: ['Secondary'] } }
        ]
    }
};

$('#example').content(buttons);
<!-- Import the component (registers lv-button) -->
<script type="module" src="/components/actions/button.js"></script>

<div style="display: flex; gap: 0.5rem;">
    <lv-button>Default</lv-button>
    <lv-button color="primary">Primary</lv-button>
    <lv-button color="secondary">Secondary</lv-button>
</div>

Reactive State

Buttons with built-in loading and state handling.

await import('/components/actions/button.js');
const { signal, tags, $ } = Lightview;
const { div, span, Button } = tags;

const isLoading = signal(false);

const button = div({ style: 'display: flex; gap: 1rem; align-items: center;' },
    Button({ 
        color: 'primary',
        loading: () => isLoading.value,
        onclick: async () => {
            isLoading.value = true;
            await new Promise(r => setTimeout(r, 2000));
            isLoading.value = false;
        }
    }, 'Save Changes'),
    span({ style: 'opacity: 0.7;' },
        () => isLoading.value ? '⏳ Saving...' : 'Click to test'
    )
);

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

const isLoading = signal(false);

const button = {
    tag: 'div',
    attributes: { style: 'display: flex; gap: 1rem; align-items: center;' },
    children: [
        { 
            tag: Button, 
            attributes: { 
                color: 'primary',
                loading: () => isLoading.value,
                onclick: async () => {
                    isLoading.value = true;
                    await new Promise(r => setTimeout(r, 2000));
                    isLoading.value = false;
                }
            }, 
            children: ['Save Changes'] 
        },
        { 
            tag: 'span', 
            attributes: { style: 'opacity: 0.7;' }, 
            children: [() => isLoading.value ? '⏳ Saving...' : 'Click to test'] 
        }
    ]
};

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

const isLoading = signal(false);

const button = {
    div: {
        style: 'display: flex; gap: 1rem; align-items: center;',
        children: [
            { 
                Button: { 
                    color: 'primary',
                    loading: () => isLoading.value,
                    onclick: async () => {
                        isLoading.value = true;
                        await new Promise(r => setTimeout(r, 2000));
                        isLoading.value = false;
                    },
                    children: ['Save Changes'] 
                } 
            },
            { 
                span: { 
                    style: 'opacity: 0.7;', 
                    children: [() => isLoading.value ? '⏳ Saving...' : 'Click to test'] 
                } 
            }
        ]
    }
};

$('#example').content(button);
<!-- Define a named signal globally -->
<script>
globalThis.signal = Lightview.signal;
signal(false, 'btnLoading');
</script>

<!-- Import Button -->
<script type="module" src="/components/actions/button.js"></script>

<div style="display: flex; gap: 1rem; align-items: center;">
    <lv-button 
        color="primary"
        loading="${signal.get('btnLoading').value}"
        onclick="signal.get('btnLoading').value = true; setTimeout(() => signal.get('btnLoading').value = false, 2000)"
    >
        Save Changes
    </lv-button>
    
    <span style="opacity: 0.7;">
        ${signal.get('btnLoading').value ? '⏳ Saving...' : 'Click to test'}
    </span>
</div>

Props

Prop Type Default Description
color string - 'primary' | 'secondary' | 'accent' | 'neutral' | 'info' | 'success' | 'warning' | 'error' | 'ghost' | 'link'
size string 'md' 'xs' | 'sm' | 'md' | 'lg'
variant string - 'outline' | 'soft' | 'dash' | 'wide' | 'block' | 'square' | 'circle'
disabled boolean | function false Disable the button (supports reactive function)
loading boolean | function false Show loading spinner (supports reactive function)
active boolean false Force active/pressed state
glass boolean false Glass morphism effect
noAnimation boolean false Disable click animation

Button Gallery

Live examples using <lv-button> custom elements.

Colors

Default Neutral Primary Secondary Accent Info Success Warning Error Ghost Link

Variants

Outline

Default Primary Secondary Accent

Soft

Primary Secondary Accent

Ghost & Link

Ghost Link

Sizes

Extra Small Small Medium Large

States

Normal Active Disabled Loading

Special Shapes

Wide Button ⊗ ✓

Mixed Combinations

Tiny Success Small Outline Soft Warning Large Error Glass Effect Soft Accent Tiny Ghost Wide Primary