@adia-ai/web-components 0.8.32 → 0.8.33

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 (70) hide show
  1. package/CHANGELOG.md +27 -0
  2. package/MIGRATION.md +136 -0
  3. package/components/accordion/accordion-item.a2ui.json +8 -0
  4. package/components/accordion/accordion-item.yaml +6 -0
  5. package/components/accordion/accordion.css +3 -1
  6. package/components/alert/alert.a2ui.json +3 -5
  7. package/components/alert/alert.class.js +3 -3
  8. package/components/alert/alert.css +5 -12
  9. package/components/alert/alert.d.ts +2 -2
  10. package/components/alert/alert.yaml +6 -5
  11. package/components/badge/badge.a2ui.json +6 -9
  12. package/components/badge/badge.class.js +4 -4
  13. package/components/badge/badge.css +105 -73
  14. package/components/badge/badge.d.ts +34 -12
  15. package/components/badge/badge.examples.md +1 -1
  16. package/components/badge/badge.yaml +37 -16
  17. package/components/button/button.a2ui.json +1 -1
  18. package/components/button/button.css +4 -2
  19. package/components/button/button.d.ts +2 -2
  20. package/components/button/button.yaml +1 -1
  21. package/components/card/card.yaml +1 -1
  22. package/components/chart/chart.class.js +8 -4
  23. package/components/integration-card/integration-card.class.js +11 -2
  24. package/components/mark/mark.a2ui.json +6 -7
  25. package/components/mark/mark.class.js +1 -1
  26. package/components/mark/mark.css +7 -4
  27. package/components/mark/mark.d.ts +2 -2
  28. package/components/mark/mark.examples.md +0 -4
  29. package/components/mark/mark.yaml +16 -6
  30. package/components/option-card/option-card.examples.md +1 -1
  31. package/components/popover/popover.a2ui.json +5 -0
  32. package/components/popover/popover.class.js +9 -4
  33. package/components/popover/popover.css +5 -2
  34. package/components/popover/popover.yaml +8 -0
  35. package/components/preview/preview.examples.md +1 -1
  36. package/components/table/cell-types.js +12 -1
  37. package/components/table-toolbar/table-toolbar.class.js +1 -1
  38. package/components/tag/tag.a2ui.json +5 -5
  39. package/components/tag/tag.class.js +1 -1
  40. package/components/tag/tag.css +86 -73
  41. package/components/tag/tag.d.ts +17 -11
  42. package/components/tag/tag.yaml +30 -19
  43. package/components/toast/toast.a2ui.json +2 -4
  44. package/components/toast/toast.css +0 -12
  45. package/components/toast/toast.yaml +3 -4
  46. package/dist/theme-provider.min.js +1 -1
  47. package/dist/web-components.min.css +1 -1
  48. package/dist/web-components.min.js +63 -63
  49. package/dist/web-components.sheet.js +1 -1
  50. package/package.json +1 -1
  51. package/patterns/admin-keys-and-export/admin-keys-and-export.examples.html +1 -1
  52. package/patterns/agent-memory/agent-memory.examples.html +5 -5
  53. package/patterns/agent-prompt-library/agent-prompt-library.examples.html +2 -2
  54. package/patterns/audit-log/audit-log.examples.js +12 -5
  55. package/patterns/bulk-action-toolbar/bulk-action-toolbar.examples.js +4 -1
  56. package/patterns/changelog-feed/changelog-feed.examples.html +1 -1
  57. package/patterns/comments-and-collaboration/comments-and-collaboration.examples.html +1 -1
  58. package/patterns/conversion-funnel/conversion-funnel.examples.html +1 -1
  59. package/patterns/diff-review/diff-review.examples.html +9 -9
  60. package/patterns/filter-bar/filter-bar.examples.html +12 -8
  61. package/patterns/filter-bar/filter-bar.examples.js +4 -1
  62. package/patterns/marketing-engagement/marketing-engagement.examples.html +1 -1
  63. package/patterns/notifications-bell-and-digest/notifications-bell-and-digest.examples.html +1 -1
  64. package/patterns/permissions-matrix/permissions-matrix.examples.html +1 -1
  65. package/patterns/permissions-sharing/permissions-sharing.examples.html +1 -1
  66. package/patterns/profile-public-and-verification/profile-public-and-verification.examples.html +2 -2
  67. package/patterns/record-detail-drawer/record-detail-drawer.examples.html +1 -1
  68. package/patterns/retention-cohort/retention-cohort.examples.html +1 -1
  69. package/patterns/retention-cohort/retention-cohort.examples.js +4 -1
  70. package/patterns/system-banners/system-banners.examples.html +3 -3
@@ -1,14 +1,41 @@
1
1
  @scope (badge-ui) {
2
2
  :where(:scope) {
3
- /* ── Tokens ── */
4
- --badge-bg: var(--a-bg-muted);
5
- --badge-fg: var(--md-sys-color-neutral-on-surface);
6
- --badge-radius: var(--a-radius-md);
3
+ /* ── Tokens ──
4
+ The family-less default was still `--a-bg-muted` + `-on-surface`
5
+ (quiet chrome) even after gh#864 made every family variant solid
6
+ by default — an inconsistency the swap missed, since it only
7
+ touched variants that HAD a family. Moved to the real
8
+ `--md-sys-color-neutral`/`-on-neutral` pair (operator ruling,
9
+ 2026-08-10) — the true parallel to `-primary`/`-on-primary` etc.,
10
+ matching badge's own "solid by default" register and <tag-ui>'s
11
+ already-solid neutral default. `[tone="muted"]` (below) still
12
+ opts into the quiet chrome this rule used to carry unconditionally. */
13
+ --badge-bg: var(--md-sys-color-neutral);
14
+ --badge-fg: var(--md-sys-color-neutral-on-neutral);
15
+ /* ── Geometry (issue 845) — aligned to tag-ui's token rhythm. Radius now
16
+ consumes the SAME --a-radius-full pill tag-ui uses (was --a-radius-md,
17
+ a squarer chip) — shape is no longer the differentiation axis between
18
+ the two (operator ruling, issue 845). Padding already shared tag's
19
+ exact token structure pre-845 (see the size-tier comment below) —
20
+ only radius moved. */
21
+ --badge-radius: var(--a-radius-full);
7
22
  --badge-px: var(--a-space-1-5);
8
23
  --badge-py: var(--a-space-0-5);
9
24
  --badge-gap: var(--a-space-1);
10
25
  --badge-font-size: var(--a-ui-sm);
11
- --badge-font-family: var(--a-font-family-ui);
26
+ /* ── Typographic register (issue 845; weight revised gh#866) — mono
27
+ TRIAL taken: kbd-ui's own stack (--a-font-family-code, kbd.css) held
28
+ up at small badge sizes (roughly a dozen logical pixels) in both
29
+ schemes once paired with wide tracking (screenshot-verified, see PR
30
+ body) — did not read starved/gappy, so the trial's fallback branch
31
+ (tracked-caps sans) was not needed. Weight moved semibold → medium
32
+ (gh#866) — it no longer distinguishes badge from tag (tag is also
33
+ weight 500). Uppercase + wide tracking + mono + tabular-nums is the
34
+ register now — this is what makes a badge unmistakably NOT a tag
35
+ (which stays proportional sentence-case) at a glance. */
36
+ --badge-font-family: var(--a-font-family-code);
37
+ --badge-weight: var(--a-weight-medium);
38
+ --badge-tracking: var(--a-font-tracking-wider); /* 0.06em — within the +0.04–0.08em ruling */
12
39
 
13
40
  /* ── Size tiers (gh#779) — md (above) is the pixel-identical default.
14
41
  Component-owned ladder, not a direct alias of the universal
@@ -38,8 +65,15 @@
38
65
  /* font-family floor — see segment.css rationale. */
39
66
  font-family: var(--badge-font-family);
40
67
  font-size: var(--badge-font-size);
41
- font-weight: 500;
68
+ font-weight: var(--badge-weight);
42
69
  line-height: 1;
70
+ /* ── Register (issue 845) — uppercase + tracking + tabular numerals is the
71
+ badge/tag differentiator now that geometry is shared (see the
72
+ --badge-radius note above). Tag stays proportional sentence-case at
73
+ weight 500 (tag.css) — never uppercase, never tracked. */
74
+ text-transform: uppercase;
75
+ letter-spacing: var(--badge-tracking);
76
+ font-variant-numeric: tabular-nums;
43
77
  border-radius: var(--badge-radius);
44
78
  white-space: nowrap;
45
79
  vertical-align: middle;
@@ -56,7 +90,7 @@
56
90
 
57
91
  /* Leading icon stamped by JS (when [icon] is set). Inherits the badge's
58
92
  foreground color so legend chips read as a single color-coded unit
59
- (e.g. accent variant → accent-colored dot + accent-colored label).
93
+ (e.g. primary variant → primary-colored dot + primary-colored label).
60
94
  ICON-HEIGHT FIX: cap the icon block-size so it cannot exceed the text
61
95
  line-height. `line-height:1` on the badge drives the block size via
62
96
  the text glyph; an icon taller than 1em would inflate the row. */
@@ -78,93 +112,91 @@
78
112
  }
79
113
 
80
114
  /* ── Variants ──
81
- Badge fg pairs with the muted (tinted) bg — use --a-{family}-text, which
82
- flips with scheme (shade in light, tint in dark) for proper contrast.
83
- --a-{family}-text-strong is for solid fills (--a-{family}-bg) and would
84
- collapse contrast on muted: warning fails in dark, danger fails in light.
85
- Accent keeps the saturated-text-on-tint look (intentional brand emphasis). */
86
- :scope[variant="accent"] {
87
- --badge-bg: var(--md-sys-color-primary-container);
88
- --badge-fg: var(--md-sys-color-primary-on-surface);
89
- }
90
-
115
+ Family fg pairs with the family's own solid bg — this is badge's
116
+ default tone (gh#864). Badge and tag had been implementing each
117
+ OTHER's reported default formula (gh#794 flipped tag's bare default to
118
+ solid a day before gh#845 ratified badge's register, with no cross-
119
+ check between the two changes) this restores badge's own: saturated
120
+ `--a-{family}-bg` + Material's on-color (`-on-{family}`, near-white by
121
+ the fixed-light-on-color law). Reads as a status stamp — the badge IS
122
+ the state. `[tone="muted"]` below opts into the tinted-container pair
123
+ instead (the shape this rule used to carry pre-gh#864).
124
+
125
+ Warning uses --a-warning-bg (semantics.css L3 redirect to the bright-
126
+ amber -20-tint) rather than the raw family token, which would collapse
127
+ to muddy brown-on-brown (-on-warning is dark, the raw mid-tone bg
128
+ isn't). See <tag-ui>'s identical workaround. */
91
129
  :scope[variant="info"] {
92
- --badge-bg: var(--md-sys-color-info-container);
93
- --badge-fg: var(--md-sys-color-info-on-surface);
130
+ --badge-bg: var(--a-info-bg);
131
+ --badge-fg: var(--md-sys-color-info-on-info);
94
132
  }
95
133
 
96
134
  :scope[variant="success"] {
97
- --badge-bg: var(--md-sys-color-success-container);
98
- --badge-fg: var(--md-sys-color-success-on-surface);
135
+ --badge-bg: var(--a-success-bg);
136
+ --badge-fg: var(--md-sys-color-success-on-success);
99
137
  }
100
138
 
101
139
  :scope[variant="warning"] {
102
- --badge-bg: var(--md-sys-color-warning-container);
103
- --badge-fg: var(--md-sys-color-warning-on-surface);
140
+ --badge-bg: var(--a-warning-bg);
141
+ --badge-fg: var(--md-sys-color-warning-on-warning);
104
142
  }
105
143
 
106
144
  :scope[variant="danger"] {
107
- --badge-bg: var(--md-sys-color-danger-container);
108
- --badge-fg: var(--md-sys-color-danger-on-surface);
145
+ --badge-bg: var(--a-danger-bg);
146
+ --badge-fg: var(--md-sys-color-danger-on-danger);
109
147
  }
110
148
 
111
- /* `primary` is the accent-filled variant — solid bg + on-accent text,
112
- used for "PRO"-style emphasis chips that should read as a brand
113
- stamp rather than tinted-on-canvas. Uses the L3 primary-* surface
114
- matrix so it tracks the same accent-strong source as button-ui's
115
- primary variant. */
149
+ /* `primary` is badge's sole brand-emphasis variant (accent retired,
150
+ gh#874 this rule is the identical solid pair the deleted
151
+ [variant="accent"] rule used to carry; renamed, not restyled).
152
+ Uses the L3 primary-* surface matrix so it tracks the same source
153
+ as button-ui's primary variant. */
116
154
  :scope[variant="primary"] {
117
155
  --badge-bg: var(--a-primary-bg);
118
156
  --badge-fg: var(--md-sys-color-primary-on-primary);
119
157
  }
120
158
 
121
- /* `muted` and `neutral` are semantic aliases of the base — same tokens
122
- as the default variant, declared explicitly so the yaml enum and the
123
- CSS contract agree. Use cases: passive metadata chips (counts, IDs,
124
- "Not set" states) where the badge should read as quiet chrome. */
125
- :scope[variant="muted"],
126
- :scope[variant="neutral"] {
127
- --badge-bg: var(--a-bg-muted);
128
- --badge-fg: var(--md-sys-color-neutral-on-surface);
129
- }
130
-
131
159
  /* ── Tone modifier — orthogonal to [variant] ──
132
- Badge's default tone is `muted` (the rules above) — quiet metadata is
133
- the primitive's identity. `[tone="solid"]` opts into the saturated-fill
134
- pair (same shape <tag-ui>'s solid default uses); `[tone="outline"]`
135
- into the transparent-fill + colored-ring shape. Same vocabulary as
136
- <tag-ui>; different defaults reflecting each primitive's role.
137
-
138
- Warning uses --a-warning-20-tint as bg (a bright amber, scheme-
139
- independent) instead of --a-warning-bg — the latter pair collapses
140
- to muddy brown-on-brown (-text-strong is dark, -bg is mid-tone).
141
- See <tag-ui>'s identical workaround. Token-system follow-up planned. */
142
- :scope[tone="solid"][variant="info"] {
143
- --badge-bg: var(--a-info-bg);
144
- --badge-fg: var(--md-sys-color-info-on-info);
160
+ Badge's default tone is `solid` (the family rules above, gh#864).
161
+ `[tone="muted"]` opts into the tinted-container pair (family-container
162
+ bg + family-on-surface fg — the shape <tag-ui>'s own default now uses,
163
+ gh#864); `[tone="outline"]` into the transparent-fill + colored-ring
164
+ shape. Same vocabulary as <tag-ui>; each component's default now
165
+ matches its own reported target instead of the other's. */
166
+ :scope[tone="muted"][variant="info"] {
167
+ --badge-bg: var(--md-sys-color-info-container);
168
+ --badge-fg: var(--md-sys-color-info-on-surface);
145
169
  }
146
- :scope[tone="solid"][variant="success"] {
147
- --badge-bg: var(--a-success-bg);
148
- --badge-fg: var(--md-sys-color-success-on-success);
170
+ :scope[tone="muted"][variant="success"] {
171
+ --badge-bg: var(--md-sys-color-success-container);
172
+ --badge-fg: var(--md-sys-color-success-on-surface);
149
173
  }
150
- :scope[tone="solid"][variant="warning"] {
151
- /* --a-warning-bg is the bright-amber step (semantics.css L3 redirect
152
- to -20-tint) — see also <tag-ui>'s warning solid pair. */
153
- --badge-bg: var(--a-warning-bg);
154
- --badge-fg: var(--md-sys-color-warning-on-warning);
174
+ :scope[tone="muted"][variant="warning"] {
175
+ --badge-bg: var(--md-sys-color-warning-container);
176
+ --badge-fg: var(--md-sys-color-warning-on-surface);
155
177
  }
156
- :scope[tone="solid"][variant="danger"] {
157
- --badge-bg: var(--a-danger-bg);
158
- --badge-fg: var(--md-sys-color-danger-on-danger);
178
+ :scope[tone="muted"][variant="danger"] {
179
+ --badge-bg: var(--md-sys-color-danger-container);
180
+ --badge-fg: var(--md-sys-color-danger-on-surface);
159
181
  }
160
- :scope[tone="solid"][variant="accent"] {
161
- --badge-bg: var(--a-primary-bg);
162
- --badge-fg: var(--md-sys-color-primary-on-primary);
182
+ :scope[tone="muted"][variant="primary"] {
183
+ --badge-bg: var(--md-sys-color-primary-container);
184
+ --badge-fg: var(--md-sys-color-primary-on-surface);
163
185
  }
164
- /* Solid on neutral default high-contrast inverse stamp. */
165
- :scope[tone="solid"]:not([variant="info"]):not([variant="success"]):not([variant="warning"]):not([variant="danger"]):not([variant="accent"]):not([variant="primary"]) {
166
- --badge-bg: var(--md-sys-color-neutral-on-surface);
167
- --badge-fg: var(--md-sys-color-neutral-background);
186
+ /* Family-less muted the quiet-chrome opt-out for passive metadata
187
+ chips (counts, IDs, "Not set"). bg is the neutral-low fill (gh#873;
188
+ first consumer of this token) paired with neutral-on-surface text —
189
+ NOT the requested neutral-high, which measures ~3:1 against
190
+ neutral-low in both schemes and fails AA at badge's ~12px text size
191
+ (pair is roster-gated in verify:contrast). Distinct from the base
192
+ (no-attribute) default, which is solid neutral/on-neutral (commit
193
+ 984a4401e) — muted is the quieter tint, solid is the stamp. NB
194
+ tag-ui's family-less [tone="muted"] intentionally stays on the
195
+ lighter --a-bg-muted pair (gh#778 dense-list rationale) — the two
196
+ components' family-less muteds are no longer the same shape. */
197
+ :scope[tone="muted"]:not([variant="info"]):not([variant="success"]):not([variant="warning"]):not([variant="danger"]):not([variant="primary"]) {
198
+ --badge-bg: var(--md-sys-color-neutral-low);
199
+ --badge-fg: var(--md-sys-color-neutral-on-surface);
168
200
  }
169
201
 
170
202
  /* ── `[tone="outline"]` — transparent bg + family-colored border + text ── */
@@ -188,12 +220,12 @@
188
220
  --badge-fg: var(--md-sys-color-danger-on-surface);
189
221
  --badge-border: var(--md-sys-color-danger-outline);
190
222
  }
191
- :scope[tone="outline"][variant="accent"] {
223
+ :scope[tone="outline"][variant="primary"] {
192
224
  --badge-fg: var(--md-sys-color-primary-on-surface);
193
225
  --badge-border: var(--md-sys-color-primary-outline);
194
226
  }
195
227
  /* Outline on neutral — fg-muted text + subtle ring. */
196
- :scope[tone="outline"]:not([variant="info"]):not([variant="success"]):not([variant="warning"]):not([variant="danger"]):not([variant="accent"]):not([variant="primary"]) {
228
+ :scope[tone="outline"]:not([variant="info"]):not([variant="success"]):not([variant="warning"]):not([variant="danger"]):not([variant="primary"]) {
197
229
  --badge-fg: var(--a-fg-muted);
198
230
  --badge-border: var(--md-sys-color-neutral-outline);
199
231
  }
@@ -6,6 +6,22 @@ event. Use badge-ui for status flags (Beta / New / Deprecated),
6
6
  notification counts, and unread indicators; use tag-ui for filter
7
7
  chips or user-managed labels.
8
8
 
9
+ REGISTER (gh issue 845; weight revised gh#866): badge and tag share
10
+ the same geometry family — pill radius (`--a-radius-full`) and
11
+ padding token rhythm are identical, so shape is NOT how you tell
12
+ them apart. Typography is: badge is UPPERCASE, mono (kbd-ui's
13
+ `--a-font-family-code` stack), medium weight, wide-tracked
14
+ (`--a-font-tracking-wider`, 0.06em), tabular numerals for counts.
15
+ Tag stays proportional sentence-case, also weight 500 — weight no
16
+ longer distinguishes the two (gh#866); case + tracking + mono carry
17
+ the register split now. Neither component exposes a prop that
18
+ crosses this line; the registers cannot be mixed à la carte.
19
+ Remaining distinctions: badge is non-interactive and carries the
20
+ semantic-color voice (status tones ARE the message, solid by
21
+ default — gh#864); tag is interactive/removable, muted/tinted by
22
+ default for family variants (gh#864), solid by default for the
23
+ family-less variant (gh#794, unaffected by gh#864).
24
+
9
25
  *
10
26
  * @see https://ui-kit.exe.xyz/site/components/badge
11
27
  *
@@ -23,26 +39,32 @@ export class UIBadge extends UIElement {
23
39
  icon: string;
24
40
  /** Badge size (sm/md/lg). For a denser or larger register, set [scale] on an ancestor. */
25
41
  size: 'sm' | 'md' | 'lg';
26
- /** Semantic status shorthand. Auto-maps to variant and sets text. `new` → success "New"; `updated` → info "Updated"; `deprecated` → warning "Deprecated"; `removed` → danger "Removed"; `beta` → accent "Beta". Use `variant` + `text` directly for custom chips. */
42
+ /** Semantic status shorthand. Auto-maps to variant and sets text. `new` → success "New"; `updated` → info "Updated"; `deprecated` → warning "Deprecated"; `removed` → danger "Removed"; `beta` → primary "Beta". Use `variant` + `text` directly for custom chips. */
27
43
  status: 'new' | 'updated' | 'deprecated' | 'removed' | 'beta';
28
44
  /** Badge text content. Falls back to existing textContent. */
29
45
  text: string;
30
46
  /** Badge display text. Renderer routes this to the `text` attribute via CSS attr(text) on ::after. */
31
47
  textContent: string;
32
- /** Fill style — orthogonal to [variant]. Badge defaults to `muted`
33
- (quiet metadata is the primitive's identity counts, IDs, status
34
- pills in dense rows). Three values:
35
- - `muted` (default) — tinted bg + scheme-paired text. Same as
36
- the existing family-variant rules.
37
- - `solid` saturated bg + on-strong text. Use for hero badges
38
- where the badge IS the state (e.g. a single inline error). The
39
- existing `primary` variant is a shortcut for accent + solid.
48
+ /** Fill style — orthogonal to [variant]. Badge defaults to `solid`
49
+ (gh#864 badge and tag were swapped relative to their reported
50
+ default formulas; this restores badge's own). Three values:
51
+ - `solid` (default) — saturated bg + on-strong text. The badge
52
+ IS the state (status stamp). `primary` is badge's sole
53
+ brand-emphasis variant (`accent` retired, gh#874).
54
+ - `muted` tinted bg + scheme-paired text. Use for quiet
55
+ metadata counts, IDs, status pills in dense rows. Family-tinted
56
+ `muted` (e.g. `variant="info" tone="muted"`) shares `<tag-ui>`'s
57
+ `[tone="muted"]` shape; family-less `tone="muted"` does NOT
58
+ (gh#873) — it renders the stronger `neutral-low` fill, while
59
+ `<tag-ui>`'s family-less muted stays on the lighter
60
+ `--a-bg-muted` pair (gh#778 dense-list rationale).
40
61
  - `outline` — transparent bg + family-colored border + family-
41
62
  colored text. Lightest visual weight; good in dense data rows.
42
- Vocabulary mirrors `<tag-ui>` (which defaults to solid, given its
43
- different role as filter / autocomplete chip).
63
+ Vocabulary mirrors `<tag-ui>` (which now defaults to `muted` for
64
+ its family variants, gh#864 — different role as filter /
65
+ autocomplete chip).
44
66
  */
45
67
  tone: 'muted' | 'solid' | 'outline';
46
68
  /** Semantic color variant. */
47
- variant: 'default' | 'accent' | 'info' | 'success' | 'warning' | 'danger' | 'primary' | 'muted' | 'neutral';
69
+ variant: 'default' | 'info' | 'success' | 'warning' | 'danger' | 'primary';
48
70
  }
@@ -46,5 +46,5 @@
46
46
  ## tone
47
47
 
48
48
  ```html
49
- <badge-ui text="Info" variant="info" tone="solid"></badge-ui>
49
+ <badge-ui text="Count" tone="muted"></badge-ui>
50
50
  ```
@@ -14,6 +14,22 @@ description: |
14
14
  event. Use badge-ui for status flags (Beta / New / Deprecated),
15
15
  notification counts, and unread indicators; use tag-ui for filter
16
16
  chips or user-managed labels.
17
+
18
+ REGISTER (gh issue 845; weight revised gh#866): badge and tag share
19
+ the same geometry family — pill radius (`--a-radius-full`) and
20
+ padding token rhythm are identical, so shape is NOT how you tell
21
+ them apart. Typography is: badge is UPPERCASE, mono (kbd-ui's
22
+ `--a-font-family-code` stack), medium weight, wide-tracked
23
+ (`--a-font-tracking-wider`, 0.06em), tabular numerals for counts.
24
+ Tag stays proportional sentence-case, also weight 500 — weight no
25
+ longer distinguishes the two (gh#866); case + tracking + mono carry
26
+ the register split now. Neither component exposes a prop that
27
+ crosses this line; the registers cannot be mixed à la carte.
28
+ Remaining distinctions: badge is non-interactive and carries the
29
+ semantic-color voice (status tones ARE the message, solid by
30
+ default — gh#864); tag is interactive/removable, muted/tinted by
31
+ default for family variants (gh#864), solid by default for the
32
+ family-less variant (gh#794, unaffected by gh#864).
17
33
  # Per ADR-0027 — primitives that programmatically create other primitives
18
34
  # do NOT auto-import them. Consumer (or demo shell) must explicitly import.
19
35
  composes:
@@ -35,7 +51,7 @@ props:
35
51
  status:
36
52
  description: Semantic status shorthand. Auto-maps to variant and sets text.
37
53
  `new` → success "New"; `updated` → info "Updated"; `deprecated` → warning
38
- "Deprecated"; `removed` → danger "Removed"; `beta` → accent "Beta".
54
+ "Deprecated"; `removed` → danger "Removed"; `beta` → primary "Beta".
39
55
  Use `variant` + `text` directly for custom chips.
40
56
  type: string
41
57
  default: ""
@@ -60,30 +76,33 @@ props:
60
76
  default: default
61
77
  enum:
62
78
  - default
63
- - accent
64
79
  - info
65
80
  - success
66
81
  - warning
67
82
  - danger
68
83
  - primary
69
- - muted
70
- - neutral
71
84
  tone:
72
85
  description: |
73
- Fill style — orthogonal to [variant]. Badge defaults to `muted`
74
- (quiet metadata is the primitive's identity counts, IDs, status
75
- pills in dense rows). Three values:
76
- - `muted` (default) — tinted bg + scheme-paired text. Same as
77
- the existing family-variant rules.
78
- - `solid` saturated bg + on-strong text. Use for hero badges
79
- where the badge IS the state (e.g. a single inline error). The
80
- existing `primary` variant is a shortcut for accent + solid.
86
+ Fill style — orthogonal to [variant]. Badge defaults to `solid`
87
+ (gh#864 badge and tag were swapped relative to their reported
88
+ default formulas; this restores badge's own). Three values:
89
+ - `solid` (default) — saturated bg + on-strong text. The badge
90
+ IS the state (status stamp). `primary` is badge's sole
91
+ brand-emphasis variant (`accent` retired, gh#874).
92
+ - `muted` tinted bg + scheme-paired text. Use for quiet
93
+ metadata counts, IDs, status pills in dense rows. Family-tinted
94
+ `muted` (e.g. `variant="info" tone="muted"`) shares `<tag-ui>`'s
95
+ `[tone="muted"]` shape; family-less `tone="muted"` does NOT
96
+ (gh#873) — it renders the stronger `neutral-low` fill, while
97
+ `<tag-ui>`'s family-less muted stays on the lighter
98
+ `--a-bg-muted` pair (gh#778 dense-list rationale).
81
99
  - `outline` — transparent bg + family-colored border + family-
82
100
  colored text. Lightest visual weight; good in dense data rows.
83
- Vocabulary mirrors `<tag-ui>` (which defaults to solid, given its
84
- different role as filter / autocomplete chip).
101
+ Vocabulary mirrors `<tag-ui>` (which now defaults to `muted` for
102
+ its family variants, gh#864 — different role as filter /
103
+ autocomplete chip).
85
104
  type: string
86
- default: muted
105
+ default: solid
87
106
  enum:
88
107
  - muted
89
108
  - solid
@@ -100,6 +119,8 @@ a2ui:
100
119
  rules:
101
120
  - rule: 'Use for small status/count labels attached to another element (notification counts, status pills, version tags).'
102
121
  reason: 'Different from <tag-ui> which is for free-standing taxonomy/filter labels.'
122
+ - rule: 'A bare Badge (no [tone]) renders a solid, saturated status stamp. Set [tone="muted"] for the quieter tinted look on dense metadata rows.'
123
+ reason: 'Badge defaults to solid (gh#864); does not need [tone] set explicitly to read as a status stamp.'
103
124
  - rule: 'Place adjacent to or absolutely-positioned over the badged element, not inside it.'
104
125
  reason: 'Light-DOM positioning; do not nest inside the badged element''s slot.'
105
126
  - rule: 'For dismissable taxonomy labels (filter chips, selected items in multi-select), use <tag-ui> instead.'
@@ -130,7 +151,7 @@ examples:
130
151
  "component": "Badge",
131
152
  "icon": "dot",
132
153
  "text": "Organic",
133
- "variant": "accent",
154
+ "variant": "primary",
134
155
  "size": "sm"
135
156
  },
136
157
  {
@@ -27,7 +27,6 @@
27
27
  "type": "string",
28
28
  "enum": [
29
29
  "default",
30
- "accent",
31
30
  "info",
32
31
  "success",
33
32
  "warning",
@@ -83,6 +82,7 @@
83
82
  "enum": [
84
83
  "default",
85
84
  "solid",
85
+ "tonal",
86
86
  "outline",
87
87
  "ghost",
88
88
  "primary"
@@ -252,8 +252,10 @@ button-ui[variant="ghost"][color="warning"]:not([disabled]):hover { --button-f
252
252
  /* ── Color (semantic axis) ──
253
253
  `[color]` carries semantic intent; `variant` carries visual style.
254
254
  Together they compose: `<button-ui variant="solid" color="danger">`
255
- vs `<button-ui variant="outline" color="danger">`.
256
- `variant="danger"` is a deprecated alias migrated to color via JS. */
255
+ vs `<button-ui variant="outline" color="danger">`. (Corrected,
256
+ variant-color-tone LLD §2: no `variant="danger"` `color` alias
257
+ JS exists in button.class.js — the prior comment claiming one was
258
+ stale.) */
257
259
  :scope[color="danger"] {
258
260
  --button-bg: var(--button-bg-danger);
259
261
  --button-fg: var(--button-fg-danger);
@@ -18,7 +18,7 @@ export class UIButton extends UIElement {
18
18
  /** HTML button type (button, submit, reset) */
19
19
  type: string;
20
20
  /** Semantic intent — composes with [variant]. `<button-ui variant="solid" color="danger">` = filled destructive action; `<button-ui variant="outline" color="success">` = outlined success affordance. */
21
- color: 'default' | 'accent' | 'info' | 'success' | 'warning' | 'danger';
21
+ color: 'default' | 'info' | 'success' | 'warning' | 'danger';
22
22
  /** Disables interaction and prevents click/press events */
23
23
  disabled: boolean;
24
24
  /** Leading Phosphor icon name (rendered before text). */
@@ -33,7 +33,7 @@ export class UIButton extends UIElement {
33
33
  textContent: string;
34
34
  /** Visual style — `solid` (default fill), `tonal` (soft container fill with in-family text — the emphasis tier between solid and outline; default rides the primary family), `outline`, `ghost`. `default` / `primary` are aliases of `solid`. Style is independent of semantic intent — to express destructive / success / info / warning intent, set [color="…"] alongside (`variant="tonal" color="danger"` = the danger family's container fill). There is deliberately no `variant="secondary"`: `secondary` names a color family in this system, and an unset variant already IS the secondary-rank look (compose-constitution); `tonal` is the named tier for a softer-than-solid filled action.
35
35
  For **inline navigation** (Terms of Service, Privacy Policy, footer links, "Sign in" / "Sign up" cross-page affordances) use `<link-ui>` instead — it carries proper `<a href>` semantics, keyboard handling (Enter only, no Space), middle-click open-new-tab, and screen-reader announces "link" instead of "button". Mixing navigation and action affordances under the same primitive is a category error fixed at this junction. */
36
- variant: 'default' | 'solid' | 'outline' | 'ghost' | 'primary';
36
+ variant: 'default' | 'solid' | 'tonal' | 'outline' | 'ghost' | 'primary';
37
37
 
38
38
  addEventListener(type: 'press', listener: (ev: ButtonPressEvent) => unknown, options?: boolean | AddEventListenerOptions): void;
39
39
  addEventListener<K extends keyof HTMLElementEventMap>(
@@ -83,6 +83,7 @@ props:
83
83
  enum:
84
84
  - default
85
85
  - solid
86
+ - tonal
86
87
  - outline
87
88
  - ghost
88
89
  - primary
@@ -95,7 +96,6 @@ props:
95
96
  default: ""
96
97
  enum:
97
98
  - default
98
- - accent
99
99
  - info
100
100
  - success
101
101
  - warning
@@ -132,7 +132,7 @@ a2ui:
132
132
  - The card's <header> grid activates only for DIRECT-child slotted elements. If you need an icon column, place the icon
133
133
  element (avatar-ui, icon-ui) directly in the header with slot="icon" — not inside a wrapper.
134
134
  - 'Heading slot accepts inline badges/metadata: <span slot="heading"><text-ui strong>Title</text-ui><badge-ui text="New"
135
- variant="accent"></badge-ui></span> renders title + badge on one row.'
135
+ variant="primary"></badge-ui></span> renders title + badge on one row.'
136
136
  - Description slot also accepts bare <p> or <small> elements as siblings of the heading — they participate in the grid's
137
137
  row 2 without needing slot="description".
138
138
  - Multiple <section> siblings are allowed and stack vertically. [bleed] on a section removes its margin for edge-to-edge
@@ -1366,9 +1366,13 @@ export class UIChart extends UIElement {
1366
1366
  const data = this.#data;
1367
1367
  const yKey = this.#yKeys()[0] || this.y;
1368
1368
  const vals = data.map(d => +(d[yKey] ?? 0));
1369
- const maxVal = Math.max(...vals) || 1;
1370
- const minVal = Math.min(...vals);
1371
- const range = maxVal - minVal || 1;
1369
+
1370
+ // Fixed 0-floor domain via niceScale — the same convention every other
1371
+ // renderer in this file uses (#renderBar, #renderLine, #renderScatter,
1372
+ // etc). A flat/single-point series then plots against a real baseline
1373
+ // instead of collapsing to the bottom edge (gh#850).
1374
+ const ticks = niceScale(0, Math.max(...vals), 5);
1375
+ const maxVal = ticks[ticks.length - 1];
1372
1376
 
1373
1377
  // Use the actual container dims so the aspect ratio matches what
1374
1378
  // the CSS allocates (otherwise the fixed 120×32 viewBox gets
@@ -1385,7 +1389,7 @@ export class UIChart extends UIElement {
1385
1389
  const labels = data.map(d => d[this.x] ?? '');
1386
1390
  const points = vals.map((v, i) => ({
1387
1391
  x: step * i,
1388
- y: h - ((v - minVal) / range) * (h - padY * 2) - padY,
1392
+ y: h - (maxVal ? (v / maxVal) * (h - padY * 2) : 0) - padY,
1389
1393
  v,
1390
1394
  label: labels[i],
1391
1395
  }));
@@ -48,11 +48,14 @@ const ACTION_FOR_STATUS = Object.freeze({
48
48
  pending: { event: 'press', emits: '', label: 'Connecting…', variant: 'outline', icon: '' },
49
49
  });
50
50
 
51
+ // `coming-soon` is a family-less badge, tone="muted" — `variant="muted"`
52
+ // retired (variant/color/tone convention cut, gh#873/874); `#renderStatusBadge()`
53
+ // below branches on `variant` vs. absent.
51
54
  const BADGE_FOR_STATUS = Object.freeze({
52
55
  connected: { variant: 'success', text: 'Connected', icon: 'check' },
53
56
  error: { variant: 'danger', text: 'Error', icon: 'warning-circle' },
54
57
  pending: { variant: 'info', text: 'Connecting…', icon: '' },
55
- 'coming-soon':{ variant: 'muted', text: 'Coming soon', icon: '' },
58
+ 'coming-soon':{ text: 'Coming soon', icon: '' },
56
59
  });
57
60
 
58
61
  // Fallback glyph per known provider when no explicit [logo] is supplied, so
@@ -312,7 +315,13 @@ export class UIIntegrationCard extends UIElement {
312
315
  return;
313
316
  }
314
317
  this.#statusEl.hidden = false;
315
- this.#statusEl.setAttribute('variant', cfg.variant);
318
+ if (cfg.variant) {
319
+ this.#statusEl.setAttribute('variant', cfg.variant);
320
+ this.#statusEl.removeAttribute('tone');
321
+ } else {
322
+ this.#statusEl.removeAttribute('variant');
323
+ this.#statusEl.setAttribute('tone', 'muted');
324
+ }
316
325
  this.#statusEl.setAttribute('text', cfg.text);
317
326
  this.#statusEl.setAttribute('size', 'sm');
318
327
  if (cfg.icon) this.#statusEl.setAttribute('icon', cfg.icon);
@@ -17,14 +17,13 @@
17
17
  "const": "Mark"
18
18
  },
19
19
  "variant": {
20
- "description": "Highlight color variant. Default `warning` is the conventional yellow-marker tone.",
20
+ "description": "Highlight color family — the only color axis mark exposes. Default `warning` is the conventional yellow-marker tone and IS mark's family-less identity, so there is no `default` member. For a neutral (non-semantic) highlight, override the public tokens instead of the variant: `--mark-bg: var(--a-bg-muted); --mark-fg: var(--md-sys-color-neutral-on-surface)` — the successor to the retired `variant=\"muted\"` (gh#881).",
21
21
  "type": "string",
22
22
  "enum": [
23
23
  "warning",
24
24
  "info",
25
25
  "success",
26
- "danger",
27
- "muted"
26
+ "danger"
28
27
  ],
29
28
  "default": "warning"
30
29
  }
@@ -87,12 +86,12 @@
87
86
  "tag": "mark-ui",
88
87
  "tokens": {
89
88
  "--mark-bg": {
90
- "description": "Background color of the highlight.",
91
- "default": "var(--a-warning-muted)"
89
+ "description": "Background color of the highlight. Override for a non-semantic (e.g. neutral) highlight — see [variant].",
90
+ "default": "var(--md-sys-color-warning-container)"
92
91
  },
93
92
  "--mark-fg": {
94
- "description": "Foreground (text) color inside the highlight.",
95
- "default": "var(--a-warning-text)"
93
+ "description": "Foreground (text) color inside the highlight. Pair every [--mark-bg] override with a matching fg so contrast holds in both schemes.",
94
+ "default": "var(--md-sys-color-warning-on-surface)"
96
95
  },
97
96
  "--mark-px": {
98
97
  "description": "Horizontal padding around the highlighted text.",
@@ -8,7 +8,7 @@ import { UIElement } from '../../core/element.js';
8
8
 
9
9
  export class UIMark extends UIElement {
10
10
  static properties = {
11
- variant: { type: String, default: 'warning', reflect: true }, // warning | info | success | danger | muted
11
+ variant: { type: String, default: 'warning', reflect: true }, // warning | info | success | danger
12
12
  };
13
13
 
14
14
  static template = () => null;
@@ -32,8 +32,11 @@
32
32
  --mark-bg: var(--md-sys-color-danger-container);
33
33
  --mark-fg: var(--md-sys-color-danger-on-surface);
34
34
  }
35
- :scope[variant="muted"] {
36
- --mark-bg: var(--a-bg-muted);
37
- --mark-fg: var(--md-sys-color-neutral-on-surface);
38
- }
35
+
36
+ /* NB `variant` is mark's ONLY color axis and it is family-only
37
+ (gh#881, the two-axis convention). The former `variant="muted"`
38
+ neutral highlight is retired; its successor is the public token
39
+ override — `--mark-bg: var(--a-bg-muted); --mark-fg:
40
+ var(--md-sys-color-neutral-on-surface)` — so a non-semantic
41
+ highlight no longer needs an enum member of its own. */
39
42
  }
@@ -22,6 +22,6 @@ background highlight behind the matched span.
22
22
  import { UIElement } from '../../core/element.js';
23
23
 
24
24
  export class UIMark extends UIElement {
25
- /** Highlight color variant. Default `warning` is the conventional yellow-marker tone. */
26
- variant: 'warning' | 'info' | 'success' | 'danger' | 'muted';
25
+ /** Highlight color family — the only color axis mark exposes. Default `warning` is the conventional yellow-marker tone and IS mark's family-less identity, so there is no `default` member. For a neutral (non-semantic) highlight, override the public tokens instead of the variant: `--mark-bg: var(--a-bg-muted); --mark-fg: var(--md-sys-color-neutral-on-surface)` — the successor to the retired `variant="muted"` (gh#881). */
26
+ variant: 'warning' | 'info' | 'success' | 'danger';
27
27
  }