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 change event.
Last counter event: none
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() and AbortSignal model lifecycle work.
manual slot content Last toggle event: none
<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 ?inline imports.
  • Custom properties cross the Shadow DOM boundary naturally.
  • Parts and state attributes remain the stable styling hooks.
themed slot
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-disclosure pairs ARIA state with a typed event and slots.
  • x-field exposes label, hint, status, and input contracts.
  • The host page observes both controls with plain DOM listeners.
Production Publish native Custom Elements without a host framework adapter. Last disclosure event: none Used by generated package names and docs examples. Last field event: none
<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.tsx sources before publishing.
  • Checkbox and toggle use the compiler-owned Form-Associated Custom Element spike.
Checkbox, toggle, and switch contribute native FormData.
Last primitive form data: none Parts, slots, data-state, and CSS variables. Behavior stays inside Naos-authored kernels or native controls. Checkbox and toggle submit through ElementInternals.

Dropdown is experimental and compiler-compatible in this first pass.

Right-click for release context actions. This section uses Zag-backed trigger and content props while keeping the Naos Custom Element contract. Browser, docs, and package-release checks must be green. Commit focused slices before moving to the next primitive. Disabled accordion items remain focus-safe. Confirm that package docs, browser tests, and release metadata are aligned before opening the release PR. Last primitive event: none
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.
Last router route: none
createRouter({
  outlet,
  routes: [{ path: "/products/:id", tag: "router-product-view", loader, action }]
})