Creating Elements

Lightview gives you four ways to build UI. Pick your favorite—or mix and match. They all use the same reactive system under the hood.

Style 1: Tagged API

The most concise way. Destructure tag functions and compose naturally:

const { signal, tags } = Lightview;
const { div, h1, p, button } = tags;

const count = signal(0);

const app = div({ class: 'container' },
    h1('Hello Lightview'),
    p(() => `Count: ${count.value}`),
    button({ onclick: () => count.value++ }, 'Click me')
);

document.body.appendChild(app.domEl);

Style 2: Element Function

More explicit. Good when you need dynamic tag names:

const { signal, element } = Lightview;

const count = signal(0);

const app = element('div', { class: 'container' }, [
    element('h1', {}, ['Hello Lightview']),
    element('p', {}, [() => `Count: ${count.value}`]),
    element('button', { onclick: () => count.value++ }, ['Click me'])
]);

document.body.appendChild(app.domEl);

Style 3: vDOM Syntax

Plain JSON objects. Great for storing in databases or generating programmatically:

const { signal, element } = Lightview;

const count = signal(0);

const app = element('div', { class: 'container' }, [
    { tag: 'h1', attributes: {}, children: ['Hello Lightview'] },
    { tag: 'p', attributes: {}, children: [() => `Count: ${count.value}`] },
    { tag: 'button', attributes: { onclick: () => count.value++ }, children: ['Click me'] }
]);

document.body.appendChild(app.domEl);

Style 4: Object DOM (lightview-x)

Compact JSON format. Requires the hypermedia extension:

// Enable Object DOM first
LightviewX.useObjectDOMSyntax();

const { signal, tags } = Lightview;
const { div } = tags;

const count = signal(0);

const app = div({ class: 'container' },
    { h1: { children: ['Hello Lightview'] } },
    { p: { children: [() => `Count: ${count.value}`] } },
    { button: { onclick: () => count.value++, children: ['Click me'] } }
);

document.body.appendChild(app.domEl);

Comparison

Style Pros Cons
Tagged API Most concise, natural to write Requires destructuring
Element Function Explicit, dynamic tag names More verbose
vDOM JSON serializable, easy to validate Most verbose
Object DOM Compact JSON, clean templates Requires lightview-x

Attributes & Events

Pass attributes as the first argument (Tagged API) or in the attributes object (others):

// Standard attributes
div({ 
    id: 'my-div',
    class: 'container active',
    style: 'color: red;',
    'data-value': '42'
})

// Reactive attributes - use functions!
div({
    class: () => isActive.value ? 'active' : 'inactive',
    style: () => `opacity: ${visible.value ? 1 : 0}`,
    disabled: () => isLoading.value
})

// Event handlers - use "on" prefix
button({
    onclick: (e) => handleClick(e),
    onmouseenter: () => setHovered(true),
    onmouseleave: () => setHovered(false)
})

Children

Children can be strings, numbers, elements, arrays, or functions:

div(
    'Static text',                          // String
    42,                                     // Number (converted to string)
    span('Nested element'),                 // Element
    () => `Dynamic: ${value.value}`,        // Reactive function
    () => items.value.map(i => li(i.name)), // Reactive list
    condition && span('Conditional')        // Conditional (falsy = not rendered)
)

The domEl Property

Every Lightview element has a domEl property - the actual DOM node:

const myDiv = div({ class: 'box' }, 'Hello');

// Access the real DOM element
document.body.appendChild(myDiv.domEl);

// You can also manipulate it directly
myDiv.domEl.classList.add('another-class');
const { signal, tags } = Lightview;
const { div, input, p } = tags;

const name = signal('World');

const app = div(
    input({ 
        type: 'text',
        value: name.value,
        oninput: (e) => name.value = e.target.value
    }),
    p(() => `Hello, ${name.value}!`)
);