@adia-ai/adia-ui-forge 0.8.62 → 0.8.63
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/.claude-plugin/plugin.json +2 -2
- package/.codex-plugin/plugin.json +3 -3
- package/CHANGELOG.md +300 -275
- package/README.md +54 -18
- package/__init__.py +8 -8
- package/agents/a2ui-maintenance-agent.corpus.json +7 -7
- package/agents/a2ui-maintenance-agent.md +6 -6
- package/agents/a2ui-planner-agent.md +11 -11
- package/agents/demo-audit-agent.corpus.json +4 -4
- package/agents/demo-audit-agent.md +8 -9
- package/agents/framework-checker.md +10 -11
- package/agents/framework-planner-agent.md +9 -10
- package/agents/gen-ui-review-agent.corpus.json +4 -4
- package/agents/gen-ui-review-agent.md +8 -8
- package/agents/package-release-agent.corpus.json +4 -4
- package/agents/package-release-agent.md +9 -10
- package/agents/primitive-authoring-agent.corpus.json +1 -1
- package/agents/primitive-authoring-agent.md +5 -5
- package/agents/routing-corpus.json +46 -46
- package/codex.interface.json +1 -1
- package/commands/gen-ui-review.md +1 -1
- package/commands/package-release.md +2 -2
- package/package.json +1 -1
- package/plugin.yaml +2 -2
- package/prompts/gen-ui-review.md +1 -1
- package/prompts/package-release.md +2 -2
- package/references/contracts/a2ui-mcp-surface.md +7 -7
- package/references/contracts/migration-guide-format.md +6 -7
- package/references/shared/content-trust.md +3 -5
- package/skills/a2ui-maintenance/SKILL.md +13 -16
- package/skills/a2ui-maintenance/evals/evals.json +2 -2
- package/skills/a2ui-maintenance/evals/routing-corpus.json +1 -1
- package/skills/a2ui-maintenance/references/anti-patterns.md +10 -10
- package/skills/a2ui-maintenance/references/chunk-authoring.md +11 -12
- package/skills/a2ui-maintenance/references/corpus-discipline.md +13 -14
- package/skills/a2ui-maintenance/references/data-model-reactivity.md +22 -25
- package/skills/a2ui-maintenance/references/eval-diagnostics.md +21 -21
- package/skills/a2ui-maintenance/references/format-extension-decisions.md +12 -13
- package/skills/a2ui-maintenance/references/leverage-rules.md +6 -6
- package/skills/a2ui-maintenance/references/mcp-pipeline-ops.md +9 -10
- package/skills/a2ui-maintenance/references/mcp-tool-reference.md +11 -12
- package/skills/a2ui-maintenance/references/pipeline-overview.md +33 -38
- package/skills/a2ui-maintenance/references/semantic-fail-lifting.md +13 -14
- package/skills/a2ui-maintenance/references/strategy-engines.md +14 -16
- package/skills/a2ui-maintenance/references/surface-lifecycle.md +10 -11
- package/skills/a2ui-maintenance/references/zettel-calibration.md +14 -16
- package/skills/component-md-authoring/SKILL.md +20 -21
- package/skills/component-md-authoring/agents/openai.yaml +1 -1
- package/skills/cross-harness-authoring-standards/SKILL.md +19 -21
- package/skills/cross-harness-authoring-standards/agents/openai.yaml +1 -1
- package/skills/cross-harness-compatibility-standards/SKILL.md +34 -35
- package/skills/cross-harness-compatibility-standards/agents/openai.yaml +1 -1
- package/skills/demo-audit/SKILL.md +38 -38
- package/skills/demo-audit/evals/routing-corpus.json +1 -1
- package/skills/demo-audit/references/admin-shell-anatomy.md +21 -25
- package/skills/demo-audit/references/app-shell-pitfalls.md +11 -13
- package/skills/demo-audit/references/auto-fix-allowlist.md +3 -3
- package/skills/demo-audit/references/card-anatomy-sweep.md +10 -11
- package/skills/demo-audit/references/chat-shell-anatomy.md +25 -26
- package/skills/demo-audit/references/editor-shell-anatomy.md +25 -28
- package/skills/demo-audit/references/html-attr-sweep.md +12 -13
- package/skills/demo-audit/references/mode7-status-battery.md +4 -4
- package/skills/demo-audit/references/native-leak-annotations.md +8 -8
- package/skills/demo-audit/references/output-contract-worked-example.md +8 -8
- package/skills/demo-audit/references/probe-discipline-and-escalation.md +2 -2
- package/skills/demo-audit/references/visual-probe-triage.md +21 -23
- package/skills/gen-ui-review/SKILL.md +27 -27
- package/skills/gen-ui-review/agents/openai.yaml +1 -1
- package/skills/gen-ui-review/evals/routing-corpus.json +1 -1
- package/skills/gen-ui-review/references/corpus-html-patterns.md +28 -29
- package/skills/gen-ui-review/references/exit-gate-mechanics.md +5 -5
- package/skills/gen-ui-review/references/lookup-maintenance.md +2 -2
- package/skills/gen-ui-review/references/loop-protocol.md +25 -25
- package/skills/gen-ui-review/references/rubric-cosmetic.md +10 -10
- package/skills/gen-ui-review/references/rubric-decompose.md +15 -16
- package/skills/gen-ui-review/references/rubric-score.md +23 -24
- package/skills/gen-ui-review/references/scorecard-worked-examples.md +12 -12
- package/skills/gen-ui-review/references/scores.schema.json +2 -2
- package/skills/llm-client-maintenance/SKILL.md +12 -12
- package/skills/llm-client-maintenance/evals/routing-corpus.json +1 -1
- package/skills/llm-client-maintenance/references/adapter-contract.md +27 -27
- package/skills/llm-client-maintenance/references/add-a-provider.md +25 -25
- package/skills/llm-client-maintenance/references/bridge-facade.md +31 -31
- package/skills/llm-client-maintenance/references/browser-proxy-boundary.md +17 -17
- package/skills/llm-client-maintenance/references/model-registry.md +14 -14
- package/skills/llm-client-maintenance/references/streaming-sse.md +21 -21
- package/skills/package-release/SKILL.md +21 -23
- package/skills/package-release/evals/evals.json +2 -2
- package/skills/package-release/evals/routing-corpus.json +2 -2
- package/skills/package-release/references/authorization-model.md +6 -8
- package/skills/package-release/references/changelog-discipline.md +25 -27
- package/skills/package-release/references/cut-procedure.md +129 -136
- package/skills/package-release/references/gates-catalog.md +42 -43
- package/skills/package-release/references/independent-package-release.md +14 -15
- package/skills/package-release/references/invariants-detail.md +9 -9
- package/skills/package-release/references/mechanization.md +11 -12
- package/skills/package-release/references/migration-guide-authoring.md +20 -20
- package/skills/package-release/references/notes-authoring.md +20 -20
- package/skills/package-release/references/recovery-paths.md +28 -28
- package/skills/primitive-authoring/SKILL.md +19 -19
- package/skills/primitive-authoring/agents/openai.yaml +1 -1
- package/skills/primitive-authoring/evals/evals.json +2 -2
- package/skills/primitive-authoring/evals/routing-corpus.json +2 -2
- package/skills/primitive-authoring/references/INDEX.md +22 -22
- package/skills/primitive-authoring/references/anti-patterns.md +76 -77
- package/skills/primitive-authoring/references/api-contract.md +63 -65
- package/skills/primitive-authoring/references/authoring-cycle.md +47 -50
- package/skills/primitive-authoring/references/canonical-pattern-index.md +118 -118
- package/skills/primitive-authoring/references/code-style.md +50 -52
- package/skills/primitive-authoring/references/common-gotchas.md +23 -23
- package/skills/primitive-authoring/references/composite-demo-protocol.md +42 -45
- package/skills/primitive-authoring/references/css-patterns.md +97 -97
- package/skills/primitive-authoring/references/for-attribute-event-contract.md +12 -12
- package/skills/primitive-authoring/references/form-control-sizing.md +16 -18
- package/skills/primitive-authoring/references/lifecycle-patterns.md +42 -42
- package/skills/primitive-authoring/references/llm-bridge.md +21 -21
- package/skills/primitive-authoring/references/module-promotion.md +51 -51
- package/skills/primitive-authoring/references/primitive-audit.md +16 -16
- package/skills/primitive-authoring/references/shell-patterns.md +81 -81
- package/skills/primitive-authoring/references/svg-authoring.md +62 -66
- package/skills/primitive-authoring/references/token-contract.md +45 -49
- package/skills/primitive-authoring/references/trait-pages.md +8 -8
- package/skills/primitive-authoring/references/worked-example.md +39 -39
- package/skills/primitive-authoring/references/yaml-contract.md +139 -143
- package/skills/site-deployment/SKILL.md +25 -26
- package/skills/site-deployment/agents/openai.yaml +1 -1
- package/skills/site-deployment/evals/routing-corpus.json +1 -1
- package/skills/site-deployment/references/deploy-playbooks.md +51 -53
- package/skills/site-docs-authoring/SKILL.md +14 -14
- package/skills/site-docs-authoring/agents/openai.yaml +1 -1
- package/skills/site-docs-authoring/evals/evals.json +1 -1
- package/skills/site-docs-authoring/evals/routing-corpus.json +1 -1
- package/skills/site-docs-authoring/intent.md +18 -18
- package/skills/ssr-compatibility/SKILL.md +24 -25
- package/skills/ssr-compatibility/agents/openai.yaml +1 -1
- package/skills/ssr-compatibility/evals/evals.json +1 -1
- package/skills/ssr-compatibility/evals/routing-corpus.json +1 -1
- package/skills/ssr-compatibility/references/consumer-workarounds.md +22 -23
- package/skills/ssr-compatibility/references/failure-shapes.md +84 -91
- package/skills/ssr-compatibility/references/guard-patterns.md +54 -58
- package/skills/ssr-compatibility/references/status-ledger.md +17 -17
- package/skills/ssr-compatibility/references/test-without-linkedom.md +26 -27
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Authoring shell components
|
|
2
2
|
|
|
3
|
-
Shell components are a distinct authoring shape from single-element primitives. They wrap an entire product surface
|
|
3
|
+
Shell components are a distinct authoring shape from single-element primitives. They wrap an entire product surface, admin app, chat streaming surface, code/canvas editor, docs page, simple splash, and exist almost entirely to wire JS behaviors that CSS can't express on top of author-provided DOM.
|
|
4
4
|
|
|
5
5
|
The **canonical authoring shape is bespoke cluster-namespaced children with state-as-attribute semantics**, per ADR-0023 (bespoke shell-tier children). Every shell-specific concern earns its own custom element with a documented attribute API; state lives as reflected attributes; parent shells coordinate via `querySelector` + slot routing without centralizing child behavior.
|
|
6
6
|
|
|
@@ -12,8 +12,8 @@ Legacy `data-*` shapes (`[data-canvas]`, `<aside-ui slot="leading">`, `<dialog d
|
|
|
12
12
|
|
|
13
13
|
You're authoring a shell when:
|
|
14
14
|
|
|
15
|
-
- The component holds no visual content of its own
|
|
16
|
-
- The component's value is in _behavior_
|
|
15
|
+
- The component holds no visual content of its own, the page author provides everything inside it.
|
|
16
|
+
- The component's value is in _behavior_, keyboard shortcuts, resize handles, ResizeObserver-driven breakpoints, localStorage persistence.
|
|
17
17
|
- More than one component instance on a page would feel wrong (one shell per surface).
|
|
18
18
|
- You're decomposing a new module-tier shell (chat / editor / simple / docs / future).
|
|
19
19
|
- You're adding a new bespoke child to an existing cluster (`<admin-*>`, `<chat-*>`, `<editor-*>`, `<simple-*>`).
|
|
@@ -21,9 +21,9 @@ You're authoring a shell when:
|
|
|
21
21
|
|
|
22
22
|
You are NOT authoring a shell when:
|
|
23
23
|
|
|
24
|
-
- The component injects its own structure (header, body, footer slots filled with default markup)
|
|
25
|
-
- The component renders a single semantic element with cosmetic variants
|
|
26
|
-
- You're extracting a cross-cluster reusable element (theme panel, command palette shared across shells)
|
|
24
|
+
- The component injects its own structure (header, body, footer slots filled with default markup), that's a regular composite. Use the `card-ui` pattern ([authoring-cycle.md](authoring-cycle.md)).
|
|
25
|
+
- The component renders a single semantic element with cosmetic variants, that's a leaf primitive. Use the button-ui / badge pattern ([authoring-cycle.md](authoring-cycle.md)).
|
|
26
|
+
- You're extracting a cross-cluster reusable element (theme panel, command palette shared across shells), that's module promotion; see [module-promotion.md](module-promotion.md).
|
|
27
27
|
|
|
28
28
|
## Architectural principles (read first)
|
|
29
29
|
|
|
@@ -31,7 +31,7 @@ You are NOT authoring a shell when:
|
|
|
31
31
|
2. **State-as-attribute.** Every consumer-queryable state is a **reflected attribute** on the relevant element. CSS `:has(<el>[state])`, JS `.hasAttribute('state')`. No threshold-math state inference.
|
|
32
32
|
3. **Cluster namespace.** Bespoke children use `<cluster-thing>` (no `-ui` suffix) per ADR-0015. `<admin-*>` for admin shell, `<chat-*>` for chat shell, `<editor-*>` for editor shell, `<simple-*>` for simple shell.
|
|
33
33
|
4. **Each child owns one concern.** If a child accumulates 3+ unrelated behaviors, split it.
|
|
34
|
-
5. **Backwards-compat window during introduction, then deprecate.** When introducing a NEW cluster's bespoke family, ship 1–2 patch releases where the host reads BOTH legacy and bespoke shapes via `:is()` selectors (so consumers can migrate). Then deprecate the legacy shape in the next MINOR cut
|
|
34
|
+
5. **Backwards-compat window during introduction, then deprecate.** When introducing a NEW cluster's bespoke family, ship 1–2 patch releases where the host reads BOTH legacy and bespoke shapes via `:is()` selectors (so consumers can migrate). Then deprecate the legacy shape in the next MINOR cut, strip the host's legacy reads, drop legacy CSS lifts, document in an ADR. The admin/chat/editor families completed this cycle (ADR-0024), legacy retired after a ~9-day compat window. Future cluster expansions should follow: introduce → migrate consumers → smoke-probe → deprecate.
|
|
35
35
|
|
|
36
36
|
## The 4-concern decomposition heuristic
|
|
37
37
|
|
|
@@ -44,7 +44,7 @@ When decomposing a shell, identify behavior in this order:
|
|
|
44
44
|
| 3. **Cluster-specific orchestration** (LLM streaming, canvas state, etc.) | the host OR a dedicated coordinator | stays in `<X-shell>` if cluster-tied; promote to coordinator if reusable |
|
|
45
45
|
| 4. **Structural composition** (chrome bars, scroll surfaces, page bands) | CSS-only stubs | one stub per region (mirrors `<admin-content>` / `<admin-topbar>` / etc.) |
|
|
46
46
|
|
|
47
|
-
**Default split for a 5-concern shell
|
|
47
|
+
**Default split for a 5-concern shell**, 2-3 JS-bearing + 5-7 CSS-only stubs = 7-10 bespoke children.
|
|
48
48
|
|
|
49
49
|
## File scaffold per child
|
|
50
50
|
|
|
@@ -53,7 +53,7 @@ When decomposing a shell, identify behavior in this order:
|
|
|
53
53
|
```text
|
|
54
54
|
packages/web-modules/<cluster>/<cluster>-<role>/
|
|
55
55
|
<cluster>-<role>.js # behavior + reflected attributes
|
|
56
|
-
<cluster>-<role>.yaml # SoT
|
|
56
|
+
<cluster>-<role>.yaml # SoT, props/events/slots/states/keywords
|
|
57
57
|
<cluster>-<role>.a2ui.json # GENERATED via npm run build:components
|
|
58
58
|
<cluster>-<role>.html # demo shell that fetches .examples.html
|
|
59
59
|
<cluster>-<role>.examples.html # living examples + behavior wiring tables
|
|
@@ -64,7 +64,7 @@ packages/web-modules/<cluster>/<cluster>-<role>/
|
|
|
64
64
|
|
|
65
65
|
```text
|
|
66
66
|
packages/web-modules/<cluster>/<cluster>-<role>/
|
|
67
|
-
<cluster>-<role>.yaml # SoT
|
|
67
|
+
<cluster>-<role>.yaml # SoT, slots only, no props/events
|
|
68
68
|
<cluster>-<role>.a2ui.json # GENERATED
|
|
69
69
|
<cluster>-<role>.html # demo shell
|
|
70
70
|
<cluster>-<role>.examples.html # composition snippet + slot vocabulary
|
|
@@ -81,7 +81,7 @@ NO `.js`, NO own `.css` for CSS-only stubs. They render as unknown `HTMLElement`
|
|
|
81
81
|
| **Reflected string** `[name="..."]` `[shortcut="cmd+k\|ctrl+k\|both"]` | Author-supplied configuration that other code reads |
|
|
82
82
|
| **Property only (no reflect)** | Internal state, perf-sensitive, or values too varied to enumerate |
|
|
83
83
|
|
|
84
|
-
**Multi-word camelCase props** map to kebab-case attributes via `attribute: '...'` (NOT `attr
|
|
84
|
+
**Multi-word camelCase props** map to kebab-case attributes via `attribute: '...'` (NOT `attr:`, see Pitfall #1):
|
|
85
85
|
|
|
86
86
|
```js
|
|
87
87
|
static properties = {
|
|
@@ -98,13 +98,13 @@ Each cluster's bespoke children get styled via a single bridge file:
|
|
|
98
98
|
packages/web-modules/<cluster>/<cluster>-shell/css/<cluster>-shell.bespoke.css
|
|
99
99
|
```
|
|
100
100
|
|
|
101
|
-
Imported **last** in `<cluster>-shell.css` so its rules layer over the legacy CSS without modification. Don't expand `:is(legacy, slot-ui, ...)` selectors throughout the legacy CSS
|
|
101
|
+
Imported **last** in `<cluster>-shell.css` so its rules layer over the legacy CSS without modification. Don't expand `:is(legacy, slot-ui, ...)` selectors throughout the legacy CSS, that's invasive and makes Phase 3 (legacy removal) harder.
|
|
102
102
|
|
|
103
103
|
## Step-by-step procedure
|
|
104
104
|
|
|
105
105
|
### 1. Audit existing shell
|
|
106
106
|
|
|
107
|
-
Read the host's `.js` file. Identify the 4 concerns + which are already in primitive sub-elements (e.g., `<pane-ui resizable>` already owns pane resize
|
|
107
|
+
Read the host's `.js` file. Identify the 4 concerns + which are already in primitive sub-elements (e.g., `<pane-ui resizable>` already owns pane resize, don't duplicate).
|
|
108
108
|
|
|
109
109
|
```bash
|
|
110
110
|
wc -l packages/web-modules/<cluster>/<cluster>-shell/<cluster>-shell.js
|
|
@@ -129,7 +129,7 @@ class ChildName extends UIElement {
|
|
|
129
129
|
camelProp: { type: String, default: '', reflect: true, attribute: 'kebab-prop' },
|
|
130
130
|
};
|
|
131
131
|
|
|
132
|
-
static template = () => null; // stamp nothing
|
|
132
|
+
static template = () => null; // stamp nothing, author owns DOM
|
|
133
133
|
|
|
134
134
|
#cleanups = [];
|
|
135
135
|
|
|
@@ -152,7 +152,7 @@ customElements.define('cluster-role', ChildName);
|
|
|
152
152
|
export { ChildName };
|
|
153
153
|
```
|
|
154
154
|
|
|
155
|
-
**The "cleanup-closure pile" pattern** (`#cleanups: [() => …, () => …]`) scales to N drag handles
|
|
155
|
+
**The "cleanup-closure pile" pattern** (`#cleanups: [() => …, () => …]`) scales to N drag handles, each handle's setup pushes a closure that removes its specific listeners and undoes any body-level pointer-events mutation. `disconnected()` just drains the pile.
|
|
156
156
|
|
|
157
157
|
The path to `core/element.js` from `packages/web-modules/<cluster>/<cluster>-<role>/` is **`../../../web-components/core/element.js`** (3 levels up).
|
|
158
158
|
|
|
@@ -163,18 +163,18 @@ Minimum 8-10 tests per JS-bearing child covering: registration, default reflecte
|
|
|
163
163
|
**Critical test-setup pitfalls**:
|
|
164
164
|
|
|
165
165
|
```js
|
|
166
|
-
// happy-dom returns 0 from getBoundingClientRect
|
|
166
|
+
// happy-dom returns 0 from getBoundingClientRect, patch in beforeEach
|
|
167
167
|
HTMLElement.prototype.getBoundingClientRect = function () {
|
|
168
168
|
const w = parseFloat(this.style?.width) || 240;
|
|
169
169
|
return { width: w, height: 600, top: 0, left: 0, right: w, bottom: 600, x: 0, y: 0 };
|
|
170
170
|
};
|
|
171
171
|
|
|
172
|
-
// happy-dom doesn't ship ResizeObserver
|
|
172
|
+
// happy-dom doesn't ship ResizeObserver, stub it
|
|
173
173
|
globalThis.ResizeObserver = class {
|
|
174
174
|
observe() {} unobserve() {} disconnect() {}
|
|
175
175
|
};
|
|
176
176
|
|
|
177
|
-
// happy-dom's <dialog> is partial
|
|
177
|
+
// happy-dom's <dialog> is partial, polyfill showModal / close / open getter
|
|
178
178
|
function patchDialogPolyfill(dialog) {
|
|
179
179
|
let isOpen = false;
|
|
180
180
|
Object.defineProperty(dialog, 'open', {
|
|
@@ -189,7 +189,7 @@ function patchDialogPolyfill(dialog) {
|
|
|
189
189
|
|
|
190
190
|
For each bespoke tag, declare structural CSS in `<cluster>-shell.bespoke.css`. Reuse tokens from the existing `<cluster>-shell.tokens.css`. Don't introduce new tokens unless the structural concern is genuinely new.
|
|
191
191
|
|
|
192
|
-
Shells follow the standard two-block `@scope` + L3 token + zero-raw-color rules from [css-patterns.md](css-patterns.md) and [token-contract.md](token-contract.md)
|
|
192
|
+
Shells follow the standard two-block `@scope` + L3 token + zero-raw-color rules from [css-patterns.md](css-patterns.md) and [token-contract.md](token-contract.md), the shell tag stem prefixes its own tokens (`--admin-shell-sidebar-w`, `--chat-shell-header-h`).
|
|
193
193
|
|
|
194
194
|
### 6. Refactor the host to coordinate
|
|
195
195
|
|
|
@@ -198,7 +198,7 @@ The host loses behavior it used to centralize. It now reflects host-level config
|
|
|
198
198
|
**Once the cluster reaches Phase 3** (legacy deprecated, ADR-0024 pattern), the host queries ONLY the bespoke children:
|
|
199
199
|
|
|
200
200
|
```js
|
|
201
|
-
// Bespoke-only (post-Phase-3
|
|
201
|
+
// Bespoke-only (post-Phase-3, current state for admin/chat/editor):
|
|
202
202
|
#findSidebar(name) {
|
|
203
203
|
return this.querySelector(`<cluster>-sidebar[slot="${name}"], <cluster>-sidebar[name="${name}"]`);
|
|
204
204
|
}
|
|
@@ -212,7 +212,7 @@ btn.addEventListener('click', () => {
|
|
|
212
212
|
**During the introduction window** (1–2 patch releases before deprecation), the host reads both shapes via `:is()` selectors with a typeof-check + legacyToggle fallback:
|
|
213
213
|
|
|
214
214
|
```js
|
|
215
|
-
// Compat window (Phase 1 + Phase 2
|
|
215
|
+
// Compat window (Phase 1 + Phase 2, pre-deprecation):
|
|
216
216
|
static SIDEBAR_SEL =
|
|
217
217
|
':is(<cluster>-sidebar[slot="leading"], <cluster>-sidebar[slot="trailing"], ' +
|
|
218
218
|
'[data-<cluster>-sidebar], aside-ui[slot="leading"], aside-ui[slot="trailing"])';
|
|
@@ -232,14 +232,14 @@ btn.addEventListener('click', () => {
|
|
|
232
232
|
export { ClusterShell } from './cluster-shell/cluster-shell.js';
|
|
233
233
|
export { ClusterSidebar } from './cluster-sidebar/cluster-sidebar.js';
|
|
234
234
|
export { ClusterCommand } from './cluster-command/cluster-command.js';
|
|
235
|
-
// CSS-only stubs don't need exports
|
|
235
|
+
// CSS-only stubs don't need exports, they don't register customElements
|
|
236
236
|
```
|
|
237
237
|
|
|
238
238
|
### 8. Run the build + verify gates
|
|
239
239
|
|
|
240
240
|
```bash
|
|
241
241
|
node scripts/build/components.mjs # picks up new yamls, generates .a2ui.json
|
|
242
|
-
node scripts/build/components.mjs --verify # must say "clean
|
|
242
|
+
node scripts/build/components.mjs --verify # must say "clean, N files up-to-date"
|
|
243
243
|
npm run check:lockstep
|
|
244
244
|
npm run verify:traits
|
|
245
245
|
npm run smoke:engines
|
|
@@ -250,7 +250,7 @@ npx vitest run packages/web-modules/<cluster>/<cluster>-<role>/<cluster>-<role>.
|
|
|
250
250
|
|
|
251
251
|
### 9. Update the host's `examples.html`
|
|
252
252
|
|
|
253
|
-
Add a "Basic shape (bespoke
|
|
253
|
+
Add a "Basic shape (bespoke, recommended)" section alongside the existing legacy section. Show the full bespoke composition. Add a "State as attribute" section with CSS `:has()` examples + JS API examples + ADR-0023 cross-reference.
|
|
254
254
|
|
|
255
255
|
### 10. Update sibling demo pages
|
|
256
256
|
|
|
@@ -258,7 +258,7 @@ Add a "Family pattern (forward-looking)" section to the shell's `<X>-shell.examp
|
|
|
258
258
|
|
|
259
259
|
### 11. Sweep verification (post-migration grep audit)
|
|
260
260
|
|
|
261
|
-
After landing a vocabulary migration or deprecation, run a comprehensive grep audit across **all extensions** for the legacy pattern set. Markup-only commits frequently leave **CSS selectors and JS comments** referencing the old vocabulary
|
|
261
|
+
After landing a vocabulary migration or deprecation, run a comprehensive grep audit across **all extensions** for the legacy pattern set. Markup-only commits frequently leave **CSS selectors and JS comments** referencing the old vocabulary, they're in different files from the markup, so a markup-only commit looks complete but leaves drift.
|
|
262
262
|
|
|
263
263
|
```bash
|
|
264
264
|
LEGACY_PATTERNS=(
|
|
@@ -288,7 +288,7 @@ This step was added after a sweep revealed apps with leftover `adia-editor-ui` +
|
|
|
288
288
|
|
|
289
289
|
After an apps/playgrounds/catalog reorg (ADR-0026) surfaced 4 categories that survived a full-path substitution sweep. **Full-path grep is necessary but insufficient.** Add these to any vocabulary migration's verification:
|
|
290
290
|
|
|
291
|
-
##### Category A
|
|
291
|
+
##### Category A, Bare-name prose mentions in narrative docs
|
|
292
292
|
|
|
293
293
|
```bash
|
|
294
294
|
LEGACY_NAMES=( 'old-folder-name' 'old-thing-name' )
|
|
@@ -300,7 +300,7 @@ for n in "${LEGACY_NAMES[@]}"; do
|
|
|
300
300
|
done
|
|
301
301
|
```
|
|
302
302
|
|
|
303
|
-
##### Category B
|
|
303
|
+
##### Category B, Skill directory names that follow folder-name convention
|
|
304
304
|
|
|
305
305
|
```bash
|
|
306
306
|
find . -type d -name '*-expert' -not -path '*/node_modules/*' \
|
|
@@ -313,12 +313,12 @@ for skill in $(find . -name 'SKILL.md' -not -path '*/node_modules/*'); do
|
|
|
313
313
|
done
|
|
314
314
|
```
|
|
315
315
|
|
|
316
|
-
##### Category C
|
|
316
|
+
##### Category C, JSON metadata fields at filename granularity
|
|
317
317
|
|
|
318
318
|
Critical: full-path sweeps catch directory moves but miss **file renames within moved directories**.
|
|
319
319
|
|
|
320
320
|
```bash
|
|
321
|
-
# Corpus chunks, sitemaps, catalog manifests
|
|
321
|
+
# Corpus chunks, sitemaps, catalog manifests, any JSON with file paths.
|
|
322
322
|
LEGACY_FILENAMES=( 'old-name.html' 'old-name.contents.html' 'old-name.contents.js' )
|
|
323
323
|
for f in "${LEGACY_FILENAMES[@]}"; do
|
|
324
324
|
grep -rn "$f" --include='*.json' \
|
|
@@ -326,9 +326,9 @@ for f in "${LEGACY_FILENAMES[@]}"; do
|
|
|
326
326
|
done
|
|
327
327
|
```
|
|
328
328
|
|
|
329
|
-
This is the **highest-impact category
|
|
329
|
+
This is the **highest-impact category**, corpus chunks with stale `source` or `page` fields cause silent harvest miss on the next rebuild (the chunk loads but won't be re-harvestable; no error).
|
|
330
330
|
|
|
331
|
-
##### Category D
|
|
331
|
+
##### Category D, Inventory tables in cross-cutting docs
|
|
332
332
|
|
|
333
333
|
```bash
|
|
334
334
|
grep -ln 'old-name' README.md AGENTS.md docs/ops/ROADMAP.md .claude/docs/specs/INDEX.md
|
|
@@ -341,7 +341,7 @@ grep -rln 'OLD_NAME' . --include='*.md' --include='*.json' \
|
|
|
341
341
|
| sort > /tmp/pre-rename-refs.txt
|
|
342
342
|
```
|
|
343
343
|
|
|
344
|
-
After the rename + path sweep, take a fresh snapshot and diff
|
|
344
|
+
After the rename + path sweep, take a fresh snapshot and diff, anything in the post-snapshot is a stale ref to investigate.
|
|
345
345
|
|
|
346
346
|
**ADR-0026 case study**: a corpus chunk's `page` field pointed at the pre-rename `app-shell.contents.html` inside the post-rename `/playgrounds/admin-shell/app/` directory. Full-path sweep caught the directory rename but missed the filename mismatch within it. Would have caused silent harvest miss on the next rebuild.
|
|
347
347
|
|
|
@@ -355,11 +355,11 @@ After the rename + path sweep, take a fresh snapshot and diff — anything in th
|
|
|
355
355
|
| Public API present + returns expected | per-child test file |
|
|
356
356
|
| Event dispatch | per-child test file |
|
|
357
357
|
| Cleanup on disconnect | per-child test file |
|
|
358
|
-
| Backwards-compat
|
|
358
|
+
| Backwards-compat, legacy markup still works | manual visual smoke against `apps/<X>-shell/` or `site/` |
|
|
359
359
|
|
|
360
360
|
## Trigger-attribute conventions (bespoke-compatible)
|
|
361
361
|
|
|
362
|
-
Author-controlled action buttons that the shell wires up follow a consistent convention. These are TRIGGER attributes (on buttons), not state attributes (on shell children)
|
|
362
|
+
Author-controlled action buttons that the shell wires up follow a consistent convention. These are TRIGGER attributes (on buttons), not state attributes (on shell children), they still work in the bespoke world:
|
|
363
363
|
|
|
364
364
|
```html
|
|
365
365
|
<button-ui icon="list" data-sidebar-toggle="leading"></button-ui>
|
|
@@ -369,19 +369,19 @@ The shell finds these via `querySelectorAll('[data-sidebar-toggle]')` and binds
|
|
|
369
369
|
|
|
370
370
|
Other trigger attributes:
|
|
371
371
|
|
|
372
|
-
- `[data-command-trigger]
|
|
373
|
-
- `[data-toolbar-action="<name>"]
|
|
372
|
+
- `[data-command-trigger]`, opens `<admin-command>` via `.show()`
|
|
373
|
+
- `[data-toolbar-action="<name>"]`, buttons inside `<editor-toolbar>` that bubble `toolbar-action` events
|
|
374
374
|
|
|
375
375
|
## Persistence (localStorage namespacing)
|
|
376
376
|
|
|
377
|
-
Sidebar-collapsed state, pane widths, drawer-open state
|
|
377
|
+
Sidebar-collapsed state, pane widths, drawer-open state, anything the user customizes, persists in `localStorage`, keyed by the cluster + region:
|
|
378
378
|
|
|
379
379
|
```js
|
|
380
380
|
const KEY = `adia-sidebar:${this.name}:width`; // adia-sidebar:leading:width
|
|
381
381
|
localStorage.setItem(KEY, String(width));
|
|
382
382
|
```
|
|
383
383
|
|
|
384
|
-
Read on `connected()`, write on resize/toggle. Always wrap reads in try/catch
|
|
384
|
+
Read on `connected()`, write on resize/toggle. Always wrap reads in try/catch, quota errors and disabled-storage modes happen.
|
|
385
385
|
|
|
386
386
|
```js
|
|
387
387
|
#restoreWidth() {
|
|
@@ -396,11 +396,11 @@ Read on `connected()`, write on resize/toggle. Always wrap reads in try/catch
|
|
|
396
396
|
|
|
397
397
|
## Document-level listeners belong to the shell, not the children
|
|
398
398
|
|
|
399
|
-
`Cmd+K` for the command palette, `Esc` for closing a drawer, `?` for a shortcuts overlay
|
|
399
|
+
`Cmd+K` for the command palette, `Esc` for closing a drawer, `?` for a shortcuts overlay, these listen on `document`, not on the shell element. The shell binds them in `connected()` with `addEventListener` on `document`, removes them in `disconnected()`. NEVER attach `document`-level listeners from a child component (a button-ui etc.), they'd persist after the child unmounts.
|
|
400
400
|
|
|
401
401
|
## Custom events for downstream consumers
|
|
402
402
|
|
|
403
|
-
Pane-resize, breakpoint-change, sidebar-collapse
|
|
403
|
+
Pane-resize, breakpoint-change, sidebar-collapse, fire `CustomEvent`s that bubble through the shell so consumers can react:
|
|
404
404
|
|
|
405
405
|
```js
|
|
406
406
|
this.dispatchEvent(new CustomEvent('sidebar-resize', {
|
|
@@ -414,7 +414,7 @@ Consumers (CodeMirror layout, canvas redraw, dependent UI) listen on the shell o
|
|
|
414
414
|
|
|
415
415
|
## Pitfalls
|
|
416
416
|
|
|
417
|
-
1. **`attr:` vs `attribute:`.** The framework uses `attribute: '...'` for camelCase to kebab-case mapping. `attr:` is silently ignored
|
|
417
|
+
1. **`attr:` vs `attribute:`.** The framework uses `attribute: '...'` for camelCase to kebab-case mapping. `attr:` is silently ignored, your custom element won't react to the kebab-case attribute. Always `attribute:`. Every JS-bearing bespoke child has at least one camelCase prop (`minWidth`, `noShortcut`, `proxyUrl`, etc.); the wrong key fails silently.
|
|
418
418
|
|
|
419
419
|
2. **Path depth in test imports.** From `packages/web-modules/<cluster>/<cluster>-<role>/`, `core/element.js` is **3 levels up** (`../../../web-components/core/element.js`), not 2.
|
|
420
420
|
|
|
@@ -424,27 +424,27 @@ Consumers (CodeMirror layout, canvas redraw, dependent UI) listen on the shell o
|
|
|
424
424
|
|
|
425
425
|
5. **Spy timing for synchronous custom-element lifecycle.** `vi.spyOn(document, 'addEventListener')` set BEFORE `mount()` should still catch listeners added in `connected()`, but happy-dom's customElements lifecycle quirks sometimes break this. When in doubt, test the **behavior** (does Cmd+K toggle?) instead of the **mechanism** (was a listener added?).
|
|
426
426
|
|
|
427
|
-
6. **Don't expand legacy `:is()` selectors.** The temptation when introducing a new cluster is to add `, <X-sidebar>[slot=leading]` to every existing `:is([data-X-sidebar], aside-ui[slot=leading])` selector in the legacy CSS. Resist. Use a new bespoke.css bridge file instead
|
|
427
|
+
6. **Don't expand legacy `:is()` selectors.** The temptation when introducing a new cluster is to add `, <X-sidebar>[slot=leading]` to every existing `:is([data-X-sidebar], aside-ui[slot=leading])` selector in the legacy CSS. Resist. Use a new bespoke.css bridge file instead, easier to drop at Phase 3 deprecation. (admin/chat/editor deprecation pass collapsed all `:is(legacy, bespoke)` lifts to bespoke-only in 6 layered CSS files via a single regex pass; would have been 100x more work if lifts were sprinkled inline.)
|
|
428
428
|
|
|
429
|
-
7. **Host LOC will grow during the compat window, then shrink at deprecation.** When introducing a new cluster's bespoke family, both code paths coexist in the host. Expected (admin-shell hit ~305 LOC during introduction). At deprecation (Phase 3
|
|
429
|
+
7. **Host LOC will grow during the compat window, then shrink at deprecation.** When introducing a new cluster's bespoke family, both code paths coexist in the host. Expected (admin-shell hit ~305 LOC during introduction). At deprecation (Phase 3, see ADR-0024 for the canonical playbook), the host shrinks dramatically: admin-shell dropped to ~87 LOC (−71%). **Don't try to "consolidate" before deprecation lands**: the dual paths are intentional during the migration window.
|
|
430
430
|
|
|
431
|
-
8. **Sibling cluster siblings.** `web-modules/shell/admin-shell/` lives next to `web-modules/shell/admin-sidebar/` (cluster-namespace siblings). For chat
|
|
431
|
+
8. **Sibling cluster siblings.** `web-modules/shell/admin-shell/` lives next to `web-modules/shell/admin-sidebar/` (cluster-namespace siblings). For chat, `web-modules/chat/chat-shell/` next to `web-modules/chat/chat-thread/`. The directory layout makes the cluster family visible at `ls`.
|
|
432
432
|
|
|
433
433
|
9. **localStorage namespace per cluster.** Each cluster's persisted state must use a cluster-distinct key prefix. Without distinct prefixes, two sidebars sharing the same slot value (`leading`) on different shells would clobber each other. Verify with a test that checks both namespaces are isolated.
|
|
434
434
|
|
|
435
|
-
10. **Bespoke event names ≠ legacy event names.** When a bespoke wrapper forwards an event from an inner primitive, give it a NEW name (e.g. `composer-submit` from `<chat-composer>` wrapping the inner `<chat-input-ui>`'s `submit` event). If the wrapper re-emits `submit`, the host's listener fires twice (once from the bubble, once from the re-emit). Lesson
|
|
435
|
+
10. **Bespoke event names ≠ legacy event names.** When a bespoke wrapper forwards an event from an inner primitive, give it a NEW name (e.g. `composer-submit` from `<chat-composer>` wrapping the inner `<chat-input-ui>`'s `submit` event). If the wrapper re-emits `submit`, the host's listener fires twice (once from the bubble, once from the re-emit). Lesson, pick a bespoke event name (`<wrapper>-<concept>` like `composer-submit`, `sidebar-toggle`, `command-select`) and document the legacy→bespoke mapping in the host's `connected()`.
|
|
436
436
|
|
|
437
|
-
11. **Delegate to primitives when they already own the concern, but don't lose state-as-attribute.** When a bespoke child wraps a primitive that already does the physical work (e.g. `<editor-sidebar>` wrapping `<pane-ui resizable>`), the bespoke tier still owns: cluster-namespace ID, state-as-attribute (`[collapsed]` reflected via `ResizeObserver` on inner pane), localStorage persistence, public API. Don't reimplement what the primitive does
|
|
437
|
+
11. **Delegate to primitives when they already own the concern, but don't lose state-as-attribute.** When a bespoke child wraps a primitive that already does the physical work (e.g. `<editor-sidebar>` wrapping `<pane-ui resizable>`), the bespoke tier still owns: cluster-namespace ID, state-as-attribute (`[collapsed]` reflected via `ResizeObserver` on inner pane), localStorage persistence, public API. Don't reimplement what the primitive does, but don't skip the bespoke tier just because the primitive exists. Principles 4 ("each child owns one concern") + 3 ("cluster namespace") combine here, the bespoke child owns the _cluster-specific framing_ of the primitive's work.
|
|
438
438
|
|
|
439
439
|
12. **Persist BEFORE snapping, not after.** When `.collapse()` is called on a sidebar, the persisted width must capture the pre-collapse expanded width so `.expand()` can restore it. If you persist after setting `style.width = SNAP_THRESHOLD`, you've overwritten storage with the collapsed value and `.expand()` falls through to its default. Pattern: `if (!this.collapsed) this.#persistWidth();` BEFORE the snap. Caught in editor-sidebar via the `expand() restores from stored width or defaults to 240` test.
|
|
440
440
|
|
|
441
|
-
13. **Stamping default content "to be helpful."** A shell that injects a default header / nav / footer commits the page author to the shell's visual language. They will copy-paste markup INTO the shell to override; you've now created two sources of truth. Stamp nothing (`static template = () => null`). The exception: a shell MAY append a tiny structural affordance the author can't reasonably write themselves
|
|
441
|
+
13. **Stamping default content "to be helpful."** A shell that injects a default header / nav / footer commits the page author to the shell's visual language. They will copy-paste markup INTO the shell to override; you've now created two sources of truth. Stamp nothing (`static template = () => null`). The exception: a shell MAY append a tiny structural affordance the author can't reasonably write themselves, a resize-handle thumb, for instance. Keep it minimal and clean it up in `disconnected()`.
|
|
442
442
|
|
|
443
443
|
14. **Document-level keydown handlers on child components.** If a child wants to react to global keys, it should listen for an event the SHELL emits, not bind a document-level listener itself. Otherwise the child outlives its hosting shell, leaks its listener, and starts reacting to keys in surfaces it has no business seeing.
|
|
444
444
|
|
|
445
|
-
15. **ResizeObserver vs media queries.** Shells respond to _their own_ width, not the viewport. When the shell collapses (because main content gets crowded), the _shell instance_ is narrow
|
|
445
|
+
15. **ResizeObserver vs media queries.** Shells respond to _their own_ width, not the viewport. When the shell collapses (because main content gets crowded), the _shell instance_ is narrow, but the viewport may still be wide. Use a `ResizeObserver` on `this` (or on a bespoke child region) to compute breakpoints, and reflect the result as a reflected attribute the CSS can match. Container queries are a complementary tool; ResizeObserver fits when you need _imperative_ state (e.g. moving an element between inline and dropdown placement based on width).
|
|
446
446
|
|
|
447
|
-
## Examples
|
|
447
|
+
## Examples, 4 canonical clusters
|
|
448
448
|
|
|
449
449
|
### admin cluster (canonical reference)
|
|
450
450
|
|
|
@@ -463,45 +463,45 @@ kept in sync with `site/index.html`'s live example rather than restated here.
|
|
|
463
463
|
|
|
464
464
|
### chat cluster (replicated pattern)
|
|
465
465
|
|
|
466
|
-
- **3 JS-bearing children
|
|
467
|
-
- **3 CSS-only structural children
|
|
468
|
-
- **CSS bridge
|
|
469
|
-
- **Replication notes
|
|
466
|
+
- **3 JS-bearing children**, `<chat-shell>` (host coordinator), `<chat-thread>` (scroll+streaming+empty), `<chat-composer>` (input wrapper+disabled propagation), `<chat-sidebar>` (mirrors admin-sidebar geometry)
|
|
467
|
+
- **3 CSS-only structural children**, `<chat-header>`, `<chat-status>`, `<chat-empty>`
|
|
468
|
+
- **CSS bridge**, `packages/web-modules/chat/chat-shell/css/chat-shell.bespoke.css`
|
|
469
|
+
- **Replication notes**, `chat-sidebar.js` was a near-copy of `admin-sidebar.js` with mechanical `s/admin/chat/g` + cluster-distinct localStorage prefix. The thread and composer required new code because their concerns (scroll-to-bottom, `[streaming]` reflection, `composer-submit` forwarding) are chat-specific. **Pattern mechanically usable for clusters with structural-mirror needs (sidebars) + adapted for cluster-specific concerns.**
|
|
470
470
|
|
|
471
|
-
### editor cluster (third replication
|
|
471
|
+
### editor cluster (third replication, confirms convention is locked in)
|
|
472
472
|
|
|
473
|
-
- **3 JS-bearing children
|
|
474
|
-
- **2 CSS-only structural children
|
|
475
|
-
- **CSS bridge
|
|
476
|
-
- **Replication notes
|
|
477
|
-
1. `<pane-ui resizable>` already owns drag (delegation
|
|
473
|
+
- **3 JS-bearing children**, `<editor-shell>` (host with `[focus-mode]` reflected), `<editor-toolbar>` (`[full-screen]` reflected, click-bubble for `[data-toolbar-action]`), `<editor-canvas>` (`[empty]` + `[focused]` reflected, zoom API), `<editor-sidebar>` (wraps `<pane-ui resizable>` rather than reimplementing drag, see Pitfall #11)
|
|
474
|
+
- **2 CSS-only structural children**, `<editor-statusbar>`, `<editor-canvas-empty>`
|
|
475
|
+
- **CSS bridge**, `packages/web-modules/editor/editor-shell/css/editor-shell.bespoke.css`
|
|
476
|
+
- **Replication notes**, Editor cluster has the **smallest bespoke family** of the three (5 children vs 9 admin / 7 chat) because:
|
|
477
|
+
1. `<pane-ui resizable>` already owns drag (delegation, Pitfall #11)
|
|
478
478
|
2. No command palette (different interaction model than admin)
|
|
479
479
|
3. Toolbar + statusbar suffice for chrome bars (no separate header/status separation like chat)
|
|
480
480
|
- **Surfaces 2 new pitfalls** (#11 delegation, #12 persist-before-snap) caught at test time
|
|
481
|
-
- **Family pattern proven across 3 distinct shell archetypes
|
|
481
|
+
- **Family pattern proven across 3 distinct shell archetypes**, admin (productivity), chat (LLM streaming), editor (design tooling). Convention is now canonical.
|
|
482
482
|
|
|
483
|
-
### Phase 3 complete
|
|
483
|
+
### Phase 3 complete, legacy deprecation
|
|
484
484
|
|
|
485
485
|
ADR-0024 closes the ADR-0023 arc. All three shell hosts dropped their priority-chain reads of legacy `data-*` / `<aside-ui slot>` / `<dialog data-command>` / `<header>` / `<footer>` shapes. The bespoke vocabulary is now the ONLY recognized authoring shape.
|
|
486
486
|
|
|
487
487
|
**LOC payoff at deprecation:**
|
|
488
488
|
|
|
489
|
-
- `admin-shell.js`: ~305 → ~87 LOC (−71%)
|
|
489
|
+
- `admin-shell.js`: ~305 → ~87 LOC (−71%), host now does only mode reflection + attribute-forwarding
|
|
490
490
|
- `chat-shell.js`: simpler `connected()` (drops 4-way `||` chains)
|
|
491
491
|
- `editor-shell.js`: simpler `connected()` (drops 2-way `||` chains)
|
|
492
492
|
- CSS layered files (`admin-shell.sidebar.css`, `chat-shell.empty.css`, etc.) all `:is(legacy, bespoke)` lifts collapsed to bespoke-only
|
|
493
493
|
|
|
494
|
-
**Lesson from deprecation:** the backwards-compat priority-chain reads were the right transition mechanism, but they accumulated 6 distinct private methods + 4 private fields + dual event-name listeners in `<admin-shell>` alone. **Keep the compat window short
|
|
494
|
+
**Lesson from deprecation:** the backwards-compat priority-chain reads were the right transition mechanism, but they accumulated 6 distinct private methods + 4 private fields + dual event-name listeners in `<admin-shell>` alone. **Keep the compat window short**, ~9 days was enough time to migrate all 6 consumers + prove the pattern via smoke probe, and avoiding longer kept the host code from rotting under the dual-shape burden.
|
|
495
495
|
|
|
496
|
-
### simple cluster (4th replication
|
|
496
|
+
### simple cluster (4th replication, pattern compounds)
|
|
497
497
|
|
|
498
498
|
The 4th cluster proves the pattern generalizes across **four distinct archetypes** now: admin (productivity), chat (LLM streaming), editor (design tooling), simple (minimal page). 23 bespoke shell-tier children total across the 4 clusters.
|
|
499
499
|
|
|
500
500
|
**Family:**
|
|
501
501
|
|
|
502
|
-
- `<simple-shell>` (JS-bearing host)
|
|
503
|
-
- `<simple-content>` (CSS-only)
|
|
504
|
-
- `<simple-hero>` (CSS-only)
|
|
502
|
+
- `<simple-shell>` (JS-bearing host), 2 reflected attrs: `[centered]` (vertical-center content), `[full-bleed]` (drops max-width)
|
|
503
|
+
- `<simple-content>` (CSS-only), article-body container with token-correct vertical rhythm
|
|
504
|
+
- `<simple-hero>` (CSS-only), optional top strip with 3 named slots: `heading`, `lede`, `actions`
|
|
505
505
|
|
|
506
506
|
**Deliberately minimal**: 1 host + 2 CSS-only children. No sidebars, no chrome bars, no command palette. Use cases: marketing splashes, error pages (404 / 500 / maintenance), thank-you pages, single-card flows (sign-in, password reset).
|
|
507
507
|
|
|
@@ -514,17 +514,17 @@ The 4th cluster proves the pattern generalizes across **four distinct archetypes
|
|
|
514
514
|
| editor (3rd) | ~2 hours | Confirms convention is canonical; introduces delegation (wraps `<pane-ui>`) |
|
|
515
515
|
| simple (4th) | **~30 minutes** | Mechanical follow-template; smallest cluster |
|
|
516
516
|
|
|
517
|
-
**Lesson**: each successive cluster is dramatically faster than the previous. The 4th cluster used this reference as a checklist + lifted demo HTMLs from the 3rd cluster + ran tests once at the end. **Skills compound when they're maintained.** If you're considering a 5th cluster (e.g., docs-shell
|
|
517
|
+
**Lesson**: each successive cluster is dramatically faster than the previous. The 4th cluster used this reference as a checklist + lifted demo HTMLs from the 3rd cluster + ran tests once at the end. **Skills compound when they're maintained.** If you're considering a 5th cluster (e.g., docs-shell, but see the decision-log note below about deferring it), expect ~20 minutes for a thin family or ~45 minutes for a richer one. The pattern is mechanically replicable.
|
|
518
518
|
|
|
519
519
|
**Decision-log note on docs-shell (deferred):**
|
|
520
520
|
|
|
521
|
-
A 5th cluster `docs-shell` was considered for documentation pages (markdown rendering, TOC right-rail, frontmatter strip). **Deferred** because `<admin-shell>` already serves the docs surface at `site/index.html
|
|
521
|
+
A 5th cluster `docs-shell` was considered for documentation pages (markdown rendering, TOC right-rail, frontmatter strip). **Deferred** because `<admin-shell>` already serves the docs surface at `site/index.html`, the only differentiating concern (TOC right-rail) is better served by a `<docs-toc>` element placed in `<admin-shell slot="trailing">` than by a competing shell. Cluster proliferation is a real anti-pattern; introduce new clusters only when a distinct archetype emerges that admin/chat/editor/simple don't cover.
|
|
522
522
|
|
|
523
523
|
## Legacy `data-*` shape (retired)
|
|
524
524
|
|
|
525
525
|
The legacy shape used `data-*` region attributes (`[data-canvas]`, `<aside-ui slot="leading">`, `<dialog data-command>`) and CSS selectors that matched those data-attributes. **Retired per ADR-0024.**
|
|
526
526
|
|
|
527
|
-
Pedagogically the design philosophy was identical to the bespoke shape
|
|
527
|
+
Pedagogically the design philosophy was identical to the bespoke shape, behavior-only shells, author-owned DOM, persistence keyed by region, ResizeObserver for breakpoint signals, document-level listeners owned by the shell. The bespoke shape moves all of those concerns onto custom elements with reflected-attribute APIs instead of data-attribute sniffing. See ADR-0024 for the full deprecation rationale and the canonical "introduce → migrate → deprecate" timing.
|
|
528
528
|
|
|
529
529
|
When you encounter a legacy reference in old documentation or commit history, the migration map is:
|
|
530
530
|
|
|
@@ -535,7 +535,7 @@ When you encounter a legacy reference in old documentation or commit history, th
|
|
|
535
535
|
| `[data-canvas]` inside `<adia-editor-ui>` | `<editor-canvas>` inside `<editor-shell>` |
|
|
536
536
|
| `[data-chat-messages]` / `[data-chat-input]` / `[data-chat-empty]` | `<chat-thread>` / `<chat-composer>` / `<chat-empty>` |
|
|
537
537
|
| `[data-pane-side]` / `[data-pane-grow]` | `<editor-sidebar>` wrapping `<pane-ui resizable>` |
|
|
538
|
-
| `data-app-shell-toggle` (trigger) | unchanged
|
|
538
|
+
| `data-app-shell-toggle` (trigger) | unchanged, trigger attributes are still data-\* |
|
|
539
539
|
|
|
540
540
|
## After implementation
|
|
541
541
|
|
|
@@ -546,18 +546,18 @@ When you encounter a legacy reference in old documentation or commit history, th
|
|
|
546
546
|
## Anti-patterns specific to shells (deduplicated)
|
|
547
547
|
|
|
548
548
|
- **Stamping default content "to be helpful."** Stamp nothing (Pitfall #13).
|
|
549
|
-
- **Hand-rolling toggle behavior in the page** instead of using `data-<shell>-toggle`. The shell wires localStorage persistence + the ResizeObserver breakpoint logic; rolling your own re-derives both badly. If the shell's trigger-attribute convention doesn't fit, the shell is missing a feature
|
|
549
|
+
- **Hand-rolling toggle behavior in the page** instead of using `data-<shell>-toggle`. The shell wires localStorage persistence + the ResizeObserver breakpoint logic; rolling your own re-derives both badly. If the shell's trigger-attribute convention doesn't fit, the shell is missing a feature, request it, don't work around it.
|
|
550
550
|
- **Document-level keydown handlers on child components.** Pitfall #14.
|
|
551
551
|
- **Persisting state without a cluster-scoped key prefix.** Pitfall #9.
|
|
552
|
-
- **Stamping invasive `:is(legacy, bespoke)` lifts in legacy CSS.** Pitfall #6
|
|
552
|
+
- **Stamping invasive `:is(legacy, bespoke)` lifts in legacy CSS.** Pitfall #6, use a new bespoke.css bridge file instead.
|
|
553
553
|
|
|
554
554
|
## Cross-references
|
|
555
555
|
|
|
556
|
-
- [authoring-cycle.md](authoring-cycle.md)
|
|
557
|
-
- [api-contract.md](api-contract.md)
|
|
558
|
-
- [css-patterns.md](css-patterns.md)
|
|
559
|
-
- [lifecycle-patterns.md](lifecycle-patterns.md)
|
|
560
|
-
- [token-contract.md](token-contract.md)
|
|
561
|
-
- [module-promotion.md](module-promotion.md)
|
|
562
|
-
- ADR-0023 / ADR-0024 / ADR-0015
|
|
563
|
-
- the **adia-factory** plugin
|
|
556
|
+
- [authoring-cycle.md](authoring-cycle.md), general 5-step authoring procedure; shell-specific rules layer on top
|
|
557
|
+
- [api-contract.md](api-contract.md), prop naming, reflection policy
|
|
558
|
+
- [css-patterns.md](css-patterns.md), two-block `@scope`, variants vs modes; §Region elements never self-style (ADR-0105), a shell that hosts `<header-ui>`/`<section-ui>`/`<footer-ui>` region children (e.g. a bespoke `<X-header>` wrapping one) owns their `@scope` layout the same way `page-ui`/`card-ui`/`drawer-ui`/`modal-ui` do
|
|
559
|
+
- [lifecycle-patterns.md](lifecycle-patterns.md), teardown patterns; the cleanup-closure pile and document-listener rules above layer on top
|
|
560
|
+
- [token-contract.md](token-contract.md), zero-raw-color + L3 alias rules apply identically to shells
|
|
561
|
+
- [module-promotion.md](module-promotion.md), the _different_ activity of lifting a cross-cluster reusable element (theme panel, command palette) into a shared module
|
|
562
|
+
- ADR-0023 / ADR-0024 / ADR-0015, decision labels for the bespoke shell-tier convention, the legacy-shape retirement, and the `<cluster-thing>` naming rule (history lives in git + PR descriptions)
|
|
563
|
+
- the **adia-factory** plugin, the _consumer_ view: how to compose with these shells once they exist
|