@adia-ai/web-modules
v0.7.22
Published
AdiaUI composite custom elements — shell, chat, editor, runtime clusters built from @adia-ai/web-components primitives. Subpath exports per cluster.
Readme
@adia-ai/web-modules
Composite custom elements built from
@adia-ai/web-components primitives. Organized
into clusters by use case; each cluster ships as a subpath export so
consumers install only what they need.
Install
npm install @adia-ai/web-modules @adia-ai/web-componentsCDN — no bundler (CodePen, marketing pages, static HTML)
Since v0.6.30, both this package and @adia-ai/web-components ship pre-flattened + minified bundles under dist/ that work via jsdelivr/unpkg with zero build tooling.
Kitchen-sink one-tag setup (CodePen / demos / drop-into-any-HTML):
<!-- CSS: all primitives + the shell tier you use -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@adia-ai/[email protected]/dist/web-components.min.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@adia-ai/[email protected]/dist/shell/admin-shell.min.css">
<!-- JS: everything in one bundle (primitives + all 4 shells + a2ui-runtime; ~190 KB gzipped) -->
<script type="module" src="https://cdn.jsdelivr.net/npm/@adia-ai/[email protected]/dist/everything.min.js"></script>
<admin-shell mode="rounded borderless">
<admin-sidebar slot="leading" resizable collapsible>
<admin-topbar slot="header">
<span slot="heading">My App</span>
</admin-topbar>
<section-ui>
<nav-ui>
<nav-item-ui icon="house" text="Home" selected></nav-item-ui>
<nav-item-ui icon="gear" text="Settings"></nav-item-ui>
</nav-ui>
</section-ui>
<div data-resize></div>
</admin-sidebar>
<admin-content>
<admin-topbar>
<breadcrumb-ui><span>Dashboard</span></breadcrumb-ui>
</admin-topbar>
<admin-scroll>
<admin-page>
<admin-page-header>
<header>
<div>
<h1>Dashboard</h1>
<div data-actions>
<button-ui text="Share" variant="outline" size="sm"></button-ui>
</div>
</div>
<p>Welcome back.</p>
</header>
</admin-page-header>
<admin-page-body>
<button-ui variant="primary" text="Click me"></button-ui>
</admin-page-body>
</admin-page>
</admin-scroll>
</admin-content>
</admin-shell>
<!--
Canonical admin-shell hierarchy (matches ui-kit.exe.xyz/site/index.html):
- <nav-ui> + <nav-item-ui> is THE primitive pair for sidebar navigation.
- <menu-ui> / <menu-item-ui> are for popover action menus (dropdowns), NOT for nav.
- <admin-topbar slot="header"> goes inside <admin-sidebar> (workspace switcher / brand).
- <admin-statusbar slot="footer"> goes inside <admin-sidebar> (user switcher / sign-in).
- <admin-scroll> wraps <admin-page> inside <admin-content>.
- <admin-page-header> wraps an inner <header> with <div><h1>+<div data-actions></div></div><p>.
The <div data-actions> slot is right-aligned for page-level action buttons.
Use <header data-flush> to drop the bottom border.
Reference: https://ui-kit.exe.xyz/site/examples/admin-dashboard +
https://github.com/adiahealth/gen-ui-kit/blob/main/site/templates/settings.html
-->Per-shell setup (advanced — only one shell tier loaded):
<script type="module" src="https://cdn.jsdelivr.net/npm/@adia-ai/[email protected]/dist/web-components.min.js"></script>
<script type="module" src="https://cdn.jsdelivr.net/npm/@adia-ai/[email protected]/dist/shell/admin-shell.min.js"></script>| Bundle | Path | Gzipped | Contents | When to use |
|---|---|---|---|---|
| Everything | /dist/everything.min.js | ~250 KB | All primitives + a2ui-runtime + all 4 shells | CodePen / one-tag demos |
| Admin shell | /dist/shell/admin-shell.min.js | ~6 KB | Shell registration; needs web-components.min.js first | Admin app, no chat/editor |
| Chat shell | /dist/chat/chat-shell.min.js | ~230 KB | Includes chat-thread/composer | Chat surface |
| Editor shell | /dist/editor/editor-shell.min.js | ~6 KB | Shell registration; needs primitives first | Editor surface |
| Simple shell | /dist/simple/simple-shell.min.js | ~5.6 KB | Shell registration; needs primitives first | Settings / forms |
Each shell needs its matching CSS (the kitchen-sink example above loads only admin-shell.min.css). Mirror the JS path — swap the shell tier:
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@adia-ai/[email protected]/dist/shell/admin-shell.min.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@adia-ai/[email protected]/dist/chat/chat-shell.min.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@adia-ai/[email protected]/dist/editor/editor-shell.min.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@adia-ai/[email protected]/dist/simple/simple-shell.min.css">The @0.7 range tracks the latest 0.6.x patch (won't jump to a breaking 0.8); pin an exact version (e.g. @0.7.13) for reproducible builds.
Pick ONE bundle path. Mixing everything.min.js with a separate web-components.min.js causes customElements.define to throw "name already defined". For CodePen the kitchen-sink path is correct.
npm-installed consumers stay on the existing cluster exports (./shell, ./chat, etc.). The new */bundled (CSS) and */js-bundled + ./everything (JS) exports are additive — only consumers without a bundler need them.
See the CDN usage guide for a full CodePen template + worked examples.
Using with AI agents
When composing UI with an AI coding agent (Claude Code / Cursor / Windsurf / Claude Desktop), load the adia-ui-kit skill in the harness — it encodes the 95-primitive catalog, composition patterns for all shells (admin / chat / editor / simple), and the Plan-Execute-Verify discipline that renders the composed surface in a real demo to verify intent. Skill lives at .agents/skills/adia-ui-kit/ in the repo.
@adia-ai/web-components is always required (modules compose primitives at runtime). Two additional peer dependencies are declared but only needed for specific clusters:
| Peer dependency | Required when you use |
|---|---|
| @adia-ai/web-components (always) | Any cluster |
| @adia-ai/a2ui-runtime | runtime cluster (<gen-root>, <a2ui-root>) — A2UI message → DOM renderer |
| @adia-ai/llm | chat cluster (<chat-shell>) — LLM proxy + streaming |
If you only use shell, editor, simple, or theme clusters, those two peers can be omitted (or kept as --legacy-peer-deps warnings under npm). pnpm with auto-install-peers will silently install them.
Import: JS
import '@adia-ai/web-modules'; // every cluster
import '@adia-ai/web-modules/shell'; // admin-shell + admin-sidebar + admin-command
import '@adia-ai/web-modules/chat'; // chat-shell + chat-thread + chat-composer + …
import '@adia-ai/web-modules/editor'; // editor-shell + editor-canvas + editor-sidebar + …
import '@adia-ai/web-modules/simple'; // simple-shell + simple-content + simple-hero
import '@adia-ai/web-modules/theme'; // theme-panel
import '@adia-ai/web-modules/runtime'; // gen-root + a2ui-rootThe per-cluster import registers the JS-backed elements only. Each cluster also has CSS-only structural children (e.g.
admin-content,admin-topbar,admin-page— see the Clusters table) that need no JS registration: they are plain custom elements styled entirely by the cluster CSS.customElements.get()returningundefinedfor one of them is expected, not a bug.
Import: CSS (since v0.4.5)
⚠️ Required — shell layouts depend on this CSS. Shell JS modules (
admin-shell,chat-shell,editor-shell,simple-shell) do not self-import their layout CSS. Omitting the matching*.cssimport for any shell you use renders that shell as unstyled stacked<div>elements with no console error — sidebars stack above content, topbar/statusbar fall off the viewport grid, nothing throws. This is the #1 cold-start silent-failure mode reported by external consumers. If your shell looks like a vertical list of blocks, you missed a line below.
CSS imports use the package specifier — the package's exports map resolves .css requests to the per-element stylesheet on disk:
import '@adia-ai/web-modules/shell/admin-shell.css';
import '@adia-ai/web-modules/chat/chat-shell.css';
import '@adia-ai/web-modules/editor/editor-shell.css';
import '@adia-ai/web-modules/simple/simple-shell.css';
import '@adia-ai/web-modules/theme/theme-panel.css';
import '@adia-ai/web-modules/runtime/gen-root.css';For pre-v0.4.5 consumers: if you were importing CSS via the relative
node_modulespath ('../node_modules/@adia-ai/web-modules/editor/editor-shell/editor-shell.css'), switch to the package-specifier form above. The relative-path form is fragile under pnpm, Yarn PnP, and npm hoisting; the new package-specifier form works under all three.
Import: JS + CSS in one line (/with-css)
For the shell cluster, the /with-css opt-in collapses the JS + CSS
imports into a single side-effect import:
import '@adia-ai/web-modules/shell/with-css';This registers the JS-backed shell elements (admin-shell,
admin-sidebar, admin-command) and mounts the shell layout CSS
(admin-shell.css bundles every sub-component style). It is the one-line
equivalent of import '@adia-ai/web-modules/shell' +
import '@adia-ai/web-modules/shell/admin-shell.css'.
The default @adia-ai/web-modules/shell subpath stays CSS-free to
preserve the explicit-import contract (ADR-0030);
/with-css is the named opt-in. Per-element companions
(@adia-ai/web-modules/shell/admin-shell/with-css) also exist for
finer-grained imports.
Each cluster carries a shell host (behavior-only orchestrator) plus a family of bespoke shell-tier children (cluster-namespaced custom elements with state-as-attribute semantics) per ADR-0023. The bespoke vocabulary is the only recognized authoring shape since v0.4.0 (ADR-0024).
The patterns directory lived inside
@adia-ai/web-componentsaspatterns/until this package was extracted (see ADR-0012). Tags, CSS, and YAML/A2UI contracts are unchanged; only the import path moves.
Clusters
| Cluster | Host | Bespoke children | What's inside |
|---|---|---|---|
| shell | <admin-shell> | <admin-sidebar>, <admin-command> (JS-bearing); <admin-content>, <admin-topbar>, <admin-statusbar>, <admin-scroll>, <admin-page>, <admin-page-header>, <admin-page-body> (CSS-only); 9 children total | Admin-shell composition: sidebars, command palette, page chrome. Resize/collapse/persistence on <admin-sidebar>; Cmd+K palette on <admin-command>. |
| chat | <chat-shell> | <chat-thread>, <chat-composer>, <chat-sidebar> (JS-bearing); <chat-empty>, <chat-header>, <chat-status> (CSS-only); 6 children total | Conversational surface — streaming messages, composer with [disabled] propagation, scroll-to-bottom thread, [streaming] reflected. |
| editor | <editor-shell> | <editor-toolbar>, <editor-canvas>, <editor-sidebar> (JS-bearing); <editor-statusbar>, <editor-canvas-empty> (CSS-only); 5 children total | Design-tool surface — toolbar with [full-screen], central canvas with [focused]/[empty], sidebar wraps <pane-ui resizable> for delegation. |
| runtime | <gen-root>, <a2ui-root> | — | Render roots that turn JSON or gen-UI intents into live DOM. |
| theme | — (controls-only) | <theme-panel> (JS-bearing); 1 child total | Appearance-preferences control surface — [theme] named themes, --a-density / --a-radius-k parametric overrides, color-scheme light/dark, opt-in [persist]. Drops into any consumer's <popover-ui slot="content"> topbar. Spec: docs/specs/theme-panel-module.md. |
Cross-package convenience subpaths
generative is not a web-modules cluster — it's a convenience barrel
that pulls in two @adia-ai/web-components primitives needed by every
generative-UI surface. Subpath listed here so consumers don't have to
hunt for it:
| Subpath | Registers | Notes |
|---|---|---|
| @adia-ai/web-modules/generative | <canvas-ui>, <a2ui-root> | Cross-package — these live in @adia-ai/web-components but compose so frequently for generative UI that we ship the registration barrel here. Per ADR-0027, primitives that compose cross-package are not in the default catalog barrel; generative is the explicit opt-in. |
Future clusters on the strategic horizon: data (kanban, filters,
table-toolbar), agent (agent-trace, reasoning panels).
See adia-ui-authoring skill, references/shell-patterns.md (absorbed bespoke-shell-children) for the canonical decomposition recipe used by all three families.
Quick start
ESM-only — bundlers (Vite, esbuild, webpack 5+, Rollup) resolve import statements for both .js and .css; in plain HTML, use <script type="module"> for JS and <link> for CSS.
⚠️ Both JS AND CSS imports are required per cluster. Importing only the JS gives you registered tags but no layout. See Import: CSS above for the failure mode.
// JS — register every primitive + the clusters you compose with
import '@adia-ai/web-components'; // primitives + nav family
import '@adia-ai/web-modules/shell'; // admin-shell + bespoke children
import '@adia-ai/web-modules/chat'; // chat-shell + bespoke children (needs @adia-ai/llm)
import '@adia-ai/web-modules/editor'; // editor-shell + bespoke children
import '@adia-ai/web-modules/runtime'; // gen-root, a2ui-root (needs @adia-ai/a2ui-runtime)
import '@adia-ai/web-modules/theme'; // theme-panel (appearance prefs)
// CSS — one stylesheet per cluster you use (REQUIRED — see callout above)
import '@adia-ai/web-components/css'; // every primitive's CSS
import '@adia-ai/web-modules/shell/admin-shell.css';
import '@adia-ai/web-modules/chat/chat-shell.css';
import '@adia-ai/web-modules/editor/editor-shell.css';
import '@adia-ai/web-modules/theme/theme-panel.css';Then in your markup (bespoke shape, canonical since v0.4.0):
<admin-shell mode="rounded">
<admin-sidebar slot="leading" resizable collapsible>
<header-ui>
<span slot="heading">App</span>
</header-ui>
<section-ui>
<nav-ui>…</nav-ui>
</section-ui>
</admin-sidebar>
<main>…</main>
<admin-command>
<command-ui placeholder="Search..."></command-ui>
</admin-command>
</admin-shell>Live demos for every cluster:
Three-tier architecture
@adia-ai/web-components — primitives (button, table, card, …)
@adia-ai/web-modules — composites (this package; clusters via subpath)
@adia-ai/web-themes — token sets per vendor/brand (future)Modules and themes both peer-depend web-components directly; they
do not import each other. Composition happens at the consumer's
site, not inside the library. See
ADR-0012
for the rationale and the patterns/modules collapse.
Migration from @adia-ai/web-components/patterns
The patterns/ directory was extracted from @adia-ai/web-components into this package in v0.0.29 (ADR-0012). If you're upgrading from a pre-v0.0.29 release:
- import '@adia-ai/web-components/patterns/app-shell/app-shell.js';
+ import '@adia-ai/web-modules/shell';
- import '@adia-ai/web-components/patterns/adia-chat/adia-chat.js';
+ import '@adia-ai/web-modules/chat';CSS paths shift the same way. Tag names + class names also changed in v0.0.31 (ADR-0015 — <app-shell-ui> → <admin-shell>, <adia-chat-ui> → <chat-shell>, <adia-editor-ui> → <editor-shell>, <gen-ui-ui> → <gen-root>) and v0.0.32 (ADR-0016 — module classes drop the Adia prefix). And the legacy authoring shapes (<aside-ui slot>, <section data-chat-messages>, etc.) were retired in v0.4.0 in favor of the bespoke vocabulary — see ADR-0024 for the full migration recipe.
Layout
web-modules/
├── shell/ 9 elements
│ ├── admin-shell/ <admin-shell> host (87 LOC JS, behavior-only)
│ ├── admin-sidebar/ resizable + collapsible + localStorage persistence
│ ├── admin-command/ Cmd+K command palette
│ └── admin-{topbar,content,statusbar,scroll,page,page-header,page-body}/
│ CSS-only structural children
├── chat/ 6 elements
│ ├── chat-shell/ <chat-shell> host (streaming-aware)
│ ├── chat-thread/ scrollable message list
│ ├── chat-composer/ input + submit + [disabled] propagation
│ ├── chat-sidebar/ conversation list
│ └── chat-{empty,header,status}/ CSS-only
├── editor/ 5 elements
│ ├── editor-shell/ <editor-shell> host (toolbar/canvas/sidebar orchestrator)
│ ├── editor-toolbar/ <editor-toolbar> with [full-screen]
│ ├── editor-canvas/ <editor-canvas> with [empty]/[focused]
│ ├── editor-sidebar/ wraps <pane-ui resizable> for delegation
│ └── editor-{statusbar,canvas-empty}/ CSS-only
├── simple/ 3 elements
│ ├── simple-shell/ <simple-shell> minimal marketing/landing shell
│ └── simple-{content,hero}/ CSS-only
├── runtime/ 2 render roots
│ ├── gen-root/ <gen-root> turns gen-UI intents into DOM
│ └── a2ui-root/ <a2ui-root> A2UI protocol → DOM (uses @adia-ai/a2ui-runtime)
├── theme/ 1 element
│ └── theme-panel/ <theme-panel> appearance-preferences control surface
└── index.js barrel re-export of every clusterEach element directory carries its .js, .css, .yaml, and .a2ui.json files — same shape as web-components/components/<x>/. The yaml + a2ui.json contracts feed the gen-UI catalog at packages/a2ui/corpus/catalog-a2ui_0_9.json; the build script at scripts/build/components.mjs scans both web-components/components/ and web-modules/<cluster>/.
Behavior contract
All <*-shell> hosts are behavior-only orchestrators — they reflect state attributes, propagate slot intent to their bespoke children, and forward events. Visual layout is owned by the children's CSS. Bespoke children fall into two classes:
- JS-bearing children carry
connected()/disconnected()lifecycle for interactive behavior (admin-sidebarresize,admin-commandpalette,chat-threadstreaming scroll,editor-canvaszoom, etc.). - CSS-only children (no
.jsfile — only.yaml+.css+.a2ui.json) declare slot intent for the host's styling system to attach against. Don't author a.jsfor these; the host handles their behavior via attribute selectors.
The decomposition recipe (when to JS-bearing vs CSS-only, how to namespace state attributes, slot vocabulary conventions) is captured in the adia-ui-authoring skill, references/shell-patterns.md (absorbed bespoke-shell-children).
License
MIT
