@adia-ai/adia-ui-factory 0.2.2 → 0.2.4

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.
Files changed (95) hide show
  1. package/.claude-plugin/plugin.json +12 -3
  2. package/.mcp.json +1 -1
  3. package/CHANGELOG.md +12 -0
  4. package/README.md +24 -1
  5. package/bin/adia-scaffold +93 -13
  6. package/package.json +1 -1
  7. package/references/shell-embed.md +10 -0
  8. package/references/spa-architecture.md +7 -0
  9. package/skills/adia-ui-kit/CHANGELOG.md +41 -0
  10. package/skills/adia-ui-kit/SKILL.md +442 -0
  11. package/skills/adia-ui-kit/assets/figma-make/guidelines/Guidelines.md +87 -0
  12. package/skills/adia-ui-kit/assets/figma-make/guidelines/components.md +142 -0
  13. package/skills/adia-ui-kit/assets/figma-make/guidelines/styles.md +118 -0
  14. package/skills/adia-ui-kit/assets/figma-make/guidelines/tokens.md +120 -0
  15. package/skills/adia-ui-kit/assets/team-scaffold/archive-README.md +30 -0
  16. package/skills/adia-ui-kit/assets/team-scaffold/drafts-README.md +57 -0
  17. package/skills/adia-ui-kit/assets/team-scaffold/inbox-README.md +76 -0
  18. package/skills/adia-ui-kit/assets/team-scaffold/outbox-README.md +46 -0
  19. package/skills/adia-ui-kit/assets/team-scaffold/team-root.README.md +51 -0
  20. package/skills/adia-ui-kit/assets/team-scaffold/tickets-README.md +208 -0
  21. package/skills/adia-ui-kit/assets/team-scaffold/tickets-REGISTRY.md +81 -0
  22. package/skills/adia-ui-kit/assets/templates/AGENTS.template.md +128 -0
  23. package/skills/adia-ui-kit/assets/templates/CLAUDE.template.md +1 -0
  24. package/skills/adia-ui-kit/assets/templates/FEEDBACK-OMISSIONS-DEFENSE.template.md +150 -0
  25. package/skills/adia-ui-kit/assets/templates/FEEDBACK.template.md +213 -0
  26. package/skills/adia-ui-kit/assets/templates/RESPONSE.template.md +114 -0
  27. package/skills/adia-ui-kit/assets/templates/figma-make-guidelines.md +90 -0
  28. package/skills/adia-ui-kit/evals/adversarial-content-trust.json +83 -0
  29. package/skills/adia-ui-kit/evals/evals.json +55 -0
  30. package/skills/adia-ui-kit/evals/routing-corpus.json +121 -0
  31. package/skills/adia-ui-kit/evals/teach-routing-cases.json +92 -0
  32. package/skills/adia-ui-kit/references/capabilities.md +245 -0
  33. package/skills/adia-ui-kit/references/catalog-lookup.md +186 -0
  34. package/skills/adia-ui-kit/references/changelog-archive/CHANGELOG-v1.md +8 -0
  35. package/skills/adia-ui-kit/references/changelog-archive/CHANGELOG-v2.md +3585 -0
  36. package/skills/adia-ui-kit/references/changelog-archive/CHANGELOG-v3.md +1899 -0
  37. package/skills/adia-ui-kit/references/common-gotchas-consumer.md +522 -0
  38. package/skills/adia-ui-kit/references/component-literacy.md +291 -0
  39. package/skills/adia-ui-kit/references/composition.md +245 -0
  40. package/skills/adia-ui-kit/references/correction-loop.md +462 -0
  41. package/skills/adia-ui-kit/references/css-policy.md +343 -0
  42. package/skills/adia-ui-kit/references/decision-model.md +158 -0
  43. package/skills/adia-ui-kit/references/diagnostic-output.md +57 -0
  44. package/skills/adia-ui-kit/references/docs-catalog.md +239 -0
  45. package/skills/adia-ui-kit/references/exclusions.md +225 -0
  46. package/skills/adia-ui-kit/references/feedback-authoring.md +466 -0
  47. package/skills/adia-ui-kit/references/figma-make.md +244 -0
  48. package/skills/adia-ui-kit/references/flows-auth.md +307 -0
  49. package/skills/adia-ui-kit/references/flows-content.md +206 -0
  50. package/skills/adia-ui-kit/references/flows-data.md +348 -0
  51. package/skills/adia-ui-kit/references/flows-interaction.md +181 -0
  52. package/skills/adia-ui-kit/references/flows-shells.md +336 -0
  53. package/skills/adia-ui-kit/references/gap-detection.md +266 -0
  54. package/skills/adia-ui-kit/references/harness.md +284 -0
  55. package/skills/adia-ui-kit/references/loading-protocol.md +406 -0
  56. package/skills/adia-ui-kit/references/local-link.md +198 -0
  57. package/skills/adia-ui-kit/references/mcp.md +401 -0
  58. package/skills/adia-ui-kit/references/migration.md +116 -0
  59. package/skills/adia-ui-kit/references/mission.md +194 -0
  60. package/skills/adia-ui-kit/references/mode-routing.md +298 -0
  61. package/skills/adia-ui-kit/references/patterns-agent.md +223 -0
  62. package/skills/adia-ui-kit/references/patterns-data.md +1065 -0
  63. package/skills/adia-ui-kit/references/patterns-forms.md +223 -0
  64. package/skills/adia-ui-kit/references/patterns-layout.md +326 -0
  65. package/skills/adia-ui-kit/references/patterns-recipes.md +1416 -0
  66. package/skills/adia-ui-kit/references/patterns-shells.md +1097 -0
  67. package/skills/adia-ui-kit/references/patterns-traits.md +259 -0
  68. package/skills/adia-ui-kit/references/patterns-wiring.md +339 -0
  69. package/skills/adia-ui-kit/references/pev-rationale.md +137 -0
  70. package/skills/adia-ui-kit/references/reasoning-gate.md +146 -0
  71. package/skills/adia-ui-kit/references/reasoning-methodologies.md +112 -0
  72. package/skills/adia-ui-kit/references/recon.md +192 -0
  73. package/skills/adia-ui-kit/references/rendering-model.md +431 -0
  74. package/skills/adia-ui-kit/references/response-authoring.md +398 -0
  75. package/skills/adia-ui-kit/references/session-log-schema.md +203 -0
  76. package/skills/adia-ui-kit/references/session-log-template.md +118 -0
  77. package/skills/adia-ui-kit/references/setup.md +652 -0
  78. package/skills/adia-ui-kit/references/skill-hygiene.md +135 -0
  79. package/skills/adia-ui-kit/references/spec-to-ui-reasoning.md +394 -0
  80. package/skills/adia-ui-kit/references/state.md +229 -0
  81. package/skills/adia-ui-kit/references/teach-protocol.md +421 -0
  82. package/skills/adia-ui-kit/references/theme.md +142 -0
  83. package/skills/adia-ui-kit/references/version-check.md +69 -0
  84. package/skills/adia-ui-kit/scripts/audit-decision-trace.mjs +198 -0
  85. package/skills/adia-ui-kit/scripts/audit-kit-roster.mjs +366 -0
  86. package/skills/adia-ui-kit/scripts/changelog-archive.mjs +126 -0
  87. package/skills/adia-ui-kit/scripts/check-adia-versions.py +404 -0
  88. package/skills/adia-ui-kit/scripts/run-skill-evals.mjs +358 -0
  89. package/skills/adia-ui-kit/scripts/validate-session-log.mjs +242 -0
  90. package/skills/adia-ui-kit/skill.json +102 -0
  91. package/skills/adia-ui-migration/CHANGELOG.md +47 -0
  92. package/skills/adia-ui-migration/SKILL.md +381 -0
  93. package/skills/adia-ui-migration/skill.json +29 -0
  94. package/skills/adia-ui-spa/SKILL.md +1 -1
  95. package/skills/adia-ui-verify/SKILL.md +2 -2
@@ -0,0 +1,223 @@
1
+ # Form Patterns
2
+
3
+ ## Basic Form
4
+
5
+ ```html
6
+ <card-ui>
7
+ <header>
8
+ <span slot="heading" variant="section">Create Account</span>
9
+ <span slot="description">Fill in your details</span>
10
+ </header>
11
+ <section>
12
+ <form>
13
+ <col-ui gap="4">
14
+ <input-ui label="Full Name" name="name" required placeholder="Jane Doe"></input-ui>
15
+ <input-ui label="Email" name="email" type="email" required placeholder="jane@example.com"></input-ui>
16
+ <input-ui label="Password" name="password" type="password" required minlength="8"></input-ui>
17
+ <field-ui label="Bio">
18
+ <textarea-ui name="bio" placeholder="Tell us about yourself"></textarea-ui>
19
+ </field-ui>
20
+ <select-ui label="Role" name="role">
21
+ <option value="developer">Developer</option>
22
+ <option value="designer">Designer</option>
23
+ <option value="manager">Manager</option>
24
+ </select-ui>
25
+ <check-ui name="terms" label="I agree to the terms"></check-ui>
26
+ <button-ui text="Create Account" variant="primary" type="submit" stretch></button-ui>
27
+ </col-ui>
28
+ </form>
29
+ </section>
30
+ </card-ui>
31
+ ```
32
+
33
+ ## Key Rules
34
+
35
+ - Use a raw `<form>` element to wrap fields for native submit serialization
36
+ - Every field needs a `name` for form data collection
37
+ - Use `label` attribute (not a separate `<label>` element)
38
+ - Use `required`, `minlength`, `maxlength`, `pattern` for constraint validation
39
+ - Custom error messages: `data-msg-required="Please enter your name"` etc.
40
+ - `<button-ui type="submit">` triggers submission
41
+ - `form-submit` event: `{ detail: { action, method, data } }`
42
+ - Form validates on submit automatically — surfaces errors on invalid fields
43
+ - On input after error: re-validates to clear as soon as value is valid
44
+
45
+ ## Validation
46
+
47
+ ```html
48
+ <!-- Built-in constraints -->
49
+ <input-ui label="Email" name="email" type="email" required
50
+ data-msg-required="Email is required"
51
+ data-msg-pattern="Enter a valid email">
52
+ </input-ui>
53
+
54
+ <input-ui label="Username" name="user" required minlength="3" maxlength="20"
55
+ pattern="[a-z0-9_]+"
56
+ data-msg-pattern="Only lowercase letters, numbers, and underscores">
57
+ </input-ui>
58
+ ```
59
+
60
+ Programmatic validation:
61
+ ```js
62
+ const field = document.querySelector('input-ui[name="email"]');
63
+ field.validate(); // returns boolean, surfaces error
64
+ field.setInvalid('Custom error message');
65
+ field.setValid();
66
+ ```
67
+
68
+ ## Login Form
69
+
70
+ ```html
71
+ <card-ui size="lg" style="max-width:400px">
72
+ <header center>
73
+ <span slot="heading" variant="section">Welcome back</span>
74
+ <span slot="description">Sign in to your account</span>
75
+ </header>
76
+ <section>
77
+ <form action="/api/login" method="post">
78
+ <col-ui gap="4">
79
+ <input-ui label="Email" name="email" type="email" required prefix="envelope"></input-ui>
80
+ <input-ui label="Password" name="password" type="password" required suffix="eye"></input-ui>
81
+ <row-ui justify="between" align="center">
82
+ <check-ui name="remember" label="Remember me"></check-ui>
83
+ <a href="/forgot" style="font-size:var(--a-font-size-xs)">Forgot password?</a>
84
+ </row-ui>
85
+ <button-ui text="Sign In" variant="primary" type="submit" stretch></button-ui>
86
+ </col-ui>
87
+ </form>
88
+ </section>
89
+ </card-ui>
90
+ ```
91
+
92
+ ## Settings Panel with Toggles
93
+
94
+ ```html
95
+ <card-ui>
96
+ <header divider>
97
+ <span slot="heading" variant="section">Notifications</span>
98
+ <span slot="description">Manage how you receive notifications</span>
99
+ </header>
100
+ <section>
101
+ <col-ui gap="4">
102
+ <row-ui justify="between" align="center">
103
+ <col-ui gap="1">
104
+ <strong>Email notifications</strong>
105
+ <small style="color:var(--a-canvas-text-subtle)">Receive updates via email</small>
106
+ </col-ui>
107
+ <switch-ui name="email-notif"></switch-ui>
108
+ </row-ui>
109
+ <divider-ui></divider-ui>
110
+ <row-ui justify="between" align="center">
111
+ <col-ui gap="1">
112
+ <strong>Push notifications</strong>
113
+ <small style="color:var(--a-canvas-text-subtle)">Browser push alerts</small>
114
+ </col-ui>
115
+ <switch-ui name="push-notif"></switch-ui>
116
+ </row-ui>
117
+ </col-ui>
118
+ </section>
119
+ </card-ui>
120
+ ```
121
+
122
+ ## Input with Icons
123
+
124
+ ```html
125
+ <input-ui label="Search" prefix="magnifying-glass" placeholder="Search..."></input-ui>
126
+ <input-ui label="Amount" prefix="currency-dollar" placeholder="0.00"></input-ui>
127
+ <input-ui label="Password" type="password" suffix="eye"></input-ui>
128
+ ```
129
+
130
+ ## Where field affordances go — status text vs buttons vs captions
131
+
132
+ Three different homes. Pick by what the affordance **is**, not where it visually sits:
133
+
134
+ | Affordance | Home | Result |
135
+ |---|---|---|
136
+ | Short **status / label text** — "Required", "Results: 12", "Light", "USD" | input-ui `prefix=` / `suffix=` (string props) | renders **inside** the input chrome, before/after the value; input stays full-width |
137
+ | **Interactive controls** — clear, copy, ⌘K hint, open-in-modal | `<button-ui slot="leading">` / `slot="trailing">` (or `<kbd-ui slot="trailing">`) **inside `<input-ui>`** | installed into the chrome; DOM order `prefix → leading → value → suffix → trailing` |
138
+ | A caption / count / submit **beside** the field (outside the input box) | `slot="trailing"` / `slot="action"` on the **`<field-ui>`** (not the input) | sits next to the input row, not inside the chrome |
139
+
140
+ ```html
141
+ <!-- status text in-chrome → input suffix; clear button → input trailing slot -->
142
+ <field-ui inline label="Filter">
143
+ <input-ui placeholder="Name or tag" suffix="Results: 12">
144
+ <button-ui slot="trailing" icon="x" variant="ghost" aria-label="Clear"></button-ui>
145
+ </input-ui>
146
+ </field-ui>
147
+ ```
148
+
149
+ **Don't** put short status text in a `slot="trailing"` element — the affordance slots are for interactive controls; text belongs in `suffix`/`prefix` so it stays in-chrome and the input keeps full width. (bug-55 / bug-60.)
150
+
151
+ ## Raw Input (embedded in custom container)
152
+
153
+ ```html
154
+ <card-ui>
155
+ <section>
156
+ <row-ui gap="2" align="center">
157
+ <icon-ui name="magnifying-glass"></icon-ui>
158
+ <input-ui raw placeholder="Search anything..." style="flex:1"></input-ui>
159
+ </row-ui>
160
+ </section>
161
+ </card-ui>
162
+ ```
163
+
164
+ `raw` strips background, border, padding, radius, outline, and height from `input-ui`.
165
+
166
+ ## OTP Input
167
+
168
+ ```html
169
+ <card-ui size="lg" style="max-width:400px;text-align:center">
170
+ <header center>
171
+ <span slot="heading" variant="section">Verify your email</span>
172
+ <span slot="description">Enter the 6-digit code</span>
173
+ </header>
174
+ <section>
175
+ <col-ui gap="4" style="align-items:center">
176
+ <otp-input-ui length="6"></otp-input-ui>
177
+ <button-ui text="Verify" variant="primary" stretch></button-ui>
178
+ </col-ui>
179
+ </section>
180
+ </card-ui>
181
+ ```
182
+
183
+ ## Wired Form (with A007)
184
+
185
+ A form that fetches data, validates, and submits via wiring:
186
+
187
+ ```json
188
+ {
189
+ "type": "wireComponents",
190
+ "surfaceId": "profile",
191
+ "data": {
192
+ "sources": [{ "id": "user", "path": "/user", "uri": "resource://users/{userId}", "refresh": "once" }],
193
+ "params": { "userId": { "from": "route", "key": "id" } }
194
+ },
195
+ "state": {
196
+ "controllers": [{ "id": "form", "type": "FormController", "host": "form-root", "config": { "validateOn": "blur" } }]
197
+ },
198
+ "actions": [{
199
+ "event": "form-submit", "source": "form-root",
200
+ "handler": "submit-resource", "method": "PUT", "uri": "resource://users/{userId}",
201
+ "body": { "from": "event-detail", "key": "data" },
202
+ "onSuccess": { "notify": "Profile saved" },
203
+ "onError": { "notify": "Save failed" }
204
+ }]
205
+ }
206
+ ```
207
+
208
+ Fields bind to the data model: `"value": { "path": "/user/name" }` — auto-populated from fetch.
209
+
210
+ ## Date, Color, Slider
211
+
212
+ ```html
213
+ <field-ui label="Appointment">
214
+ <datetime-picker-ui name="appt"></datetime-picker-ui>
215
+ </field-ui>
216
+ <field-ui label="Date of Birth">
217
+ <calendar-picker-ui name="dob"></calendar-picker-ui>
218
+ </field-ui>
219
+ <field-ui label="Brand Color">
220
+ <color-picker-ui name="color"></color-picker-ui>
221
+ </field-ui>
222
+ <slider-ui min="0" max="100" value="50"></slider-ui>
223
+ ```
@@ -0,0 +1,326 @@
1
+ # Layout Patterns
2
+
3
+ ## Card — The Universal Container
4
+
5
+ Every surface is built from cards. The content model is mandatory.
6
+
7
+ ```html
8
+ <card-ui>
9
+ <header>
10
+ <span slot="icon"><icon-ui name="users"></icon-ui></span>
11
+ <span slot="heading" variant="section">Team Members</span>
12
+ <span slot="description">Active members in your workspace</span>
13
+ <button-ui slot="action" text="Add" variant="ghost" icon="plus" size="sm"></button-ui>
14
+ </header>
15
+ <section>
16
+ <col-ui gap="2">
17
+ <!-- content always inside col-ui -->
18
+ </col-ui>
19
+ </section>
20
+ <footer divider>
21
+ <span slot="description">12 members total</span>
22
+ <button-ui slot="action" text="View All" size="sm"></button-ui>
23
+ </footer>
24
+ </card-ui>
25
+ ```
26
+
27
+ Header grid adapts to present slots:
28
+ - `icon` + `action`: `max-content 1fr max-content`
29
+ - `icon` only: `max-content 1fr`
30
+ - `action` only: `1fr max-content`
31
+ - Neither: `1fr`
32
+
33
+ `[divider]` on header/footer adds a border separator with padding.
34
+ `[center]` on header centers text and items.
35
+ `[bleed]` on section removes padding (edge-to-edge content like images or tables).
36
+
37
+ ## Card Sizes
38
+
39
+ ```html
40
+ <card-ui size="xl">Hero-level — largest inset, biggest radius</card-ui>
41
+ <card-ui size="lg">Spacious — old default card scale</card-ui>
42
+ <card-ui>Default (md) — standard card</card-ui>
43
+ <card-ui size="sm">Compact — row-level density</card-ui>
44
+ <card-ui size="xs">Ultra-dense — minimal inset</card-ui>
45
+ ```
46
+
47
+ Each size sets: `--inset` (padding), `--radius`, `--gap`, and all heading/text font sizes.
48
+
49
+ ## Card Variants
50
+
51
+ ```html
52
+ <card-ui variant="outlined">Visible border, transparent background, no shadow</card-ui>
53
+ <card-ui variant="filled">Filled background</card-ui>
54
+ <card-ui variant="ghost">Transparent background and border</card-ui>
55
+ <card-ui raw>No background, border, or shadow — structural wrapper only</card-ui>
56
+ <card-ui elevation="0">Flat (no shadow)</card-ui>
57
+ <card-ui elevation="2">Medium shadow</card-ui>
58
+ <card-ui elevation="3">Strong shadow</card-ui>
59
+ ```
60
+
61
+ `raw` strips all chrome. The card's content model (header/section/footer) still applies.
62
+
63
+ ## Stack Layout
64
+
65
+ ```html
66
+ <!-- Vertical stack -->
67
+ <col-ui gap="4">
68
+ <input-ui label="Name"></input-ui>
69
+ <input-ui label="Email"></input-ui>
70
+ <button-ui text="Submit" variant="primary"></button-ui>
71
+ </col-ui>
72
+
73
+ <!-- Horizontal row -->
74
+ <row-ui gap="2" justify="between" align="center">
75
+ <span>Total: $49.99</span>
76
+ <button-ui text="Pay Now" variant="primary"></button-ui>
77
+ </row-ui>
78
+
79
+ <!-- Nested: action bar -->
80
+ <row-ui justify="between">
81
+ <button-ui text="Back" variant="ghost"></button-ui>
82
+ <row-ui gap="2">
83
+ <button-ui text="Cancel"></button-ui>
84
+ <button-ui text="Save" variant="primary"></button-ui>
85
+ </row-ui>
86
+ </row-ui>
87
+ ```
88
+
89
+ `justify` values: `start`, `end`, `center`, `between`, `around`, `evenly`.
90
+ `align` values: `start`, `end`, `center`, `stretch`, `baseline`.
91
+
92
+ All three string props (`gap`, `align`, `justify`) on `col-ui` and `row-ui` accept `@bp` responsive notation — see **Responsive Layout** below.
93
+
94
+ ## Grid
95
+
96
+ ```html
97
+ <!-- Equal columns -->
98
+ <grid-ui columns="3" gap="4">
99
+ <card-ui>Card 1</card-ui>
100
+ <card-ui>Card 2</card-ui>
101
+ <card-ui>Card 3</card-ui>
102
+ </grid-ui>
103
+
104
+ <!-- Asymmetric: 3:2 split -->
105
+ <grid-ui columns="5" gap="4">
106
+ <card-ui span="3">Wide</card-ui>
107
+ <card-ui span="2">Narrow</card-ui>
108
+ </grid-ui>
109
+ ```
110
+
111
+ Canonical ratios: `2:1 → columns="3" + span="2"` · `3:2 → columns="5" + span="3"+"2"` · `4:1 → columns="5" + span="4"` · `3:1 → columns="4" + span="3"`.
112
+
113
+ Never set `grid-template-columns` via inline style — use `columns=` and child `span=` instead. `columns` and `gap` both accept `@bp` notation.
114
+
115
+ > ⚠️ **`gap=` and `columns=` take NUMERIC tokens, NOT size keywords.** Valid: `gap="3"`, `gap="4"`, `gap="6"`, `columns="3"`, `columns="2 4@md"`. **Invalid**: `gap="md"`, `gap="lg"`, `gap="small"`, `columns="auto"`. The numbers map to `--a-space-N` density tokens — `gap="4"` resolves to `var(--a-space-4)`. Size keywords are a `<button-ui size="sm">` / `<badge-ui size="lg">` convention; layout primitives use numeric density tokens. Same rule applies to `col-ui` and `row-ui` `gap=`. Anti-pattern visible in agent-generated DOM: `<grid-ui columns="3" gap="md">` — renders without gap (invalid token falls back to default 0 or browser default).
116
+
117
+ ## Responsive Layout
118
+
119
+ Props on `grid-ui`, `col-ui`, `row-ui`, `text-ui`, and `block-ui` accept `@bp` annotations for viewport-driven layout. No media queries, no utility classes, no hidden elements.
120
+
121
+ ### Syntax
122
+
123
+ Append `@breakpoint` to any value that should apply from that breakpoint upward. The unannotated value is the mobile-first base (smallest screens). The largest annotation that is ≤ the active breakpoint wins.
124
+
125
+ ```
126
+ columns="1 2@sm 4@lg" → 1 at xs · 2 at sm/md · 4 at lg/xl
127
+ gap="2 4@md" → 2 below md · 4 from md up
128
+ justify="start between@md"
129
+ ```
130
+
131
+ ### Breakpoint scale
132
+
133
+ | Name | Min-width | Typical target |
134
+ |---|---|---|
135
+ | `xs` | 0 px | Portrait phone (base — no annotation needed) |
136
+ | `sm` | 480 px | Large phone / portrait tablet |
137
+ | `md` | 768 px | Landscape tablet |
138
+ | `lg` | 1024 px | Small desktop |
139
+ | `xl` | 1280 px | Standard desktop+ |
140
+
141
+ ### Supported props
142
+
143
+ | Component | Responsive props |
144
+ |---|---|
145
+ | `grid-ui` | `columns`, `gap` |
146
+ | `col-ui` | `gap`, `align`, `justify` |
147
+ | `row-ui` | `gap`, `align`, `justify`; `wrap-at="bp"` for responsive wrap |
148
+ | `text-ui` | `size` |
149
+ | `block-ui` | `padding`, `margin` |
150
+
151
+ ### Common patterns
152
+
153
+ ```html
154
+ <!-- Dashboard KPI grid: 2×2 on mobile, 4-up from tablet -->
155
+ <grid-ui columns="2 4@md" gap="4">
156
+ <card-ui>...</card-ui>
157
+ <card-ui>...</card-ui>
158
+ <card-ui>...</card-ui>
159
+ <card-ui>...</card-ui>
160
+ </grid-ui>
161
+
162
+ <!-- Chart + sidebar: stacked on mobile, 3:2 split from tablet -->
163
+ <grid-ui columns="1 5@md" gap="4">
164
+ <card-ui span="3">Chart</card-ui>
165
+ <card-ui span="2">Sidebar</card-ui>
166
+ </grid-ui>
167
+
168
+ <!-- 3-up strip: stacked on mobile, side-by-side from tablet -->
169
+ <grid-ui columns="1 3@md" gap="4">
170
+ <card-ui>Team</card-ui>
171
+ <card-ui>Actions</card-ui>
172
+ <card-ui>Storage</card-ui>
173
+ </grid-ui>
174
+
175
+ <!-- Toolbar: stacked + tight on mobile, spread + roomy on desktop -->
176
+ <row-ui gap="2 4@md" justify="start between@md" align="start center@md" wrap>
177
+ <text-ui strong>Recent transactions</text-ui>
178
+ <row-ui gap="2">
179
+ <button-ui text="Export"></button-ui>
180
+ <button-ui text="+ New" variant="primary"></button-ui>
181
+ </row-ui>
182
+ </row-ui>
183
+
184
+ <!-- Responsive text size -->
185
+ <text-ui variant="heading" size="sm md@lg">Welcome back</text-ui>
186
+
187
+ <!-- Less padding on mobile -->
188
+ <block-ui padding="sm md@lg">...</block-ui>
189
+ ```
190
+
191
+ **Responsive wrap** — boolean attrs like `wrap` can't use `@bp` value syntax; use `wrap-at="bp"` instead:
192
+
193
+ ```html
194
+ &lt;!-- Toolbar: single row on desktop, wraps on mobile --&gt;
195
+ &lt;row-ui gap="2 3@md" wrap-at="sm"&gt;
196
+ &lt;input-ui placeholder="Search..."&gt;&lt;/input-ui&gt;
197
+ &lt;button-ui text="Export"&gt;&lt;/button-ui&gt;
198
+ &lt;button-ui text="+ New" variant="primary"&gt;&lt;/button-ui&gt;
199
+ &lt;/row-ui&gt;
200
+ ```
201
+
202
+ **Anti-pattern:** never write `@media` blocks, inline `style=`, or hidden-element tricks for layout breakpoints on these components. The `@bp` attribute is the canonical path and is understood by the A2UI generation pipeline.
203
+
204
+ ## App Shell
205
+
206
+ Full application layout with sidebar, header bar, and content area.
207
+
208
+ ```html
209
+ <admin-shell mode="sidebar">
210
+ <nav slot="sidebar">
211
+ <sidebar-ui>
212
+ <header><span slot="heading" variant="section">MyApp</span></header>
213
+ <nav-ui>
214
+ <a href="/" data-active>Dashboard</a>
215
+ <a href="/settings">Settings</a>
216
+ <a href="/team">Team</a>
217
+ </nav-ui>
218
+ </sidebar-ui>
219
+ </nav>
220
+ <header slot="header">
221
+ <row-ui justify="between" align="center" style="padding:var(--a-space-2) var(--a-space-4)">
222
+ <h3 variant="section">Dashboard</h3>
223
+ <avatar-ui text="Jane" size="sm"></avatar-ui>
224
+ </row-ui>
225
+ </header>
226
+ <main slot="content">
227
+ <!-- page content -->
228
+ </main>
229
+ </app-shell-ui>
230
+ ```
231
+
232
+ Modes: `sidebar` (default), `sidebar-collapsed`, `header-only`, `minimal`.
233
+
234
+ **Pitfall — flat CSS selector collapses shell layout (FB-04):**
235
+ Consumer boilerplate sometimes includes a `/* Shell fill */` block:
236
+ ```css
237
+ /* ❌ collapses the shell */
238
+ admin-shell { display: block; height: 100dvh; }
239
+ ```
240
+ Because `admin-shell` is a custom element, a flat CSS selector on the tag name wins the cascade when imported after the shell's own stylesheet (`display: flex` from the component). The entire sidebar + content grid collapses to a block stack. **Never set `display` on `admin-shell` directly.** The shell already manages its own display. To fill the viewport, set `height: 100dvh` on the `<body>` or a wrapping `<div>` instead, or use `min-height`:
241
+ ```css
242
+ /* ✅ safe */
243
+ body { margin: 0; height: 100dvh; display: flex; flex-direction: column; }
244
+ admin-shell { flex: 1; min-height: 0; }
245
+ ```
246
+ To adjust shell geometry, override the shell's CSS custom properties (e.g. `--page-sidebar-width-leading`, `--page-header-height`) rather than the component's structural CSS.
247
+
248
+ ## Tabs
249
+
250
+ Tabs are a button strip. Content panels are **siblings**, not children.
251
+
252
+ ```html
253
+ <col-ui gap="4">
254
+ <tabs-ui value="profile">
255
+ <tab-ui value="profile" text="Profile"></tab-ui>
256
+ <tab-ui value="security" text="Security"></tab-ui>
257
+ <tab-ui value="billing" text="Billing"></tab-ui>
258
+ </tabs-ui>
259
+ <!-- Panels shown/hidden based on active tab -->
260
+ <card-ui><!-- profile panel --></card-ui>
261
+ </col-ui>
262
+ ```
263
+
264
+ Variants: `line` (underline indicator) or `pill` (filled background).
265
+
266
+ ## Modal / Dialog / Drawer
267
+
268
+ Modal is a chromeless overlay — child content owns all visual styling:
269
+
270
+ ```html
271
+ <modal-ui open size="md">
272
+ <card-ui>
273
+ <header><span slot="heading" variant="section">Confirm</span></header>
274
+ <section><p>Are you sure?</p></section>
275
+ <footer>
276
+ <button-ui text="Cancel"></button-ui>
277
+ <button-ui text="Confirm" variant="primary"></button-ui>
278
+ </footer>
279
+ </card-ui>
280
+ </modal-ui>
281
+ ```
282
+
283
+ Dialog for simple confirmations (uses `<confirm-dialog-ui>` from web-modules/feedback):
284
+ ```html
285
+ <confirm-dialog-ui title="Delete?" description="This cannot be undone." confirm-text="Delete" cancel-text="Keep"></confirm-dialog-ui>
286
+ ```
287
+
288
+ Drawer slides from an edge:
289
+ ```html
290
+ <drawer-ui open side="right">
291
+ <header><span slot="heading" variant="section">Details</span></header>
292
+ <section>Content</section>
293
+ </drawer-ui>
294
+ ```
295
+
296
+ ## Theming
297
+
298
+ ```html
299
+ <!-- CSS-only preset (zero JS) -->
300
+ <div theme="ocean">
301
+ <card-ui>Ocean themed</card-ui>
302
+ </div>
303
+
304
+ <!-- Interactive theme switcher (renders preset buttons + optional sliders) -->
305
+ <popover-ui>
306
+ <button-ui slot="trigger" text="Theme"></button-ui>
307
+ <theme-panel slot="content" parametric presets scheme-toggle></theme-panel>
308
+ </popover-ui>
309
+ ```
310
+
311
+ Presets: default, ocean, forest, sunset, lavender, rose, slate, midnight.
312
+
313
+ Parametric tuning (applied as CSS custom properties on the wrapping element when `[parametric]` is set on `<theme-panel>`): `--a-density`, `--a-radius-k`, `--a-chroma`, `--a-space-scale`, `--a-shadow-scale`, `--a-motion-scale`.
314
+
315
+ ## Headings
316
+
317
+ Use `[variant]` for visual emphasis — `<h1>`-`<h6>` are purely structural:
318
+
319
+ ```html
320
+ <h1 variant="display">Hero text</h1>
321
+ <h2 variant="title">Page title</h2>
322
+ <h3 variant="section">Section heading</h3>
323
+ <span variant="label">Label text</span>
324
+ <span variant="eyebrow">Overline</span>
325
+ <span variant="caption">Caption</span>
326
+ ```