Use case 01
Reactive counter
A focused component that combines state(),
computed(), effect(), and a typed native
CustomEvent.
- Local state is read through accessors and changed with setters.
- Derived text updates from a read-only computed value.
- The host page receives a bubbling
changeevent.
const count = state(0)
const text = computed(() => `Count: ${count()}`)
Use case 02
Reactive scheduling probe
A small fixture that exercises dependency-gated updates, batched state setters, effects, and synchronous host flushing.
- Unrelated state changes leave sibling bindings untouched.
- Multiple synchronous setters coalesce into one update pass.
host().flushSync()applies pending DOM updates immediately.
primary.set(primary() + 1)
host().flushSync()
Use case 03
List reconcilers
A fixture for item-keyed <For> rows and
position-keyed <Index> rows.
-
<For>moves keyed nodes without recreating them. -
<Index>keeps row nodes stable while values rebind. - Input focus survives state updates from editable primitive rows.
<For each={rows()}>
<Index each={names()}>
Use case 04
Primitive toggle
A small design-system primitive using Shadow DOM, parts, slots, state attributes, typed DOM event helpers, and explicit control flow.
part,data-state, and ARIA form the styling contract.<Show>and keyed.map()keep dynamic trees analyzable.host()andAbortSignalmodel lifecycle work.
<button part="root control"
data-state={pressed() ? "on" : "off"}>
Use case 05
PascalCase composition
Authoring code composes imported components by their TypeScript names. The native kebab-case tag names remain compiler output details.
<Counter />compiles to the inferred counter element.<Toggle />compiles to the inferred toggle element.- The page listens to native events without a framework adapter.
import { Counter } from "./counter.wc.tsx"
return <Counter label="Nested count" />
Use case 06
CSS variable theming
v0.1 keeps CSS flat and bundler-owned. Host pages theme generated elements through custom properties rather than an Naos CSS graph.
- CSS text arrives from Vite
?inlineimports. - Custom properties cross the Shadow DOM boundary naturally.
- Parts and state attributes remain the stable styling hooks.
style="--naos-control-bg: #f5f3ff"
Use case 07
Design-system primitives
A small primitive set shows Naos output as framework-neutral UI: interactive disclosure and field controls expose native attributes, events, slots, parts, and CSS variables.
x-disclosurepairs ARIA state with a typed event and slots.x-fieldexposes label, hint, status, and input contracts.- The host page observes both controls with plain DOM listeners.
<x-disclosure> and <x-field>
dispatch native CustomEvents.
Use case 08
Packaged primitives
The first @naos-ui/primitives package ships compiled
Naos-authored Web Components. These are package imports, not local
demo fixtures.
- Buttons, toggles, checkbox, field, tabs, and dropdown share parts and state attributes.
- The package build compiles
.wc.tsxsources before publishing. - Checkbox and toggle use the compiler-owned Form-Associated Custom Element spike.
Dropdown is experimental and compiler-compatible in this first pass.
import "@naos-ui/primitives"
Use case 09
Custom Element router
The optional @naos-ui/router package maps browser URLs to
native Custom Element views without a framework runtime.
- Route records target custom-element tags.
- Anchors remain ordinary
<a href>links. - Loaders, actions, params, active links, and not-found fallback are DOM-visible.
createRouter({
outlet,
routes: [{ path: "/products/:id", tag: "router-product-view", loader, action }]
})