lightview
Version:
A reactive UI library with features of Bau, Juris, and HTMX plus safe LLM UI generation
220 lines (179 loc) • 8.18 kB
HTML
<!-- SEO-friendly SPA Shim -->
<script src="/lightview-router.js?base=/index.html"></script>
<link rel="stylesheet" href="../components/index.css">
<div class="docs-layout">
<aside class="docs-sidebar" src="./nav.html" data-preserve-scroll="docs-nav"></aside>
<main class="docs-content">
<h1>Enhance</h1>
<p>
The <code>enhance()</code> function lets you add Lightview's reactivity to existing HTML elements.
Perfect for progressive enhancement - start with plain HTML and add interactivity where needed.
</p>
<h2>Why Enhance?</h2>
<p>
Sometimes you have existing HTML - maybe from a CMS, a server-rendered template, or just plain HTML.
Rather than rebuilding everything with Lightview elements, <code>enhance()</code> lets you
incrementally add reactivity to what's already there.
</p>
<h2>Basic Usage</h2>
<pre><code>const { signal, enhance } = Lightview;
// Select an existing element and make it reactive
const counter = signal(0);
enhance('#my-element', {
innerText: () => `Count: ${counter.value}`
});
// Now when counter changes, the element updates automatically!</code></pre>
<h2>Syntax</h2>
<pre><code>enhance(selectorOrNode, options)
// selectorOrNode: CSS selector string or DOM element
// options: { innerText?, innerHTML?, ...attributes }
// Returns: Lightview element wrapper (or null if not found)</code></pre>
<h2>Live Example: Basic Enhancement</h2>
<pre><script>
examplify(document.currentScript.nextElementSibling, {
at: document.currentScript.parentElement,
scripts: ['/lightview.js'],
type: 'module',
minHeight: 180,
html: `<!-- This HTML exists in the page before enhancement -->
<div id="greeting-card" style="padding: 1rem; background: #f8f9fa; border-radius: 8px; border: 1px solid #dee2e6;">
<h3 id="greeting-title">Welcome!</h3>
<p id="greeting-message">Enter your name below</p>
<input id="name-input" type="text" placeholder="Your name..." style="width: 100%; padding: 0.5rem; margin: 0.5rem 0; border: 1px solid #ccc; border-radius: 4px;">
<button id="reset-btn" style="padding: 0.5rem 1rem; background: #6c757d; color: white; border: none; border-radius: 4px; cursor: pointer;">Reset</button>
</div>`
});
</script><code contenteditable="true">const { signal, enhance } = Lightview;
const name = signal('');
// Enhance the input field
enhance('#name-input', {
oninput: (e) => name.value = e.target.value,
value: () => name.value
});
// Enhance the greeting title
enhance('#greeting-title', {
innerText: () => name.value ? `Hello, ${name.value}!` : 'Welcome!'
});
// Enhance the greeting message
enhance('#greeting-message', {
innerText: () => name.value
? `Nice to meet you, ${name.value}!`
: 'Enter your name below',
style: () => name.value
? 'color: #28a745; font-weight: 500;'
: 'color: #6c757d;'
});
// Enhance the reset button
enhance('#reset-btn', {
onclick: () => name.value = '',
disabled: () => !name.value,
style: () => `padding: 0.5rem 1rem; background: ${name.value ? '#dc3545' : '#6c757d'}; color: white; border: none; border-radius: 4px; cursor: ${name.value ? 'pointer' : 'not-allowed'}; opacity: ${name.value ? 1 : 0.5};`
});</code></pre>
<h2>Options</h2>
<h3>innerText</h3>
<p>Replace the text content of an element. Can be static or reactive:</p>
<pre><code>// Static text
enhance('#greeting', { innerText: 'Hello World' });
// Reactive text - updates when signal changes
const name = signal('Alice');
enhance('#greeting', { innerText: () => `Hello ${name.value}` });</code></pre>
<h3>innerHTML</h3>
<p>Replace the HTML content. Use with caution - only with trusted content:</p>
<pre><code>const html = signal('<strong>Bold text</strong>');
enhance('#content', { innerHTML: () => html.value });</code></pre>
<h3>Attributes</h3>
<p>Any other properties in options are treated as attributes. These can also be reactive:</p>
<pre><code>const isDisabled = signal(false);
const theme = signal('light');
enhance('#my-button', {
disabled: () => isDisabled.value,
class: () => `btn btn-${theme.value}`,
'data-active': () => !isDisabled.value
});</code></pre>
<h2>Live Example: Reactive Attributes</h2>
<pre><script>
examplify(document.currentScript.nextElementSibling, {
at: document.currentScript.parentElement,
scripts: ['/lightview.js', '/lightview-x.js'],
type: 'module',
maxHeight: 50,
html: `
<span id="attr-demo">
<button id="toggle-btn">Enable/Disable</button>
<button id="target-btn">Target Button</button>
</span>`
});
</script><code contenteditable="true">const { signal, enhance, tags } = Lightview;
const { div } = tags;
const disabled = signal(false);
enhance('#toggle-btn', {
onclick: () => disabled.value = !disabled.value,
innerText: () => disabled.value ? 'Enable' : 'Disable'
});
enhance('#target-btn', {
disabled: () => disabled.value,
style: () => `opacity: ${disabled.value ? 0.5 : 1}; cursor: ${disabled.value ? 'not-allowed' : 'pointer'};`
});</code></pre>
<h2>Progressive Enhancement Pattern</h2>
<p>
Start with semantic HTML that works without JavaScript, then enhance with Lightview:
</p>
<pre><code><!-- server-rendered HTML -->
<div id="user-info">
<h2>Guest</h2>
<p>Please log in</p>
</div>
<script>
// Enhancement kicks in when JS loads
const { signal, enhance } = Lightview;
const user = signal(null);
// Fetch user data
fetch('/api/user').then(r => r.json()).then(data => {
user.value = data;
});
// Enhance the existing markup
enhance('#user-info h2', {
innerText: () => user.value?.name ?? 'Guest'
});
enhance('#user-info p', {
innerText: () => user.value
? `Welcome back, ${user.value.name}!`
: 'Please log in'
});
</script></code></pre>
<h2>Return Value</h2>
<p>
<code>enhance()</code> returns a Lightview element wrapper with a <code>domEl</code> property
pointing to the actual DOM node. This lets you further manipulate it:
</p>
<pre><code>const el = enhance('#my-div', { class: 'enhanced' });
// Access the wrapped element
if (el) {
console.log(el.domEl); // The actual DOM node
el.attributes.id = 'new-id'; // Update attributes reactively
}</code></pre>
<h2>Tips & Patterns</h2>
<h3>Enhance Multiple Elements</h3>
<pre><code>// Enhance a list of elements
document.querySelectorAll('.counter').forEach(el => {
const count = signal(0);
enhance(el, {
innerText: () => count.value,
onclick: () => count.value++
});
});</code></pre>
<h3>Reusing Elements</h3>
<p>If you call <code>enhance()</code> on an already-enhanced element, it merges the new options:</p>
<pre><code>// First enhancement
enhance('#btn', { innerText: 'Click me' });
// Second enhancement - adds to the first
enhance('#btn', { onclick: "alert('clicked')" });
// Result: <button onclick="alert('clicked')">Click me</button></code></pre>
<h3>When to Use</h3>
<ul>
<li><strong>Use enhance():</strong> When you have existing HTML (server-rendered, CMS, etc.)</li>
<li><strong>Use element/tags:</strong> When building new UI from scratch in JavaScript</li>
<li><strong>Mix both:</strong> Enhance static structure, build dynamic parts with tags</li>
</ul>
</main>
</div>