@adia-ai/a2ui-corpus 0.6.20 → 0.6.22
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +13 -0
- package/catalog-a2ui_0_9.json +830 -208
- package/catalog-a2ui_0_9_rules.txt +657 -6
- package/package.json +1 -1
|
@@ -4,70 +4,677 @@
|
|
|
4
4
|
# cannot express. Concatenated into the agent system prompt.
|
|
5
5
|
# Generated from each component YAML's `a2ui.rules:` entries.
|
|
6
6
|
|
|
7
|
+
## AccordionItem
|
|
8
|
+
- Child of <accordion-ui> — places one collapsible section with header + body.
|
|
9
|
+
- Toggle behavior: click anywhere on the row toggles, unless inside [slot='actions'] or [data-no-toggle].
|
|
10
|
+
- For single-button disclosures (one expanding panel without a list) use <details>/<summary> or compose <button-ui> + <section-ui>.
|
|
11
|
+
|
|
12
|
+
## Accordion
|
|
13
|
+
- Hosts <accordion-item-ui> children. One or more sections may be open simultaneously (set single= to enforce only-one-open).
|
|
14
|
+
- For tab-switched panels (always exactly one open) use <tabs-ui>; accordion supports zero-open and multi-open.
|
|
15
|
+
- Item ordering is DOM-order; no auto-sort.
|
|
16
|
+
|
|
17
|
+
## ActionItem
|
|
18
|
+
- Child of <action-list-ui> — one inline-action row with icon + label + optional shortcut + optional sublabel.
|
|
19
|
+
- Different from <menu-item-ui>: action-items live inline in content surfaces; menu-items live inside <menu-ui> popovers.
|
|
20
|
+
- For navigation entries (route-changing) use <nav-item-ui> instead.
|
|
21
|
+
|
|
22
|
+
## ActionList
|
|
23
|
+
- Hosts <action-item-ui> children as a vertical command list inline in content surfaces.
|
|
24
|
+
- For popover-style menus use <menu-ui> + <menu-item-ui> instead.
|
|
25
|
+
- Typical use: command palettes, settings panels, agent suggestion lists.
|
|
26
|
+
|
|
27
|
+
## AgentArtifact
|
|
28
|
+
- Inline container for structured agent payloads inside <chat-thread-ui> message bodies or <inspector-ui> panes.
|
|
29
|
+
- kind attribute (a2ui|json|ticket|code|...) sets content-type-aware rendering and icon/badge styling.
|
|
30
|
+
- For free-text agent output use <text-ui> or <richtext-ui>; artifact-ui is for structured payloads only.
|
|
31
|
+
- primary + secondary slots for header chrome; default slot for the artifact body.
|
|
32
|
+
|
|
33
|
+
## AgentFeedbackBar
|
|
34
|
+
- Thumbs-up / thumbs-down rating row + optional Save action, rendered beneath an LLM-generated message.
|
|
35
|
+
- Different from <rating-ui> (star-based ordinal) — agent-feedback is binary good/bad.
|
|
36
|
+
- Emits feedback events with value=up|down and optional save action; consumer wires the actual feedback API call.
|
|
37
|
+
- Place at the end of an assistant message in <chat-thread-ui>, not on user messages.
|
|
38
|
+
|
|
39
|
+
## AgentQuestions
|
|
40
|
+
- Multi-choice clarifying-question card emitted by an agent when it needs disambiguation before proceeding.
|
|
41
|
+
- multi attribute controls single-select (default) vs multi-select answer behavior.
|
|
42
|
+
- Slot accepts <button-ui> answer chips; for radio-card style use <segmented-ui> + <segment-ui> children instead.
|
|
43
|
+
- Different from <agent-suggestions-ui> (follow-up suggestions, optional) — agent-questions is gating (agent waits for answer).
|
|
44
|
+
|
|
45
|
+
## AgentReasoning
|
|
46
|
+
- Agent inner-monologue + pipeline viewer with steps, thoughts, plans, and iterations.
|
|
47
|
+
- Composes <timeline-ui> internally — pass reasoning steps as children rendered as <timeline-item-ui>.
|
|
48
|
+
- noAutocollapse attribute prevents the auto-collapse-on-complete behavior; useful for debug surfaces.
|
|
49
|
+
- Different from <agent-trace-ui> (metrics + tool-call summary) — reasoning is narrative, trace is structured-data.
|
|
50
|
+
|
|
51
|
+
## AgentSuggestions
|
|
52
|
+
- Row of follow-up suggestion chips presented under an agent response. User taps to send the chip text as the next prompt.
|
|
53
|
+
- Hosts <button-ui> children with chip-style variant; auto-applies variant if children don't set one.
|
|
54
|
+
- Different from <agent-questions-ui> (required disambiguation) — suggestions are optional and the agent doesn't wait.
|
|
55
|
+
- Place at the end of an assistant message in <chat-thread-ui>; not for first-message empty-state suggestions (use <empty-state-ui>).
|
|
56
|
+
|
|
57
|
+
## AgentTrace
|
|
58
|
+
- Collapsible metrics + training-feedback panel showing reasoning steps, tool calls, latency, and token counts.
|
|
59
|
+
- Place inside <chat-thread-ui> message bodies for expert/debug views; hide by default in user-facing chat.
|
|
60
|
+
- Different from <agent-reasoning-ui> (narrative inner monologue) — agent-trace is structured metrics.
|
|
61
|
+
- Default collapsed=true; expand-on-demand keeps chat-thread visual density low.
|
|
62
|
+
|
|
63
|
+
## Alert
|
|
64
|
+
- Inline alert/banner for status messages within a content region. Severity via variant (info, success, warn, error).
|
|
65
|
+
- For ephemeral toast notifications use <toast-ui> (or post to <feed-ui>); alert-ui is persistent inline.
|
|
66
|
+
- For modal-style critical alerts use <modal-ui> with alert content.
|
|
67
|
+
|
|
68
|
+
## Aside
|
|
69
|
+
- Use <aside-ui> as a slot stub inside an IN-PAGE primitive container parent (<card-ui>, <drawer-ui>, <modal-ui>, <page-ui>) for two-column layouts with a semantic side region. It ships no behavior; the parent reads [collapsible] and [width] via @scope. Typical contents: <list-ui> / <tree-ui> / <nav-ui variant="section">.
|
|
70
|
+
- Do NOT use <aside-ui> for app-shell sidebars. <admin-shell> no longer reads <aside-ui slot="leading|trailing"> (retired in v0.4.0 per ADR-0024). Use the bespoke <admin-sidebar slot="leading|trailing" collapsible resizable> with reflected [collapsed] / [resizing] state. Same rule for <chat-sidebar> under <chat-shell> and <editor-sidebar> under <editor-shell>.
|
|
71
|
+
- Do NOT confuse <aside-ui> with <pane-ui>: aside-ui declares the semantic side role (a11y + parent layout hint); <pane-ui> owns resize / collapse interaction. When you need interactive resize inside an aside, nest <pane-ui resizable> inside.
|
|
72
|
+
- Width hints map to tokens: `width="rail"` ≈ icon-only nav, `width="panel"` ≈ nav with labels, `width="wide"` ≈ workspace pane. Unset defers to the parent default. Only pair `collapsible` with parents that wire a toggle (the prop is a hint, not a behavior).
|
|
73
|
+
- For the settings-page description rail (label + help text on the left, controls on the right) use plain HTML <aside> inside a [data-section] flex layout — see apps/saas/billing and apps/saas/members. That pattern is NOT aside-ui; the primitive is for slotted container parents only.
|
|
74
|
+
|
|
75
|
+
## AvatarGroup
|
|
76
|
+
- Cluster of overlapping <avatar-ui> children with negative-margin stacking + +N overflow indicator.
|
|
77
|
+
- max attribute controls visible-avatar count before +N overflow kicks in.
|
|
78
|
+
- For a single user use <avatar-ui> standalone; avatar-group only for 2+ users.
|
|
79
|
+
|
|
80
|
+
## Avatar
|
|
81
|
+
- Use for representing a single person, account, or entity. Image, initials, or icon fallback in priority order.
|
|
82
|
+
- For clusters of multiple users, wrap multiple <avatar-ui> in <avatar-group-ui> instead of placing them inline.
|
|
83
|
+
- Do not embed inside <button-ui> for clickable avatars — make the <avatar-ui> itself the click target with role='button'.
|
|
84
|
+
|
|
85
|
+
## Badge
|
|
86
|
+
- Use for small status/count labels attached to another element (notification counts, status pills, version tags).
|
|
87
|
+
- Place adjacent to or absolutely-positioned over the badged element, not inside it.
|
|
88
|
+
- For dismissable taxonomy labels (filter chips, selected items in multi-select), use <tag-ui> instead.
|
|
89
|
+
|
|
90
|
+
## Block
|
|
91
|
+
- Generic semantic block — use for arbitrary content groupings without strong layout semantics.
|
|
92
|
+
- For row/column layouts use <row-ui> / <col-ui>; for grid use <stack-ui>; block is for content-flow groupings.
|
|
93
|
+
- Block-ui does not impose padding/gap by default — wrap in <section-ui> if you want chrome.
|
|
94
|
+
|
|
95
|
+
## Breadcrumb
|
|
96
|
+
- Canonical placement: render <breadcrumb-ui> inside <admin-topbar> for hierarchical page-context display. It is the topbar's heading region — typically preceded by a sidebar-toggle <button-ui icon="sidebar" variant="ghost" size="sm"> and followed by topbar actions in [slot="action"]. The host stamps role="navigation" + aria-label="Breadcrumb" automatically.
|
|
97
|
+
- Child shape: each crumb is either an <a href> (ancestor link) or a plain <span> (terminal / non-link current page). The LAST child is the current page and MUST be a plain <span> — the component auto-applies aria-current="page" and disables pointer events on it. Optional first child may be an <icon-ui> (or <a> wrapping one with aria-label) for an app / home glyph.
|
|
98
|
+
- Separator + overflow: do NOT insert your own separator elements ([data-sep] spans are stamped automatically between children). For deep trails (4+ items) prefer the `collapse` attribute over manual truncation; tune visible edges with [collapse-keep-leading] / [collapse-keep-trailing]. Collapsed middle crumbs are presented as a `…` <menu-ui data-overflow> popover.
|
|
99
|
+
- Decision rule: <breadcrumb-ui> is read-only PATH-CONTEXT display ("where am I"). For primary navigation (sidebar) use <nav-ui> + <nav-item-ui> inside <admin-sidebar>. For switching sub-views within a page use <tabs-ui>. Never use <breadcrumb-ui> as the primary navigation control or wrap navigation controls (selects, tabs, form controls) inside it.
|
|
100
|
+
|
|
101
|
+
## Button
|
|
102
|
+
- Canonical clickable affordance — text + optional icon. Variant attribute sets primary/secondary/ghost/destructive intent.
|
|
103
|
+
- Do not repeat the icon's glyph in text=. Icon provides the symbol; text= carries only the words.
|
|
104
|
+
- For navigation (route-change) use <nav-item-ui> or anchor; button-ui is for actions only.
|
|
105
|
+
- For toggleable on/off state use <switch-ui>; for multi-select clusters use <toggle-group-ui> + <toggle-option-ui>.
|
|
106
|
+
|
|
107
|
+
## CalendarPicker
|
|
108
|
+
- Form-associated date input. Trigger button + popover calendar grid; emits ISO date string via change events.
|
|
109
|
+
- Use for single-date input. For date ranges compose two pickers or use a dedicated range component.
|
|
110
|
+
- min/max attributes constrain selectable range; disabled-dates accepts a function or date list.
|
|
111
|
+
|
|
112
|
+
## Canvas
|
|
113
|
+
- A2UI rendering surface — consumes a DocStore / A2UI document and renders the component tree from it.
|
|
114
|
+
- Typically wrapped by <a2ui-root> internally; for direct-mount use <canvas-ui> as the root.
|
|
115
|
+
- Do not place static children inside — the runtime owns the rendered DOM.
|
|
116
|
+
- theme attribute scopes the AdiaUI token theme to the canvas subtree.
|
|
117
|
+
|
|
7
118
|
## Card
|
|
8
119
|
- The card's <header> grid activates only for DIRECT-child slotted elements. If you need an icon column, place the icon element (avatar-ui, icon-ui) directly in the header with slot="icon" — not inside a wrapper.
|
|
9
120
|
- Heading slot accepts inline badges/metadata: <span slot="heading"><text-ui strong>Title</text-ui><badge-ui text="New" variant="accent"></badge-ui></span> renders title + badge on one row.
|
|
10
121
|
- Description slot also accepts bare <p> or <small> elements as siblings of the heading — they participate in the grid's row 2 without needing slot="description".
|
|
11
122
|
- Multiple <section> siblings are allowed and stack vertically. [bleed] on a section removes its margin for edge-to-edge content (tables, charts); [padding] adds a canvas-scrim background for hero regions.
|
|
12
123
|
- Footer with a [slot="description"] + [slot="action"] pair triggers justify-content: space-between — useful for a "Last saved …" note on the left and a Save/Cancel button group on the right.
|
|
124
|
+
- Do NOT substitute <card-ui> for shell/page containers. <admin-page>, <admin-content>, and <page-ui> own routed page layout; <card-ui> is a localized bordered surface that lives INSIDE them. For overlays use <modal-ui> (centered) or <drawer-ui> (edge-anchored) — both share the same 4-stub <header>/<section>/<footer> vocabulary.
|
|
125
|
+
- Use [raw] when a parent already owns the surface chrome (e.g. an auth screen centred on the viewport — see apps/user-flow/auth). Use [elevation] 0–3 for shadow depth; [variant="ghost"|"flat"] to remove shadow without removing structure. [draggable] emits a drag-end event; only enable on cards meant to move.
|
|
126
|
+
|
|
127
|
+
## ChartLegend
|
|
128
|
+
- Standalone legend primitive — a row of <badge-ui>+<swatch-ui> chips that are keyboard-focusable and click-toggleable.
|
|
129
|
+
- Pairs with <chart-ui> via [for] id-ref (auto-bidirectional series toggling) or via items= for standalone use.
|
|
130
|
+
- position attribute (top|bottom|left|right) places legend relative to its chart; static= disables interactivity.
|
|
131
|
+
|
|
132
|
+
## Chart
|
|
133
|
+
- Declarative SVG chart supporting 18 types via the type attribute (bar, line, pie, donut, radar, area, ...).
|
|
134
|
+
- For density-grid visualizations (calendar heatmap, etc.) use <heatmap-ui> instead.
|
|
135
|
+
- Pair with <chart-legend-ui [for]=...> for keyboard-toggleable series legends; otherwise use the built-in inline legend.
|
|
136
|
+
- title + empty slots for chart chrome; canvas slot for chart-internal overlays.
|
|
13
137
|
|
|
14
138
|
## ChatInput
|
|
15
139
|
- ChatInput is a self-contained composer — it stamps its own textarea + model picker + send button. DO NOT add a separate Button sibling for "send" inside the same parent. The user gets two send buttons (one built-in, one redundant).
|
|
16
140
|
- For chat interfaces emit ChatInput as the sole input component inside the chat shell. The submit event fires on Enter or send-button click; `detail` is `{ text, model }`.
|
|
17
141
|
- To customize models, set the `models` prop with an array of {value, label} option objects. Do not stamp a separate Select next to ChatInput for model selection — the built-in model picker handles it.
|
|
18
142
|
|
|
143
|
+
## ChatThread
|
|
144
|
+
- Primitive chat-message scroll container — ad-hoc message rendering surface.
|
|
145
|
+
- Different from the bespoke <chat-thread> (module-tier, lives inside <chat-shell-ui>, owns scroll + load-more affordances).
|
|
146
|
+
- Hosts arbitrary children — typical content: agent + user message blocks, <agent-feedback-bar-ui>, <agent-suggestions-ui>.
|
|
147
|
+
- streaming attribute hints the consumer to show a streaming indicator (composes well with <stream-ui> children).
|
|
148
|
+
|
|
19
149
|
## Check
|
|
20
150
|
- Self-labeling widget — use the [label] attribute directly; do NOT wrap in <field-ui>. The widget renders its own label inline via CSS attr() pattern. Wrapping breaks the consent-row layout (see field-ui anti_patterns).
|
|
151
|
+
- Three states supported: unchecked (default), checked (via [checked]), and indeterminate (via [indeterminate]); form-associated.
|
|
152
|
+
- For binary on/off toggles where visual switch metaphor matters, use <switch-ui> instead; check-ui is for multi-select sets and form-acceptance gates.
|
|
153
|
+
|
|
154
|
+
## Code
|
|
155
|
+
- Inline (default) for short tokens in prose; block variant (display='block') for multi-line snippets.
|
|
156
|
+
- Do not use for editable code — use <richtext-ui> with code variant or a dedicated editor primitive.
|
|
157
|
+
- Inside <agent-artifact-ui> blocks for agent-emitted code snippets; lang= sets syntax-highlighting hint.
|
|
158
|
+
|
|
159
|
+
## Col
|
|
160
|
+
- Vertical-stack flex container. Children flow top-to-bottom with token-driven gap.
|
|
161
|
+
- Pair with <row-ui> for horizontal layouts; both share the same gap-token contract.
|
|
162
|
+
- Set align/justify attributes for cross-axis / main-axis alignment; default is start/start.
|
|
163
|
+
|
|
164
|
+
## ColorInput
|
|
165
|
+
- Use <color-input-ui> for any form-row color field — it canonicalizes the popover + button + color-picker recipe and is the only form-bearing color primitive. Do not hand-roll the composition; reach for color-input-ui directly.
|
|
166
|
+
- Set [format="oklch"] when the persisted value feeds CSS tokens or perceptual math; [format="hex"] for legacy / design-tool interop. Event detail (`change` / `input`) carries BOTH `hex` and `oklch` views regardless of [format], plus parsed `{l, c, h}` channel scalars.
|
|
167
|
+
- For brand-palette constraints, set [maxChroma] / [minL] / [maxL] / [hueDriftMax] (with [baseHue]) on the host — they forward to the inner <color-picker-ui> and clamp generation. Useful for Tokens-Studio-style guarded color generation.
|
|
168
|
+
- Use <color-picker-ui> DIRECTLY (no color-input-ui wrapper) only for full-surface editors where the picker IS the page (e.g. Tokens Studio main canvas). For inline form-row use, always reach for <color-input-ui>.
|
|
169
|
+
- Per ADR-0027 (cross-primitive composition imports), consumer pages MUST explicitly import <button-ui>, <popover-ui>, and <color-picker-ui> before <color-input-ui>. The primitive composes them but does NOT auto-register them.
|
|
170
|
+
|
|
171
|
+
## ColorPicker
|
|
172
|
+
- OKLCH-native color picker with 2D color area + H/C/L sliders. Form-associated; emits OKLCH color strings.
|
|
173
|
+
- For simple color swatches (read-only display) use <swatch-ui>; for hex/rgb text input use <color-input-ui>.
|
|
174
|
+
- Output format defaults to oklch(); set format= to override (hex, rgb, hsl).
|
|
175
|
+
|
|
176
|
+
## Command
|
|
177
|
+
- <command-ui> is the searchable PALETTE primitive (input + option list). For Cmd+K palettes, wrap it in <admin-command> at the shell tier — admin-command owns the native <dialog>, focus management, and the Cmd+K / Ctrl+K shortcut listener. command-ui is content-only and does NOT own the dialog or shortcut. Do NOT hand-roll a <dialog> + Cmd+K key listener.
|
|
178
|
+
- Author items as native <option value data-icon data-shortcut> elements inside <optgroup label="…"> for grouped sections. The `select` event's detail.category mirrors the parent optgroup's label. Detail = { value, label, category }.
|
|
179
|
+
- Decision rule vs adjacent surfaces. Use <menu-ui> for small NON-searchable popover menus (≤10 actions, triggered by a button). Use <modal-ui> for generic centered dialogs. Reach for <command-ui> only when you need a searchable, keyboard-navigable list of commands or destinations.
|
|
180
|
+
- command-ui MAY render inline (no dialog) for embedded search panels, but the canonical AdiaUI admin pattern is exactly one <command-ui placeholder="…"> as the sole child of <admin-command> inside <admin-shell>. See site/index.html and playgrounds/admin-shell/ for production references.
|
|
181
|
+
|
|
182
|
+
## DemoToggle
|
|
183
|
+
- Demo-page-only — toggles between live and code views in component documentation surfaces.
|
|
184
|
+
- Do not use in apps/ — restrict to packages/web-components/components/*/<name>.html demo pages and docs surfaces.
|
|
185
|
+
- Behavior: shows/hides the [data-code] block when toggled.
|
|
186
|
+
|
|
187
|
+
## DescriptionList
|
|
188
|
+
- Use for key:value pairs in dense detail views (user profile fields, metadata panels, audit logs).
|
|
189
|
+
- Do not use for editable forms — use <fields-ui> instead.
|
|
190
|
+
- Pairs render as label + value on the same row by default; use vertical variant for narrow panes.
|
|
191
|
+
|
|
192
|
+
## Divider
|
|
193
|
+
- Use to separate visually distinct sections within a container; horizontal default, vertical via orientation='vertical'.
|
|
194
|
+
- Inside menus / popovers use <menu-divider-ui> instead; it has menu-specific token spacing.
|
|
195
|
+
- Do not stack multiple consecutive dividers — use a single divider or restructure the section.
|
|
196
|
+
|
|
197
|
+
## Drawer
|
|
198
|
+
- Direct children of <drawer-ui> MUST be <header>, <section> (1..n), <footer>, or an element with slot="header|body|footer". Wrap stray <col-ui> / <row-ui> / <div> / <text-ui> in a <section>. Enforced by scripts/audit/audit-drawer-structure.mjs. Bypassing the body slot loses the section inset and teaches the gen-UI corpus the wrong pattern.
|
|
199
|
+
- Reflect open state via the [open] boolean attribute on the host (open=true / open=false). Do NOT toggle visibility with CSS, [hidden], or a [data-open] proxy — drawer-ui owns the native <dialog> lifecycle, focus trap, and ::backdrop. Listen for the `close` event (detail.reason ∈ escape | backdrop | close-button | programmatic) to react to dismiss.
|
|
200
|
+
- Use drawer-ui (not modal-ui) for edge-anchored detail / edit panels and mobile bottom-sheet patterns. Pick side="right" for inspector flows opened FROM a row/list item, side="bottom" for sheets, side="left" for navigation drawers on narrow viewports. Centered confirmations belong in modal-ui.
|
|
201
|
+
- Compose the drawer header with [slot="icon|heading|description| action"] direct-child elements to activate the card-ui-aligned 3-column grid (icon | heading+description | action+close). The close button is auto-stamped; do not author your own X button unless using [permanent] (which suppresses the close button).
|
|
202
|
+
- Never set drawer.innerHTML wholesale — it wipes the stamped <dialog> part and the author skeleton. Mutate a stable inner element inside a persistent <section> instead. Same rule as <modal-ui>.
|
|
203
|
+
|
|
204
|
+
## Embed
|
|
205
|
+
- Responsive sandboxed <iframe> wrapper at constrained aspect ratio. Safe sandbox attributes are applied by default.
|
|
206
|
+
- For raster/vector images use <image-ui>; for icons use <icon-ui>; embed-ui is for live external content only.
|
|
207
|
+
- aspect attribute locks ratio (e.g. 16/9, 4/3) to prevent layout shift; width/height override when needed.
|
|
208
|
+
- Do not embed first-party AdiaUI app routes — use direct component composition instead.
|
|
209
|
+
|
|
210
|
+
## EmptyState
|
|
211
|
+
- Use <empty-state-ui> for zero-data states: empty lists, no-results search, fresh accounts. Not for loading (use <skeleton-ui>). For inline notices within populated content use <alert-ui>. For full-section error states where the data cannot be shown at all (API failure, permission error), use <empty-state-ui variant="danger"> — the centered layout is more appropriate than an inline banner when the entire content area is replaced.
|
|
212
|
+
- Canonical placement: slotted into cluster-specific wrappers — <chat-empty> inside <chat-thread>, <editor-canvas-empty> inside <editor-canvas>, OR inside <card-ui><section> for in-card empty states. Compose with an <icon-ui> for the leading glyph (pick a Phosphor name that mirrors the missing entity — folder, inbox, magnifying-glass).
|
|
213
|
+
- Put AT MOST ONE CTA in slot="action". It should be the single next step (Create, Retry, Clear filters). Prefer [variant="primary"] for create-flows; [variant="outline"] for retry / secondary actions.
|
|
214
|
+
- Use [minimal] for inline empty rows inside <table-ui> / <list-ui> where full-canvas chrome is too prominent. The `minimal` flag (§223 v0.5.9) drops chrome for a compact placeholder cell.
|
|
215
|
+
- Per ADR-0027, empty-state-ui composes <icon-ui> but does NOT auto-register it. Consumer pages must explicitly import <icon-ui> before <empty-state-ui> renders correctly.
|
|
216
|
+
|
|
217
|
+
## FeedItem
|
|
218
|
+
- One notification entry inside <feed-ui>. Title + description + optional icon + auto-dismiss timer.
|
|
219
|
+
- Typically created programmatically via UIFeed.post(...); do not place declaratively.
|
|
220
|
+
- Different from <alert-ui> (inline persistent) and <toast-ui> (standalone ephemeral); feed-item is feed-scoped.
|
|
221
|
+
|
|
222
|
+
## Feed
|
|
223
|
+
- Top-layer notification feed channel — singleton per position (top-right, bottom-center, etc.) mounted lazily into document.body.
|
|
224
|
+
- Hosts <feed-item-ui> children programmatically via static API (UIFeed.post(...)). Do not place feed-items declaratively.
|
|
225
|
+
- For inline persistent alerts inside content regions use <alert-ui> instead; feed is ephemeral overlay.
|
|
21
226
|
|
|
22
227
|
## Field
|
|
23
228
|
- field-ui is for WIDE controls (input-ui, select-ui, textarea-ui, slider-ui, etc.) that need a separate label row. Small self-labeling widgets (check-ui, switch-ui, radio-ui, toggle-ui) carry their own [label] attribute and MUST NOT be wrapped in field-ui.
|
|
24
229
|
- field-ui[inline] is for inline WIDE-control rows (e.g. search field with trailing kbd hint), NOT for compact-widget rows. For settings rows or consent rows, use the widget's own [label] attribute directly without a field-ui wrapper.
|
|
25
230
|
|
|
231
|
+
## Fields
|
|
232
|
+
- Container for form rows. Hosts <field-ui> children (or <row-ui>/<col-ui> with labeled inputs) with consistent label + control + help layout.
|
|
233
|
+
- Different from <description-list-ui> (read-only key:value display) — fields-ui is for editable inputs.
|
|
234
|
+
- For dynamic field arrays (repeat-able rows) compose fields-ui with manual add/remove controls.
|
|
235
|
+
|
|
236
|
+
## Footer
|
|
237
|
+
- Use <footer-ui> as the bottom chrome row inside a PRIMITIVE container parent (<card-ui>, <drawer-ui>, <modal-ui>, <page-ui>). Typically holds 1–3 <button-ui> children — the most common pattern is a Cancel / Confirm pair inside <modal-ui> or <drawer-ui>.
|
|
238
|
+
- Use `justify="end"` (default) for Cancel+Confirm and trailing action clusters; `justify="between"` when one action lives left and one right (e.g. Back / Submit); `justify="center"` for single-button confirm flows; `justify="start"` for solo leading actions like Back.
|
|
239
|
+
- Do NOT substitute <footer-ui> for bespoke shell-tier bottom chrome. Inside <admin-sidebar slot="footer"> use <admin-statusbar>; inside <editor-shell> use <editor-statusbar>. <footer-ui> is exclusively the in-container action bar at the primitive tier.
|
|
240
|
+
- Do NOT wrap children in <row-ui> just to align them — the `justify` prop already lays children out horizontally. A nested row-ui double-applies layout and breaks the chrome's gap tokens.
|
|
241
|
+
- Prefer flat <button-ui> children. If you need non-button content (text summary, pagination indicator), keep it as a single flat child so `justify` resolves cleanly.
|
|
242
|
+
|
|
26
243
|
## Grid
|
|
27
|
-
- For asymmetric column ratios, use [columns="N"] plus [span="M"] on the child that should be wider. Never set
|
|
244
|
+
- For asymmetric column ratios, use [columns="N"] plus [span="M"] on the child that should be wider. Never set gridTemplateColumns via inline style in compositions — the component's responsive resolver sets it internally for @bp values; direct inline style bypasses that and reads as a local hack.
|
|
28
245
|
- Canonical ratios: 1:1 → columns="2"; 2:1 → columns="3" + span="2"; 3:1 → columns="4" + span="3"; 3:2 → columns="5" + span="3"+"2"; 4:1 → columns="5" + span="4". Round unusual ratios (e.g. 7:5) to 3:2.
|
|
29
246
|
- The default (no columns attribute) gives equal auto-columns flowing in a single row. Prefer the explicit numeric attribute for dashboard rows so the layout is predictable when items wrap.
|
|
247
|
+
- For viewport-responsive layouts use `@bp` notation on [columns] and [gap]: columns="1 2@sm 4@lg" gives 1 column on xs, 2 from sm, 4 from lg/xl. Breakpoints (mobile-first, min-width): xs=0, sm=480, md=768, lg=1024, xl=1280. Unannotated value = base (smallest). Each @bp overrides upward until the next larger annotation takes over.
|
|
248
|
+
|
|
249
|
+
## Header
|
|
250
|
+
- Use <header-ui> as the top chrome row inside a PRIMITIVE container parent: <card-ui>, <drawer-ui>, <modal-ui>, <page-ui>. It is a CSS-only slot stub — no JS, no events. The parent's @scope rules drive layout and styling.
|
|
251
|
+
- Compose with the default slot for the heading (typically <text-ui variant="title">) and slot="action" for trailing controls (button-ui, badge-ui). The slot vocabulary (icon / heading / description / action) is shared with <aside-ui> / <section-ui> / <footer-ui> per ADR-0009.
|
|
252
|
+
- Do NOT substitute <header-ui> for bespoke shell-tier chrome. Inside <admin-content> / <admin-sidebar> use <admin-topbar>; inside <chat-shell> use <chat-header>; inside <editor-shell> use <editor-toolbar>. Those modules carry shell-specific slot vocabulary and CSS that <header-ui> does not. (admin-topbar.yaml codifies this explicitly.)
|
|
253
|
+
- Do NOT wrap header-ui's children in <col-ui> or <row-ui>. The container parent's @scope already lays out default+icon+heading+description+action via slot vocabulary; extra layout primitives fight the chrome styling.
|
|
254
|
+
- The `padding` attribute is a bare boolean — it enables default header padding, but the *scale* is set by the container parent's own `padding` prop. Do not pass numeric values.
|
|
255
|
+
|
|
256
|
+
## Heatmap
|
|
257
|
+
- Grid-cell heatmap visualization (calendar heatmap, density grid). Cells colored by value via OKLCH scale.
|
|
258
|
+
- For continuous time-series use <chart-ui> with appropriate variant; heatmap is for grid-cell density.
|
|
259
|
+
- Tooltip on hover shows cell value; click events emit cell coordinates.
|
|
260
|
+
|
|
261
|
+
## Icon
|
|
262
|
+
- [name] must be a registered Phosphor key (e.g. "house", "gear", "trash", "warning-circle"). Free-form names render empty. When unsure, default to a semantically obvious glyph (check, x, warning-circle, info).
|
|
263
|
+
- Set [label] when the icon is the ONLY content of an interactive control (icon-only button); omit [label] when icon is decorative beside a text label. The host stamps role="img" + aria-label when [label] is set.
|
|
264
|
+
- Use named [size] tokens (sm | md | lg | xl) — px / rem values only when matching a strict design spec. [size="xl"] is conventional for empty-state hero icons; [size="md"] is the default for inline use.
|
|
265
|
+
- Use slot="icon" on parent primitives (<button-ui>, <badge-ui>, <alert-ui>, <list-item-ui>, <input-ui>, <nav-item-ui>, every chrome bar) — do NOT bare-render <icon-ui> beside text in a <row-ui> when the parent supports the [slot="icon"] convention.
|
|
266
|
+
- Use [weight="fill"] for selected / active toggles, [weight="regular"] (default) for inactive. Do not mix weights in the same set; the visual inconsistency reads as a bug.
|
|
267
|
+
|
|
268
|
+
## Image
|
|
269
|
+
- Use for content images (illustrations, screenshots, user-uploaded photos). For icons use <icon-ui>; for embedded artifacts use <embed-ui>.
|
|
270
|
+
- Set aspect-ratio attribute to lock dimensions and prevent layout shift during load.
|
|
271
|
+
- For decorative-only images, set alt='' and aria-hidden='true' so screen readers skip them.
|
|
272
|
+
|
|
273
|
+
## Input
|
|
274
|
+
- <input-ui> is the canonical single-line text input. The host IS the contenteditable surface — NEVER wrap a native <input>. The sole exception is type="password", which internally uses a real <input type="password"> for masking (per ADR-0025).
|
|
275
|
+
- Wrap <input-ui> in <field-ui label="…" hint="…" error="…"> for the canonical stacked label / hint / error chrome. The inline [label] / [hint] / [error] props are also supported on the primitive for compact use.
|
|
276
|
+
- Form participation is implicit via UIFormElement. Set [name] for FormData submission; [required] / [disabled] / [readonly] reflect; listen for `change` (blur or Enter commit) and `input` (per keystroke). `submit` event fires when Enter commits the value (used by <chat-composer>'s `composer-submit` forwarding).
|
|
277
|
+
- For numeric input use [type="number"] with [min] [max] [step] [precision] [prefix] / [suffix] — this stamps a contenteditable surface + <button-ui> / <icon-ui> stepper column with ARIA spinbutton semantics. Read `el.valueAsNumber` for the parsed Number. Never substitute a native <input type="number">.
|
|
278
|
+
- Inside <chat-composer>, the canonical inner input is <chat-input-ui submit-on-enter> (chat variant subclass — owns the submit-on-enter contract explicitly). The plain <input-ui> primitive already fires `submit` on Enter, but only chat-input-ui reflects the [submit-on-enter] attribute.
|
|
279
|
+
|
|
280
|
+
## Inspector
|
|
281
|
+
- Developer-tools pane for A2UI runtime state — composes <tabs-ui> + <code-ui> internally.
|
|
282
|
+
- Binds to a <canvas-ui> / <a2ui-root> via value= or implicit selector; shows live doc JSON + rendered HTML + event log.
|
|
283
|
+
- Use only in dev/debug surfaces; not for product UI.
|
|
284
|
+
- Place in a right-pane inside <editor-shell-ui>'s editor-sidebar slot for editor-style inspector layouts.
|
|
285
|
+
|
|
286
|
+
## Kbd
|
|
287
|
+
- Inline-only — content from innerHTML, typically one or two key labels.
|
|
288
|
+
- In menu items, use the kbd= attribute on <menu-item-ui> instead of nesting <kbd-ui> directly.
|
|
289
|
+
- Chord notation uses + between keys (Ctrl+Shift+P); platform-symbol variants ⌘⌥⇧ are fine.
|
|
30
290
|
|
|
31
291
|
## Link
|
|
32
292
|
- Use `<link-ui>` for navigation; use `<button-ui>` for actions. They are NOT interchangeable.
|
|
33
293
|
- When wrapping action affordances that visually mimic links (e.g. 'Forgot password?' that triggers a reset flow), prefer `<button-ui variant="ghost">` over a fake `<link-ui>` — the affordance is semantically a button, just visually understated.
|
|
34
294
|
- For inline-sentence affordances ('I agree to the [Terms] and [Privacy]'), nest `<link-ui>` directly inside `<text-ui>` so it inherits the paragraph's font / size / line-height.
|
|
35
295
|
|
|
296
|
+
## ListItem
|
|
297
|
+
- Child of <list-ui> — one row of generic-list content.
|
|
298
|
+
- For navigation lists use <nav-item-ui> inside <nav-ui>; for menu items use <menu-item-ui>; for tree rows use <tree-item-ui>.
|
|
299
|
+
- Interactive list-items should have role='button' or be wrapped in <button-ui>; default is non-interactive.
|
|
300
|
+
|
|
301
|
+
## List
|
|
302
|
+
- Generic vertical list container — hosts <list-item-ui> or arbitrary children.
|
|
303
|
+
- For interactive selection lists use <nav-ui> (single-select navigation) or <menu-ui> (action menu); list-ui is content display.
|
|
304
|
+
- For data-grid / sortable / sticky-header needs use <table-ui> instead.
|
|
305
|
+
|
|
306
|
+
## MenuDivider
|
|
307
|
+
- <menu-divider-ui> MUST be a direct child of <menu-ui>; a raw <hr> will render OUTSIDE the popover because <menu-ui> only hoists <menu-item-ui> and <menu-divider-ui> children via its direct-child selector.
|
|
308
|
+
- Use to group items by semantic tier — primary actions → secondary → destructive (danger). Avoid leading / trailing dividers and consecutive dividers; they produce visual noise without grouping value.
|
|
309
|
+
- Do not place a divider as the first or last child of <menu-ui> — the top / bottom popover padding already provides separation from the chrome.
|
|
310
|
+
- Has no props, slots, or events. Treat as an inert separator with role="separator". If you need a labeled group, split into multiple <menu-ui> instances stacked, not custom content inside a divider.
|
|
311
|
+
|
|
312
|
+
## MenuItem
|
|
313
|
+
- <menu-item-ui> MUST be a direct child of <menu-ui>; do not place inside arbitrary containers or other components — <menu-ui> hoists items into its top-layer popover via a `:scope > menu-item-ui` selector that requires direct descendancy.
|
|
314
|
+
- Always set a stable [value] — it is the only identifier surfaced on the parent's `action` event detail. [text] is the visible label; optional [icon] is a Phosphor icon name shown leading the label.
|
|
315
|
+
- Use [variant="danger"] exclusively for destructive / irreversible actions (Delete, Remove). "Sign out" is NOT danger. Pair danger items with an explicit confirm flow (<modal-ui> destructive-confirm pattern) when the action cannot be undone.
|
|
316
|
+
- Set [disabled] (not [hidden]) when an action is contextually unavailable — disabled items remain visible for affordance discoverability but skip roving focus + don't fire `action`.
|
|
317
|
+
- Prefer [icon] + [text] props over slotted markup for consistency. Use slot="icon" / slot="text" only when you need custom markup (e.g. <avatar-ui slot="icon">, <kbd slot="trailing"> shortcut hint).
|
|
318
|
+
|
|
319
|
+
## Menu
|
|
320
|
+
- <menu-ui> MUST have exactly one child with slot="trigger" (typically <button-ui>, but any focusable element works). Without it the menu cannot open. The trigger lives in light DOM; the items are hoisted to a top-layer popover on open.
|
|
321
|
+
- Default slot accepts only <menu-item-ui> and <menu-divider-ui> children — no submenus, headers, or arbitrary content. Roving tabindex + Arrow / Home / End / Enter / Escape keyboard nav is built in.
|
|
322
|
+
- Listen for the `action` event on <menu-ui> (or an ancestor — bubbles). Detail = { value, text }. Do NOT treat menu-ui as a value-holder; for single-select form input use <select-ui> instead. Menu fires actions, doesn't store state.
|
|
323
|
+
- Use <menu-ui> for transient action surfaces (kebab / ⋯ row actions, workspace / user switchers, view-as toggles). For persistent side navigation use <nav-ui>; for inline (non-popover) command lists use <action-list-ui>; for searchable command palettes use <command-ui> inside <admin-command>.
|
|
324
|
+
- Set [placement="top-start"] or [placement="top-end"] when the trigger sits near the bottom of the viewport (statusbar / footer menus); default [placement="bottom-start"] otherwise. Adjust [gap] (default 4px) only when chrome demands it.
|
|
325
|
+
|
|
326
|
+
## Modal
|
|
327
|
+
- Reflect modal visibility via the [open] boolean attribute on the host (open=true / open=false). Do NOT toggle [hidden], CSS display, or wrap in a sibling visibility container — modal-ui owns the native <dialog> lifecycle, focus trap, ::backdrop, and Escape-dismiss. Listen for the `close` event to react to dismiss.
|
|
328
|
+
- Compose modal-ui with the same triplet as drawer-ui / card-ui: <header> (or [slot="header"]) + <section> (or default body) + <footer> (or [slot="footer"]). Set the title via [text] (which stamps the heading + aria-label) or a <span slot="heading">. Do not author your own close button unless using [permanent].
|
|
329
|
+
- Use modal-ui (centered, interruptive) for short confirmations, destructive prompts, and transient previews — typically ≤2 form fields or a single decision. For edge-anchored multi-field detail editors and mobile sheets, use <drawer-ui> instead. The destructive-confirm-modal pattern lives at catalog/ui-patterns/app/destructive-confirm-modal/ as the canonical reference.
|
|
330
|
+
- modal-ui is NOT the Cmd+K command palette. The palette is a bespoke shell-tier component (<admin-command> under <admin-shell>); do not model command palettes as modal-ui surfaces even though the visual is overlay-like. The palette owns its own keyboard / filter loop.
|
|
331
|
+
- Use [size] presets (sm = 24rem | md = 32rem | lg = 48rem | xl = 95vw) to scale width. Do not override width with inline style or wrap modal-ui in a sizing container — the [size] attribute is the only supported width contract.
|
|
332
|
+
|
|
333
|
+
## NavGroup
|
|
334
|
+
- Composition: <nav-group-ui> MUST be a direct child of <nav-ui> (or standalone with explicit variant="section" outside a rail). Default slot accepts <nav-item-ui> children; do NOT wrap them in layout primitives — selection, keyboard, and the section-variant cascade all rely on direct descendancy.
|
|
335
|
+
- Variant cascade: when parent <nav-ui variant="section">, this group inherits section styling (static kicker header, children always visible) via CSS — without touching its JS state. Set [variant="section"] explicitly only when there is no <nav-ui> parent, OR to override a primary-rail context.
|
|
336
|
+
- Collapsibility: primary variant — [collapsible] (default true) toggles [open] via header click / Enter / Space; fires `group-toggle` event with detail {text, open}. When the parent <nav-ui> is collapsed to icon-only, the header opens a popover with this group's children instead. Section variant ignores [open] / [collapsible] (children always visible).
|
|
337
|
+
- Decision rule: use <nav-group-ui> to group ≥2 related navigation links under one label inside <nav-ui>. For a single link, use <nav-item-ui> directly. For switching sub-views inside one page, use <tabs-ui> / <tab-ui>, never <nav-group-ui>.
|
|
338
|
+
- Anti-patterns: do NOT nest <nav-group-ui> inside another <nav-group-ui> (flatten the hierarchy or split into two groups). Do NOT place non-<nav-item-ui> content in the default slot. Do NOT use it as a generic disclosure — for that use <accordion-ui> or <details>.
|
|
339
|
+
|
|
340
|
+
## NavItem
|
|
341
|
+
- Composition: <nav-item-ui> MUST be a direct child of <nav-ui> or <nav-group-ui>. Never wrap in <col-ui> / <row-ui> / <li> / <a> — the item is already a focusable, accessible link element; wrapping breaks selection, ARIA, and the section-variant CSS cascade.
|
|
342
|
+
- Variant cascade: when an ancestor <nav-ui variant="section"> (or sibling-group with section variant) is present, this item inherits section styling (flat row, no reserved icon space when icon absent, left-edge selected accent) via CSS. Set [variant="section"] explicitly only when used standalone outside a section rail, or [variant="primary"] to override the cascade for a single highlighted item.
|
|
343
|
+
- Selection: [selected] is set by the parent <nav-ui>'s select() method; do NOT set it on multiple items simultaneously. Provide [value] as a route or anchor; consumers listen for `nav-select` on <nav-ui> rather than per-item.
|
|
344
|
+
- Decision rule: use <nav-item-ui> for a single navigable link (route or anchor). For an in-page view toggle, use <tab-ui>. For a popover menu action, use <menu-item-ui>. For an action button styled like a nav row, use <button-ui variant="ghost"> — not <nav-item-ui>.
|
|
345
|
+
- Authoring options: default stamping renders icon+text+badge from attributes. Named slots `icon`, `text`, `trailing` are also supported for custom content (e.g. a `<kbd slot="trailing">⌘K</kbd>` shortcut hint on a command-trigger item — see the admin-shell playground). Do NOT nest <nav-item-ui> inside another <nav-item-ui>.
|
|
346
|
+
|
|
347
|
+
## Nav
|
|
348
|
+
- Composition: place <nav-ui> inside <admin-sidebar slot="leading"> wrapped in <section-ui> for app sidebars; inside an <aside data-subnav> with variant="section" for section / subnav rails; standalone on docs / auth pages. Children: <nav-group-ui>, <nav-item-ui>, optional <hr data-nav-divider>.
|
|
349
|
+
- Variants: variant="primary" (default) — app sidebar; ResizeObserver collapses to icon-only ≤96px; collapsible groups open as a popover when collapsed. variant="section" — subnav rail; quieter chrome; optional [heading] kicker rendered via ::before.
|
|
350
|
+
- Section-variant cascade (ADR-0015 § Nav consolidation): variant="section" on <nav-ui> cascades visually to direct <nav-group-ui> / <nav-item-ui> descendants via CSS `:not([variant])`. Children's JS state is NOT mutated; the cascade is purely visual. Explicit [variant] on a child always wins — use it to escape the cascade or style a standalone group/item.
|
|
351
|
+
- Decision rule: if the user navigates AWAY (different page, route, or anchor) → <nav-ui>. If the user switches VIEWS within the same logical page → <tabs-ui>. Never use <nav-ui> as an in-page section switcher.
|
|
352
|
+
- Anti-patterns: do NOT wrap <nav-ui> children in <col-ui> / <row-ui> — wrapping breaks selection bubbling + the variant cascade. Do NOT nest <nav-ui> inside <nav-ui>. The legacy 6-element family (<app-nav-ui> / <section-nav-ui> / <app-nav-item-ui> / <section-nav-item-ui> / <app-nav-group-ui> / <section-nav-group-ui>) was retired in ADR-0015 — only <nav-ui> / <nav-group-ui> / <nav-item-ui> remain.
|
|
353
|
+
|
|
354
|
+
## Noodles
|
|
355
|
+
- SVG connection lines between children with declared ports — bezier (default), step, or straight curves.
|
|
356
|
+
- Place inside <canvas-ui> with port-declaring children (nodes); noodles draws connections between matching port refs.
|
|
357
|
+
- editable attribute enables drag-to-connect interactions; default is render-only.
|
|
358
|
+
- For data-flow visualizations only — for general-purpose lines/shapes use raw SVG.
|
|
359
|
+
|
|
360
|
+
## OptionCard
|
|
361
|
+
- Use <option-card-ui> for one-of-N choices where each option needs a heading + description, a leading icon, or both (onboarding personas, plan tiers, source pickers). Use <radio-ui> for dense forms with short labels and no descriptions. Use <segmented-ui> for compact horizontal single-select with short labels.
|
|
362
|
+
- Group siblings by sharing the same [name] attribute — they auto-form a radiogroup. Form participation is implicit via UIFormElement: submits `name=value` with parent form. Wrap the group in <col-ui gap="2"> for default layout or <grid-ui> for [layout="tile"] hero pickers.
|
|
363
|
+
- Set [checked] on the recommended / default option. Never leave the group with zero checked at first paint unless [required] is set and the form intentionally demands a deliberate choice.
|
|
364
|
+
- Use [layout="tile"] only for hero pickers (3–4 options max) where the icon is a primary brand cue (plan tiers, role pickers). Use [layout="default"] (left-indicator) for everything else.
|
|
365
|
+
- Put conditional follow-up inputs (a <textarea-ui> on "Other", a <select-ui> on "Custom") in the default slot — the spillover content auto-hides when the card is not checked. Do NOT duplicate this visibility logic in JS.
|
|
366
|
+
|
|
367
|
+
## OtpInput
|
|
368
|
+
- Use <otp-input-ui> for any fixed-length verification code (TOTP, email / SMS OTP, MFA enrollment) — NOT <input-ui type="number">. otp-input-ui provides per-digit focus management, paste-splitting of full codes, and the `complete` event that fires exactly once when all digits are filled.
|
|
369
|
+
- Always set [autocomplete="one-time-code"] so iOS / Android keyboards surface inbound SMS codes via the platform autofill UI.
|
|
370
|
+
- Listen for `complete` to auto-submit (fires exactly once per fill cycle), and `change` / `input` for live validation. Form participation is implicit via UIFormElement: [name] for FormData; [disabled] reflects.
|
|
371
|
+
- Default [length=6]. Use [length=4] only for legacy 4-digit SMS codes and [length=8] for backup codes. Never compose two <otp-input-ui> side-by-side — use a single one with the right length.
|
|
372
|
+
- Canonical placement: inside a <col-ui align="center"> beneath a description text. Do NOT wrap in <field-ui> — otp-input-ui has no label slot and visual centering is the canonical chrome.
|
|
373
|
+
|
|
374
|
+
## Page
|
|
375
|
+
- Top-level page container — wraps an entire route's content surface.
|
|
376
|
+
- Inside <admin-shell-ui>, <chat-shell-ui>, or <editor-shell-ui>, use the shell's own body slot instead; page-ui is for standalone routes without shell chrome.
|
|
377
|
+
- Hosts arbitrary children — no enforced child contract.
|
|
378
|
+
|
|
379
|
+
## Pagination
|
|
380
|
+
- Renders below tables, card grids, or list views for paginated data. Emits page-change events.
|
|
381
|
+
- For cursor-based / infinite-scroll patterns use a custom load-more <button-ui> instead; pagination-ui is offset-based.
|
|
382
|
+
- Page-number range auto-truncates with ellipsis for high counts; set siblings= to control visible window size.
|
|
383
|
+
|
|
384
|
+
## Pane
|
|
385
|
+
- pane-ui is a resizable / collapsible content panel. As a standalone primitive (no [side] attribute), it carries its own four-sided chrome and a right-edge resize grabber. As a horizontal-sibling child of a layout container (set [side="leading"] or [side="trailing"]), the chrome and grabber move to the inner edge so adjacent panes share a single seam.
|
|
386
|
+
- Wrapped by <editor-sidebar slot="leading|trailing"> inside <editor-shell>, and by <admin-sidebar slot="leading|trailing"> inside <admin-shell>. The bespoke sidebar owns [collapsed] / [resizing] reflected state + localStorage persistence; the inner pane-ui owns the physical drag. Don't reimplement drag in the bespoke sidebar — delegate to <pane-ui resizable>.
|
|
387
|
+
- Inner shape inside a pane-ui is the conventional <header> + <section> + optional <footer> slot pattern. Headers carry [slot="action"] button clusters; sections hold the navigator tree, inspector form rows, or other primary content.
|
|
388
|
+
- For a standalone resizable two-pane layout (no shell), nest panes directly inside a flex row — both with [side]-typed chrome — and the resize handle will live on the seam between them. For a non-resizable summary pane (a fixed-width detail rail), drop [resizable] and pane-ui collapses to a static container.
|
|
389
|
+
|
|
390
|
+
## PipelineStatus
|
|
391
|
+
- Single updating pipeline status indicator — status pill with optional progress bar.
|
|
392
|
+
- stage + complete + message attributes drive the current display state.
|
|
393
|
+
- For multi-step wizards use <stepper-ui>; for chronological history use <timeline-ui>; pipeline-status is a single current-state pill.
|
|
394
|
+
- Renders inline — place inside toolbars, status bars, or agent message bodies.
|
|
395
|
+
|
|
396
|
+
## Popover
|
|
397
|
+
- <popover-ui> wraps a focusable trigger (slot="trigger", typically <button-ui>) + arbitrary interactive content (slot="content"). Never put bare text in slot="trigger" — it must be focusable so keyboard users can open the popover.
|
|
398
|
+
- Decision rule vs adjacent surfaces. (a) For a list of action items use <menu-ui> instead — menu-ui is the specialized popover with role=menu + roving tabindex. (b) For read-only hover hints use <tooltip-ui>. (c) For centered focus-trapping dialogs use <modal-ui>. (d) For edge-anchored multi-field forms use <drawer-ui>. popover-ui is the GENERAL anchored surface for everything else (inline forms, color pickers, theme panels, export menus with non-action content).
|
|
399
|
+
- Use [placement="bottom-end"] for topbar overflow / settings buttons; [placement="bottom-start"] for inline form fields; top-* variants when trigger sits low in the viewport (statusbar). [gap] (default 4px) controls offset from anchor.
|
|
400
|
+
- [trigger="hover"] is for non-essential disclosure only — never use it for popovers containing inputs, destructive actions, or anything the user must interact with via keyboard. Default [trigger="click"] for everything interactive.
|
|
401
|
+
- Do NOT nest <modal-ui> or <drawer-ui> inside slot="content"; popovers are non-modal anchored surfaces, not dialog hosts. Stacking dialog surfaces inside a popover breaks focus management.
|
|
402
|
+
|
|
403
|
+
## ProgressRow
|
|
404
|
+
- Labeled progress row — composes a label + <progress-ui> + optional value display in one horizontal row.
|
|
405
|
+
- For standalone progress bars without a row context use <progress-ui> directly.
|
|
406
|
+
- Inside lists (multiple tasks with progress) stack multiple progress-rows in a <col-ui>.
|
|
407
|
+
|
|
408
|
+
## Progress
|
|
409
|
+
- Use for in-progress task feedback with known or indeterminate state. Value < 0 = indeterminate animation.
|
|
410
|
+
- For labeled task lists (multiple progress bars with row labels), use <progress-row-ui> instead.
|
|
411
|
+
- Spinner variant (variant='spinner') for circular loading indicators; bar variant default for linear.
|
|
412
|
+
|
|
36
413
|
## Radio
|
|
37
414
|
- Self-labeling widget — use the [label] attribute directly; do NOT wrap in <field-ui>. The widget renders its own label inline via CSS attr() pattern. For radio groups, the canonical pattern is a column of bare <radio-ui label='…'> elements sharing a [name=] — no field-ui wrapper around each radio.
|
|
415
|
+
- Use the [name] attribute to group radios — exactly one is selected per name group; form-associated.
|
|
416
|
+
- For button-style single-select clusters (visually richer) use <segmented-ui> + <segment-ui> instead.
|
|
417
|
+
|
|
418
|
+
## Range
|
|
419
|
+
- Two-handle slider for selecting a range (min + max). Form-associated; emits two-value change events.
|
|
420
|
+
- Different from <slider-ui> (single value) — use range when both endpoints matter.
|
|
421
|
+
- Step attribute controls handle increments; min/max set the bound rails.
|
|
422
|
+
|
|
423
|
+
## Rating
|
|
424
|
+
- Star/icon-based ordinal rating input. Form-associated; emits numeric value 0..max via change events.
|
|
425
|
+
- For thumbs-up/down agent feedback use <agent-feedback-bar-ui> instead — different semantics + visual.
|
|
426
|
+
- max attribute sets the scale (default 5); allow-half attribute enables half-step granularity.
|
|
427
|
+
|
|
428
|
+
## RichText
|
|
429
|
+
- Rich-text display + editor primitive. Renders paragraphs, lists, headings, and inline formatting; contenteditable when editable= is set.
|
|
430
|
+
- Different from <text-ui> (single semantic block) — richtext handles multi-paragraph + inline marks.
|
|
431
|
+
- For plain code use <code-ui> or richtext with code variant; for chat input use <chat-composer-ui>.
|
|
432
|
+
|
|
433
|
+
## Row
|
|
434
|
+
- Horizontal-stack flex container. Children flow left-to-right with token-driven gap.
|
|
435
|
+
- Pair with <col-ui> for vertical layouts; both share the same gap-token contract.
|
|
436
|
+
- Wrap attribute enables flex-wrap; default is nowrap.
|
|
437
|
+
|
|
438
|
+
## Search
|
|
439
|
+
- Search-input variant of <input-ui> with built-in search icon + clear affordance.
|
|
440
|
+
- For command-palette interactions use <command-ui> (which composes search + menu).
|
|
441
|
+
- Emits input events on each keystroke; debounce in the consumer for live-search.
|
|
442
|
+
|
|
443
|
+
## Section
|
|
444
|
+
- Use <section-ui> as the content body region inside a primitive container parent (<card-ui>, <drawer-ui>, <modal-ui>, <page-ui>) OR inside the body region of a bespoke shell-tier sidebar (<admin-sidebar> nav body — site/index.html and the admin-shell playground use this canonically). It is a CSS-only chrome stub for ADR-0009 slot vocabulary; the parent's @scope handles padding and borders.
|
|
445
|
+
- `scroll` is a CONDITIONAL attribute. It makes section-ui the scroll container ONLY inside <card-ui> / <drawer-ui> / <modal-ui>. Inside <page-ui> and shell-tier hosts (<admin-shell>, <admin-page-body>) it is a no-op — those parents own their own scroll surface. Never nest <section-ui scroll> inside another scroll container (nested scroll is a UX anti-pattern).
|
|
446
|
+
- Use `bleed` to remove section padding so children reach the card / drawer edges — typical for cover images, full-width charts, or media galleries (apps/saas/members.contents.html uses this pattern to wrap <table-ui raw>). Mix bleed and non-bleed sections in the same card to alternate edge-to-edge media with padded prose.
|
|
447
|
+
- Do NOT substitute <section-ui> for bespoke shell-tier body regions. Inside <admin-page> use <admin-page-body>; inside <admin-content> use the bespoke children. <section-ui> is reserved for the primitive container chrome triad + the <admin-sidebar> nav body.
|
|
448
|
+
- <section-ui> is the right place for layout primitives (<col-ui>, <row-ui>, <grid-ui>) that organize body content. Do NOT put those layout primitives inside <header-ui> or <footer-ui> — the parent's chrome scope already lays those rows out.
|
|
449
|
+
|
|
450
|
+
## Segment
|
|
451
|
+
- Child of <segmented-ui> — one selectable option button in a single-select group.
|
|
452
|
+
- Different from <toggle-option-ui> (which is multi-select inside <toggle-group-ui>).
|
|
453
|
+
- Selected state managed by parent <segmented-ui> via active attribute; do not set selected directly on segment.
|
|
454
|
+
|
|
455
|
+
## Segmented
|
|
456
|
+
- Single-select segmented control. Hosts <segment-ui> children; exactly one selected at a time.
|
|
457
|
+
- For multi-select use <toggle-group-ui> + <toggle-option-ui> instead.
|
|
458
|
+
- Use for view-mode switches (grid/list, light/dark) or short filter sets (3-5 options); for longer sets use <tabs-ui> or <select-ui>.
|
|
459
|
+
|
|
460
|
+
## Select
|
|
461
|
+
- Use <select-ui> for single-select with > 4 options or any list that benefits from a popover. Prefer <segmented-ui> / <radio-ui> when ≤ 4 visible options fit the row.
|
|
462
|
+
- Compose options via native <option> / <optgroup> children — other tag names are silently ignored (per §225 v0.5.9) and warned once at runtime. Or set `.options` programmatically as an array of `{value, label, disabled?}` (grouped form: `{label, options:[…]}`).
|
|
463
|
+
- For dynamic option lists rendered inside <editor-shell>, set the JSON via the [data-options] attribute — <editor-shell>'s wireSelects() finds select-ui[data-options], JSON.parses the attribute, and assigns `.options` on connect. Useful for static-HTML toolbars where JS hydration would be awkward.
|
|
464
|
+
- <select-ui> owns its own label / hint / error chrome (via [label] / [hint] / [error] props). Only wrap in <field-ui> when you need to share the field-chrome stack with sibling inputs in the same form row group.
|
|
465
|
+
- Enable [searchable] for > 10 options; add [free-text] only when unmatched values are valid (tag entry, email-with-suggestion). Use [multiple searchable] for multi-select rather than authoring a separate multi-select primitive.
|
|
466
|
+
|
|
467
|
+
## Skeleton
|
|
468
|
+
- Use to placeholder content during loading. Shape via CSS sizing (width/height/border-radius); shimmer is automatic.
|
|
469
|
+
- Compose multiple <skeleton-ui> blocks to mock the actual content shape (card-skeleton, row-skeleton, etc.).
|
|
470
|
+
- For post-load empty states use <empty-state-ui> instead; skeleton is pre-load only.
|
|
471
|
+
|
|
472
|
+
## Slider
|
|
473
|
+
- Single-handle slider for selecting one value in a range. Form-associated; emits numeric change events.
|
|
474
|
+
- For two-handle range selection use <range-ui> instead.
|
|
475
|
+
- Step attribute controls increments; show-value enables an inline value label.
|
|
476
|
+
|
|
477
|
+
## Stack
|
|
478
|
+
- Overlay/layer stacking container — children occupy the same area, stacked on the z-axis.
|
|
479
|
+
- Use for overlapping content (image + overlay, badge-over-avatar, drop-shadow stacks).
|
|
480
|
+
- Do not use for vertical content flow — that's <col-ui>. Stack-ui is overlap-only.
|
|
481
|
+
|
|
482
|
+
## Stat
|
|
483
|
+
- Use for prominent metric/KPI displays inside dashboard cards. Value + label + optional delta indicator.
|
|
484
|
+
- For inline percent/progress displays use <progress-ui>; stat is for standalone metrics, progress for completion bars.
|
|
485
|
+
- Delta indicator uses positive/negative semantic tokens; pass change= attribute with sign.
|
|
486
|
+
|
|
487
|
+
## StepProgress
|
|
488
|
+
- Compact step indicator — N dots/segments showing current step out of total.
|
|
489
|
+
- Different from <stepper-ui> (labeled, expanded) — step-progress is dense and label-free.
|
|
490
|
+
- For multi-task progress bars (multiple labeled rows) use <progress-row-ui> stack.
|
|
491
|
+
|
|
492
|
+
## StepperItem
|
|
493
|
+
- Child of <stepper-ui> — one numbered step with label + complete/current/upcoming state.
|
|
494
|
+
- State driven by parent's active-index; do not set state directly on stepper-item.
|
|
495
|
+
- For chronological events (no completion semantics) use <timeline-item-ui> instead.
|
|
496
|
+
|
|
497
|
+
## Stepper
|
|
498
|
+
- Hosts <stepper-item-ui> children with a parent active-index driving complete/current/upcoming states.
|
|
499
|
+
- Use for wizards, onboarding flows, multi-step forms.
|
|
500
|
+
- For read-only event history use <timeline-ui>; stepper requires forward progress semantics.
|
|
501
|
+
|
|
502
|
+
## Stream
|
|
503
|
+
- Renders an AsyncIterable<string> as streaming text — canonical for LLM token streaming.
|
|
504
|
+
- Place inside <chat-thread-ui> message bodies for LLM responses; standalone for log tailing.
|
|
505
|
+
- pace attribute controls typewriter-effect speed; hide-cursor disables the blinking caret.
|
|
506
|
+
- For static (post-stream) display use <text-ui> or <richtext-ui>; stream-ui assumes live token feed.
|
|
507
|
+
|
|
508
|
+
## Swatch
|
|
509
|
+
- Use to display a single color sample with optional label. For interactive color picking use <color-picker-ui>.
|
|
510
|
+
- Inside design-token displays or palette grids; not for general decoration.
|
|
511
|
+
- Color value accepts hex, rgb, hsl, or oklch; oklch preferred for AdiaUI token alignment.
|
|
512
|
+
|
|
513
|
+
## Swiper
|
|
514
|
+
- Horizontal slide carousel with touch + arrow nav. Hosts arbitrary children as slides.
|
|
515
|
+
- For tab-switched peer views use <tabs-ui>; swiper is for content browsing, not panel switching.
|
|
516
|
+
- Set autoplay attribute for timed-rotation; otherwise user-driven only.
|
|
38
517
|
|
|
39
518
|
## Switch
|
|
40
519
|
- Self-labeling widget — use the [label] attribute directly; do NOT wrap in <field-ui>. The widget renders its own label inline via CSS attr() pattern. For settings rows (label-left, switch-right), put the descriptive text in switch-ui's own [label] attribute; do not introduce a field-ui wrapper. For descriptive helper text below the switch, use <text-ui variant='caption'> as a sibling — not field-ui's hint slot.
|
|
520
|
+
- Binary on/off only — no third state. For tri-state controls use <check-ui> with [indeterminate].
|
|
521
|
+
- Use for settings toggles, feature flags, mode switches; for form gates / consent / multi-select use <check-ui> instead.
|
|
522
|
+
|
|
523
|
+
## TableToolbar
|
|
524
|
+
- Pair <table-toolbar-ui> with <table-ui> via [for="<table-id>"] (or rely on first-sibling fallback when both are inside the same parent). One toolbar per table. Do NOT also use <card-ui>'s <header> on the same card — that produces a doubled chrome row.
|
|
525
|
+
- All four affordances (search, filter, sort, columns) default ON. Opt out individually via [no-search] / [no-filter] / [no-sort] / [no-columns]. The previous [searchable] / [filterable] attributes are deprecated — do NOT emit them.
|
|
526
|
+
- Place the toolbar ABOVE the <card-ui> containing the table-ui, or use [variant="card"] when standing alone outside a card-ui parent (the variant wraps the toolbar in card-style chrome).
|
|
527
|
+
- Use slot="action" (or [slot="actions"]) for trailing primary buttons (Invite, Export, +New). Use [text] / [count] props for the left cluster, or slotted [slot="title"] / [slot="count"] when content is markup (a <span> + <badge-ui>, etc.).
|
|
528
|
+
- Listen for toolbar events (`search`, `filter-change`, `sort-change`, `columns-change`) only to mirror state to URL / persistence / analytics. The toolbar already wires its changes into the bound table — you don't need to manually update the table.
|
|
529
|
+
|
|
530
|
+
## Table
|
|
531
|
+
- Canonical composition: wrap <table-ui> in <card-ui><section bleed> for edge-to-edge tables. The [bleed] removes section padding so columns span the full card width (see apps/saas/members, billing, admin-dashboard).
|
|
532
|
+
- Pair with <table-toolbar-ui for="<table-id>"> for any table that needs search / filter / sort / columns visibility. Do NOT re-implement those affordances in the card header — the toolbar auto-wires search/filter/sort/columns changes into the bound table.
|
|
533
|
+
- Cells truncate single-line by default (v0.6.21 §403 truncate-default). Opt out per-table with [wrap] for whole-table multiline, or per-cell with [data-wrap] on a single column / cell.
|
|
534
|
+
- Use [raw] in production app consumers — it disables the demo seed data so the table renders only consumer-provided rows / columns / data props.
|
|
535
|
+
- Listen for the `sort` event with detail.key + detail.dir (NOT .column / .direction). `cell-click` detail carries {key, row, value, dataIndex}. Per ADR-0027, table-ui composes check-ui, icon-ui, progress-ui, pagination-ui, skeleton-ui, badge-ui — consumer pages must explicitly import the ones they use.
|
|
536
|
+
|
|
537
|
+
## Tab
|
|
538
|
+
- <tab-ui> only renders inside <tabs-ui>. Never use it standalone. The parent reads each tab's [text] + [icon] + [value] to render the button strip; the tab's default slot is the panel content that the parent auto-hides when inactive.
|
|
539
|
+
- [value] is required and must be unique among siblings — the parent <tabs-ui> matches its own [value] against each <tab-ui>[value] to decide which is active. [text] is the visible button label; optional [icon] is a Phosphor icon name shown leading the label.
|
|
540
|
+
- Use the default slot for panel content. Inactive <tab-ui> children are auto-hidden by the parent's [hidden] toggling; do NOT set [hidden] yourself unless you want to remove the button from the strip entirely (i.e. a temporarily-disabled tab whose strip button shouldn't render at all).
|
|
541
|
+
- Use [disabled] to keep a tab visible in the strip but non-selectable. Do not pair <tab-ui> with <button-ui> wrappers — the strip button is parent-rendered. Do not nest <tab-ui> inside another <tab-ui>.
|
|
542
|
+
|
|
543
|
+
## Tabs
|
|
544
|
+
- Decision rule: use <tabs-ui> when switching VIEWS within the same logical page (no route change, no URL change). For navigating AWAY (different page / route / anchor), use <nav-ui> instead. For a form-control segmented selector that returns a value, use <segmented-ui>.
|
|
545
|
+
- Children of <tabs-ui> MUST be <tab-ui> elements. The button strip is rendered from each child's [text] + optional [icon]; the parent auto-toggles [hidden] on inactive <tab-ui> children. Do not place arbitrary markup directly inside <tabs-ui> — wrap it in <tab-ui>.
|
|
546
|
+
- Canonical placements: inside <card-ui>'s <header> for in-card section switching; inside <editor-canvas-toolbar> for editor sub-views (see the editor sub-views recipe in patterns-recipes.md); or standalone as an in-page switcher. When standalone, wire sibling <div data-view="…"> panels via the `change` event (detail.value); for tabs whose content lives inside the <tab-ui> child, the auto-hide handles visibility.
|
|
547
|
+
- Set [value] to the initially active tab. If omitted, the first non-disabled <tab-ui> becomes active on connect. Set [orientation="vertical"] for left-rail tab strips.
|
|
548
|
+
- Variant caveat: only [variant="bordered"] is implemented (adds a subtle divider). [variant="underline"] is widely used in source but is equivalent to default (no-op). [variant="pills"] and [variant="segmented"] are declared in the enum but NOT styled — do NOT emit them; for a form-style selector use <segmented-ui>.
|
|
549
|
+
|
|
550
|
+
## Tag
|
|
551
|
+
- Use <tag-ui> for INTERACTIVE / DISMISSABLE labels — filter chips, autocomplete tokens, user-managed labels. Tag-ui fires a `remove` event when [removable] is set. For READ-ONLY status flags (counts, Beta / New / Deprecated markers, notification dots) use <badge-ui> instead — badge has no remove event and includes the [status] shorthand.
|
|
552
|
+
- Set [removable] and listen for the `remove` event (detail: {text, value}) when the tag represents a user-applied filter or selection that can be cleared.
|
|
553
|
+
- [variant] maps to semantic state of the underlying record: success = active / approved, warning = pending, danger = blocked / error, info = neutral-emphasis. Default (no variant) for unlabeled categories.
|
|
554
|
+
- Use [size="sm"] for inline-with-text contexts (doc page headers, table cells, badges next to titles); [size="md"] (default) for filter-bar chips and standalone tag rows.
|
|
555
|
+
- Group multiple tags inside a <row-ui gap="2"> — never stack them vertically; vertical lists of dismissable items are an <action-list-ui> use case, not <tag-ui>.
|
|
556
|
+
|
|
557
|
+
## Text
|
|
558
|
+
- Use for typographic content with semantic role (heading, body, label, caption). Variant attribute sets the role.
|
|
559
|
+
- For inline-flow rich content with multiple paragraphs, use <richtext-ui> instead.
|
|
560
|
+
- Heading variants (h1, h2, ...) are not auto-tagged — set the role explicitly via variant.
|
|
561
|
+
|
|
562
|
+
## Textarea
|
|
563
|
+
- <textarea-ui> is the canonical multi-line text input. The host IS the contenteditable surface — NEVER use a native <textarea> (banned by ADR-0025).
|
|
564
|
+
- Wrap <textarea-ui> in <field-ui label="…" hint="…" error="…"> for the canonical labeled stack. The inline [label] / [hint] / [error] props are also supported on the primitive for compact use.
|
|
565
|
+
- Form participation is implicit via UIFormElement. Set [name] for FormData submission; [required] / [disabled] / [readonly] reflect; listen for `change` (on blur after value change) and `input` (per keystroke).
|
|
566
|
+
- Use [rows] to set initial height (default 3) and [resize] (vertical | horizontal | both | none; default vertical) to control user resize. Never substitute a native <textarea> just to get rows / resize.
|
|
567
|
+
- Enter inserts a newline — <textarea-ui> does NOT emit a `submit` event. For Enter-to-send multi-line composers, use <chat-input-ui submit-on-enter> inside <chat-composer>, not textarea-ui.
|
|
568
|
+
|
|
569
|
+
## TimelineItem
|
|
570
|
+
- Child of <timeline-ui> — one chronological event with timestamp + content + optional icon dot.
|
|
571
|
+
- Different from <stepper-item-ui> (process steps with completion state) — timeline-item is event history.
|
|
572
|
+
- Order is DOM-order — no auto-sort by timestamp.
|
|
573
|
+
|
|
574
|
+
## Timeline
|
|
575
|
+
- Use for chronological event lists (audit log, activity feed, version history).
|
|
576
|
+
- Hosts <timeline-item-ui> children only.
|
|
577
|
+
- For multi-step processes with progress state use <stepper-ui> instead; timeline is read-only history.
|
|
578
|
+
|
|
579
|
+
## Toast
|
|
580
|
+
- Single ephemeral notification item — auto-dismissing or manually-closable.
|
|
581
|
+
- Typically posted into <feed-ui> via UIFeed.post(...); for inline persistent alerts use <alert-ui> instead.
|
|
582
|
+
- Variant maps to severity (info, success, warn, error); same tokens as <alert-ui>.
|
|
583
|
+
|
|
584
|
+
## ToggleGroup
|
|
585
|
+
- Multi-select button cluster — hosts <toggle-option-ui> children, each independently toggleable.
|
|
586
|
+
- Different from <segmented-ui> (single-select) — toggle-group emits a SET of active values.
|
|
587
|
+
- Use for filter chips, multi-flag toggles, day-of-week pickers; for binary on/off use <switch-ui>.
|
|
588
|
+
|
|
589
|
+
## ToggleOption
|
|
590
|
+
- Child of <toggle-group-ui> — one independently-toggleable button in a multi-select cluster.
|
|
591
|
+
- Different from <segment-ui> (which is single-select inside <segmented-ui>).
|
|
592
|
+
- Active state controlled via the toggle-option's own active attribute (independent of siblings).
|
|
41
593
|
|
|
42
594
|
## ToggleScheme
|
|
43
595
|
- Place toggle-scheme-ui in the shell topbar's trailing action cluster — slot="action" inside <admin-topbar slot="header"> of <admin-content>. It is a persistent, app-wide preference control; never put it in a sidebar footer / <admin-statusbar>, which hosts user-account items only.
|
|
596
|
+
- Stores user override in localStorage and writes color-scheme inline-style to the target; falls back to prefers-color-scheme if no override is set.
|
|
597
|
+
- Singleton per page — placing more than one in DOM creates conflicting writes to the same target.
|
|
598
|
+
|
|
599
|
+
## ToolbarGroup
|
|
600
|
+
- Child of <toolbar-ui> — clusters related action buttons with token-driven internal gap.
|
|
601
|
+
- Separate clusters with <divider-ui> siblings inside <toolbar-ui>.
|
|
602
|
+
- Do not nest toolbar-groups; flat hierarchy only.
|
|
603
|
+
|
|
604
|
+
## Toolbar
|
|
605
|
+
- Horizontal action bar — hosts <button-ui>, <toolbar-group-ui>, and <divider-ui> children.
|
|
606
|
+
- Cluster related buttons inside <toolbar-group-ui> with <divider-ui> separating clusters.
|
|
607
|
+
- For navigation use <nav-ui>; for modal/popover action bars use the modal's footer slot. Toolbar is for inline action bars within content regions.
|
|
608
|
+
|
|
609
|
+
## Tooltip
|
|
610
|
+
- Use <tooltip-ui> to label icon-only <button-ui> elements (text="Save" on a save-icon button, etc.) and for short descriptive hover hints. Never use it for content the user must read carefully (the bubble is transient + non-focusable).
|
|
611
|
+
- Never place INTERACTIVE children inside <tooltip-ui> — it is a read-only hint, not a surface. If the user must click or type, use <popover-ui> instead. Tooltips never receive keyboard focus.
|
|
612
|
+
- [follows="pointer"] mode requires [for] pointing at a <chart-ui> or <heatmap-ui> [id]; the tooltip subscribes to that target's `chart-hover` / `chart-leave` events to render data-viz annotations that track the cursor. Without [for] the tooltip renders nothing in pointer mode.
|
|
613
|
+
- Set [delay=0] only for high-frequency exploratory surfaces (sparkline ticks, chart hover). Keep the default 400ms delay elsewhere to avoid hover noise.
|
|
614
|
+
- [indicator] (dot | line | dashed) is meaningful only in pointer mode for per-series swatches. Omit it or leave default "none" for text-mode tooltips.
|
|
615
|
+
|
|
616
|
+
## TreeItem
|
|
617
|
+
- <tree-item-ui> MUST be a direct or nested descendant of <tree-ui>. It is not a standalone primitive — outside a <tree-ui> parent, selection / expansion / keyboard nav don't wire.
|
|
618
|
+
- Provide a stable [value] attribute on every <tree-item-ui> that consumers will select. The `tree-select` event's detail.value is the identifier downstream code reads to know which node was picked.
|
|
619
|
+
- Use [open] to pre-expand branch nodes on initial render. Do NOT set [selected] declaratively on more than one item — the parent <tree-ui> manages selection. The host listens for click / Enter / Space / ArrowRight (expand) / ArrowLeft (collapse) per WAI-ARIA tree-view APG.
|
|
620
|
+
- Use [icon] (Phosphor name) for affordance (folder / file / component icons); use [badge] for counts or short status labels (§184 v0.5.5).
|
|
621
|
+
- Nest further <tree-item-ui> in the default slot only — no <list-item-ui>, <nav-item-ui>, or arbitrary content inside a tree row. The chevron is auto-stamped when the row has nested tree-item-ui children.
|
|
622
|
+
|
|
623
|
+
## Tree
|
|
624
|
+
- Use <tree-ui> only when data is hierarchical with arbitrary nesting AND a single selected node is meaningful. For flat lists use <list-ui>; for flat sidebar navigation use <nav-ui>; for one-level collapsible groups use <accordion-ui>.
|
|
625
|
+
- Canonical mount: inside <editor-sidebar slot="leading"> → <pane-ui side="leading" resizable> → <section> → <tree-ui id="…"> as the structure / navigator pane of the three-pane editor shell. Pair with a <header> in the same pane (e.g. "Structure", "Layers", "Files").
|
|
626
|
+
- Direct children of <tree-ui> MUST be <tree-item-ui>. No other element types in the default slot. <tree-ui> manages single-selection across the whole subtree and implements WAI-ARIA tree-view keyboard navigation (Arrow keys, Enter / Space, Home / End).
|
|
627
|
+
- Listen for `tree-select` on the <tree-ui>, NOT on individual rows — selection is managed by the parent and bubbles once. Detail = {item, text, value, ctrlKey, metaKey, shiftKey}.
|
|
628
|
+
- Per ADR-0027, <tree-ui> composes <icon-ui> (for chevrons) but does NOT auto-import its children. Consumer pages must explicitly import both <tree-ui> and <tree-item-ui>.
|
|
629
|
+
|
|
630
|
+
## Upload
|
|
631
|
+
- File-upload input with drop zone + browse button. Form-associated; emits file-list change events.
|
|
632
|
+
- Multiple attribute enables multi-file selection; accept= constrains file types.
|
|
633
|
+
- For agent chat attachments use <chat-composer-ui>'s built-in upload affordance instead.
|
|
44
634
|
|
|
45
635
|
## ChatComposer
|
|
46
636
|
- chat-composer is the bespoke replacement for legacy <chat-input-ui data-chat-input> inside <chat-shell>. Place an inner <chat-input-ui submit-on-enter> as the primary input.
|
|
47
637
|
- The host listens for 'composer-submit' on the composer (not on the inner input). The event detail mirrors the inner submit event so existing handlers Just Work.
|
|
638
|
+
- Default slot holds a single <chat-input-ui> child; trailing/attach/leading slots host action buttons (send, attach, model picker).
|
|
639
|
+
- For non-chat input surfaces (forms, prompts, search) use <chat-input-ui> directly without the composer wrapper.
|
|
48
640
|
|
|
49
641
|
## ChatEmpty
|
|
50
642
|
- chat-empty is the bespoke replacement for legacy <empty-state-ui data-chat-empty>. Place as the first child of <chat-thread>; visibility is automatic via the [empty] reflected attribute.
|
|
643
|
+
- CSS-only — no JS module needed in shell HTML imports.
|
|
644
|
+
- For non-chat empty states (lists, tables, canvas) use <empty-state-ui> primitive instead; chat-empty is chat-cluster-namespaced.
|
|
51
645
|
|
|
52
646
|
## ChatHeader
|
|
53
647
|
- chat-header replaces the legacy <header> chrome bar inside <chat-shell>. Use named slots for canonical clusters; ad-hoc content goes in the default slot.
|
|
648
|
+
- Slots: [slot="name"] for chat title, [slot="status"] for streaming/connection indicator (<chat-status>), [slot="action"] for action buttons.
|
|
649
|
+
- For admin-shell-style chrome bars inside chat-shell, use <admin-topbar> instead — chat-header is for in-chat metadata only.
|
|
54
650
|
|
|
55
651
|
## ChatShell
|
|
56
|
-
- chat-shell
|
|
652
|
+
- chat-shell takes bespoke chat-* children only. The canonical composition is <chat-thread> (with optional first-child <chat-empty>) followed by <chat-composer> wrapping a <chat-input-ui submit-on-enter>. Add <chat-header> / <chat-sidebar> / <chat-status> as needed.
|
|
653
|
+
- Don't nest col-ui / row-ui or generic layout primitives directly inside chat-shell — the shell's CSS reads child tag selectors to lay them out. Generic layout goes inside the bespoke children.
|
|
654
|
+
- The shell listens for 'composer-submit' on <chat-composer> (not on the inner input). Streaming state is reflected on this host and propagates to <chat-thread>[streaming] + <chat-composer>[disabled] automatically — don't toggle child attributes manually.
|
|
655
|
+
- Legacy data-attribute shapes were retired in v0.4.0 per ADR-0024. Do not author <section data-chat-messages>, <chat-input-ui data-chat-input>, <empty-state-ui data-chat-empty>, or <header data-chat-name> inside chat-shell.
|
|
57
656
|
|
|
58
657
|
## ChatSidebar
|
|
59
658
|
- chat-sidebar is the bespoke replacement for legacy <aside data-sidebar>. Use slot="leading" or slot="trailing" to position. Add resizable + collapsible attributes to opt in to interactive behaviors.
|
|
60
659
|
- For chrome bars inside the sidebar, prefer <admin-topbar slot="header"> and <admin-statusbar slot="footer"> over raw <header-ui> / <footer-ui> when authoring shell-tier markup.
|
|
660
|
+
- Use cluster-distinct localStorage key (adia-chat-sidebar-*) to avoid collisions with admin (adia-sidebar-*) and editor (adia-editor-sidebar-*) sidebars.
|
|
661
|
+
- For chat-list / conversation-switcher content, host <nav-ui> + <nav-item-ui> children in the default slot.
|
|
61
662
|
|
|
62
663
|
## ChatStatus
|
|
63
664
|
- chat-status replaces legacy <span data-chat-status> for the streaming/connection indicator. Place inside <chat-header slot="status">.
|
|
665
|
+
- CSS-only — content is innerHTML (typically a short status word like 'connected' or 'streaming' or an icon).
|
|
666
|
+
- Use [data-state="streaming|connected|disconnected|..."] for token-driven coloring; the CSS reads the state attribute for tinting.
|
|
64
667
|
|
|
65
668
|
## ChatThread
|
|
66
669
|
- chat-thread is the bespoke replacement for legacy <section data-chat-messages> inside <chat-shell>. Use it for the message scroll surface; the host appends dynamic message divs as children.
|
|
67
670
|
- Place <chat-empty> as an optional first child for the empty state; the [empty] reflected attribute drives its visibility via CSS (no JS toggling).
|
|
671
|
+
- Different from primitive <chat-thread-ui>: chat-thread (no -ui suffix) is the module-tier shell-aware version with scroll-on-new-message + load-more + empty-state coordination.
|
|
672
|
+
- Hosts message blocks (typically agent/user message rows) as default-slot children; <chat-empty> goes as first child for the empty state.
|
|
68
673
|
|
|
69
674
|
## EditorCanvasEmpty
|
|
70
675
|
- editor-canvas-empty is the bespoke empty-state slot for <editor-canvas>. Place as the first child of <editor-canvas>; visibility is automatic via the [empty] reflected attribute.
|
|
676
|
+
- CSS-only — no JS module needed in shell HTML imports.
|
|
677
|
+
- For non-editor canvas empty states (raw <canvas-ui>) use <empty-state-ui> instead; editor-canvas-empty is editor-cluster-namespaced.
|
|
71
678
|
|
|
72
679
|
## EditorCanvasToolbar
|
|
73
680
|
- editor-canvas-toolbar is the bespoke chrome strip for the <editor-canvas> top edge. Use it to hold view-mode tabs (preview / schema / DOM) or breadcrumb-style navigation scoped to the canvas region.
|
|
@@ -80,71 +687,115 @@
|
|
|
80
687
|
- Place <editor-canvas-toolbar> as the first child to mount view-mode tabs (preview / schema / DOM, etc.), breadcrumbs, or canvas-scoped actions above the content body. Replaces the ad-hoc <div data-view-strip> pattern. Distinct from <editor-toolbar> (app-scope) — this is canvas-scope.
|
|
81
688
|
|
|
82
689
|
## EditorShell
|
|
83
|
-
- editor-shell
|
|
690
|
+
- editor-shell takes bespoke editor-* children only. The canonical composition is <editor-toolbar> + <editor-sidebar slot="leading"> + <editor-canvas> + <editor-sidebar slot="trailing"> + <editor-statusbar>. Each child is optional except the canvas.
|
|
691
|
+
- Don't nest col-ui / row-ui or generic layout primitives directly inside editor-shell — the shell's CSS reads child tag selectors to lay them out. Generic layout goes inside the bespoke children.
|
|
692
|
+
- <editor-sidebar> WRAPS <pane-ui resizable> rather than implementing drag itself (delegation pattern). Inside each sidebar place a single <pane-ui resizable size="sm"> filled with <header> + <section> slots.
|
|
693
|
+
- For editor-inside-admin nested-shell pages, place the editor-shell inside <admin-page-body> with `flex: 1; min-height: 0` on every ancestor in the flex chain. Without min-height: 0 the inner shell collapses to zero height.
|
|
694
|
+
- Legacy data-attribute shapes were retired in v0.4.0 per ADR-0024. Do not author <div data-editor-body>, <pane-ui data-left|data-right>, <div data-canvas>, <span data-spacer>, or bare <header>/<footer> chrome inside editor-shell.
|
|
84
695
|
|
|
85
696
|
## EditorSidebar
|
|
86
697
|
- editor-sidebar wraps <pane-ui resizable> rather than implementing drag itself. Place a <pane-ui resizable> as the only structural child; fill the pane with header / section / footer slots.
|
|
87
698
|
- The cluster-distinct localStorage prefix (adia-editor-sidebar-*) keeps editor sidebars from colliding with admin (adia-sidebar-*) and chat (adia-chat-sidebar-*) sidebars on the same domain.
|
|
699
|
+
- Wraps a SINGLE <pane-ui resizable> as its only structural child; fill the pane with sub-views (nav, inspector, layers panel, etc.).
|
|
700
|
+
- For multiple panes (e.g. left nav + right inspector), use two <editor-sidebar> instances at slot="leading" and slot="trailing" of <editor-shell>.
|
|
88
701
|
|
|
89
702
|
## EditorStatusbar
|
|
90
703
|
- editor-statusbar replaces legacy <footer> chrome bar inside <editor-shell>. Use named slots for canonical clusters; ad-hoc content goes in the default slot.
|
|
704
|
+
- Slots: [slot="status"] for save/sync state, [slot="cursor"] for cursor position, [slot="zoom"] for zoom level, [slot="action"] for actions. All optional.
|
|
705
|
+
- Different from <admin-statusbar> (which is for admin-shell); editor-statusbar has editor-specific slot vocabulary (cursor, zoom).
|
|
91
706
|
|
|
92
707
|
## EditorToolbar
|
|
93
708
|
- editor-toolbar replaces legacy <header> chrome bar inside <editor-shell>. Use named slots (title / status / action / action-leading) for canonical clusters; ad-hoc inline content goes in the default slot.
|
|
94
709
|
- Buttons that should trigger named actions get [data-toolbar-action="<name>"]. The toolbar bubbles a single 'toolbar-action' event up to the host with the name in detail.
|
|
710
|
+
- Different from <admin-topbar> (admin-shell chrome) — editor-toolbar has [full-screen] state + editor-specific [data-toolbar-action] event bubbling.
|
|
711
|
+
- Place full-screen toggle buttons inside the toolbar with [data-toolbar-action="toggle-full-screen"]; host reflects [full-screen] up to <editor-shell>.
|
|
712
|
+
|
|
713
|
+
## A2UIRoot
|
|
714
|
+
- Mount point for an A2UI-rendered composition. Hosts the runtime-emitted DOM tree.
|
|
715
|
+
- Different from <gen-root> (which is for the generative-UI lane with LLM-driven streaming).
|
|
716
|
+
- Do not place static children inside; runtime owns the contents.
|
|
95
717
|
|
|
96
718
|
## GenRoot
|
|
97
719
|
- gen-root is an integration shell. Prefer admin-shell for admin UIs; use gen-root only for chat+canvas tooling.
|
|
720
|
+
- Hosts <chat-thread-ui>, <canvas-ui>, and <inspector-ui> children via named slots — chat slot for the conversation lane, canvas slot for the artifact lane, inspector slot for the dev-tools lane.
|
|
721
|
+
- Mode attribute (chat-only|split|canvas-only) controls layout; transitions are CSS-animated.
|
|
98
722
|
|
|
99
723
|
## AdminCommand
|
|
100
724
|
- admin-command wraps a native <dialog>; the inner <command-ui> is the actual palette. Keyboard shortcut defaults to both Cmd+K (mac) and Ctrl+K (other) — the AdiaUI convention.
|
|
101
725
|
- Place admin-command as a direct child of admin-shell, NOT inside a sidebar or main column. The host coordinates triggers ([data-command-trigger]) by reaching across siblings.
|
|
726
|
+
- For inline content-region command surfaces use <command-ui> directly; admin-command is the modal wrapper that opens the palette as an overlay.
|
|
727
|
+
- Triggers anywhere in the shell via [data-command-trigger] attribute on any element; the host wires the open/close cycle.
|
|
102
728
|
|
|
103
729
|
## AdminContent
|
|
104
730
|
- admin-content is the bespoke replacement for raw <main> inside admin-shell. CSS-only; the shell's css/main.css selectors target both shapes via :is(main, admin-content).
|
|
731
|
+
- Place as a direct child of <admin-shell>, not inside a sidebar or topbar; admin-content owns the center column.
|
|
732
|
+
- Hosts <admin-page> children OR raw page content via the default slot; for chrome bars use <admin-topbar slot="header">.
|
|
105
733
|
|
|
106
734
|
## AdminEntityItem
|
|
107
735
|
- admin-entity-item is the canonical icon + label + badge identity row for shell surfaces. Slot it whole into [slot="heading"] of an <admin-topbar> / <admin-statusbar> so the icon + label + badge collapse together inside a collapsible <admin-sidebar>. Do NOT re-implement it with a bare <span> or an ad-hoc flex <div> — those have no shared collapse boundary.
|
|
108
736
|
- For an INTERACTIVE workspace switcher use <select-ui variant="ghost"> instead — admin-entity-item is read-only identity display.
|
|
737
|
+
- Slot whole into [slot="heading"] of <admin-topbar>/<admin-statusbar>; do not nest inside other admin-entity-items.
|
|
738
|
+
- Flat hierarchy: icon + label + badge in three slots, no extra wrapping. For full-width metadata strips compose multiple inside <row-ui> instead.
|
|
109
739
|
|
|
110
740
|
## AdminPageBody
|
|
111
741
|
- admin-page-body is the centered body band of <admin-page>. Wraps an inner <section-ui> for centered reading-column rhythm; can host full-bleed content directly to opt out.
|
|
742
|
+
- Wraps an inner <section-ui> by default for centered reading-column rhythm; for full-bleed content (tables, canvas grids) use [data-full-bleed] on the section.
|
|
743
|
+
- Always inside <admin-page slot="body">; do not place admin-page-body outside admin-page.
|
|
112
744
|
|
|
113
745
|
## AdminPageHeader
|
|
114
746
|
- admin-page-header is the sticky top band of <admin-page>. Wraps an inner <header-ui> for centered reading-column rhythm.
|
|
747
|
+
- Wraps an inner <header-ui> for centered reading-column rhythm; admin-page-header owns sticky positioning + border, header-ui owns the content layout.
|
|
748
|
+
- Always inside <admin-page slot="header">; for shell-tier chrome use <admin-topbar> instead.
|
|
115
749
|
|
|
116
750
|
## AdminPage
|
|
117
751
|
- admin-page is the bespoke replacement for <article data-content-root>. Provides the page-content named container query so descendants can use @container page-content (max-width: 720px) etc.
|
|
752
|
+
- Hosts a single page surface via [slot="body"] (typically <admin-page-body>) with optional [slot="header"] (<admin-page-header>) and [slot="footer"].
|
|
753
|
+
- Sits inside <admin-content>'s default slot; do not place outside admin-shell.
|
|
118
754
|
|
|
119
755
|
## AdminScroll
|
|
120
756
|
- admin-scroll is the bespoke replacement for the legacy <section> child of <main> inside admin-shell. Single child convention — typically wraps an <admin-page> for sticky-band layout.
|
|
757
|
+
- Wraps a single <admin-page> child typically; do not place multiple admin-pages side-by-side as siblings here.
|
|
758
|
+
- For horizontal scrolling regions (data grids, canvas surfaces) use overflow on the inner content instead — admin-scroll is vertical-only.
|
|
121
759
|
|
|
122
760
|
## AppShell
|
|
123
|
-
- admin-shell
|
|
761
|
+
- admin-shell takes bespoke admin-* children only. The canonical composition is <admin-topbar> + <admin-sidebar slot="leading"> + <admin-content> + <admin-sidebar slot="trailing"> + <admin-command> + optional <admin-statusbar>. The shell's CSS grid reads child tag selectors to place them.
|
|
762
|
+
- Don't nest col-ui / row-ui or generic layout primitives directly inside admin-shell — app-shell.css handles grid layout based on bespoke child tags. Generic layout goes inside <admin-content> or inside <admin-page-body>.
|
|
763
|
+
- Click forwarding patterns — [data-sidebar-toggle="<name>"] on a button forwards to <admin-sidebar[slot="<name>"]>.toggle(); [data-command-trigger] on a button forwards to <admin-command>.show(). The shell doesn't need to know about the buttons; the bespoke children own the behavior.
|
|
764
|
+
- Legacy data-attribute shapes were retired in v0.4.0 per ADR-0024. Do not author <aside data-sidebar>, <dialog data-command>, [data-resize], <aside-ui slot=>, <span data-spacer>, or <div data-actions> inside admin-shell.
|
|
124
765
|
|
|
125
766
|
## AdminSidebar
|
|
126
767
|
- admin-sidebar is the bespoke replacement for legacy <aside data-sidebar>. Use slot="leading" or slot="trailing" to position. Add resizable + collapsible attributes to opt in to interactive behaviors.
|
|
127
768
|
- For chrome bars inside the sidebar, prefer <admin-topbar slot="header"> and <admin-statusbar slot="footer"> over raw <header-ui> / <footer-ui> when authoring shell-tier markup.
|
|
769
|
+
- [resizable] attribute enables drag-resize via internal <pane-ui resizable>; persists collapsed/width to localStorage under adia-sidebar-* keys.
|
|
770
|
+
- For non-resizable static rails (fixed-width nav), omit [resizable]; the same primitive serves both modes.
|
|
128
771
|
|
|
129
772
|
## AdminStatusbar
|
|
130
773
|
- admin-statusbar replaces <footer-ui> at shell-tier. Same slot vocabulary as <admin-topbar>; visual treatment differs (the shell css applies a top-border instead of bottom).
|
|
131
|
-
- When placed inside <admin-sidebar> or <admin-content>, admin-statusbar MUST carry slot="footer". Without it the statusbar lands in the default body slot instead of the chrome footer band. Canonical: <admin-statusbar slot="footer">…</admin-statusbar>. admin-shell logs a one-shot console.warn when the slot is missing.
|
|
132
774
|
- For a user-identity row (avatar + name + role badge), slot a single <admin-entity-item slot="heading"> rather than separate slot="icon" + slot="heading" children — the wrapper collapses the name + badge together inside a collapsible <admin-sidebar>, keeping the avatar.
|
|
775
|
+
- All slots optional; common pattern is [slot="heading"] + [slot="action"] only. Empty admin-statusbar renders zero-height (no visual chrome).
|
|
776
|
+
- Sits at slot="footer" of <admin-shell>, <admin-content>, or <admin-sidebar>; do not place inside <admin-page slot="footer"> (use raw <footer-ui> there).
|
|
133
777
|
|
|
134
778
|
## AdminTopbar
|
|
135
779
|
- admin-topbar replaces <header-ui> at shell-tier — use it for chrome bars inside admin-shell, admin-content, admin-sidebar. Use <header-ui> for primitive containers (Card / Drawer / Modal).
|
|
136
|
-
- When placed inside <admin-sidebar> or <admin-content>, admin-topbar MUST carry slot="header". Without it the topbar lands in the default body slot and renders below the content instead of as the chrome header band. Canonical: <admin-topbar slot="header">…</admin-topbar>. admin-shell logs a one-shot console.warn when the slot is missing.
|
|
137
780
|
- For an icon + label (+ optional badge) identity row — workspace or product identity — slot a single <admin-entity-item slot="heading"> rather than separate slot="icon" + slot="heading" children. The wrapper keeps the icon and label as one unit so they truncate and collapse together inside a collapsible <admin-sidebar>.
|
|
781
|
+
- All slots optional; common pattern is [slot="heading"] + [slot="action"] only. Empty admin-topbar renders zero-height (no visual chrome).
|
|
782
|
+
- Sits at slot="header" of <admin-shell>, <admin-content>, or <admin-sidebar>; do not place inside <admin-page slot="header"> (use <admin-page-header> there).
|
|
138
783
|
|
|
139
784
|
## SimpleContent
|
|
140
785
|
- simple-content is the article surface inside simple-shell. Use for primary page body. Sibling to <simple-hero> (optional).
|
|
786
|
+
- CSS-only — do not import its JS module (there isn't one); does not need an `import` in shell HTML.
|
|
787
|
+
- For multi-page apps with chrome (nav, topbar, command palette) use <admin-shell-ui> with <admin-content> instead.
|
|
141
788
|
|
|
142
789
|
## SimpleHero
|
|
143
790
|
- simple-hero is the optional top strip inside simple-shell. Use for marketing splashes, error-page reassurance text, or single- flow page intros. Always followed by <simple-content> for body.
|
|
791
|
+
- Three named slots: heading (large title), lede (supporting subtitle), actions (button cluster). All optional but order is fixed.
|
|
792
|
+
- CSS-only — sibling to <simple-content> inside <simple-shell>. Do not nest hero inside content or vice versa.
|
|
144
793
|
|
|
145
794
|
## SimpleShell
|
|
146
795
|
- simple-shell is the bespoke shell for thin / minimal page surfaces. Use when the page has no nav rail, no chrome bars, no command palette. For full app surfaces use admin-shell; for chat surfaces use chat-shell; for design tools use editor-shell.
|
|
147
796
|
- Compose with <simple-hero> (optional top hero strip) and <simple-content> (main article body). Both are CSS-only structural children — no JS, no state.
|
|
797
|
+
- [centered] reflected attribute centers content vertically; [full-bleed] drops the max-width constraint on <simple-content> children. Both optional, default unset.
|
|
798
|
+
- For multi-page apps with chrome (nav, topbar, command palette) use <admin-shell> instead; simple-shell has zero chrome.
|
|
148
799
|
|
|
149
800
|
## ThemePanel
|
|
150
801
|
- theme-panel is the canonical appearance-preferences popover. Compose inside a <popover-ui slot="content"> in the topbar of a shell (admin, chat, editor, simple) when the page exposes user theming. Avoid hardcoding it as a shell child — placement is the consumer's call.
|