1.9 KiB
1.9 KiB
zulip
A minimal, no-build web app kit using only Lit-based web components via importmaps.
Quick Start Example
1. Define a Component
// components/counter.js
import { LitElement, html, css } from 'lit'
class Counter extends LitElement {
static properties = {
count: { type: Number, state: true }
}
constructor() {
super()
this.count = 0
}
static styles = css`
button { padding: 1rem; font-size: 1.2rem; }
`
render() {
return html`
<div>
<p>Count: ${this.count}</p>
<button @click=${() => this.count++}>
Increment
</button>
</div>
`
}
}
customElements.define('my-counter', Counter)
2. Use in App root (or other composition node)
import "./my-counter.js";
class AppRoot extends LitElement {
...
render() {
return html`<my-counter .count=${0}></my-counter>`;
}
}
3. Define Data Flows
Parent-to-Child (Props)
// Parent passes data down
html`<child-component .items=${this.items}></child-component>`
// Child receives via properties
static properties = {
items: { type: Array }
}
Child-to-Parent (Events)
// Child emits event
this.dispatchEvent(new CustomEvent('add-item', {
detail: { item: newItem },
bubbles: true,
composed: true
}))
// Parent listens
html`<child-component @add-item=${(e) => this.handleAdd(e.detail.item)}></child-component>`
Benefits Over TSX
-
No build step - Edit and refresh, instant feedback
-
Minimal dependencies - Just Lit, nothing else
-
Smaller bundle - No framework runtime, just standards
-
Better encapsulation - Shadow DOM, scoped styles
-
Framework agnostic - Works anywhere, even in React apps
-
Future-proof - Built on web standards
-
Easy to learn - Simple mental model for state, with natural evolution into Zustand/IndexedDB or similar extensions