@adia-ai/web-components 0.8.12 → 0.8.14

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 (75) hide show
  1. package/CHANGELOG.md +27 -0
  2. package/components/adia-mark/adia-mark.examples.md +3 -12
  3. package/components/adia-wordmark/adia-wordmark.examples.md +4 -12
  4. package/components/agent-artifact/agent-artifact.examples.md +0 -9
  5. package/components/agent-feedback-bar/agent-feedback-bar.examples.md +0 -11
  6. package/components/alert/alert.examples.md +1 -1
  7. package/components/badge/badge.examples.md +35 -4
  8. package/components/block/block.examples.md +5 -5
  9. package/components/blockquote/blockquote.examples.md +22 -0
  10. package/components/button/button.examples.md +4 -4
  11. package/components/card/card.examples.md +1 -1
  12. package/components/check/check.examples.md +23 -4
  13. package/components/col/col.examples.md +29 -0
  14. package/components/combobox/combobox.examples.md +9 -15
  15. package/components/command/command.examples.md +3 -3
  16. package/components/context-menu/context-menu.a2ui.json +1 -1
  17. package/components/context-menu/context-menu.css +3 -1
  18. package/components/context-menu/context-menu.examples.md +50 -0
  19. package/components/context-menu/context-menu.yaml +1 -1
  20. package/components/date-range-picker/date-range-picker.examples.md +9 -21
  21. package/components/datetime-picker/datetime-picker.examples.md +9 -30
  22. package/components/demo-toggle/demo-toggle.examples.md +1 -1
  23. package/components/display-field/display-field.examples.md +5 -30
  24. package/components/drawer/drawer.examples.md +17 -32
  25. package/components/field/field.examples.md +30 -11
  26. package/components/grid/grid.examples.md +27 -0
  27. package/components/heatmap/heatmap.examples.md +2 -2
  28. package/components/inline-edit/inline-edit.examples.md +32 -0
  29. package/components/integration-card/integration-card.examples.md +10 -27
  30. package/components/list-window/list-window.examples.md +5 -59
  31. package/components/loading-overlay/loading-overlay.examples.md +19 -36
  32. package/components/mark/mark.examples.md +62 -0
  33. package/components/menu/menu.css +8 -2
  34. package/components/nav/nav.examples.md +2 -2
  35. package/components/nav-group/nav-group.class.js +8 -0
  36. package/components/nav-group/nav-group.examples.md +2 -2
  37. package/components/nav-group/nav-group.test.js +35 -0
  38. package/components/nav-item/nav-item.class.js +6 -0
  39. package/components/nav-item/nav-item.css +21 -6
  40. package/components/noodles/noodles.examples.md +11 -11
  41. package/components/number-format/number-format.examples.md +19 -0
  42. package/components/page/page.examples.md +43 -20
  43. package/components/password-strength/password-strength.examples.md +28 -0
  44. package/components/popover/popover.css +7 -1
  45. package/components/preview/preview.examples.md +30 -0
  46. package/components/progress/progress.examples.md +3 -3
  47. package/components/qr-code/qr-code.examples.md +19 -0
  48. package/components/radio/radio.examples.md +23 -4
  49. package/components/relative-time/relative-time.examples.md +19 -0
  50. package/components/row/row.examples.md +20 -0
  51. package/components/skip-nav/skip-nav.examples.md +27 -0
  52. package/components/spinner/spinner.examples.md +5 -12
  53. package/components/stack/stack.examples.md +17 -0
  54. package/components/stat/stat.examples.md +23 -4
  55. package/components/swatch/swatch.examples.md +2 -2
  56. package/components/switch/switch.examples.md +23 -4
  57. package/components/table-toolbar/table-toolbar.examples.md +46 -0
  58. package/components/tabs/tabs.examples.md +13 -16
  59. package/components/tag/tag.examples.md +4 -4
  60. package/components/tags-input/tags-input.examples.md +6 -73
  61. package/components/text/text.examples.md +37 -6
  62. package/components/time-picker/time-picker.examples.md +3 -15
  63. package/components/toc/toc.examples.md +69 -0
  64. package/components/tour/tour.examples.md +119 -0
  65. package/components/visually-hidden/visually-hidden.examples.md +26 -0
  66. package/dist/theme-provider.min.js +7 -7
  67. package/dist/themes.min.css +1 -1
  68. package/dist/themes.sheet.js +1 -1
  69. package/dist/web-components.min.css +1 -1
  70. package/dist/web-components.min.js +2 -2
  71. package/dist/web-components.sheet.js +1 -1
  72. package/package.json +1 -1
  73. package/styles/host.css +2 -0
  74. package/styles/theme-fonts-url.txt +9 -0
  75. package/styles/themes.css +1936 -135
@@ -1,44 +1,19 @@
1
1
  # display-field — Examples
2
2
 
3
- A display-only labeled value. No input semantics (no focus, no
4
- contenteditable, no form participation). For an editable field use
5
- `field-ui` + `input-ui`; for a metric use `stat-ui`; for many read-only
6
- pairs use `description-list-ui`.
7
-
8
- ## Basic
3
+ ## basic
9
4
 
10
5
  ```html
11
6
  <display-field-ui label="Account ID" value="acct_1Q9xK2"></display-field-ui>
12
7
  ```
13
8
 
14
- ## Masked value
15
-
16
- ```html
17
- <display-field-ui
18
- label="Card on file"
19
- value="•••• •••• •••• 4242"
20
- variant="masked"></display-field-ui>
21
- ```
22
-
23
- ## With a leading icon and a hint
9
+ ## variant="masked"
24
10
 
25
11
  ```html
26
- <display-field-ui
27
- label="Card on file"
28
- value="•••• 4242"
29
- variant="masked"
30
- icon="lock"
31
- hint="Expires 12/26"></display-field-ui>
12
+ <display-field-ui label="Card on file" value="•••• •••• •••• 4242" variant="masked"></display-field-ui>
32
13
  ```
33
14
 
34
- ## Hosting a third-party element (Stripe Element)
35
-
36
- Slot the foreign element as the default child; it takes the value region
37
- under the label. The host's `role="group"` + `aria-labelledby` names it for
38
- assistive tech.
15
+ ## icon + hint
39
16
 
40
17
  ```html
41
- <display-field-ui label="Card number">
42
- <div id="card-element"><!-- stripe.elements().create('card').mount('#card-element') --></div>
43
- </display-field-ui>
18
+ <display-field-ui label="Card on file" value="•••• 4242" variant="masked" icon="lock" hint="Expires 12/26"></display-field-ui>
44
19
  ```
@@ -1,42 +1,16 @@
1
1
  # drawer — Examples
2
2
 
3
- ## Authoring
4
-
5
- ```html
6
- <drawer-ui side="right" size="md">
7
- <header>
8
- <span slot="icon">
9
- <avatar-ui icon="user"></avatar-ui>
10
- </span>
11
- <span slot="heading">
12
- <text-ui strong>Profile</text-ui>
13
- <badge-ui text="Pro" variant="accent"></badge-ui>
14
- </span>
15
- <span slot="description">
16
- <text-ui color="subtle" size="sm">Update your account</text-ui>
17
- </span>
18
- </header>
19
- <section>...</section>
20
- <footer>
21
- <grid-ui>
22
- <button-ui text="Cancel" variant="ghost"></button-ui>
23
- <button-ui text="Save" variant="primary"></button-ui>
24
- </grid-ui>
25
- </footer>
26
- </drawer-ui>
27
- ```
28
-
29
3
  ## side
30
4
 
31
5
  ```html
32
6
  <button-ui text="Left" variant="outline" onclick="this.nextElementSibling.open=true"></button-ui>
33
7
  <drawer-ui text="Navigation" side="left" size="sm">
34
- <section>
35
- <col-ui gap="1">
36
- <button-ui text="Dashboard" icon="house" variant="ghost"></button-ui>
37
- <button-ui text="Projects" icon="folder" variant="ghost"></button-ui>
38
- <button-ui text="Settings" icon="gear" variant="ghost"></button-ui>
39
- </col-ui>
8
+ <section bleed>
9
+ <nav-ui>
10
+ <nav-item-ui icon="house" text="Dashboard" value="dashboard"></nav-item-ui>
11
+ <nav-item-ui icon="folder" text="Projects" value="projects"></nav-item-ui>
12
+ <nav-item-ui icon="gear" text="Settings" value="settings"></nav-item-ui>
13
+ </nav-ui>
40
14
  </section>
41
15
  </drawer-ui>
42
16
  ```
@@ -61,3 +35,14 @@
61
35
  </section>
62
36
  </drawer-ui>
63
37
  ```
38
+
39
+ ## text
40
+
41
+ ```html
42
+ <button-ui text="text=&quot;Settings&quot;" variant="outline" onclick="this.nextElementSibling.open=true"></button-ui>
43
+ <drawer-ui text="Settings" side="right">
44
+ <section>
45
+ <text-ui color="subtle">No header authored — the drawer stamps the title from the text attribute.</text-ui>
46
+ </section>
47
+ </drawer-ui>
48
+ ```
@@ -8,22 +8,41 @@
8
8
  </field-ui>
9
9
  ```
10
10
 
11
- ## Inline layout
11
+ ## Typography registers
12
12
 
13
13
  ```html
14
- <field-ui inline label="Search">
15
- <input-ui type="search" placeholder="Type a command…"></input-ui>
16
- </field-ui>
14
+ <row-ui gap="6" align="start" wrap>
15
+ <col-ui gap="2">
16
+ <text-ui variant="caption" color="muted">verse</text-ui>
17
+ <div verse style="width:220px">
18
+ <field-ui label="Email">
19
+ <input-ui type="email" placeholder="you@example.com"></input-ui>
20
+ </field-ui>
21
+ </div>
22
+ </col-ui>
23
+ <col-ui gap="2">
24
+ <text-ui variant="caption" color="muted">regular</text-ui>
25
+ <div style="width:220px">
26
+ <field-ui label="Email">
27
+ <input-ui type="email" placeholder="you@example.com"></input-ui>
28
+ </field-ui>
29
+ </div>
30
+ </col-ui>
31
+ <col-ui gap="2">
32
+ <text-ui variant="caption" color="muted">prose</text-ui>
33
+ <div prose style="width:220px">
34
+ <field-ui label="Email">
35
+ <input-ui type="email" placeholder="you@example.com"></input-ui>
36
+ </field-ui>
37
+ </div>
38
+ </col-ui>
39
+ </row-ui>
17
40
  ```
18
41
 
19
- ## Any form control
42
+ ## Inline layout
20
43
 
21
44
  ```html
22
- <field-ui label="Priority">
23
- <select-ui>
24
- <option value="low">Low</option>
25
- <option value="med" selected>Medium</option>
26
- <option value="high">High</option>
27
- </select-ui>
45
+ <field-ui inline label="Search">
46
+ <input-ui type="search" placeholder="Type a command…"></input-ui>
28
47
  </field-ui>
29
48
  ```
@@ -19,3 +19,30 @@
19
19
  <card-ui>Side panel</card-ui>
20
20
  </grid-ui>
21
21
  ```
22
+
23
+ ## Rendered demos
24
+
25
+ ```html
26
+ <grid-ui columns="4" gap="3">
27
+ <card-ui>
28
+ <section>
29
+ <stat-ui label="Revenue" value="$12,400" change="+8.4%" trend="up" icon="currency-dollar"></stat-ui>
30
+ </section>
31
+ </card-ui>
32
+ <card-ui>
33
+ <section>
34
+ <stat-ui label="Users" value="2,840" change="+12%" trend="up" icon="users"></stat-ui>
35
+ </section>
36
+ </card-ui>
37
+ <card-ui>
38
+ <section>
39
+ <stat-ui label="Conversion" value="3.2%" change="-0.3%" trend="down" icon="chart-line"></stat-ui>
40
+ </section>
41
+ </card-ui>
42
+ <card-ui>
43
+ <section>
44
+ <stat-ui label="Avg. Order" value="$87" change="+$4" trend="up" icon="receipt"></stat-ui>
45
+ </section>
46
+ </card-ui>
47
+ </grid-ui>
48
+ ```
@@ -12,8 +12,8 @@
12
12
  <heatmap-ui id="hm-matrix" type="matrix" rows="7" cols="12" color-scheme="accent"></heatmap-ui>
13
13
  ```
14
14
 
15
- ## Data stream (data-stream-*)
15
+ ## color-scheme
16
16
 
17
17
  ```html
18
- <heatmap-ui type="matrix" rows="5" cols="4" color-scheme="accent" aria-label="Commit activity from activity.json" data-stream-src="/site/mock/activity.json"></heatmap-ui>
18
+ <heatmap-ui type="matrix" rows="7" cols="12" color-scheme="warning"></heatmap-ui>
19
19
  ```
@@ -0,0 +1,32 @@
1
+ # inline-edit — Examples
2
+
3
+ ## Basic click-to-edit
4
+
5
+ ```html
6
+ <col-ui gap="2">
7
+ <text-ui size="sm" color="subtle">Draft document title</text-ui>
8
+ <h2 style="margin: 0;">
9
+ <inline-edit-ui value="Quarterly revenue report — Q4 2025"></inline-edit-ui>
10
+ </h2>
11
+ </col-ui>
12
+ ```
13
+
14
+ ## Empty + placeholder
15
+
16
+ ```html
17
+ <col-ui gap="2">
18
+ <text-ui size="sm" color="subtle">Untitled item</text-ui>
19
+ <h3 style="margin: 0;">
20
+ <inline-edit-ui placeholder="Click to name this draft"></inline-edit-ui>
21
+ </h3>
22
+ </col-ui>
23
+ ```
24
+
25
+ ## Commit policy
26
+
27
+ ```html
28
+ <col-ui gap="2">
29
+ <text-ui size="sm" color="subtle">commit="blur" — default</text-ui>
30
+ <inline-edit-ui value="Click outside to save" commit="blur"></inline-edit-ui>
31
+ </col-ui>
32
+ ```
@@ -1,41 +1,24 @@
1
1
  # integration-card — Examples
2
2
 
3
- ## Available (default)
3
+ ## status
4
4
 
5
5
  ```html
6
- <integration-card-ui
7
- provider="slack"
8
- name="Slack"
9
- logo="/integrations/slack.svg"
10
- description="Send AI replies and notifications to channels."
11
- status="available">
12
- </integration-card-ui>
6
+ <integration-card-ui provider="slack" name="Slack" description="Send AI replies and notifications to channels." status="available"></integration-card-ui>
13
7
  ```
14
8
 
15
- ## Connected — overflow menu
9
+ ## logo
16
10
 
17
11
  ```html
18
- <integration-card-ui provider="github" name="GitHub" status="connected"
19
- logo="/integrations/github.svg"
20
- description="Sync issues and pull requests.">
21
- <menu-ui slot="actions" label="More" trigger-icon="dots-three" trigger-variant="ghost">
22
- <menu-item-ui action="reauth">Re-authenticate</menu-item-ui>
23
- <menu-item-ui action="disconnect" variant="danger">Disconnect</menu-item-ui>
24
- </menu-ui>
25
- </integration-card-ui>
12
+ <integration-card-ui provider="webhook" name="Webhook" description="POST events to a custom endpoint." logo="lightning" status="available"></integration-card-ui>
26
13
  ```
27
14
 
28
- ## Error — Retry
15
+ ## actions slot
29
16
 
30
17
  ```html
31
- <integration-card-ui provider="stripe" name="Stripe" status="error"
32
- error-message="Token expired re-authenticate.">
33
- </integration-card-ui>
34
- ```
35
-
36
- ## Coming soon (non-interactive)
37
-
38
- ```html
39
- <integration-card-ui provider="zapier" name="Zapier" status="coming-soon">
18
+ <integration-card-ui provider="github" name="GitHub" description="Sync issues and pull requests." status="connected">
19
+ <menu-ui slot="actions" label="More" trigger-icon="dots-three" trigger-variant="ghost">
20
+ <menu-item-ui action="reauth">Re-authenticate</menu-item-ui>
21
+ <menu-item-ui action="disconnect" variant="danger">Disconnect</menu-item-ui>
22
+ </menu-ui>
40
23
  </integration-card-ui>
41
24
  ```
@@ -1,73 +1,19 @@
1
1
  # list-window — Examples
2
2
 
3
- ## basic — fixed-size rows
3
+ ## basic — fixed-size rows, 1000 items
4
4
 
5
5
  ```html
6
- <list-window-ui item-size="40" overscan="3" style="height:320px">
7
- </list-window-ui>
8
- <script>
9
- const el = document.querySelector('list-window-ui');
10
- el.renderRow = (item) => {
11
- const row = document.createElement('list-item-ui');
12
- row.setAttribute('text', item.text);
13
- return row;
14
- };
15
- el.items = Array.from({ length: 1000 }, (_, i) => ({
16
- id: `b-${i}`,
17
- text: `Row ${i + 1}`,
18
- }));
19
- </script>
6
+ <list-window-ui id="lw-basic" item-size="40" overscan="3" style="height: 320px; border: 1px solid var(--md-sys-color-neutral-outline-variant); border-radius: var(--a-radius-md);"></list-window-ui>
20
7
  ```
21
8
 
22
9
  ## 10,000 rows
23
10
 
24
11
  ```html
25
- <list-window-ui item-size="32" overscan="5" style="height:320px">
26
- </list-window-ui>
27
- <script>
28
- const el = document.querySelector('list-window-ui');
29
- el.items = Array.from({ length: 10_000 }, (_, i) => ({
30
- id: `lg-${i}`,
31
- text: `Log line ${i}`,
32
- }));
33
- </script>
12
+ <list-window-ui id="lw-large" item-size="32" overscan="5" style="height: 320px; border: 1px solid var(--md-sys-color-neutral-outline-variant); border-radius: var(--a-radius-md); font-family: var(--a-font-mono);"></list-window-ui>
34
13
  ```
35
14
 
36
- ## pin-bottomchat-thread / log-tail
15
+ ## variable-heightfeed-card rows
37
16
 
38
17
  ```html
39
- <list-window-ui item-size="28" pin-bottom style="height:240px">
40
- </list-window-ui>
41
- <script>
42
- const el = document.querySelector('list-window-ui');
43
- el.items = initialMessages;
44
- // Appending keeps scroll pinned at the bottom.
45
- el.items = [...el.items, ...newMessages];
46
- </script>
47
- ```
48
-
49
- ## variable-height — feed cards
50
-
51
- ```html
52
- <list-window-ui estimated-size="120" overscan="2" style="height:360px">
53
- </list-window-ui>
54
- <script>
55
- const el = document.querySelector('list-window-ui');
56
- el.renderRow = (item) => buildCardElement(item);
57
- el.items = cards;
58
- </script>
59
- ```
60
-
61
- ## loading state
62
-
63
- ```html
64
- <list-window-ui item-size="48" loading style="height:240px"></list-window-ui>
65
- ```
66
-
67
- ## empty state
68
-
69
- ```html
70
- <list-window-ui item-size="40" style="height:160px">
71
- <div slot="empty">No items to display.</div>
72
- </list-window-ui>
18
+ <list-window-ui id="lw-variable" estimated-size="120" overscan="2" style="height: 360px; border: 1px solid var(--md-sys-color-neutral-outline-variant); border-radius: var(--a-radius-md);"></list-window-ui>
73
19
  ```
@@ -1,50 +1,33 @@
1
1
  # loading-overlay — Examples
2
2
 
3
- ## Default (auto-stamped spinner)
4
-
5
- The host parent must be positioned (`position: relative` or similar);
6
- the overlay does not mutate parent layout. When the default slot is
7
- empty, a centered `<spinner-ui size="lg">` is auto-stamped.
8
-
9
- ```html
10
- <card-ui style="position: relative;">
11
- <section>
12
- <table-ui id="orders" data-stream-src="/api/orders"></table-ui>
13
- <loading-overlay-ui active label="Loading orders…"></loading-overlay-ui>
14
- </section>
15
- </card-ui>
16
- ```
17
-
18
- ## Skeleton placeholder
19
-
20
- Pair `variant="transparent"` with a slotted skeleton stack to render
21
- shape-of-content placeholders instead of a centered spinner.
3
+ ## Default
22
4
 
23
5
  ```html
24
- <div style="position: relative;">
25
- <loading-overlay-ui active variant="transparent" label="Loading content">
26
- <stack-ui>
27
- <skeleton-ui width="100%" height="1rem"></skeleton-ui>
28
- <skeleton-ui width="80%" height="1rem"></skeleton-ui>
29
- <skeleton-ui width="60%" height="1rem"></skeleton-ui>
30
- </stack-ui>
31
- </loading-overlay-ui>
6
+ <div style="position:relative; width:240px; height:180px; padding:var(--a-space-4); border:1px solid var(--md-sys-color-neutral-outline-variant); border-radius:var(--a-radius-md);">
7
+ <p style="margin:0;">Card content the overlay is covering.</p>
8
+ <loading-overlay-ui active label="Loading…" delay="0"></loading-overlay-ui>
32
9
  </div>
33
10
  ```
34
11
 
35
- ## Fast-load (no flash)
36
-
37
- The default 200 ms grace window suppresses paint on fast-resolving
38
- loads. If the underlying work resolves before the timer fires, the
39
- overlay never paints.
12
+ ## variant
40
13
 
41
14
  ```html
42
- <loading-overlay-ui active delay="200"></loading-overlay-ui>
15
+ <div style="position:relative; width:200px; height:140px; padding:var(--a-space-4); border:1px solid var(--md-sys-color-neutral-outline-variant); border-radius:var(--a-radius-md);">
16
+ <p style="margin:0;">Content</p>
17
+ <loading-overlay-ui active variant="default" label="Loading" delay="0"></loading-overlay-ui>
18
+ </div>
43
19
  ```
44
20
 
45
- For known-slow operations (server-side jobs, large uploads) opt out
46
- with `delay="0"`:
21
+ ## Skeleton placeholder
47
22
 
48
23
  ```html
49
- <loading-overlay-ui active delay="0" label="Generating report…"></loading-overlay-ui>
24
+ <div style="position:relative; width:280px; height:200px; padding:var(--a-space-4); border:1px solid var(--md-sys-color-neutral-outline-variant); border-radius:var(--a-radius-md);">
25
+ <loading-overlay-ui active variant="transparent" label="Loading content" delay="0">
26
+ <div style="display:flex; flex-direction:column; gap:var(--a-space-2); width:100%; padding:var(--a-space-4); box-sizing:border-box;">
27
+ <skeleton-ui width="100%" height="1.2rem"></skeleton-ui>
28
+ <skeleton-ui width="80%" height="1rem"></skeleton-ui>
29
+ <skeleton-ui width="60%" height="1rem"></skeleton-ui>
30
+ </div>
31
+ </loading-overlay-ui>
32
+ </div>
50
33
  ```
@@ -0,0 +1,62 @@
1
+ # mark — Examples
2
+
3
+ ## Search-result match
4
+
5
+ ```html
6
+ <col-ui gap="3">
7
+ <text-ui size="lg">
8
+ Quarterly
9
+ <mark-ui>revenue</mark-ui>
10
+ report — Q4 2025
11
+ </text-ui>
12
+ <text-ui size="lg">
13
+ Annual
14
+ <mark-ui>revenue</mark-ui>
15
+ projections — 2026 outlook
16
+ </text-ui>
17
+ <text-ui size="lg">
18
+ Marketing spend vs
19
+ <mark-ui>revenue</mark-ui>
20
+ attribution
21
+ </text-ui>
22
+ </col-ui>
23
+ ```
24
+
25
+ ## Variants
26
+
27
+ ```html
28
+ <col-ui gap="2">
29
+ <text-ui>
30
+ <mark-ui>warning</mark-ui>
31
+ — the default; classic highlighter yellow.
32
+ </text-ui>
33
+ <text-ui>
34
+ <mark-ui variant="info">info</mark-ui>
35
+ — brand-color emphasis.
36
+ </text-ui>
37
+ <text-ui>
38
+ <mark-ui variant="success">success</mark-ui>
39
+ — added line, "new since".
40
+ </text-ui>
41
+ <text-ui>
42
+ <mark-ui variant="danger">danger</mark-ui>
43
+ — removed line, conflict.
44
+ </text-ui>
45
+ <text-ui>
46
+ <mark-ui variant="muted">muted</mark-ui>
47
+ — neutral emphasis.
48
+ </text-ui>
49
+ </col-ui>
50
+ ```
51
+
52
+ ## Diff prose (success / danger)
53
+
54
+ ```html
55
+ <text-ui>
56
+ We now ship
57
+ <mark-ui variant="success">light-DOM web components</mark-ui>
58
+ for theme-aware rendering, replacing the previous
59
+ <mark-ui variant="danger">shadow-DOM module system</mark-ui>
60
+ . The migration is incremental.
61
+ </text-ui>
62
+ ```
@@ -3,7 +3,11 @@
3
3
  --menu-popover-padding: var(--a-space-1);
4
4
  --menu-popover-border: var(--md-sys-color-neutral-outline-variant);
5
5
  --menu-popover-radius: var(--a-radius-lg);
6
- --menu-popover-bg: var(--a-bg-subtle);
6
+ /* surface-bright — the one elevated-overlay plane shared with
7
+ select-ui's dropdown, popover-ui, and context-menu-ui. Was
8
+ --a-bg-subtle (--md-sys-color-neutral-surface), i.e. page level, so a
9
+ menu floating over the page read flat against it in dark mode. */
10
+ --menu-popover-bg: var(--md-sys-color-neutral-surface-bright);
7
11
  --menu-popover-shadow: var(--a-shadow-lg);
8
12
  --menu-popover-min-width: 10rem;
9
13
  --menu-popover-font-size: var(--a-ui-size);
@@ -49,7 +53,9 @@ menu-ui [data-menu-popover] {
49
53
  padding: var(--a-space-1);
50
54
  border: 1px solid var(--md-sys-color-neutral-outline-variant);
51
55
  border-radius: var(--a-radius-lg);
52
- background: var(--a-bg-subtle);
56
+ /* Keep in sync with --menu-popover-bg above — the top-layer element can't
57
+ inherit the scoped token (see the note at this block's head). */
58
+ background: var(--md-sys-color-neutral-surface-bright);
53
59
  box-shadow: var(--a-shadow-lg);
54
60
  min-width: 10rem;
55
61
  font-family: var(--menu-font-family, var(--a-font-family-ui));
@@ -3,7 +3,7 @@
3
3
  ## variant — primary
4
4
 
5
5
  ```html
6
- <nav-ui style="width:240px;height:280px;border:1px solid var(--a-border);border-radius:var(--a-radius-md);padding:var(--a-space-2);">
6
+ <nav-ui style="width:240px;height:280px;border:1px solid var(--md-sys-color-neutral-outline);border-radius:var(--a-radius-md);padding:var(--a-space-2);">
7
7
  <nav-item-ui text="Dashboard" icon="house" value="dashboard" selected></nav-item-ui>
8
8
  <nav-item-ui text="Reports" icon="chart-bar" value="reports"></nav-item-ui>
9
9
  <nav-group-ui text="Settings" icon="gear">
@@ -28,7 +28,7 @@
28
28
  ## collapsed
29
29
 
30
30
  ```html
31
- <nav-ui collapsed style="width:64px;height:280px;border:1px solid var(--a-border);border-radius:var(--a-radius-md);padding:var(--a-space-2);">
31
+ <nav-ui collapsed style="width:64px;height:280px;border:1px solid var(--md-sys-color-neutral-outline);border-radius:var(--a-radius-md);padding:var(--a-space-2);">
32
32
  <nav-item-ui text="Dashboard" icon="house" value="dashboard" selected></nav-item-ui>
33
33
  <nav-item-ui text="Reports" icon="chart-bar" value="reports"></nav-item-ui>
34
34
  <nav-group-ui text="Settings" icon="gear">
@@ -86,6 +86,14 @@ export class UINavGroup extends UIElement {
86
86
  if (badgeEl) badgeEl.textContent = this.badge;
87
87
 
88
88
  this.setAttribute('aria-expanded', String(this.open));
89
+
90
+ // Mirrors nav-item-ui's selected → fill convention: an open group
91
+ // reads as the active section via the same filled-glyph treatment
92
+ // [open] already drives (nav-group.css's [open] > [slot=header] color
93
+ // rule) — a state-driven weight swap, not a CSS color change, since
94
+ // Phosphor ships filled/regular as distinct SVGs.
95
+ const iconEl = this.querySelector('[slot="header"] [slot="icon"] icon-ui');
96
+ if (iconEl) iconEl.setAttribute('weight', this.open ? 'fill' : 'regular');
89
97
  }
90
98
 
91
99
  showPopover() {
@@ -3,7 +3,7 @@
3
3
  ## text + icon
4
4
 
5
5
  ```html
6
- <nav-ui style="width:240px;border:1px solid var(--a-border);border-radius:var(--a-radius-md);padding:var(--a-space-2);">
6
+ <nav-ui style="width:240px;border:1px solid var(--md-sys-color-neutral-outline);border-radius:var(--a-radius-md);padding:var(--a-space-2);">
7
7
  <nav-group-ui text="Settings" icon="gear">
8
8
  <nav-item-ui text="Profile" value="settings/profile"></nav-item-ui>
9
9
  <nav-item-ui text="Billing" value="settings/billing"></nav-item-ui>
@@ -14,7 +14,7 @@
14
14
  ## badge
15
15
 
16
16
  ```html
17
- <nav-ui style="width:240px;border:1px solid var(--a-border);border-radius:var(--a-radius-md);padding:var(--a-space-2);">
17
+ <nav-ui style="width:240px;border:1px solid var(--md-sys-color-neutral-outline);border-radius:var(--a-radius-md);padding:var(--a-space-2);">
18
18
  <nav-group-ui text="Notifications" icon="bell" badge="3" open>
19
19
  <nav-item-ui text="Mentions" value="notif/mentions"></nav-item-ui>
20
20
  <nav-item-ui text="Follows" value="notif/follows"></nav-item-ui>
@@ -30,3 +30,38 @@ describe('nav-group-ui — header stamp-if-absent (wrapper trap)', () => {
30
30
  expect(headers[0].dataset.test).toBe('h');
31
31
  });
32
32
  });
33
+
34
+ describe('nav-group-ui — [open] drives the header icon weight', () => {
35
+ beforeEach(() => { document.body.innerHTML = ''; });
36
+
37
+ it('defaults the auto-stamped header icon to weight="regular"', async () => {
38
+ const el = mount('<nav-group-ui text="Reports" icon="folder"></nav-group-ui>');
39
+ await tick();
40
+ const icon = el.querySelector('[slot="header"] [slot="icon"] icon-ui');
41
+ expect(icon.getAttribute('weight')).toBe('regular');
42
+ });
43
+
44
+ it('switches the header icon to weight="fill" when [open] is set', async () => {
45
+ const el = mount('<nav-group-ui text="Reports" icon="folder"></nav-group-ui>');
46
+ await tick();
47
+ el.open = true;
48
+ await tick();
49
+ const icon = el.querySelector('[slot="header"] [slot="icon"] icon-ui');
50
+ expect(icon.getAttribute('weight')).toBe('fill');
51
+ });
52
+
53
+ it('reverts to weight="regular" when [open] is cleared', async () => {
54
+ const el = mount('<nav-group-ui text="Reports" icon="folder" open></nav-group-ui>');
55
+ await tick();
56
+ el.open = false;
57
+ await tick();
58
+ const icon = el.querySelector('[slot="header"] [slot="icon"] icon-ui');
59
+ expect(icon.getAttribute('weight')).toBe('regular');
60
+ });
61
+
62
+ it('is a no-op when the group has no icon (empty icon slot, no icon-ui)', async () => {
63
+ const el = mount('<nav-group-ui text="Reports" open></nav-group-ui>');
64
+ await tick();
65
+ expect(el.querySelector('[slot="header"] [slot="icon"] icon-ui')).toBeNull();
66
+ });
67
+ });
@@ -77,6 +77,12 @@ export class UINavItem extends UIElement {
77
77
  this.setAttribute('tabindex', this.disabled ? '-1' : '0');
78
78
  if (this.selected) this.setAttribute('aria-current', 'page');
79
79
  else this.removeAttribute('aria-current');
80
+
81
+ // Selected rows read as filled glyphs, unselected as regular weight —
82
+ // a state-driven weight swap (Phosphor ships filled/regular as distinct
83
+ // SVGs, so this can't be a CSS-only color change).
84
+ const iconEl = this.querySelector('[slot="icon"] icon-ui');
85
+ if (iconEl) iconEl.setAttribute('weight', this.selected ? 'fill' : 'regular');
80
86
  }
81
87
 
82
88
  disconnected() {