Elements

Lightview is uniquely flexible. It doesn't force you into a single way of describing your DOM. Whether you prefer concise JavaScript functions, structured JSON, or standard HTML, the same signal-based reactivity powers it all.

Comparison

Syntax Style Best For Requirement
Tagged API div(h1('Title')) Application logic, dynamic UIs Core
vDOM { tag: 'div', ... } Serialization, data-driven UI Core
Object DOM (oDOM) { div: { ... } } Concise templates, config files Lightview X
Custom Elements <lv-button> Progressive enhancement, CMS Lightview X
cDOM (Experimental) 'sum($/cart/items...price)' Declarative logic, LLM generation lightview-cdom.js

Note: An exciting 5th option is coming, the Computational DOM, a.k.a. cDOM.

Tagged API

Inspired by Bau.js, this is the most concise way to build UIs in JavaScript. Every HTML tag is available as a function.

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')
);
$('#example').content(app);

Pros: Extremely readable, feels like "HTML in JS" without a compiler, full IDE autocomplete.

vDOM Syntax

Represent your UI as plain JavaScript objects. This is the underlying format for all non-string elements in Lightview.

const { signal, element, $, tags } = Lightview;
const { div } = tags;
const count = signal(0);
// will accept either a function or string as tag, function avoids typos better
const app = { tag:div, attributes: { class: 'container' }, children: [
    { tag: 'h1', attributes: {}, children: ['Hello Lightview'] },
    { tag: 'p', attributes: {}, children: [() => `Count: ${count.value}`] },
    { tag: 'button', attributes: { onclick: () => count.value++ }, children: ['Click me'] }
]};
$('#example').content(app);

Pros: Unambiguous, easy to serialize/deserialize as JSON, perfect for programmatic generation.

Object DOM (oDOM)

A more compact JSON representation provided by Lightview X. It uses the tag name as a key to reduce verbosity.

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

Pros: Highly readable for templates stored in JSON, significantly less boilerplate than standard vDOM.

HTML Custom Elements

Use standard HTML tags to instantiate Lightview components. Ideal for multi-page apps or content managed by a CMS.

<!-- Requires registered components & Lightview X -->
<lv-card>
    <h3 slot="title">User Profile</h3>
    <lv-badge color="primary">Admin</lv-badge>
    <p>Active since 2024</p>
    <lv-button onclick="alert('Clicked!')">Settings</lv-button>
</lv-card>

Pros: Familiar HTML syntax, framework-agnostic, excellent for progressive enhancement of server-rendered pages.

Pseudo-elements

Lightview supports special "pseudo-elements" that perform specific tasks rather than creating a standard HTML element.

shadowDOM

The shadowDOM tag allows you to attach a Shadow Root to the parent element and render children inside it. This is useful for building encapsulated components without manual attachShadow calls.

const { tags } = Lightview;
const { div, shadowDOM, h2, p } = tags;

const MyComponent = () => div(
    shadowDOM({ mode: 'open', styles: ['/my-styles.css'] },
        h2('Encapsulated Title'),
        p('This content is inside the shadow root.')
    )
);

text

The text tag creates a single Text node containing the concatenated content of all its children, separated by spaces. It supports reactivity, meaning if any child is a function, the text node will update automatically.

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

const firstName = signal('John');
const lastName = signal('Doe');

const greeting = div(
    text('Hello,', () => firstName.value, () => lastName.value, '!')
);
// Initial result: 
Hello, John Doe !

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');