@adia-ai/web-components 0.8.33 → 0.8.34

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 (40) hide show
  1. package/CHANGELOG.md +24 -0
  2. package/components/agent-reasoning/agent-reasoning.a2ui.json +1 -1
  3. package/components/agent-reasoning/agent-reasoning.yaml +3 -3
  4. package/components/badge/badge.css +6 -4
  5. package/components/button/button.css +12 -0
  6. package/components/combobox/combobox.a2ui.json +1 -1
  7. package/components/combobox/combobox.yaml +3 -0
  8. package/components/command/command.a2ui.json +4 -0
  9. package/components/command/command.class.js +54 -4
  10. package/components/command/command.d.ts +2 -0
  11. package/components/command/command.yaml +25 -3
  12. package/components/date-range-picker/date-range-picker.a2ui.json +1 -1
  13. package/components/date-range-picker/date-range-picker.class.js +42 -43
  14. package/components/date-range-picker/date-range-picker.css +11 -0
  15. package/components/date-range-picker/date-range-picker.yaml +6 -3
  16. package/components/description-list/description-list.css +16 -4
  17. package/components/modal/modal.class.js +43 -2
  18. package/components/modal/modal.css +23 -0
  19. package/components/nav-group/nav-group.css +15 -4
  20. package/components/nav-item/nav-item.css +11 -3
  21. package/components/richtext/richtext.css +5 -1
  22. package/components/segment/segment.css +10 -0
  23. package/components/step-progress/step-progress.css +16 -3
  24. package/components/table/cell-types.js +8 -0
  25. package/components/table/table.a2ui.json +1 -1
  26. package/components/table/table.class.js +11 -0
  27. package/components/table/table.css +9 -0
  28. package/components/table/table.d.ts +1 -1
  29. package/components/table/table.yaml +1 -1
  30. package/components/tabs/tabs.css +3 -1
  31. package/components/tag/tag.css +7 -4
  32. package/core/element.js +31 -0
  33. package/core/signals.js +3 -1
  34. package/dist/theme-provider.min.js +2 -2
  35. package/dist/web-components.min.css +1 -1
  36. package/dist/web-components.min.js +40 -40
  37. package/dist/web-components.sheet.js +1 -1
  38. package/package.json +1 -1
  39. package/patterns/responsive-shell-sidebar/responsive-shell-sidebar.examples.html +135 -147
  40. package/styles/colors/semantics/core.css +22 -2
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adia-ai/web-components",
3
- "version": "0.8.33",
3
+ "version": "0.8.34",
4
4
  "description": "AdiaUI web components \u2014 vanilla custom elements. A2UI runtime (renderer, registry, streams, wiring) lives in @adia-ai/a2ui-runtime.",
5
5
  "type": "module",
6
6
  "types": "./index.d.ts",
@@ -1,62 +1,57 @@
1
- <!DOCTYPE html>
2
- <html lang="en" theme="auto">
3
- <head>
4
- <meta charset="utf-8">
5
- <meta name="viewport" content="width=device-width, initial-scale=1">
6
- <title>Responsive Shell Sidebar examples</title>
7
-
8
- <link rel="stylesheet" href="../../styles/resets.css">
9
- <link rel="stylesheet" href="../../styles/tokens.css">
10
-
11
- <link rel="stylesheet" href="../../components/button/button.css">
12
- <link rel="stylesheet" href="../../components/card/card.css">
13
- <link rel="stylesheet" href="../../components/col/col.css">
14
- <link rel="stylesheet" href="../../components/drawer/drawer.css">
15
- <link rel="stylesheet" href="../../components/icon/icon.css">
16
- <link rel="stylesheet" href="../../components/list/list.css">
17
- <link rel="stylesheet" href="../../components/pane/pane.css">
18
- <link rel="stylesheet" href="../../components/row/row.css">
19
- <link rel="stylesheet" href="../../components/text/text.css">
20
-
21
- <script type="module" src="../../components/button/button.js"></script>
22
- <script type="module" src="../../components/card/card.js"></script>
23
- <script type="module" src="../../components/col/col.js"></script>
24
- <script type="module" src="../../components/drawer/drawer.js"></script>
25
- <script type="module" src="../../components/icon/icon.js"></script>
26
- <script type="module" src="../../components/list/list.js"></script>
27
- <script type="module" src="../../components/pane/pane.js"></script>
28
- <script type="module" src="../../components/row/row.js"></script>
29
- <script type="module" src="../../components/text/text.js"></script>
30
-
31
- <script type="module" src="../../core/icons-phosphor.js"></script>
32
-
33
- <link rel="stylesheet" href="responsive-shell-sidebar.css">
34
-
35
- <style>
36
- body { margin: 0; }
37
- h1, h2, h3 { margin: 0; }
38
- .doc-body { max-width: 800px; margin: 0 auto; padding: var(--a-space-4); }
39
- .doc-body h2 { margin-top: var(--a-space-6); }
40
- .doc-body pre {
41
- background: var(--a-bg-muted);
42
- padding: var(--a-space-3);
43
- border-radius: var(--a-radius);
44
- overflow-x: auto;
45
- font-size: 13px;
1
+ <!-- Pattern source: packages/web-components/patterns/responsive-shell-sidebar/responsive-shell-sidebar.html (fragment port of the standalone demo page — gh#959) -->
2
+ <style>
3
+ /* Page-local copy of responsive-shell-sidebar.css, bounded for the docs
4
+ page (the standalone page's `height: 100vh` shell becomes a fixed-height
5
+ frame so the docs route scrolls normally). */
6
+ .wide-only { display: contents; }
7
+ .narrow-only { display: none; }
8
+
9
+ [data-rss-shell] {
10
+ display: grid;
11
+ grid-template-columns: 240px 1fr 320px;
12
+ gap: var(--a-space-3);
13
+ height: 420px;
14
+ padding: var(--a-space-3);
15
+ box-sizing: border-box;
16
+ border: 1px solid var(--md-sys-color-neutral-outline-variant);
17
+ border-radius: var(--a-radius-lg);
18
+ overflow: auto;
19
+ }
20
+
21
+ [data-rss-toolbar] { display: none; }
22
+
23
+ @media (max-width: 900px) {
24
+ .wide-only { display: none; }
25
+ .narrow-only { display: block; }
26
+ [data-rss-shell] { grid-template-columns: 1fr; }
27
+ [data-rss-toolbar] {
28
+ display: flex;
29
+ gap: var(--a-space-2);
30
+ padding-bottom: var(--a-space-2);
31
+ border-bottom: 1px solid var(--md-sys-color-neutral-outline);
46
32
  }
47
- </style>
48
- </head>
49
- <body data-chunk="responsive-shell-sidebar" data-chunk-kind="page" data-chunk-domain="layout"
50
- data-chunk-description="Editor-shell with leading + trailing sidebars that collapse to drawers below a 900px viewport breakpoint. Dual-mount: same content renders inline on wide viewports + inside <drawer-ui> twins on narrow. State shared via single signal source consumed by both mount points.">
51
-
52
- <!-- ═══ INLINE shell (wide-only) ═══ -->
53
- <div class="shell">
54
- <!-- Leading sidebar inline mount (wide-only) -->
33
+ }
34
+ </style>
35
+
36
+ <header>
37
+ <div>
38
+ <h1>Responsive Shell Sidebar</h1>
39
+ <div data-actions>
40
+ <tag-ui size="sm">drawer-ui</tag-ui> <tag-ui size="sm">pane-ui</tag-ui> <tag-ui size="sm">list-ui</tag-ui> <tag-ui size="sm">button-ui</tag-ui>
41
+ </div>
42
+ </div>
43
+ <p>Editor-shell with leading + trailing sidebars that collapse to drawers below a 900px viewport breakpoint. Dual-mount: the same content renders inline on wide viewports and inside <code>&lt;drawer-ui&gt;</code> twins on narrow; state is shared via a single signal source consumed by both mount points.</p>
44
+ </header>
45
+
46
+ <section data-section data-property="demo">
47
+ <h2 variant="section">Live demo</h2>
48
+ <p data-note>Resize the viewport: at ≤900px the leading + trailing sidebars collapse to drawers triggered by the toolbar buttons. Above 900px the sidebars are inline.</p>
49
+
50
+ <div data-rss-shell data-chunk="responsive-shell-sidebar" data-chunk-kind="page" data-chunk-domain="layout"
51
+ data-chunk-description="Editor-shell with leading + trailing sidebars that collapse to drawers below a 900px viewport breakpoint. Dual-mount: same content renders inline on wide viewports + inside drawer-ui twins on narrow. State shared via single signal source consumed by both mount points.">
55
52
  <aside class="wide-only" data-chunk-slot="leading-inline">
56
53
  <pane-ui>
57
- <header>
58
- <h3>Tokens</h3>
59
- </header>
54
+ <header><h3>Tokens</h3></header>
60
55
  <section>
61
56
  <list-ui>
62
57
  <list-item-ui>Primary</list-item-ui>
@@ -68,85 +63,26 @@
68
63
  </pane-ui>
69
64
  </aside>
70
65
 
71
- <!-- Main content (always inline) -->
72
66
  <main data-chunk-slot="main">
73
- <!-- ═══ Narrow toolbar (drawer triggers) ═══ -->
74
- <row-ui class="toolbar" data-chunk-slot="narrow-toolbar">
67
+ <row-ui data-rss-toolbar data-chunk-slot="narrow-toolbar">
75
68
  <button-ui id="open-leading" text="Tokens" icon="list" variant="ghost" size="sm"></button-ui>
76
69
  <button-ui id="open-trailing" text="Settings" icon="sliders" variant="ghost" size="sm"></button-ui>
77
70
  </row-ui>
78
71
 
79
72
  <card-ui>
80
- <header>
81
- <h2>Responsive Shell Sidebar pattern</h2>
82
- </header>
73
+ <header><h2>Responsive Shell Sidebar pattern</h2></header>
83
74
  <section>
84
75
  <text-ui>
85
- Resize this viewport: at ≤900px the leading + trailing sidebars collapse
86
- to drawers triggered by the toolbar buttons. Above 900px the sidebars are
87
- inline. The same content is mounted in both surfaces; consumer signals
88
- drive both copies via the parent template's re-read.
76
+ The same sidebar content is mounted in both surfaces; consumer
77
+ signals drive both copies via the parent template's re-read.
89
78
  </text-ui>
90
79
  </section>
91
80
  </card-ui>
92
-
93
- <div class="doc-body">
94
- <h2>The pattern</h2>
95
- <p>Three pieces:</p>
96
- <ol>
97
- <li><strong>Inline mounts</strong> for the sidebars wrapped in <code>.wide-only</code> (display: contents at &gt;900px; display: none at ≤900px).</li>
98
- <li><strong>Drawer twins</strong> with the same children, mounted outside the shell's named slots, controlled by toolbar buttons inside <code>.narrow-only</code>.</li>
99
- <li><strong>MediaQueryList</strong> listener that auto-closes the drawers on viewport widening (the gap FEEDBACK-06 §3 explicitly flagged).</li>
100
- </ol>
101
-
102
- <h2>Dual-mount caveat</h2>
103
- <p>Components with <strong>local DOM state</strong> (uncontrolled form inputs, scroll position, focused element) will lose state when the viewport crosses the breakpoint — the inline copy unmounts and the drawer copy mounts (or vice versa). <strong>Signal-bound components are safe</strong> because their state lives in the signal, not the DOM. Most AdiaUI primitives are signal-backed; the affected cases are:</p>
104
- <ul>
105
- <li>Native <code>&lt;input&gt;</code>/<code>&lt;textarea&gt;</code> with no signal binding</li>
106
- <li>Components using <code>this.querySelector(...)</code> with imperative state</li>
107
- <li>Scroll-position-sensitive containers (e.g. chat threads at a specific scroll)</li>
108
- </ul>
109
- <p>For these, either: (a) lift the state to a signal in the parent, or (b) document the unmount-on-resize edge.</p>
110
-
111
- <h2>Auto-close on viewport widening</h2>
112
- <code-ui language="javascript">const mql = window.matchMedia('(max-width: 900px)');
113
- mql.addEventListener('change', (e) =&gt; {
114
- if (!e.matches) {
115
- // Viewport widened past breakpoint — close any open drawers
116
- document.getElementById('leading-drawer').open = false;
117
- document.getElementById('trailing-drawer').open = false;
118
- }
119
- });</code-ui>
120
-
121
- <h2>State sharing</h2>
122
- <p>Single signal source consumed by both copies. The parent template reads the signal once and passes the extracted value to both the inline mount AND the drawer mount; on signal change the parent re-renders both:</p>
123
- <code-ui language="javascript">import { signal } from '@adia-ai/web-components/core';
124
-
125
- const activeToken = signal('primary');
126
-
127
- static template = () =&gt; {
128
- const current = activeToken.value; // dep read here
129
- return html`
130
- &lt;aside class="wide-only"&gt;
131
- &lt;list-ui&gt; ... .active=${current === 'primary'} ... &lt;/list-ui&gt;
132
- &lt;/aside&gt;
133
- &lt;drawer-ui id="leading-drawer"&gt;
134
- &lt;list-ui&gt; ... .active=${current === 'primary'} ... &lt;/list-ui&gt;
135
- &lt;/drawer-ui&gt;
136
- `;
137
- }</code-ui>
138
-
139
- <h2>Future v0.6.0: built-in <code>responsive-breakpoint</code></h2>
140
- <p>FEEDBACK-06 §3 Option A proposed a built-in <code>&lt;editor-sidebar responsive-breakpoint="900"&gt;</code> attribute that auto-stamps the drawer twin. Deferred to v0.6.0 — requires editor-shell + pane-ui semantics audit (focus handoff at the inline↔drawer transition, dual-mount event-listener deduplication, etc.). Pairs with a <code>&lt;show-when breakpoint="..."&gt;</code> trait. Until then, the pattern above is the canonical recipe.</p>
141
- </div>
142
81
  </main>
143
82
 
144
- <!-- Trailing sidebar — inline mount (wide-only) -->
145
83
  <aside class="wide-only" data-chunk-slot="trailing-inline">
146
84
  <pane-ui>
147
- <header>
148
- <h3>Settings</h3>
149
- </header>
85
+ <header><h3>Settings</h3></header>
150
86
  <section>
151
87
  <list-ui>
152
88
  <list-item-ui>Lightness</list-item-ui>
@@ -158,11 +94,8 @@ static template = () =&gt; {
158
94
  </aside>
159
95
  </div>
160
96
 
161
- <!-- ═══ DRAWER twins (narrow-only) ═══ -->
162
97
  <drawer-ui id="leading-drawer" side="left" size="sm" data-chunk-slot="leading-drawer">
163
- <header>
164
- <h3>Tokens</h3>
165
- </header>
98
+ <header><h3>Tokens</h3></header>
166
99
  <section>
167
100
  <list-ui>
168
101
  <list-item-ui>Primary</list-item-ui>
@@ -174,9 +107,7 @@ static template = () =&gt; {
174
107
  </drawer-ui>
175
108
 
176
109
  <drawer-ui id="trailing-drawer" side="right" size="sm" data-chunk-slot="trailing-drawer">
177
- <header>
178
- <h3>Settings</h3>
179
- </header>
110
+ <header><h3>Settings</h3></header>
180
111
  <section>
181
112
  <list-ui>
182
113
  <list-item-ui>Lightness</list-item-ui>
@@ -185,24 +116,81 @@ static template = () =&gt; {
185
116
  </list-ui>
186
117
  </section>
187
118
  </drawer-ui>
119
+ </section>
120
+
121
+ <section data-section data-property="pattern">
122
+ <h2 variant="section">The pattern</h2>
123
+ <p>Three pieces:</p>
124
+ <ol>
125
+ <li><strong>Inline mounts</strong> for the sidebars wrapped in <code>.wide-only</code> (display: contents at &gt;900px; display: none at ≤900px).</li>
126
+ <li><strong>Drawer twins</strong> with the same children, mounted outside the shell's named slots, controlled by toolbar buttons inside <code>.narrow-only</code>.</li>
127
+ <li><strong>MediaQueryList</strong> listener that auto-closes the drawers on viewport widening (the gap FEEDBACK-06 §3 explicitly flagged).</li>
128
+ </ol>
129
+ </section>
130
+
131
+ <section data-section data-property="dual-mount-caveat">
132
+ <h2 variant="section">Dual-mount caveat</h2>
133
+ <p>Components with <strong>local DOM state</strong> (uncontrolled form inputs, scroll position, focused element) will lose state when the viewport crosses the breakpoint — the inline copy unmounts and the drawer copy mounts (or vice versa). <strong>Signal-bound components are safe</strong> because their state lives in the signal, not the DOM. Most AdiaUI primitives are signal-backed; the affected cases are:</p>
134
+ <ul>
135
+ <li>Native <code>&lt;input&gt;</code>/<code>&lt;textarea&gt;</code> with no signal binding</li>
136
+ <li>Components using <code>this.querySelector(...)</code> with imperative state</li>
137
+ <li>Scroll-position-sensitive containers (e.g. chat threads at a specific scroll)</li>
138
+ </ul>
139
+ <p>For these, either: (a) lift the state to a signal in the parent, or (b) document the unmount-on-resize edge.</p>
140
+ </section>
141
+
142
+ <section data-section data-property="auto-close">
143
+ <h2 variant="section">Auto-close on viewport widening</h2>
144
+ <code-ui language="javascript">const mql = window.matchMedia('(max-width: 900px)');
145
+ mql.addEventListener('change', (e) =&gt; {
146
+ if (!e.matches) {
147
+ // Viewport widened past breakpoint — close any open drawers
148
+ document.getElementById('leading-drawer').open = false;
149
+ document.getElementById('trailing-drawer').open = false;
150
+ }
151
+ });</code-ui>
152
+ </section>
153
+
154
+ <section data-section data-property="state-sharing">
155
+ <h2 variant="section">State sharing</h2>
156
+ <p>Single signal source consumed by both copies. The parent template reads the signal once and passes the extracted value to both the inline mount AND the drawer mount; on signal change the parent re-renders both:</p>
157
+ <code-ui language="javascript">import { signal } from '@adia-ai/web-components/core';
158
+
159
+ const activeToken = signal('primary');
188
160
 
189
- <script type="module">
190
- // Wire toolbar buttons to drawer triggers
191
- document.getElementById('open-leading')?.addEventListener('press', () => {
192
- document.getElementById('leading-drawer').open = true;
193
- });
194
- document.getElementById('open-trailing')?.addEventListener('press', () => {
195
- document.getElementById('trailing-drawer').open = true;
196
- });
197
-
198
- // Auto-close drawers when viewport crosses breakpoint (widening)
199
- const mql = window.matchMedia('(max-width: 900px)');
200
- mql.addEventListener('change', (e) => {
201
- if (!e.matches) {
202
- document.getElementById('leading-drawer').open = false;
203
- document.getElementById('trailing-drawer').open = false;
204
- }
205
- });
206
- </script>
207
- </body>
208
- </html>
161
+ static template = () =&gt; {
162
+ const current = activeToken.value; // dep read here
163
+ return html`
164
+ &lt;aside class="wide-only"&gt;
165
+ &lt;list-ui&gt; ... .active=${current === 'primary'} ... &lt;/list-ui&gt;
166
+ &lt;/aside&gt;
167
+ &lt;drawer-ui id="leading-drawer"&gt;
168
+ &lt;list-ui&gt; ... .active=${current === 'primary'} ... &lt;/list-ui&gt;
169
+ &lt;/drawer-ui&gt;
170
+ `;
171
+ }</code-ui>
172
+ </section>
173
+
174
+ <section data-section data-property="future">
175
+ <h2 variant="section">Future: built-in <code>responsive-breakpoint</code></h2>
176
+ <p>FEEDBACK-06 §3 Option A proposed a built-in <code>&lt;editor-sidebar responsive-breakpoint="900"&gt;</code> attribute that auto-stamps the drawer twin. Deferred — requires editor-shell + pane-ui semantics audit (focus handoff at the inline↔drawer transition, dual-mount event-listener deduplication, etc.). Pairs with a <code>&lt;show-when breakpoint="..."&gt;</code> trait. Until then, the pattern above is the canonical recipe.</p>
177
+ </section>
178
+
179
+ <script type="module">
180
+ // Wire toolbar buttons to drawer triggers
181
+ document.getElementById('open-leading')?.addEventListener('press', () => {
182
+ document.getElementById('leading-drawer').open = true;
183
+ });
184
+ document.getElementById('open-trailing')?.addEventListener('press', () => {
185
+ document.getElementById('trailing-drawer').open = true;
186
+ });
187
+
188
+ // Auto-close drawers when viewport crosses breakpoint (widening)
189
+ const mql = window.matchMedia('(max-width: 900px)');
190
+ mql.addEventListener('change', (e) => {
191
+ if (!e.matches) {
192
+ document.getElementById('leading-drawer').open = false;
193
+ document.getElementById('trailing-drawer').open = false;
194
+ }
195
+ });
196
+ </script>
@@ -46,7 +46,22 @@
46
46
  ══════════════════════════════════════════════════════════════ */
47
47
 
48
48
  /* L2 — family tokens (re-sourced from --md-sys-color-neutral-*
49
- static export, 2026-07-14 — see file header) */
49
+ static export, 2026-07-14 — see file header)
50
+
51
+ "-strong" MEANS DIFFERENT THINGS BY FAMILY TYPE (gh#969 — documented
52
+ so the divergence stops reading as a mapping bug):
53
+ · --a-canvas-strong (THIS family — structural, non-interactive,
54
+ no active state) is a SURFACE-TONAL tier: the brightest neutral
55
+ surface step (-surface-high).
56
+ · --a-{family}-strong for every INTERACTIVE family (primary /
57
+ secondary / tertiary / info / success / warning / danger) is the
58
+ saturated pressed/high-emphasis FOREGROUND: {family}-active.
59
+ It is deliberately NOT the -container-high tonal tier —
60
+ --a-{family}-subtle is the role that maps there.
61
+ Ruled by material-color-bridge-contract.md's role-class mapping
62
+ (role-class table + the --a-primary-strong worked example). Every
63
+ in-tree consumer of a family -strong uses it as fg/icon/border
64
+ emphasis on a neutral canvas — exactly -active's job. */
50
65
  --a-canvas-strong: var(--md-sys-color-neutral-surface-high);
51
66
  --a-canvas: var(--md-sys-color-neutral-surface);
52
67
  --a-canvas-subtle: var(--md-sys-color-neutral-surface-dim);
@@ -142,7 +157,12 @@
142
157
  ══════════════════════════════════════════════════════════════ */
143
158
 
144
159
  /* L2 — family tokens (re-sourced from --md-sys-color-primary-* static
145
- export, 2026-07-14 — see file header) */
160
+ export, 2026-07-14 — see file header)
161
+ -strong here = {family}-active, the saturated high-emphasis
162
+ FOREGROUND — not a tonal container tier. Interactive families all
163
+ follow this shape; only --a-canvas-strong (no active state to point
164
+ at) means "brightest surface" instead. See the canvas block's
165
+ "-strong MEANS DIFFERENT THINGS" note (gh#969). */
146
166
  --a-primary-strong: var(--md-sys-color-primary-active);
147
167
  --a-primary: var(--md-sys-color-primary);
148
168
  --a-primary-subtle: var(--md-sys-color-primary-container-high);