@adia-ai/web-components 0.7.28 → 0.8.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +29 -0
- package/components/accordion/accordion.css +13 -4
- package/components/action-list/action-list.css +3 -3
- package/components/agent-artifact/agent-artifact.css +4 -4
- package/components/agent-questions/agent-questions.css +8 -8
- package/components/agent-reasoning/agent-reasoning.css +6 -6
- package/components/agent-trace/agent-trace.css +4 -4
- package/components/agent-trace/agent-trace.js +1 -1
- package/components/alert/alert.css +16 -16
- package/components/avatar/avatar.css +3 -3
- package/components/badge/badge.css +32 -32
- package/components/blockquote/blockquote.css +1 -1
- package/components/breadcrumb/breadcrumb.css +2 -2
- package/components/button/button.css +14 -14
- package/components/calendar-grid/calendar-grid.a2ui.json +3 -3
- package/components/calendar-grid/calendar-grid.css +10 -10
- package/components/calendar-grid/calendar-grid.yaml +3 -3
- package/components/calendar-picker/calendar-picker.css +11 -11
- package/components/canvas/canvas.css +2 -2
- package/components/card/card.css +15 -15
- package/components/chart/chart.css +23 -23
- package/components/chart-legend/chart-legend.css +2 -2
- package/components/chat-thread/chat-input.css +6 -6
- package/components/chat-thread/chat-thread.css +7 -7
- package/components/check/check.css +4 -4
- package/components/code/code-editor.js +1 -1
- package/components/code/code.css +45 -22
- package/components/color-picker/color-picker.css +4 -4
- package/components/combobox/combobox.css +6 -6
- package/components/command/command.class.js +14 -3
- package/components/command/command.css +4 -4
- package/components/context-menu/context-menu.css +2 -2
- package/components/date-range-picker/date-range-picker.a2ui.json +3 -3
- package/components/date-range-picker/date-range-picker.css +8 -8
- package/components/date-range-picker/date-range-picker.yaml +3 -3
- package/components/datetime-picker/datetime-picker.css +6 -6
- package/components/demo-toggle/demo-toggle.css +4 -4
- package/components/description-list/description-list.css +1 -1
- package/components/display-field/display-field.css +2 -2
- package/components/divider/divider.css +1 -1
- package/components/drawer/drawer.css +7 -7
- package/components/embed/embed.css +1 -1
- package/components/empty-state/empty-state.css +5 -5
- package/components/feed/feed.css +7 -7
- package/components/field/field.css +2 -2
- package/components/heatmap/heatmap.css +8 -8
- package/components/inline-edit/inline-edit.a2ui.json +1 -1
- package/components/inline-edit/inline-edit.css +3 -3
- package/components/inline-edit/inline-edit.yaml +1 -1
- package/components/inline-message/inline-message.css +4 -4
- package/components/input/input.css +1 -1
- package/components/inspector/inspector.css +1 -1
- package/components/integration-card/integration-card.css +3 -3
- package/components/kbd/kbd.css +2 -2
- package/components/link/link.css +2 -2
- package/components/list/list.css +10 -10
- package/components/list-window/list-window.css +2 -2
- package/components/mark/mark.css +9 -9
- package/components/menu/menu.css +9 -9
- package/components/modal/modal.css +4 -4
- package/components/nav/nav.css +1 -1
- package/components/nav-group/nav-group.css +7 -16
- package/components/nav-item/nav-item.css +1 -1
- package/components/noodles/noodles.a2ui.json +1 -1
- package/components/noodles/noodles.css +3 -3
- package/components/noodles/noodles.d.ts +1 -1
- package/components/noodles/noodles.yaml +1 -1
- package/components/option-card/option-card.css +11 -11
- package/components/otp-input/otp-input.css +1 -1
- package/components/page/page.css +2 -2
- package/components/pane/pane.css +5 -5
- package/components/password-strength/password-strength.css +1 -1
- package/components/pipeline-status/pipeline-status.css +9 -9
- package/components/popover/popover.css +2 -2
- package/components/preview/preview.css +14 -3
- package/components/progress/progress.a2ui.json +1 -1
- package/components/progress/progress.css +1 -1
- package/components/progress/progress.d.ts +1 -1
- package/components/progress/progress.yaml +1 -1
- package/components/progress-row/progress-row.css +2 -2
- package/components/radio/radio.css +4 -4
- package/components/range/range.css +2 -2
- package/components/rating/rating.css +2 -2
- package/components/richtext/richtext.class.js +4 -0
- package/components/richtext/richtext.css +5 -5
- package/components/richtext/richtext.yaml +1 -0
- package/components/row/row.css +1 -1
- package/components/select/select.css +8 -8
- package/components/skip-nav/skip-nav.a2ui.json +2 -2
- package/components/skip-nav/skip-nav.css +3 -3
- package/components/skip-nav/skip-nav.yaml +2 -2
- package/components/slider/slider.css +5 -5
- package/components/spinner/spinner.css +2 -2
- package/components/spinner/spinner.test.js +4 -2
- package/components/stat/stat.css +1 -1
- package/components/step-progress/step-progress.a2ui.json +1 -1
- package/components/step-progress/step-progress.class.js +1 -1
- package/components/step-progress/step-progress.css +2 -2
- package/components/step-progress/step-progress.d.ts +1 -1
- package/components/step-progress/step-progress.yaml +1 -1
- package/components/stepper/stepper.css +22 -22
- package/components/stream/stream.css +2 -2
- package/components/swatch/swatch.class.js +1 -1
- package/components/swatch/swatch.css +11 -11
- package/components/swiper/swiper.css +5 -5
- package/components/switch/switch.css +5 -5
- package/components/table/cell-types.js +1 -1
- package/components/table/table.css +16 -11
- package/components/table-toolbar/table-toolbar.css +8 -8
- package/components/tabs/tabs.css +5 -5
- package/components/tag/tag.css +41 -29
- package/components/tag/tag.test.js +22 -29
- package/components/tags-input/tags-input.a2ui.json +2 -2
- package/components/tags-input/tags-input.class.js +93 -20
- package/components/tags-input/tags-input.css +3 -3
- package/components/tags-input/tags-input.test.js +109 -0
- package/components/tags-input/tags-input.yaml +18 -4
- package/components/text/text.css +4 -4
- package/components/textarea/textarea.css +1 -1
- package/components/time-picker/time-picker.css +2 -2
- package/components/timeline/timeline.css +31 -31
- package/components/toast/toast.css +19 -19
- package/components/toc/toc.a2ui.json +1 -1
- package/components/toc/toc.css +3 -3
- package/components/toc/toc.yaml +1 -1
- package/components/toggle-group/toggle-group.css +3 -3
- package/components/toolbar/toolbar.css +3 -3
- package/components/tooltip/tooltip.css +9 -9
- package/components/tour/tour.css +3 -3
- package/components/tree/tree.css +2 -2
- package/components/upload/upload.css +7 -7
- package/dist/host.min.css +1 -1
- package/dist/host.sheet.js +1 -1
- package/dist/theme-provider.min.js +7 -7
- package/dist/themes.min.css +1 -1
- package/dist/themes.sheet.js +1 -1
- package/dist/web-components.min.css +1 -1
- package/dist/web-components.min.js +41 -41
- package/dist/web-components.sheet.js +1 -1
- package/package.json +3 -3
- package/styles/api/text.css +1 -1
- package/styles/colors/bridges/material-bridge.css +30 -0
- package/styles/colors/index.css +19 -1
- package/styles/colors/material-static.css +771 -0
- package/styles/colors/parameters.css +40 -4
- package/styles/colors/primitives-primary.css +89 -0
- package/styles/colors/primitives-secondary.css +89 -0
- package/styles/colors/primitives-tertiary.css +89 -0
- package/styles/colors/primitives.css +3 -1
- package/styles/colors/scrims.css +19 -180
- package/styles/colors/semantics/aliases.css +25 -11
- package/styles/colors/semantics/buckets.css +28 -12
- package/styles/colors/semantics/core.css +330 -202
- package/styles/colors/semantics/data-viz.css +13 -13
- package/styles/colors/semantics/features.css +31 -13
- package/styles/colors/surfaces.css +41 -31
- package/styles/themes.css +15 -15
- package/styles/colors/primitives-accent.css +0 -89
package/components/tag/tag.css
CHANGED
|
@@ -8,7 +8,7 @@ tag-ui[removable]:not([disabled]):hover {
|
|
|
8
8
|
:where(:scope) {
|
|
9
9
|
/* ── Tokens ── */
|
|
10
10
|
--tag-bg: var(--a-bg-muted);
|
|
11
|
-
--tag-fg: var(--
|
|
11
|
+
--tag-fg: var(--md-sys-color-neutral-on-surface);
|
|
12
12
|
--tag-border: transparent;
|
|
13
13
|
--tag-radius: var(--a-radius-full);
|
|
14
14
|
--tag-px: var(--a-space-1-5);
|
|
@@ -51,6 +51,16 @@ tag-ui[removable]:not([disabled]):hover {
|
|
|
51
51
|
box-sizing: border-box;
|
|
52
52
|
display: inline-flex;
|
|
53
53
|
align-items: center;
|
|
54
|
+
/* align-self: start — TKT-0021. A flex-column ancestor (col-ui
|
|
55
|
+
defaults to align-items: stretch) otherwise stretches a bare
|
|
56
|
+
tag-ui to the column's full width; a chip should size to its own
|
|
57
|
+
content regardless of ancestor. justify-content: center is the
|
|
58
|
+
matching defensive default badge-ui/button-ui already carry
|
|
59
|
+
(badge.css/button.css) — if the box is ever wider than its
|
|
60
|
+
content for any other reason, the label still centers instead of
|
|
61
|
+
reading left-aligned in an oversized pill. */
|
|
62
|
+
align-self: start;
|
|
63
|
+
justify-content: center;
|
|
54
64
|
gap: var(--tag-gap);
|
|
55
65
|
padding: var(--tag-py) var(--tag-px);
|
|
56
66
|
border-radius: var(--tag-radius);
|
|
@@ -85,26 +95,28 @@ tag-ui[removable]:not([disabled]):hover {
|
|
|
85
95
|
metadata-chip surfaces in dense lists. */
|
|
86
96
|
:scope[variant="info"] {
|
|
87
97
|
--tag-bg: var(--a-info-bg);
|
|
88
|
-
--tag-fg: var(--
|
|
98
|
+
--tag-fg: var(--md-sys-color-info-on-info);
|
|
89
99
|
}
|
|
90
100
|
|
|
91
101
|
:scope[variant="success"] {
|
|
92
102
|
--tag-bg: var(--a-success-bg);
|
|
93
|
-
--tag-fg: var(--
|
|
103
|
+
--tag-fg: var(--md-sys-color-success-on-success);
|
|
94
104
|
}
|
|
95
105
|
|
|
96
|
-
/*
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
106
|
+
/* Same shape as the sibling families since the Material static-token
|
|
107
|
+
migration: amber fill + the palette's own fixed-light on-color
|
|
108
|
+
(`on-warning`, white in both schemes per Material's on-color law).
|
|
109
|
+
The pre-migration dark-brown-text override is gone — its
|
|
110
|
+
lower-than-siblings contrast is a known, operator-accepted
|
|
111
|
+
consequence (TKT-0018, wontfix pending palette adjustment). */
|
|
100
112
|
:scope[variant="warning"] {
|
|
101
113
|
--tag-bg: var(--a-warning-bg);
|
|
102
|
-
--tag-fg: var(--
|
|
114
|
+
--tag-fg: var(--md-sys-color-warning-on-warning);
|
|
103
115
|
}
|
|
104
116
|
|
|
105
117
|
:scope[variant="danger"] {
|
|
106
118
|
--tag-bg: var(--a-danger-bg);
|
|
107
|
-
--tag-fg: var(--
|
|
119
|
+
--tag-fg: var(--md-sys-color-danger-on-danger);
|
|
108
120
|
}
|
|
109
121
|
|
|
110
122
|
/* `default` (no family) stays as quiet chrome — a stark fg/bg-inverse
|
|
@@ -112,7 +124,7 @@ tag-ui[removable]:not([disabled]):hover {
|
|
|
112
124
|
stamp via `[tone="solid"]` when you want a high-contrast neutral pill. */
|
|
113
125
|
:scope[variant="default"] {
|
|
114
126
|
--tag-bg: var(--a-bg-muted);
|
|
115
|
-
--tag-fg: var(--
|
|
127
|
+
--tag-fg: var(--md-sys-color-neutral-on-surface);
|
|
116
128
|
}
|
|
117
129
|
|
|
118
130
|
/* ── Tone modifier — orthogonal to [variant] ──
|
|
@@ -122,28 +134,28 @@ tag-ui[removable]:not([disabled]):hover {
|
|
|
122
134
|
uses as its default. Use on metadata chips in dense lists where the
|
|
123
135
|
saturated default would compete for attention. */
|
|
124
136
|
:scope[tone="muted"][variant="info"] {
|
|
125
|
-
--tag-bg: var(--
|
|
126
|
-
--tag-fg: var(--
|
|
137
|
+
--tag-bg: var(--md-sys-color-info-container);
|
|
138
|
+
--tag-fg: var(--md-sys-color-info-on-surface);
|
|
127
139
|
}
|
|
128
140
|
:scope[tone="muted"][variant="success"] {
|
|
129
|
-
--tag-bg: var(--
|
|
130
|
-
--tag-fg: var(--
|
|
141
|
+
--tag-bg: var(--md-sys-color-success-container);
|
|
142
|
+
--tag-fg: var(--md-sys-color-success-on-surface);
|
|
131
143
|
}
|
|
132
144
|
:scope[tone="muted"][variant="warning"] {
|
|
133
|
-
--tag-bg: var(--
|
|
134
|
-
--tag-fg: var(--
|
|
145
|
+
--tag-bg: var(--md-sys-color-warning-container);
|
|
146
|
+
--tag-fg: var(--md-sys-color-warning-on-surface);
|
|
135
147
|
}
|
|
136
148
|
:scope[tone="muted"][variant="danger"] {
|
|
137
|
-
--tag-bg: var(--
|
|
138
|
-
--tag-fg: var(--
|
|
149
|
+
--tag-bg: var(--md-sys-color-danger-container);
|
|
150
|
+
--tag-fg: var(--md-sys-color-danger-on-surface);
|
|
139
151
|
}
|
|
140
152
|
|
|
141
153
|
/* `[tone="solid"]` on the neutral default (or no variant) inverts the
|
|
142
154
|
chrome — solid fg-color bg with bg-color text. High-contrast neutral
|
|
143
155
|
stamp. Explicit opt-in; the variant-less default stays quiet chrome. */
|
|
144
156
|
:scope[tone="solid"]:not([variant="info"]):not([variant="success"]):not([variant="warning"]):not([variant="danger"]) {
|
|
145
|
-
--tag-bg: var(--
|
|
146
|
-
--tag-fg: var(--
|
|
157
|
+
--tag-bg: var(--md-sys-color-neutral-on-surface);
|
|
158
|
+
--tag-fg: var(--md-sys-color-neutral-background);
|
|
147
159
|
}
|
|
148
160
|
|
|
149
161
|
/* ── `[tone="outline"]` — transparent bg + family-colored border + text ──
|
|
@@ -155,25 +167,25 @@ tag-ui[removable]:not([disabled]):hover {
|
|
|
155
167
|
--tag-bg: transparent;
|
|
156
168
|
}
|
|
157
169
|
:scope[tone="outline"][variant="info"] {
|
|
158
|
-
--tag-fg: var(--
|
|
159
|
-
--tag-border: var(--
|
|
170
|
+
--tag-fg: var(--md-sys-color-info-on-surface);
|
|
171
|
+
--tag-border: var(--md-sys-color-info-outline);
|
|
160
172
|
}
|
|
161
173
|
:scope[tone="outline"][variant="success"] {
|
|
162
|
-
--tag-fg: var(--
|
|
163
|
-
--tag-border: var(--
|
|
174
|
+
--tag-fg: var(--md-sys-color-success-on-surface);
|
|
175
|
+
--tag-border: var(--md-sys-color-success-outline);
|
|
164
176
|
}
|
|
165
177
|
:scope[tone="outline"][variant="warning"] {
|
|
166
|
-
--tag-fg: var(--
|
|
167
|
-
--tag-border: var(--
|
|
178
|
+
--tag-fg: var(--md-sys-color-warning-on-surface);
|
|
179
|
+
--tag-border: var(--md-sys-color-warning-outline);
|
|
168
180
|
}
|
|
169
181
|
:scope[tone="outline"][variant="danger"] {
|
|
170
|
-
--tag-fg: var(--
|
|
171
|
-
--tag-border: var(--
|
|
182
|
+
--tag-fg: var(--md-sys-color-danger-on-surface);
|
|
183
|
+
--tag-border: var(--md-sys-color-danger-outline);
|
|
172
184
|
}
|
|
173
185
|
/* Outline on neutral (no family) — fg-muted text + subtle border. */
|
|
174
186
|
:scope[tone="outline"]:not([variant="info"]):not([variant="success"]):not([variant="warning"]):not([variant="danger"]) {
|
|
175
187
|
--tag-fg: var(--a-fg-muted);
|
|
176
|
-
--tag-border: var(--
|
|
188
|
+
--tag-border: var(--md-sys-color-neutral-outline);
|
|
177
189
|
}
|
|
178
190
|
|
|
179
191
|
/* Size handled by universal [size] attribute system. */
|
|
@@ -50,50 +50,43 @@ describe('tag-ui — content: attr(text) gating', () => {
|
|
|
50
50
|
// ── Tone defaults (solid by default for families; muted as opt-out) ──
|
|
51
51
|
//
|
|
52
52
|
// Default tone is `solid` for family variants — the base `:scope[variant=…]`
|
|
53
|
-
// rules
|
|
54
|
-
// (the chip IS the
|
|
55
|
-
//
|
|
53
|
+
// rules pair the saturated `--a-{family}-bg` fill with the palette's own
|
|
54
|
+
// Material on-color `--md-sys-color-{family}-on-{family}` (the chip IS the
|
|
55
|
+
// state). `[tone="muted"]` opts back into the Material container pair
|
|
56
|
+
// `--md-sys-color-{family}-container` + `-on-surface` (same look as
|
|
56
57
|
// <badge-ui>'s default). The `default` (no-family) variant stays quiet
|
|
57
|
-
// chrome unless `[tone="solid"]` is set explicitly (then it inverts
|
|
58
|
-
//
|
|
58
|
+
// chrome unless `[tone="solid"]` is set explicitly (then it inverts to a
|
|
59
|
+
// high-contrast neutral stamp). Token names updated for the Material
|
|
60
|
+
// static-token migration (material-color-bridge-contract.md, 2026-07-15).
|
|
59
61
|
|
|
60
62
|
describe('tag-ui — variant defaults to solid fill', () => {
|
|
61
63
|
it.each([
|
|
62
64
|
['info'],
|
|
63
65
|
['success'],
|
|
66
|
+
['warning'],
|
|
64
67
|
['danger'],
|
|
65
|
-
])('[variant="%s"] base rule uses --a-{family}-bg + --
|
|
68
|
+
])('[variant="%s"] base rule uses --a-{family}-bg + --md-sys-color-{family}-on-{family}', (family) => {
|
|
66
69
|
const block = new RegExp(
|
|
67
70
|
`:scope\\[variant="${family}"\\]\\s*\\{[^}]*` +
|
|
68
71
|
`--tag-bg:\\s*var\\(--a-${family}-bg\\)[^}]*` +
|
|
69
|
-
`--tag-fg:\\s*var\\(--
|
|
72
|
+
`--tag-fg:\\s*var\\(--md-sys-color-${family}-on-${family}\\)`,
|
|
70
73
|
's'
|
|
71
74
|
);
|
|
72
75
|
expect(TAG_CSS).toMatch(block);
|
|
73
76
|
});
|
|
74
|
-
|
|
75
|
-
it('[variant="warning"] uses the canonical --a-warning-bg + --a-warning-fg pair', () => {
|
|
76
|
-
// v0.6.36 token-system fix: --a-warning-bg now redirects to
|
|
77
|
-
// --a-warning-20-tint at the L3 layer (semantics.css), so consumers
|
|
78
|
-
// can pair `-bg` + `-fg` cleanly without local overrides. The pair
|
|
79
|
-
// resolves to bright-amber-bg + dark-brown-text in both schemes.
|
|
80
|
-
expect(TAG_CSS).toMatch(
|
|
81
|
-
/:scope\[variant="warning"\]\s*\{[^}]*--tag-bg:\s*var\(--a-warning-bg\)[^}]*--tag-fg:\s*var\(--a-warning-fg\)/s
|
|
82
|
-
);
|
|
83
|
-
});
|
|
84
77
|
});
|
|
85
78
|
|
|
86
|
-
describe('tag-ui — [tone="muted"] opts out to
|
|
79
|
+
describe('tag-ui — [tone="muted"] opts out to the Material container pair', () => {
|
|
87
80
|
it.each([
|
|
88
81
|
['info'],
|
|
89
82
|
['success'],
|
|
90
83
|
['warning'],
|
|
91
84
|
['danger'],
|
|
92
|
-
])('[tone="muted"][variant="%s"] uses
|
|
85
|
+
])('[tone="muted"][variant="%s"] uses -container + -on-surface', (family) => {
|
|
93
86
|
const block = new RegExp(
|
|
94
87
|
`:scope\\[tone="muted"\\]\\[variant="${family}"\\]\\s*\\{[^}]*` +
|
|
95
|
-
`--tag-bg:\\s*var\\(--
|
|
96
|
-
`--tag-fg:\\s*var\\(--
|
|
88
|
+
`--tag-bg:\\s*var\\(--md-sys-color-${family}-container\\)[^}]*` +
|
|
89
|
+
`--tag-fg:\\s*var\\(--md-sys-color-${family}-on-surface\\)`,
|
|
97
90
|
's'
|
|
98
91
|
);
|
|
99
92
|
expect(TAG_CSS).toMatch(block);
|
|
@@ -101,15 +94,15 @@ describe('tag-ui — [tone="muted"] opts out to canonical muted pair', () => {
|
|
|
101
94
|
});
|
|
102
95
|
|
|
103
96
|
describe('tag-ui — neutral default + explicit solid stamp', () => {
|
|
104
|
-
it('[variant="default"] stays quiet chrome (--a-bg-muted +
|
|
97
|
+
it('[variant="default"] stays quiet chrome (--a-bg-muted + neutral on-surface)', () => {
|
|
105
98
|
expect(TAG_CSS).toMatch(
|
|
106
|
-
/:scope\[variant="default"\]\s*\{[^}]*--tag-bg:\s*var\(--a-bg-muted\)[^}]*--tag-fg:\s*var\(--
|
|
99
|
+
/:scope\[variant="default"\]\s*\{[^}]*--tag-bg:\s*var\(--a-bg-muted\)[^}]*--tag-fg:\s*var\(--md-sys-color-neutral-on-surface\)/s
|
|
107
100
|
);
|
|
108
101
|
});
|
|
109
102
|
|
|
110
|
-
it('[tone="solid"] without a family inverts to
|
|
103
|
+
it('[tone="solid"] without a family inverts to a high-contrast neutral stamp', () => {
|
|
111
104
|
expect(TAG_CSS).toMatch(
|
|
112
|
-
/:scope\[tone="solid"\]:not\(\[variant="info"\]\)[\s\S]*?--tag-bg:\s*var\(--
|
|
105
|
+
/:scope\[tone="solid"\]:not\(\[variant="info"\]\)[\s\S]*?--tag-bg:\s*var\(--md-sys-color-neutral-on-surface\)[\s\S]*?--tag-fg:\s*var\(--md-sys-color-neutral-background\)/
|
|
113
106
|
);
|
|
114
107
|
});
|
|
115
108
|
});
|
|
@@ -129,16 +122,16 @@ describe('tag-ui — [tone="outline"] strips fill + colors border', () => {
|
|
|
129
122
|
])('[tone="outline"][variant="%s"] colors fg + border per family', (family) => {
|
|
130
123
|
const block = new RegExp(
|
|
131
124
|
`:scope\\[tone="outline"\\]\\[variant="${family}"\\]\\s*\\{[^}]*` +
|
|
132
|
-
`--tag-fg:\\s*var\\(--
|
|
133
|
-
`--tag-border:\\s*var\\(--
|
|
125
|
+
`--tag-fg:\\s*var\\(--md-sys-color-${family}-on-surface\\)[^}]*` +
|
|
126
|
+
`--tag-border:\\s*var\\(--md-sys-color-${family}-outline\\)`,
|
|
134
127
|
's'
|
|
135
128
|
);
|
|
136
129
|
expect(TAG_CSS).toMatch(block);
|
|
137
130
|
});
|
|
138
131
|
|
|
139
|
-
it('[tone="outline"] on neutral uses --a-fg-muted text +
|
|
132
|
+
it('[tone="outline"] on neutral uses --a-fg-muted text + neutral outline ring', () => {
|
|
140
133
|
expect(TAG_CSS).toMatch(
|
|
141
|
-
/:scope\[tone="outline"\]:not\(\[variant="info"\]\)[\s\S]*?--tag-fg:\s*var\(--a-fg-muted\)[\s\S]*?--tag-border:\s*var\(--
|
|
134
|
+
/:scope\[tone="outline"\]:not\(\[variant="info"\]\)[\s\S]*?--tag-fg:\s*var\(--a-fg-muted\)[\s\S]*?--tag-border:\s*var\(--md-sys-color-neutral-outline\)/
|
|
142
135
|
);
|
|
143
136
|
});
|
|
144
137
|
});
|
|
@@ -227,7 +227,7 @@
|
|
|
227
227
|
],
|
|
228
228
|
"slots": {
|
|
229
229
|
"chip": {
|
|
230
|
-
"description": "Custom chip template
|
|
230
|
+
"description": "Custom per-token chip template (TKT-0023). Provide a single\n`<template slot=\"chip\">` child; it's cloned once per committed\ntoken, with `{{value}}` / `{{index}}` substituted into every text\nnode and attribute value in the clone (e.g.\n`<tag-ui removable text=\"{{value}}\" title=\"Item #{{index}}\">`).\nThe template's first element child is the reconcile unit — data-*\nbookkeeping attrs land on it, so removal / re-render still track\nby position the same way the default chip does. When absent, or\nwhen the template has no element content (malformed), each token\nrenders as the default `<tag-ui removable text=\"<value>\">`.\nReadonly/disabled toggling of the built-in `removable` affordance\nonly applies to the default chip — a custom template always owns\nits own removability, independent of the host's readonly/disabled\nstate."
|
|
231
231
|
}
|
|
232
232
|
},
|
|
233
233
|
"states": [
|
|
@@ -261,7 +261,7 @@
|
|
|
261
261
|
"name": "disabled"
|
|
262
262
|
},
|
|
263
263
|
{
|
|
264
|
-
"description": "Read-only; chips render without remove affordance.",
|
|
264
|
+
"description": "Read-only; default chips render without remove affordance (a\ncustom `chip` template owns its own removability and is\nunaffected).",
|
|
265
265
|
"attribute": "readonly",
|
|
266
266
|
"name": "readonly"
|
|
267
267
|
}
|
|
@@ -238,6 +238,11 @@ export class UITagsInput extends UIFormElement {
|
|
|
238
238
|
this.#bindListeners();
|
|
239
239
|
return;
|
|
240
240
|
}
|
|
241
|
+
// Capture any author-declared chip template (TKT-0023) BEFORE the
|
|
242
|
+
// wholesale `innerHTML` replacement below, which would otherwise
|
|
243
|
+
// discard it — the captured reference stays valid (just detached)
|
|
244
|
+
// across the replacement and gets re-appended after.
|
|
245
|
+
const chipTemplate = this.querySelector(':scope > template[slot="chip"]');
|
|
241
246
|
const suggestId = `${this.#instanceId}-suggestions`;
|
|
242
247
|
const inputId = `${this.#instanceId}-input`;
|
|
243
248
|
this.innerHTML = `
|
|
@@ -257,6 +262,7 @@ export class UITagsInput extends UIFormElement {
|
|
|
257
262
|
</span>
|
|
258
263
|
<div data-suggestions id="${suggestId}" role="listbox" hidden></div>
|
|
259
264
|
`;
|
|
265
|
+
if (chipTemplate) this.appendChild(chipTemplate);
|
|
260
266
|
this.#queryRefs();
|
|
261
267
|
this.#bindListeners();
|
|
262
268
|
}
|
|
@@ -299,29 +305,38 @@ export class UITagsInput extends UIFormElement {
|
|
|
299
305
|
}
|
|
300
306
|
|
|
301
307
|
// ── Render chips ──
|
|
308
|
+
//
|
|
309
|
+
// SPEC-042 §chip slot (TKT-0023): an author-provided
|
|
310
|
+
// `<template slot="chip">` overrides the default `<tag-ui>` render, one
|
|
311
|
+
// clone per token. `{{value}}` / `{{index}}` are substituted into every
|
|
312
|
+
// text node and attribute value in the cloned subtree — declarative, no
|
|
313
|
+
// JS required, so it works from static markup and a2ui-generated pages.
|
|
302
314
|
|
|
303
315
|
#renderChips() {
|
|
304
316
|
if (!this.#chipList) return;
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
//
|
|
308
|
-
//
|
|
309
|
-
|
|
317
|
+
const template = this.querySelector(':scope > template[slot="chip"]');
|
|
318
|
+
const mode = template ? 'custom' : 'default';
|
|
319
|
+
// Reconcile in place: an existing chip at a position keeps its node
|
|
320
|
+
// when its value + mode haven't changed (so :hover / :focus / animation
|
|
321
|
+
// states don't flicker on each typed-character render); a changed or
|
|
322
|
+
// absent position gets a fresh node; excess chips drop; new ones append.
|
|
323
|
+
const existing = Array.from(this.#chipList.children);
|
|
310
324
|
for (let i = 0; i < this.#value.length; i++) {
|
|
311
325
|
const v = this.#value[i];
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
} else {
|
|
322
|
-
chip.setAttribute('removable', '');
|
|
326
|
+
const current = existing[i];
|
|
327
|
+
const reusable = current && current.dataset.chipMode === mode && current.dataset.chipValue === v;
|
|
328
|
+
if (reusable) {
|
|
329
|
+
current.setAttribute('data-index', String(i));
|
|
330
|
+
if (!template) {
|
|
331
|
+
if (this.readonly || this.disabled) current.removeAttribute('removable');
|
|
332
|
+
else current.setAttribute('removable', '');
|
|
333
|
+
}
|
|
334
|
+
continue;
|
|
323
335
|
}
|
|
324
|
-
|
|
336
|
+
const fresh = template ? this.#buildCustomChip(template, v, i) : this.#buildDefaultChip(v, i);
|
|
337
|
+
if (current) this.#chipList.replaceChild(fresh, current);
|
|
338
|
+
else this.#chipList.appendChild(fresh);
|
|
339
|
+
existing[i] = fresh;
|
|
325
340
|
}
|
|
326
341
|
// Drop overflow chips.
|
|
327
342
|
for (let i = this.#value.length; i < existing.length; i++) {
|
|
@@ -329,6 +344,58 @@ export class UITagsInput extends UIFormElement {
|
|
|
329
344
|
}
|
|
330
345
|
}
|
|
331
346
|
|
|
347
|
+
#buildDefaultChip(value, index) {
|
|
348
|
+
const chip = document.createElement('tag-ui');
|
|
349
|
+
chip.setAttribute('role', 'listitem');
|
|
350
|
+
chip.setAttribute('text', value);
|
|
351
|
+
if (!(this.readonly || this.disabled)) chip.setAttribute('removable', '');
|
|
352
|
+
chip.setAttribute('data-index', String(index));
|
|
353
|
+
chip.dataset.chipMode = 'default';
|
|
354
|
+
chip.dataset.chipValue = value;
|
|
355
|
+
return chip;
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
#buildCustomChip(template, value, index) {
|
|
359
|
+
const frag = template.content.cloneNode(true);
|
|
360
|
+
this.#substitutePlaceholders(frag, value, index);
|
|
361
|
+
// Reconcile unit = first element child (ignores incidental whitespace
|
|
362
|
+
// text nodes from formatted template markup).
|
|
363
|
+
const root = frag.firstElementChild;
|
|
364
|
+
if (!root) return this.#buildDefaultChip(value, index); // malformed template — degrade to default rather than render nothing
|
|
365
|
+
root.setAttribute('role', 'listitem');
|
|
366
|
+
root.setAttribute('data-index', String(index));
|
|
367
|
+
root.dataset.chipMode = 'custom';
|
|
368
|
+
root.dataset.chipValue = value;
|
|
369
|
+
return root;
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
/** Replace `{{value}}` / `{{index}}` in every text node + attribute of
|
|
373
|
+
* `root` (a cloned template fragment), in place. Single-pass regex —
|
|
374
|
+
* chained `.replaceAll()` calls would let a token whose literal text is
|
|
375
|
+
* `{{index}}` get re-matched by the second pass after the first pass
|
|
376
|
+
* substitutes it in. */
|
|
377
|
+
#substitutePlaceholders(root, value, index) {
|
|
378
|
+
const idxStr = String(index);
|
|
379
|
+
const substitute = (str) =>
|
|
380
|
+
str.replace(/\{\{value\}\}|\{\{index\}\}/g, (m) => (m === '{{value}}' ? value : idxStr));
|
|
381
|
+
const walker = document.createTreeWalker(root, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_TEXT);
|
|
382
|
+
let node;
|
|
383
|
+
// eslint-disable-next-line no-cond-assign
|
|
384
|
+
while ((node = walker.nextNode())) {
|
|
385
|
+
if (node.nodeType === Node.TEXT_NODE) {
|
|
386
|
+
if (node.data.includes('{{')) {
|
|
387
|
+
node.data = substitute(node.data);
|
|
388
|
+
}
|
|
389
|
+
} else {
|
|
390
|
+
for (const attr of node.attributes) {
|
|
391
|
+
if (attr.value.includes('{{')) {
|
|
392
|
+
attr.value = substitute(attr.value);
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
|
|
332
399
|
#renderSuggestions() {
|
|
333
400
|
if (!this.#suggestEl) return;
|
|
334
401
|
const typed = this.#inputEl ? (this.#inputEl.textContent || '').trim().toLowerCase() : '';
|
|
@@ -516,7 +583,12 @@ export class UITagsInput extends UIFormElement {
|
|
|
516
583
|
}
|
|
517
584
|
|
|
518
585
|
#handleChipRemove(e) {
|
|
519
|
-
|
|
586
|
+
// `[data-index]` (not `tag-ui[data-index]`) — a chip-slot template
|
|
587
|
+
// (TKT-0023) may wrap its own `<tag-ui removable>` inside an arbitrary
|
|
588
|
+
// root element; `data-index` is stamped on whichever node is the
|
|
589
|
+
// reconcile unit for that position (see `#buildCustomChip`), so
|
|
590
|
+
// `closest()` finds the right ancestor regardless of its tag name.
|
|
591
|
+
const chip = e.target.closest('[data-index]');
|
|
520
592
|
if (!chip) return;
|
|
521
593
|
// tag-ui's `remove` CustomEvent bubbles SYNCHRONOUSLY before tag-ui's
|
|
522
594
|
// own `this.remove()` runs (see tag/tag.class.js:59-63 — dispatch then
|
|
@@ -525,8 +597,9 @@ export class UITagsInput extends UIFormElement {
|
|
|
525
597
|
// positional reconcile in `#renderChips()` mutates the WRONG chip's
|
|
526
598
|
// text — visually erasing one or more adjacent chips. Pre-emptively
|
|
527
599
|
// detach the source chip ourselves so the DOM matches `#value` before
|
|
528
|
-
// render. tag-ui's later `this.remove()` is a harmless no-op
|
|
529
|
-
// already-detached node
|
|
600
|
+
// render. tag-ui's later `this.remove()` is a harmless no-op — either
|
|
601
|
+
// on an already-detached node (default chip == the tag-ui itself), or
|
|
602
|
+
// on a nested tag-ui whose ancestor `chip` root was just detached.
|
|
530
603
|
e.stopPropagation();
|
|
531
604
|
const idx = Number(chip.dataset.index);
|
|
532
605
|
if (!Number.isInteger(idx)) return;
|
|
@@ -25,10 +25,10 @@
|
|
|
25
25
|
--tags-input-easing: var(--a-easing);
|
|
26
26
|
|
|
27
27
|
/* ── Chip overrides — cascaded into nested <tag-ui> ── */
|
|
28
|
-
--tags-input-chip-bg-invalid: var(--
|
|
28
|
+
--tags-input-chip-bg-invalid: var(--md-sys-color-danger-container);
|
|
29
29
|
|
|
30
30
|
/* ── Suggestions popover ── */
|
|
31
|
-
--tags-input-suggestions-bg: var(--
|
|
31
|
+
--tags-input-suggestions-bg: var(--md-sys-color-neutral-surface-bright);
|
|
32
32
|
--tags-input-suggestions-border: var(--a-ui-border);
|
|
33
33
|
--tags-input-suggestions-radius: var(--a-radius);
|
|
34
34
|
--tags-input-suggestions-shadow: var(--a-shadow-lg);
|
|
@@ -169,7 +169,7 @@ tags-input-ui [data-suggestions] {
|
|
|
169
169
|
padding: var(--a-space-1);
|
|
170
170
|
border: 1px solid var(--a-ui-border);
|
|
171
171
|
border-radius: var(--a-radius);
|
|
172
|
-
background: var(--
|
|
172
|
+
background: var(--md-sys-color-neutral-surface-bright);
|
|
173
173
|
box-shadow: var(--a-shadow-lg);
|
|
174
174
|
font-family: inherit;
|
|
175
175
|
font-size: var(--a-ui-size);
|
|
@@ -320,6 +320,115 @@ describe('tags-input-ui — disabled / readonly / form', () => {
|
|
|
320
320
|
});
|
|
321
321
|
});
|
|
322
322
|
|
|
323
|
+
describe('tags-input-ui — chip slot template (TKT-0023)', () => {
|
|
324
|
+
beforeEach(() => { document.body.innerHTML = ''; });
|
|
325
|
+
|
|
326
|
+
it('with no template, renders the default <tag-ui removable text>', async () => {
|
|
327
|
+
const el = mount('<tags-input-ui value=\'["a"]\'></tags-input-ui>');
|
|
328
|
+
await tick();
|
|
329
|
+
const chip = el.querySelector(':scope > [data-chip-list] > *');
|
|
330
|
+
expect(chip.tagName.toLowerCase()).toBe('tag-ui');
|
|
331
|
+
expect(chip.getAttribute('text')).toBe('a');
|
|
332
|
+
expect(chip.hasAttribute('removable')).toBe(true);
|
|
333
|
+
});
|
|
334
|
+
|
|
335
|
+
it('an author <template slot="chip"> overrides the default render, substituting {{value}}/{{index}}', async () => {
|
|
336
|
+
const el = mount(`
|
|
337
|
+
<tags-input-ui value='["alpha","beta"]'>
|
|
338
|
+
<template slot="chip"><tag-ui removable text="{{value}}" title="Item #{{index}}"></tag-ui></template>
|
|
339
|
+
</tags-input-ui>
|
|
340
|
+
`);
|
|
341
|
+
await tick();
|
|
342
|
+
const chips = el.querySelectorAll(':scope > [data-chip-list] > *');
|
|
343
|
+
expect(chips).toHaveLength(2);
|
|
344
|
+
expect(chips[0].getAttribute('text')).toBe('alpha');
|
|
345
|
+
expect(chips[0].getAttribute('title')).toBe('Item #0');
|
|
346
|
+
expect(chips[1].getAttribute('text')).toBe('beta');
|
|
347
|
+
expect(chips[1].getAttribute('title')).toBe('Item #1');
|
|
348
|
+
});
|
|
349
|
+
|
|
350
|
+
it('the chip template survives the first-connect shell stamp (not wiped by innerHTML replacement)', async () => {
|
|
351
|
+
const el = mount(`
|
|
352
|
+
<tags-input-ui value='["x"]'>
|
|
353
|
+
<template slot="chip"><span class="custom">{{value}}</span></template>
|
|
354
|
+
</tags-input-ui>
|
|
355
|
+
`);
|
|
356
|
+
await tick();
|
|
357
|
+
expect(el.querySelector(':scope > template[slot="chip"]')).toBeTruthy();
|
|
358
|
+
const chip = el.querySelector(':scope > [data-chip-list] > .custom');
|
|
359
|
+
expect(chip?.textContent).toBe('x');
|
|
360
|
+
});
|
|
361
|
+
|
|
362
|
+
it('substitutes {{value}}/{{index}} in attribute values, not just text content', async () => {
|
|
363
|
+
const el = mount(`
|
|
364
|
+
<tags-input-ui value='["a","b"]'>
|
|
365
|
+
<template slot="chip"><span data-slot-value="{{value}}" data-slot-index="{{index}}">{{value}}</span></template>
|
|
366
|
+
</tags-input-ui>
|
|
367
|
+
`);
|
|
368
|
+
await tick();
|
|
369
|
+
const chips = el.querySelectorAll(':scope > [data-chip-list] > span');
|
|
370
|
+
expect(chips[0].dataset.slotValue).toBe('a');
|
|
371
|
+
expect(chips[0].dataset.slotIndex).toBe('0');
|
|
372
|
+
expect(chips[1].dataset.slotValue).toBe('b');
|
|
373
|
+
expect(chips[1].dataset.slotIndex).toBe('1');
|
|
374
|
+
});
|
|
375
|
+
|
|
376
|
+
it('reconciles by position: adding a token appends without recreating existing custom chips', async () => {
|
|
377
|
+
const el = mount(`
|
|
378
|
+
<tags-input-ui value='["a"]'>
|
|
379
|
+
<template slot="chip"><span>{{value}}</span></template>
|
|
380
|
+
</tags-input-ui>
|
|
381
|
+
`);
|
|
382
|
+
await tick();
|
|
383
|
+
const first = el.querySelector(':scope > [data-chip-list] > span');
|
|
384
|
+
el.addToken('b');
|
|
385
|
+
await tick();
|
|
386
|
+
const chips = el.querySelectorAll(':scope > [data-chip-list] > span');
|
|
387
|
+
expect(chips).toHaveLength(2);
|
|
388
|
+
expect(chips[0]).toBe(first); // unchanged position — same node, no flicker
|
|
389
|
+
expect(chips[1].textContent).toBe('b');
|
|
390
|
+
});
|
|
391
|
+
|
|
392
|
+
it('a custom chip participates in removal via a bubbling `remove` event from a nested tag-ui', async () => {
|
|
393
|
+
const el = mount(`
|
|
394
|
+
<tags-input-ui value='["a","b"]'>
|
|
395
|
+
<template slot="chip"><span class="wrap"><tag-ui removable text="{{value}}"></tag-ui></span></template>
|
|
396
|
+
</tags-input-ui>
|
|
397
|
+
`);
|
|
398
|
+
await tick();
|
|
399
|
+
const nestedTag = el.querySelector(':scope > [data-chip-list] .wrap tag-ui[text="a"]');
|
|
400
|
+
nestedTag.dispatchEvent(new CustomEvent('remove', { bubbles: true }));
|
|
401
|
+
await tick();
|
|
402
|
+
expect(el.value).toEqual(['b']);
|
|
403
|
+
});
|
|
404
|
+
|
|
405
|
+
it('a malformed template (no element content) degrades to the default chip rather than rendering nothing', async () => {
|
|
406
|
+
const el = mount(`
|
|
407
|
+
<tags-input-ui value='["a"]'>
|
|
408
|
+
<template slot="chip"> </template>
|
|
409
|
+
</tags-input-ui>
|
|
410
|
+
`);
|
|
411
|
+
await tick();
|
|
412
|
+
const chip = el.querySelector(':scope > [data-chip-list] > *');
|
|
413
|
+
expect(chip.tagName.toLowerCase()).toBe('tag-ui');
|
|
414
|
+
expect(chip.getAttribute('text')).toBe('a');
|
|
415
|
+
});
|
|
416
|
+
|
|
417
|
+
it('a token literally equal to "{{index}}" is not clobbered by the index substitution pass', async () => {
|
|
418
|
+
const el = mount(`
|
|
419
|
+
<tags-input-ui value='["{{index}}","real"]'>
|
|
420
|
+
<template slot="chip"><span data-slot-index="{{index}}">{{value}}</span></template>
|
|
421
|
+
</tags-input-ui>
|
|
422
|
+
`);
|
|
423
|
+
await tick();
|
|
424
|
+
const chips = el.querySelectorAll(':scope > [data-chip-list] > span');
|
|
425
|
+
expect(chips[0].textContent).toBe('{{index}}');
|
|
426
|
+
expect(chips[0].dataset.slotIndex).toBe('0');
|
|
427
|
+
expect(chips[1].textContent).toBe('real');
|
|
428
|
+
expect(chips[1].dataset.slotIndex).toBe('1');
|
|
429
|
+
});
|
|
430
|
+
});
|
|
431
|
+
|
|
323
432
|
describe('tags-input-ui — change event', () => {
|
|
324
433
|
beforeEach(() => { document.body.innerHTML = ''; });
|
|
325
434
|
|
|
@@ -186,9 +186,20 @@ events:
|
|
|
186
186
|
slots:
|
|
187
187
|
chip:
|
|
188
188
|
description: |-
|
|
189
|
-
Custom chip template
|
|
190
|
-
|
|
191
|
-
|
|
189
|
+
Custom per-token chip template (TKT-0023). Provide a single
|
|
190
|
+
`<template slot="chip">` child; it's cloned once per committed
|
|
191
|
+
token, with `{{value}}` / `{{index}}` substituted into every text
|
|
192
|
+
node and attribute value in the clone (e.g.
|
|
193
|
+
`<tag-ui removable text="{{value}}" title="Item #{{index}}">`).
|
|
194
|
+
The template's first element child is the reconcile unit — data-*
|
|
195
|
+
bookkeeping attrs land on it, so removal / re-render still track
|
|
196
|
+
by position the same way the default chip does. When absent, or
|
|
197
|
+
when the template has no element content (malformed), each token
|
|
198
|
+
renders as the default `<tag-ui removable text="<value>">`.
|
|
199
|
+
Readonly/disabled toggling of the built-in `removable` affordance
|
|
200
|
+
only applies to the default chip — a custom template always owns
|
|
201
|
+
its own removability, independent of the host's readonly/disabled
|
|
202
|
+
state.
|
|
192
203
|
states:
|
|
193
204
|
- name: idle
|
|
194
205
|
description: No tokens; no typed text.
|
|
@@ -208,7 +219,10 @@ states:
|
|
|
208
219
|
description: Non-interactive; dimmed.
|
|
209
220
|
attribute: disabled
|
|
210
221
|
- name: readonly
|
|
211
|
-
description:
|
|
222
|
+
description: |-
|
|
223
|
+
Read-only; default chips render without remove affordance (a
|
|
224
|
+
custom `chip` template owns its own removability and is
|
|
225
|
+
unaffected).
|
|
212
226
|
attribute: readonly
|
|
213
227
|
traits: []
|
|
214
228
|
tokens:
|
package/components/text/text.css
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
--text-leading: var(--a-body-leading);
|
|
9
9
|
--text-tracking: var(--a-body-tracking);
|
|
10
10
|
--text-case: var(--a-body-case);
|
|
11
|
-
--text-color: var(--
|
|
11
|
+
--text-color: var(--md-sys-color-neutral-on-surface);
|
|
12
12
|
--text-color-strong: var(--a-fg-strong);
|
|
13
13
|
}
|
|
14
14
|
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
}
|
|
39
39
|
|
|
40
40
|
/* ── Variants ── */
|
|
41
|
-
:scope[variant="body"] { --text-family: var(--a-body-family); --text-weight: var(--a-body-weight); --text-size: var(--a-body-size); --text-leading: var(--a-body-leading); --text-tracking: var(--a-body-tracking); --text-case: var(--a-body-case); --text-color: var(--
|
|
41
|
+
:scope[variant="body"] { --text-family: var(--a-body-family); --text-weight: var(--a-body-weight); --text-size: var(--a-body-size); --text-leading: var(--a-body-leading); --text-tracking: var(--a-body-tracking); --text-case: var(--a-body-case); --text-color: var(--md-sys-color-neutral-on-surface); }
|
|
42
42
|
:scope[variant="display"] { --text-family: var(--a-display-family); --text-weight: var(--a-display-weight); --text-size: var(--a-display-size); --text-leading: var(--a-display-leading); --text-tracking: var(--a-display-tracking); --text-case: var(--a-display-case); --text-color: var(--a-display-color); }
|
|
43
43
|
:scope[variant="title"] { --text-family: var(--a-title-family); --text-weight: var(--a-title-weight); --text-size: var(--a-title-size); --text-leading: var(--a-title-leading); --text-tracking: var(--a-title-tracking); --text-case: var(--a-title-case); --text-color: var(--a-title-color); }
|
|
44
44
|
:scope[variant="heading"] { --text-family: var(--a-heading-family); --text-weight: var(--a-heading-weight); --text-size: var(--a-heading-size); --text-leading: var(--a-heading-leading); --text-tracking: var(--a-heading-tracking); --text-case: var(--a-heading-case); --text-color: var(--a-heading-color); }
|
|
@@ -78,10 +78,10 @@
|
|
|
78
78
|
|
|
79
79
|
/* color — default | subtle | strong | accent | danger | success | warning
|
|
80
80
|
(no value = variant default; "default" is an explicit reset). */
|
|
81
|
-
:scope[color="default"] { --text-color: var(--
|
|
81
|
+
:scope[color="default"] { --text-color: var(--md-sys-color-neutral-on-surface); }
|
|
82
82
|
:scope[color="subtle"] { --text-color: var(--a-fg-muted); }
|
|
83
83
|
:scope[color="strong"] { --text-color: var(--a-fg-strong); }
|
|
84
|
-
:scope[color="accent"] { --text-color: var(--
|
|
84
|
+
:scope[color="accent"] { --text-color: var(--md-sys-color-primary); }
|
|
85
85
|
:scope[color="danger"] { --text-color: var(--a-danger-bg); }
|
|
86
86
|
:scope[color="success"] { --text-color: var(--a-success-bg); }
|
|
87
87
|
:scope[color="warning"] { --text-color: var(--a-warning-bg); }
|