@urbicon-ui/blocks 6.40.4 → 6.43.2

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 (107) hide show
  1. package/README.md +1 -1
  2. package/dist/components/Calendar/calendar.variants.d.ts +63 -63
  3. package/dist/components/Chat/A2UIView/A2UINode.svelte +20 -39
  4. package/dist/components/Chat/A2UIView/A2UIView.svelte +47 -50
  5. package/dist/components/Chat/A2UIView/a2ui-basic-catalog.d.ts +17 -0
  6. package/dist/components/Chat/A2UIView/a2ui-basic-catalog.js +69 -0
  7. package/dist/components/Chat/A2UIView/a2ui-catalog.d.ts +95 -0
  8. package/dist/components/Chat/A2UIView/a2ui-catalog.js +87 -0
  9. package/dist/components/Chat/A2UIView/a2ui-node-common.d.ts +40 -0
  10. package/dist/components/Chat/A2UIView/a2ui-node-common.js +72 -0
  11. package/dist/components/Chat/A2UIView/a2ui-prompt.d.ts +21 -10
  12. package/dist/components/Chat/A2UIView/a2ui-prompt.js +170 -24
  13. package/dist/components/Chat/A2UIView/a2ui-registry.d.ts +1 -1
  14. package/dist/components/Chat/A2UIView/a2ui-registry.js +2 -1
  15. package/dist/components/Chat/A2UIView/a2ui-render.d.ts +30 -0
  16. package/dist/components/Chat/A2UIView/a2ui-render.js +61 -23
  17. package/dist/components/Chat/A2UIView/a2ui-router.d.ts +136 -0
  18. package/dist/components/Chat/A2UIView/a2ui-router.js +264 -0
  19. package/dist/components/Chat/A2UIView/a2ui-schema.d.ts +45 -0
  20. package/dist/components/Chat/A2UIView/a2ui-schema.js +133 -0
  21. package/dist/components/Chat/A2UIView/a2ui-stream.d.ts +120 -0
  22. package/dist/components/Chat/A2UIView/a2ui-stream.js +406 -0
  23. package/dist/components/Chat/A2UIView/a2ui-transcript.d.ts +65 -0
  24. package/dist/components/Chat/A2UIView/a2ui-transcript.js +101 -0
  25. package/dist/components/Chat/A2UIView/a2ui-validate.d.ts +33 -1
  26. package/dist/components/Chat/A2UIView/a2ui-validate.js +167 -63
  27. package/dist/components/Chat/A2UIView/a2ui.types.d.ts +50 -0
  28. package/dist/components/Chat/A2UIView/a2ui.types.js +38 -1
  29. package/dist/components/Chat/A2UIView/index.d.ts +35 -2
  30. package/dist/components/Chat/A2UIView/index.js +13 -0
  31. package/dist/components/Chat/A2UIView/urbicon/UrbiconA2UINode.svelte +831 -0
  32. package/dist/components/Chat/A2UIView/urbicon/UrbiconA2UINode.svelte.d.ts +4 -0
  33. package/dist/components/Chat/A2UIView/urbicon/a2ui-urbicon-catalog.d.ts +14 -0
  34. package/dist/components/Chat/A2UIView/urbicon/a2ui-urbicon-catalog.js +87 -0
  35. package/dist/components/Chat/A2UIView/urbicon/a2ui-urbicon-registry.d.ts +78 -0
  36. package/dist/components/Chat/A2UIView/urbicon/a2ui-urbicon-registry.js +783 -0
  37. package/dist/components/Chat/A2UIView/urbicon/a2ui-urbicon.variants.d.ts +43 -0
  38. package/dist/components/Chat/A2UIView/urbicon/a2ui-urbicon.variants.js +33 -0
  39. package/dist/components/Chat/A2UIView/urbicon/urbicon-axes.gen.d.ts +7 -0
  40. package/dist/components/Chat/A2UIView/urbicon/urbicon-axes.gen.js +86 -0
  41. package/dist/components/Chat/ChatMessage/ChatMessage.svelte +93 -67
  42. package/dist/components/Chat/ChatMessage/chat-message.variants.d.ts +26 -19
  43. package/dist/components/Chat/ChatMessage/chat-message.variants.js +45 -12
  44. package/dist/components/Chat/ChatMessage/index.d.ts +20 -5
  45. package/dist/components/Chat/CodeBlock/CodeBlock.svelte +59 -33
  46. package/dist/components/Chat/CodeBlock/code-block.variants.d.ts +7 -0
  47. package/dist/components/Chat/CodeBlock/code-block.variants.js +28 -13
  48. package/dist/components/Chat/CodeBlock/index.d.ts +39 -4
  49. package/dist/components/Chat/PromptInput/PromptInput.svelte +9 -16
  50. package/dist/components/Chat/PromptInput/prompt-input.variants.js +16 -15
  51. package/dist/components/Chat/ToolCallCard/ToolCallCard.svelte +9 -4
  52. package/dist/components/Chat/ToolCallCard/index.d.ts +4 -3
  53. package/dist/components/Chat/ToolCallCard/tool-call-card.variants.d.ts +0 -3
  54. package/dist/components/Chat/ToolCallCard/tool-call-card.variants.js +4 -4
  55. package/dist/components/CopyButton/CopyButton.svelte +9 -19
  56. package/dist/components/CopyButton/copy-button.variants.d.ts +4 -4
  57. package/dist/components/FileUpload/fileUpload.variants.js +15 -4
  58. package/dist/components/PinInput/PinInput.svelte +1 -0
  59. package/dist/components/PinInput/pin-input.variants.js +14 -1
  60. package/dist/components/TimeInput/time-input.variants.js +16 -1
  61. package/dist/i18n/index.d.ts +398 -2
  62. package/dist/internal/copy-state.svelte.d.ts +60 -0
  63. package/dist/internal/copy-state.svelte.js +76 -0
  64. package/dist/internal/field-chrome.d.ts +18 -1
  65. package/dist/internal/field-chrome.js +19 -2
  66. package/dist/primitives/Alert/alert.variants.d.ts +8 -8
  67. package/dist/primitives/Avatar/avatar.variants.js +4 -1
  68. package/dist/primitives/Badge/badge.variants.js +11 -2
  69. package/dist/primitives/Button/button.variants.js +4 -1
  70. package/dist/primitives/Card/card.variants.js +4 -1
  71. package/dist/primitives/Checkbox/checkbox.variants.js +7 -1
  72. package/dist/primitives/Combobox/Combobox.svelte +9 -1
  73. package/dist/primitives/Combobox/combobox.variants.d.ts +25 -0
  74. package/dist/primitives/Combobox/combobox.variants.js +43 -7
  75. package/dist/primitives/Combobox/index.d.ts +8 -2
  76. package/dist/primitives/Dialog/dialog.variants.js +4 -1
  77. package/dist/primitives/Drawer/drawer.variants.js +4 -1
  78. package/dist/primitives/Input/input.variants.js +17 -1
  79. package/dist/primitives/JourneyTimeline/journey-timeline.variants.d.ts +22 -22
  80. package/dist/primitives/Menu/menu.variants.js +5 -1
  81. package/dist/primitives/Progress/progress.variants.js +5 -2
  82. package/dist/primitives/RadioGroup/radioGroup.variants.js +74 -10
  83. package/dist/primitives/Select/select.variants.js +14 -5
  84. package/dist/primitives/Slider/Slider.svelte +4 -1
  85. package/dist/primitives/Slider/slider.variants.js +9 -2
  86. package/dist/primitives/Spinner/spinner.variants.d.ts +16 -16
  87. package/dist/primitives/Stepper/stepper.variants.d.ts +11 -11
  88. package/dist/primitives/Stepper/stepper.variants.js +2 -1
  89. package/dist/primitives/Tab/tab.variants.js +4 -1
  90. package/dist/primitives/Textarea/textarea.variants.js +16 -2
  91. package/dist/primitives/Toast/toast.variants.d.ts +12 -12
  92. package/dist/primitives/Toast/toast.variants.js +5 -1
  93. package/dist/primitives/Toggle/toggle.variants.js +94 -18
  94. package/dist/primitives/Tooltip/tooltip.variants.d.ts +3 -3
  95. package/dist/primitives/Tooltip/tooltip.variants.js +5 -1
  96. package/dist/style/foundation.css +19 -9
  97. package/dist/style/semantic.css +49 -2
  98. package/dist/style/themes/forest.css +2 -2
  99. package/dist/style/themes/neutral.css +2 -2
  100. package/dist/style/themes/ocean.css +2 -2
  101. package/dist/style/themes/rose.css +2 -2
  102. package/dist/style/themes/sunset.css +2 -2
  103. package/dist/utils/figma-token-export.js +7 -3
  104. package/dist/utils/persistent-state.svelte.d.ts +25 -1
  105. package/dist/utils/persistent-state.svelte.js +98 -10
  106. package/docs/MIGRATION-v5.md +29 -0
  107. package/package.json +3 -3
@@ -2,7 +2,7 @@ import { type SlotNames, type VariantProps } from '../../utils/variants.js';
2
2
  export declare const journeyTimelineVariants: ((props?: {
3
3
  orientation?: "horizontal" | "vertical" | undefined;
4
4
  size?: "sm" | "md" | "lg" | undefined;
5
- status?: "blocked" | "attention" | "active" | "complete" | "pending" | "skipped" | undefined;
5
+ status?: "complete" | "active" | "pending" | "attention" | "blocked" | "skipped" | undefined;
6
6
  focused?: boolean | undefined;
7
7
  interactive?: boolean | undefined;
8
8
  travelled?: boolean | undefined;
@@ -13,7 +13,7 @@ export declare const journeyTimelineVariants: ((props?: {
13
13
  base: (props?: ({
14
14
  orientation?: "horizontal" | "vertical" | undefined;
15
15
  size?: "sm" | "md" | "lg" | undefined;
16
- status?: "blocked" | "attention" | "active" | "complete" | "pending" | "skipped" | undefined;
16
+ status?: "complete" | "active" | "pending" | "attention" | "blocked" | "skipped" | undefined;
17
17
  focused?: boolean | undefined;
18
18
  interactive?: boolean | undefined;
19
19
  travelled?: boolean | undefined;
@@ -26,7 +26,7 @@ export declare const journeyTimelineVariants: ((props?: {
26
26
  rail: (props?: ({
27
27
  orientation?: "horizontal" | "vertical" | undefined;
28
28
  size?: "sm" | "md" | "lg" | undefined;
29
- status?: "blocked" | "attention" | "active" | "complete" | "pending" | "skipped" | undefined;
29
+ status?: "complete" | "active" | "pending" | "attention" | "blocked" | "skipped" | undefined;
30
30
  focused?: boolean | undefined;
31
31
  interactive?: boolean | undefined;
32
32
  travelled?: boolean | undefined;
@@ -39,7 +39,7 @@ export declare const journeyTimelineVariants: ((props?: {
39
39
  node: (props?: ({
40
40
  orientation?: "horizontal" | "vertical" | undefined;
41
41
  size?: "sm" | "md" | "lg" | undefined;
42
- status?: "blocked" | "attention" | "active" | "complete" | "pending" | "skipped" | undefined;
42
+ status?: "complete" | "active" | "pending" | "attention" | "blocked" | "skipped" | undefined;
43
43
  focused?: boolean | undefined;
44
44
  interactive?: boolean | undefined;
45
45
  travelled?: boolean | undefined;
@@ -52,7 +52,7 @@ export declare const journeyTimelineVariants: ((props?: {
52
52
  metaColumn: (props?: ({
53
53
  orientation?: "horizontal" | "vertical" | undefined;
54
54
  size?: "sm" | "md" | "lg" | undefined;
55
- status?: "blocked" | "attention" | "active" | "complete" | "pending" | "skipped" | undefined;
55
+ status?: "complete" | "active" | "pending" | "attention" | "blocked" | "skipped" | undefined;
56
56
  focused?: boolean | undefined;
57
57
  interactive?: boolean | undefined;
58
58
  travelled?: boolean | undefined;
@@ -65,7 +65,7 @@ export declare const journeyTimelineVariants: ((props?: {
65
65
  meta: (props?: ({
66
66
  orientation?: "horizontal" | "vertical" | undefined;
67
67
  size?: "sm" | "md" | "lg" | undefined;
68
- status?: "blocked" | "attention" | "active" | "complete" | "pending" | "skipped" | undefined;
68
+ status?: "complete" | "active" | "pending" | "attention" | "blocked" | "skipped" | undefined;
69
69
  focused?: boolean | undefined;
70
70
  interactive?: boolean | undefined;
71
71
  travelled?: boolean | undefined;
@@ -78,7 +78,7 @@ export declare const journeyTimelineVariants: ((props?: {
78
78
  markerColumn: (props?: ({
79
79
  orientation?: "horizontal" | "vertical" | undefined;
80
80
  size?: "sm" | "md" | "lg" | undefined;
81
- status?: "blocked" | "attention" | "active" | "complete" | "pending" | "skipped" | undefined;
81
+ status?: "complete" | "active" | "pending" | "attention" | "blocked" | "skipped" | undefined;
82
82
  focused?: boolean | undefined;
83
83
  interactive?: boolean | undefined;
84
84
  travelled?: boolean | undefined;
@@ -91,7 +91,7 @@ export declare const journeyTimelineVariants: ((props?: {
91
91
  marker: (props?: ({
92
92
  orientation?: "horizontal" | "vertical" | undefined;
93
93
  size?: "sm" | "md" | "lg" | undefined;
94
- status?: "blocked" | "attention" | "active" | "complete" | "pending" | "skipped" | undefined;
94
+ status?: "complete" | "active" | "pending" | "attention" | "blocked" | "skipped" | undefined;
95
95
  focused?: boolean | undefined;
96
96
  interactive?: boolean | undefined;
97
97
  travelled?: boolean | undefined;
@@ -104,7 +104,7 @@ export declare const journeyTimelineVariants: ((props?: {
104
104
  connector: (props?: ({
105
105
  orientation?: "horizontal" | "vertical" | undefined;
106
106
  size?: "sm" | "md" | "lg" | undefined;
107
- status?: "blocked" | "attention" | "active" | "complete" | "pending" | "skipped" | undefined;
107
+ status?: "complete" | "active" | "pending" | "attention" | "blocked" | "skipped" | undefined;
108
108
  focused?: boolean | undefined;
109
109
  interactive?: boolean | undefined;
110
110
  travelled?: boolean | undefined;
@@ -117,7 +117,7 @@ export declare const journeyTimelineVariants: ((props?: {
117
117
  content: (props?: ({
118
118
  orientation?: "horizontal" | "vertical" | undefined;
119
119
  size?: "sm" | "md" | "lg" | undefined;
120
- status?: "blocked" | "attention" | "active" | "complete" | "pending" | "skipped" | undefined;
120
+ status?: "complete" | "active" | "pending" | "attention" | "blocked" | "skipped" | undefined;
121
121
  focused?: boolean | undefined;
122
122
  interactive?: boolean | undefined;
123
123
  travelled?: boolean | undefined;
@@ -130,7 +130,7 @@ export declare const journeyTimelineVariants: ((props?: {
130
130
  card: (props?: ({
131
131
  orientation?: "horizontal" | "vertical" | undefined;
132
132
  size?: "sm" | "md" | "lg" | undefined;
133
- status?: "blocked" | "attention" | "active" | "complete" | "pending" | "skipped" | undefined;
133
+ status?: "complete" | "active" | "pending" | "attention" | "blocked" | "skipped" | undefined;
134
134
  focused?: boolean | undefined;
135
135
  interactive?: boolean | undefined;
136
136
  travelled?: boolean | undefined;
@@ -143,7 +143,7 @@ export declare const journeyTimelineVariants: ((props?: {
143
143
  header: (props?: ({
144
144
  orientation?: "horizontal" | "vertical" | undefined;
145
145
  size?: "sm" | "md" | "lg" | undefined;
146
- status?: "blocked" | "attention" | "active" | "complete" | "pending" | "skipped" | undefined;
146
+ status?: "complete" | "active" | "pending" | "attention" | "blocked" | "skipped" | undefined;
147
147
  focused?: boolean | undefined;
148
148
  interactive?: boolean | undefined;
149
149
  travelled?: boolean | undefined;
@@ -156,7 +156,7 @@ export declare const journeyTimelineVariants: ((props?: {
156
156
  trigger: (props?: ({
157
157
  orientation?: "horizontal" | "vertical" | undefined;
158
158
  size?: "sm" | "md" | "lg" | undefined;
159
- status?: "blocked" | "attention" | "active" | "complete" | "pending" | "skipped" | undefined;
159
+ status?: "complete" | "active" | "pending" | "attention" | "blocked" | "skipped" | undefined;
160
160
  focused?: boolean | undefined;
161
161
  interactive?: boolean | undefined;
162
162
  travelled?: boolean | undefined;
@@ -169,7 +169,7 @@ export declare const journeyTimelineVariants: ((props?: {
169
169
  trailing: (props?: ({
170
170
  orientation?: "horizontal" | "vertical" | undefined;
171
171
  size?: "sm" | "md" | "lg" | undefined;
172
- status?: "blocked" | "attention" | "active" | "complete" | "pending" | "skipped" | undefined;
172
+ status?: "complete" | "active" | "pending" | "attention" | "blocked" | "skipped" | undefined;
173
173
  focused?: boolean | undefined;
174
174
  interactive?: boolean | undefined;
175
175
  travelled?: boolean | undefined;
@@ -182,7 +182,7 @@ export declare const journeyTimelineVariants: ((props?: {
182
182
  labelGroup: (props?: ({
183
183
  orientation?: "horizontal" | "vertical" | undefined;
184
184
  size?: "sm" | "md" | "lg" | undefined;
185
- status?: "blocked" | "attention" | "active" | "complete" | "pending" | "skipped" | undefined;
185
+ status?: "complete" | "active" | "pending" | "attention" | "blocked" | "skipped" | undefined;
186
186
  focused?: boolean | undefined;
187
187
  interactive?: boolean | undefined;
188
188
  travelled?: boolean | undefined;
@@ -195,7 +195,7 @@ export declare const journeyTimelineVariants: ((props?: {
195
195
  title: (props?: ({
196
196
  orientation?: "horizontal" | "vertical" | undefined;
197
197
  size?: "sm" | "md" | "lg" | undefined;
198
- status?: "blocked" | "attention" | "active" | "complete" | "pending" | "skipped" | undefined;
198
+ status?: "complete" | "active" | "pending" | "attention" | "blocked" | "skipped" | undefined;
199
199
  focused?: boolean | undefined;
200
200
  interactive?: boolean | undefined;
201
201
  travelled?: boolean | undefined;
@@ -208,7 +208,7 @@ export declare const journeyTimelineVariants: ((props?: {
208
208
  subtitle: (props?: ({
209
209
  orientation?: "horizontal" | "vertical" | undefined;
210
210
  size?: "sm" | "md" | "lg" | undefined;
211
- status?: "blocked" | "attention" | "active" | "complete" | "pending" | "skipped" | undefined;
211
+ status?: "complete" | "active" | "pending" | "attention" | "blocked" | "skipped" | undefined;
212
212
  focused?: boolean | undefined;
213
213
  interactive?: boolean | undefined;
214
214
  travelled?: boolean | undefined;
@@ -221,7 +221,7 @@ export declare const journeyTimelineVariants: ((props?: {
221
221
  segment: (props?: ({
222
222
  orientation?: "horizontal" | "vertical" | undefined;
223
223
  size?: "sm" | "md" | "lg" | undefined;
224
- status?: "blocked" | "attention" | "active" | "complete" | "pending" | "skipped" | undefined;
224
+ status?: "complete" | "active" | "pending" | "attention" | "blocked" | "skipped" | undefined;
225
225
  focused?: boolean | undefined;
226
226
  interactive?: boolean | undefined;
227
227
  travelled?: boolean | undefined;
@@ -234,7 +234,7 @@ export declare const journeyTimelineVariants: ((props?: {
234
234
  detail: (props?: ({
235
235
  orientation?: "horizontal" | "vertical" | undefined;
236
236
  size?: "sm" | "md" | "lg" | undefined;
237
- status?: "blocked" | "attention" | "active" | "complete" | "pending" | "skipped" | undefined;
237
+ status?: "complete" | "active" | "pending" | "attention" | "blocked" | "skipped" | undefined;
238
238
  focused?: boolean | undefined;
239
239
  interactive?: boolean | undefined;
240
240
  travelled?: boolean | undefined;
@@ -247,7 +247,7 @@ export declare const journeyTimelineVariants: ((props?: {
247
247
  detailInner: (props?: ({
248
248
  orientation?: "horizontal" | "vertical" | undefined;
249
249
  size?: "sm" | "md" | "lg" | undefined;
250
- status?: "blocked" | "attention" | "active" | "complete" | "pending" | "skipped" | undefined;
250
+ status?: "complete" | "active" | "pending" | "attention" | "blocked" | "skipped" | undefined;
251
251
  focused?: boolean | undefined;
252
252
  interactive?: boolean | undefined;
253
253
  travelled?: boolean | undefined;
@@ -260,7 +260,7 @@ export declare const journeyTimelineVariants: ((props?: {
260
260
  detailContent: (props?: ({
261
261
  orientation?: "horizontal" | "vertical" | undefined;
262
262
  size?: "sm" | "md" | "lg" | undefined;
263
- status?: "blocked" | "attention" | "active" | "complete" | "pending" | "skipped" | undefined;
263
+ status?: "complete" | "active" | "pending" | "attention" | "blocked" | "skipped" | undefined;
264
264
  focused?: boolean | undefined;
265
265
  interactive?: boolean | undefined;
266
266
  travelled?: boolean | undefined;
@@ -273,7 +273,7 @@ export declare const journeyTimelineVariants: ((props?: {
273
273
  panel: (props?: ({
274
274
  orientation?: "horizontal" | "vertical" | undefined;
275
275
  size?: "sm" | "md" | "lg" | undefined;
276
- status?: "blocked" | "attention" | "active" | "complete" | "pending" | "skipped" | undefined;
276
+ status?: "complete" | "active" | "pending" | "attention" | "blocked" | "skipped" | undefined;
277
277
  focused?: boolean | undefined;
278
278
  interactive?: boolean | undefined;
279
279
  travelled?: boolean | undefined;
@@ -5,7 +5,11 @@ export const menuVariants = tv({
5
5
  trigger: ['w-full justify-between gap-3 min-w-36'],
6
6
  triggerText: ['flex flex-1 items-center text-left truncate'],
7
7
  chevron: [
8
- 'w-4 h-4 shrink-0 opacity-70 transition-[opacity,transform] duration-[var(--blocks-duration-fast)] ease-out'
8
+ // `rotate,translate`, NOT `transform`: Tailwind 4 emits `rotate-*` /
9
+ // `translate-*` as the discrete `rotate:` / `translate:` properties. The
10
+ // `chevronAnimation` axis drives exactly those two (rotate-0 ↔ rotate-180,
11
+ // translate-y-0 ↔ translate-y-1), so a `transform` entry animated neither.
12
+ 'w-4 h-4 shrink-0 opacity-70 transition-[opacity,rotate,translate] duration-[var(--blocks-duration-fast)] ease-out'
9
13
  ],
10
14
  // Floating panel surface. Position is owned by the wrapping Popover
11
15
  // (Floating UI sets `top` / `left` on its container); this slot just
@@ -6,8 +6,11 @@ export const progressVariants = tv({
6
6
  label: ['text-sm font-medium text-text-secondary'],
7
7
  valueText: ['text-sm tabular-nums text-text-tertiary'],
8
8
  // tier: commit — progress bar reads as a continuous status pill.
9
+ // Track fill is `surface-interactive` for the same reason as Slider's:
10
+ // `surface-subtle` equals `surface-elevated` in both modes, which made the
11
+ // track disappear on elevated surfaces (cards, popovers, dialogs).
9
12
  track: [
10
- 'relative w-full overflow-hidden rounded-commit bg-surface-subtle',
13
+ 'relative w-full overflow-hidden rounded-commit bg-surface-interactive',
11
14
  'transition-[background-color] duration-[var(--blocks-duration-fast)] ease-out'
12
15
  ],
13
16
  fill: [
@@ -16,7 +19,7 @@ export const progressVariants = tv({
16
19
  'transition-[width,background-color] duration-[var(--blocks-duration-normal)] ease-out'
17
20
  ],
18
21
  circularWrapper: ['relative inline-flex items-center justify-center'],
19
- circularTrack: ['stroke-current text-surface-subtle'],
22
+ circularTrack: ['stroke-current text-surface-interactive'],
20
23
  circularFill: [
21
24
  'stroke-current transition-[stroke-dashoffset] duration-[var(--blocks-duration-normal)] ease-out'
22
25
  ],
@@ -39,13 +39,32 @@ export const radioItemVariants = tv({
39
39
  // a radio indicator declares status, conventionally circular.
40
40
  indicator: [
41
41
  'relative flex items-center justify-center shrink-0 border',
42
- 'transition-[color,background-color,border-color,box-shadow] duration-[var(--blocks-duration-fast)] ease-out',
42
+ 'transition-[color,background-color,border-color,box-shadow,scale] duration-[var(--blocks-duration-fast)] ease-out',
43
+ // Press feedback on the control surface — the same small-element press
44
+ // cue Checkbox took from Badge/Avatar (`scale-95`); `group-active` so
45
+ // pressing the label squeezes the indicator too. It sits on the
46
+ // indicator rather than the dot: the dot already owns the `scale`
47
+ // bucket for its own check-in animation (`scale-0` → `scale-100`), and
48
+ // scaling the parent carries the dot along multiplicatively instead of
49
+ // fighting that bucket — the whole control squeezes as one, exactly as
50
+ // Checkbox's box does with its check glyph. `scale` is in the
51
+ // transition list above, and reduced motion collapses
52
+ // `--blocks-duration-fast` to 1ms.
53
+ 'group-active:scale-95',
43
54
  'peer-focus-visible:ring-2 peer-focus-visible:ring-primary/50',
44
55
  'peer-focus-visible:ring-offset-2 peer-focus-visible:ring-offset-surface-base'
45
56
  ],
46
57
  dot: [
47
58
  'opacity-0 scale-0',
48
- 'transition-[opacity,transform] duration-[var(--blocks-duration-fast)] ease-out'
59
+ // `scale`, not `transform`: Tailwind 4 compiles `scale-*` to the
60
+ // discrete `scale` property (`scale: var(--tw-scale-x) …`), which a
61
+ // `transition-property: transform` does NOT cover — so the check-in
62
+ // used to pop to full size instantly while only the opacity faded.
63
+ // (The shorthand `transition-transform` would work, since v4 expands it
64
+ // to `transform, translate, scale, rotate`; the explicit list has to
65
+ // name the property it actually animates.) Both durations are tokens,
66
+ // so reduced motion collapses the whole check-in to 1ms.
67
+ 'transition-[opacity,scale] duration-[var(--blocks-duration-fast)] ease-out'
49
68
  ],
50
69
  label: ['text-text-primary select-none leading-snug'],
51
70
  description: ['text-text-tertiary leading-snug']
@@ -66,7 +85,12 @@ export const radioItemVariants = tv({
66
85
  indicator: 'w-3.5 h-3.5 mt-px',
67
86
  dot: 'w-1.5 h-1.5',
68
87
  label: 'text-xs',
69
- description: 'text-3xs'
88
+ // `description` carries full sentences, so it stops at the body-copy
89
+ // floor (`text-xs`) instead of continuing the ladder down to `text-3xs`
90
+ // (10px) — 2xs/3xs are for marks, hints and dense grids, never for prose
91
+ // (see the tokens page). At this size the label/description hierarchy is
92
+ // carried by colour (text-primary vs text-tertiary) rather than size.
93
+ description: 'text-xs'
70
94
  },
71
95
  sm: {
72
96
  item: 'gap-2',
@@ -139,41 +163,81 @@ export const radioItemVariants = tv({
139
163
  class: { indicator: 'bg-transparent border-transparent group-hover:bg-surface-subtle' }
140
164
  },
141
165
  // Checked intent colors
166
+ // Hover/active darken through the intent interaction-layer tokens — the
167
+ // same `bg-<intent>-hover` / `bg-<intent>-active` ladder Button and
168
+ // Checkbox use — via `group-*` so hovering/pressing the label counts too.
169
+ // The border stays on the base intent stop (as in Checkbox).
170
+ //
171
+ // The dot keeps ONE colour across all three stops: it is the intent's
172
+ // paired on-colour, and `style/contrast.test.ts` measures exactly that
173
+ // pairing (`--color-<intent>` / `-hover` / `-active` against
174
+ // `--color-text-on-primary` / `-on-warning`) across every theme × mode ×
175
+ // state — 126 combinations, all ≥ AA 4.5:1, and all ≥ the 3:1
176
+ // UI-component floor that actually binds a non-text mark. That includes
177
+ // the one adverse direction, `warning/light/active`, where the fill
178
+ // darkens *toward* the dark `text-on-warning`; warning-700 is pinned as
179
+ // the lowest press stop that still clears AA. So a state-dependent dot
180
+ // colour would buy nothing the token graph does not already guarantee.
142
181
  {
143
182
  checked: true,
144
183
  intent: 'primary',
145
- class: { indicator: 'bg-primary border-primary', dot: 'bg-text-on-primary' }
184
+ class: {
185
+ indicator: 'bg-primary border-primary group-hover:bg-primary-hover group-active:bg-primary-active',
186
+ dot: 'bg-text-on-primary'
187
+ }
146
188
  },
147
189
  {
148
190
  checked: true,
149
191
  intent: 'secondary',
150
- class: { indicator: 'bg-secondary border-secondary', dot: 'bg-text-on-primary' }
192
+ class: {
193
+ indicator: 'bg-secondary border-secondary group-hover:bg-secondary-hover group-active:bg-secondary-active',
194
+ dot: 'bg-text-on-primary'
195
+ }
151
196
  },
152
197
  {
153
198
  checked: true,
154
199
  intent: 'success',
155
- class: { indicator: 'bg-success border-success', dot: 'bg-text-on-primary' }
200
+ class: {
201
+ indicator: 'bg-success border-success group-hover:bg-success-hover group-active:bg-success-active',
202
+ dot: 'bg-text-on-primary'
203
+ }
156
204
  },
157
205
  {
158
206
  checked: true,
159
207
  intent: 'warning',
160
- class: { indicator: 'bg-warning border-warning', dot: 'bg-text-on-warning' }
208
+ class: {
209
+ indicator: 'bg-warning border-warning group-hover:bg-warning-hover group-active:bg-warning-active',
210
+ dot: 'bg-text-on-warning'
211
+ }
161
212
  },
162
213
  {
163
214
  checked: true,
164
215
  intent: 'danger',
165
- class: { indicator: 'bg-danger border-danger', dot: 'bg-text-on-primary' }
216
+ class: {
217
+ indicator: 'bg-danger border-danger group-hover:bg-danger-hover group-active:bg-danger-active',
218
+ dot: 'bg-text-on-primary'
219
+ }
166
220
  },
167
221
  {
168
222
  checked: true,
169
223
  intent: 'neutral',
170
- class: { indicator: 'bg-neutral border-neutral', dot: 'bg-text-on-primary' }
224
+ class: {
225
+ indicator: 'bg-neutral border-neutral group-hover:bg-neutral-hover group-active:bg-neutral-active',
226
+ dot: 'bg-text-on-primary'
227
+ }
171
228
  },
172
229
  // Error overrides unchecked border
230
+ // `group-hover:border-danger` pins the hover bucket too: the unchecked
231
+ // compounds above carry a `group-hover:border-*` step, and a plain
232
+ // `border-danger` does not fold it (modifier prefixes are part of the
233
+ // conflict bucket), so without this the error boundary went neutral the
234
+ // moment the pointer arrived — exactly when the mark matters.
173
235
  {
174
236
  error: true,
175
237
  checked: false,
176
- class: { indicator: 'border-danger peer-focus-visible:ring-danger/40' }
238
+ class: {
239
+ indicator: 'border-danger group-hover:border-danger peer-focus-visible:ring-danger/40'
240
+ }
177
241
  }
178
242
  ],
179
243
  defaultVariants: {
@@ -1,4 +1,7 @@
1
+ import { FIELD_MESSAGE_TONES, fieldErrorFrame } from '../../internal/field-chrome.js';
1
2
  import { tv } from '../../utils/variants.js';
3
+ // The trigger is the focusable element, so the error ring lives on it directly.
4
+ const focus = 'focus-visible';
2
5
  export const selectVariants = tv({
3
6
  slots: {
4
7
  wrapper: ['flex flex-col w-full gap-1.5'],
@@ -75,7 +78,7 @@ export const selectVariants = tv({
75
78
  variant: {
76
79
  outlined: { trigger: 'border-border-subtle' },
77
80
  filled: {
78
- trigger: 'bg-surface-interactive border-transparent hover:bg-surface-hover focus-visible:bg-surface-base'
81
+ trigger: 'bg-surface-interactive border-transparent hover:bg-surface-interactive-hover focus-visible:bg-surface-base'
79
82
  },
80
83
  ghost: {
81
84
  trigger: 'bg-transparent border-transparent hover:bg-surface-subtle focus-visible:bg-surface-base focus-visible:border-border-subtle'
@@ -146,13 +149,19 @@ export const selectVariants = tv({
146
149
  // Declared BEFORE `error` so the error tone wins the message-color
147
150
  // bucket in every call shape — `{ error: true }` alone must read red.
148
151
  messageType: {
149
- error: { message: 'text-danger' },
150
- helper: { message: 'text-text-tertiary' }
152
+ error: { message: FIELD_MESSAGE_TONES.error },
153
+ helper: { message: FIELD_MESSAGE_TONES.helper }
151
154
  },
155
+ // Same error frame as every other field (shared fragment, so a token fix
156
+ // can't miss Select again). Unlike Input/Textarea/PinInput/TimeInput,
157
+ // Select has no `intent` axis, so nothing competes for the border/ring
158
+ // buckets and the frame can stay on the axis. If an `intent` axis is ever
159
+ // added here, move this to the compound stage — see the precedence note in
160
+ // input.variants.ts.
152
161
  error: {
153
162
  true: {
154
- trigger: 'border-danger focus-visible:border-danger focus-visible:ring-danger/20',
155
- message: 'text-danger'
163
+ trigger: fieldErrorFrame(focus),
164
+ message: FIELD_MESSAGE_TONES.error
156
165
  }
157
166
  },
158
167
  required: {
@@ -160,7 +160,7 @@
160
160
  if (status === 'insideValidOnly') return 'var(--color-warning-subtle)';
161
161
  if (status === 'outsideValidDanger') return 'var(--color-danger-subtle)';
162
162
  if (status === 'outsideValidWarning') return 'var(--color-warning-subtle)';
163
- return 'var(--color-surface-subtle)';
163
+ return 'var(--color-surface-interactive)';
164
164
  };
165
165
 
166
166
  const points = [min, ...zoneBoundaries, max];
@@ -460,6 +460,7 @@
460
460
  ? `${label} minimum`
461
461
  : bt('accessibility.minimum') || 'Minimum'}
462
462
  aria-describedby={describedBy}
463
+ aria-invalid={error ? 'true' : undefined}
463
464
  aria-disabled={disabled || undefined}
464
465
  class={unstyled ? (slotClasses?.thumb ?? '') : styles.thumb({ class: slotClasses?.thumb })}
465
466
  style="left: {thumbStartPosition}%"
@@ -479,6 +480,7 @@
479
480
  ? `${label} maximum`
480
481
  : bt('accessibility.maximum') || 'Maximum'}
481
482
  aria-describedby={describedBy}
483
+ aria-invalid={error ? 'true' : undefined}
482
484
  aria-disabled={disabled || undefined}
483
485
  class={unstyled ? (slotClasses?.thumb ?? '') : styles.thumb({ class: slotClasses?.thumb })}
484
486
  style="left: {thumbEndPosition}%"
@@ -495,6 +497,7 @@
495
497
  aria-labelledby={ariaLabelledby}
496
498
  aria-label={ariaLabelledby ? undefined : label || bt('accessibility.slider') || 'Slider'}
497
499
  aria-describedby={describedBy}
500
+ aria-invalid={error ? 'true' : undefined}
498
501
  aria-disabled={disabled || undefined}
499
502
  class={unstyled ? (slotClasses?.thumb ?? '') : styles.thumb({ class: slotClasses?.thumb })}
500
503
  style="left: {thumbPosition}%"
@@ -7,8 +7,11 @@ export const sliderVariants = tv({
7
7
  valueText: ['text-sm tabular-nums text-text-tertiary'],
8
8
  base: ['relative flex items-center w-full touch-none select-none cursor-pointer'],
9
9
  // tier: commit — slider is a continuous-value pill (track + range + thumb).
10
+ // Track fill is `surface-interactive`, matching Toggle's unchecked track:
11
+ // `surface-subtle` resolves to the SAME neutral step as `surface-elevated`
12
+ // in both modes, so the groove vanished on any elevated card/popover.
10
13
  track: [
11
- 'relative w-full overflow-hidden rounded-commit bg-surface-subtle',
14
+ 'relative w-full overflow-hidden rounded-commit bg-surface-interactive',
12
15
  'transition-[background-color] duration-[var(--blocks-duration-fast)]'
13
16
  ],
14
17
  range: [
@@ -20,7 +23,11 @@ export const sliderVariants = tv({
20
23
  'absolute rounded-commit bg-surface-base border-2',
21
24
  'shadow-[var(--blocks-shadow-sm)]',
22
25
  '-translate-x-1/2 -translate-y-1/2 top-1/2',
23
- 'transition-[box-shadow,transform] duration-[var(--blocks-duration-fast)]',
26
+ // `scale`, NOT `transform`: Tailwind 4 emits `scale-*` as the discrete
27
+ // `scale:` property — `hover:scale-110` is the only animated transform
28
+ // here, so it is the only one listed. The centring `-translate-*` above
29
+ // is static (the thumb travels via `left`), so `translate` stays out.
30
+ 'transition-[box-shadow,scale] duration-[var(--blocks-duration-fast)]',
24
31
  'hover:scale-110 hover:shadow-[var(--blocks-shadow-md)]',
25
32
  'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-offset-surface-base'
26
33
  ],