@urbicon-ui/blocks 6.21.2 → 6.22.0

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 (37) hide show
  1. package/dist/components/Calendar/Calendar.svelte +9 -0
  2. package/dist/components/Calendar/CalendarMiniMonth.svelte +10 -8
  3. package/dist/components/Calendar/calendar.context.d.ts +3 -0
  4. package/dist/components/Calendar/calendar.drag.js +19 -7
  5. package/dist/components/Calendar/calendar.variants.d.ts +63 -63
  6. package/dist/components/CompositionBar/CompositionBar.svelte +6 -2
  7. package/dist/components/Sankey/Sankey.svelte +18 -2
  8. package/dist/i18n/index.d.ts +378 -2
  9. package/dist/primitives/Alert/alert.variants.d.ts +8 -8
  10. package/dist/primitives/Avatar/avatar.variants.d.ts +6 -6
  11. package/dist/primitives/Badge/Badge.svelte +6 -4
  12. package/dist/primitives/Button/button.variants.d.ts +4 -4
  13. package/dist/primitives/ButtonGroup/index.d.ts +1 -1
  14. package/dist/primitives/Card/card.variants.d.ts +5 -5
  15. package/dist/primitives/Checkbox/Checkbox.svelte +18 -9
  16. package/dist/primitives/Checkbox/checkbox.variants.js +58 -16
  17. package/dist/primitives/Combobox/combobox.variants.d.ts +24 -24
  18. package/dist/primitives/Dialog/dialog.variants.d.ts +9 -9
  19. package/dist/primitives/Input/Input.svelte +10 -1
  20. package/dist/primitives/Input/input.variants.d.ts +9 -9
  21. package/dist/primitives/JourneyTimeline/journey-timeline.variants.d.ts +22 -22
  22. package/dist/primitives/Popover/Popover.svelte +24 -3
  23. package/dist/primitives/Select/Select.svelte +10 -1
  24. package/dist/primitives/Select/select.variants.d.ts +17 -17
  25. package/dist/primitives/Skeleton/skeleton.variants.d.ts +3 -3
  26. package/dist/primitives/Slider/Slider.svelte +8 -5
  27. package/dist/primitives/Spinner/spinner.variants.d.ts +32 -32
  28. package/dist/primitives/Stepper/stepper.variants.d.ts +11 -11
  29. package/dist/primitives/Textarea/Textarea.svelte +10 -1
  30. package/dist/primitives/Textarea/textarea.variants.d.ts +7 -7
  31. package/dist/primitives/Toast/toast.variants.d.ts +12 -12
  32. package/dist/primitives/Toolbar/toolbar.variants.d.ts +6 -6
  33. package/dist/primitives/Tooltip/tooltip.variants.d.ts +3 -3
  34. package/dist/style/semantic.css +55 -29
  35. package/dist/utils/figma-token-export.d.ts +13 -0
  36. package/dist/utils/figma-token-export.js +99 -26
  37. package/package.json +3 -3
@@ -183,7 +183,12 @@
183
183
 
184
184
  /* === SHADOWS ===
185
185
  Dark mode uses higher alpha to compensate for low contrast against
186
- dark surfaces. light-dark() handles the whole multi-layer shadow.
186
+ dark surfaces. light-dark() may wrap ONLY the per-layer <color> —
187
+ it is a color function, and layers must stay top-level
188
+ comma-separated. Wrapping the whole multi-layer list made every
189
+ `box-shadow: var(--blocks-shadow-*)` invalid at computed-value time
190
+ (shadows silently rendered as none, library-wide) — verified in
191
+ chromium before the 2026-07-13 fix.
187
192
 
188
193
  The shadow tint (`--blocks-shadow-tint`) is an oklch L C H triplet
189
194
  WITHOUT the alpha channel — declared on `:root` (not inside @theme)
@@ -192,34 +197,55 @@
192
197
  their shadow palette — e.g. editorial sets it to a dark brown so
193
198
  shadows blend with cream surfaces instead of reading as cool
194
199
  smudges. */
195
- --color-shadow-xs: light-dark(
196
- 0 1px 2px 0 oklch(var(--blocks-shadow-tint) / 0.05),
197
- 0 1px 2px 0 oklch(var(--blocks-shadow-tint) / 0.2)
198
- );
199
- --color-shadow-sm: light-dark(
200
- 0 1px 3px 0 oklch(var(--blocks-shadow-tint) / 0.1) 0 1px 2px -1px
201
- oklch(var(--blocks-shadow-tint) / 0.1),
202
- 0 1px 3px 0 oklch(var(--blocks-shadow-tint) / 0.3) 0 1px 2px -1px
203
- oklch(var(--blocks-shadow-tint) / 0.3)
204
- );
205
- --color-shadow-base: light-dark(
206
- 0 4px 6px -1px oklch(var(--blocks-shadow-tint) / 0.1) 0 2px 4px -2px
207
- oklch(var(--blocks-shadow-tint) / 0.1),
208
- 0 4px 6px -1px oklch(var(--blocks-shadow-tint) / 0.4) 0 2px 4px -2px
209
- oklch(var(--blocks-shadow-tint) / 0.4)
210
- );
211
- --color-shadow-md: light-dark(
212
- 0 10px 15px -3px oklch(var(--blocks-shadow-tint) / 0.1) 0 4px 6px -4px
213
- oklch(var(--blocks-shadow-tint) / 0.1),
214
- 0 10px 15px -3px oklch(var(--blocks-shadow-tint) / 0.4) 0 4px 6px -4px
215
- oklch(var(--blocks-shadow-tint) / 0.4)
216
- );
217
- --color-shadow-lg: light-dark(
218
- 0 20px 25px -5px oklch(var(--blocks-shadow-tint) / 0.1) 0 8px 10px -6px
219
- oklch(var(--blocks-shadow-tint) / 0.1),
220
- 0 20px 25px -5px oklch(var(--blocks-shadow-tint) / 0.5) 0 8px 10px -6px
221
- oklch(var(--blocks-shadow-tint) / 0.5)
222
- );
200
+ --color-shadow-xs: 0 1px 2px 0
201
+ light-dark(
202
+ oklch(var(--blocks-shadow-tint) / 0.05),
203
+ oklch(var(--blocks-shadow-tint) / 0.2)
204
+ );
205
+ --color-shadow-sm:
206
+ 0 1px 3px 0
207
+ light-dark(
208
+ oklch(var(--blocks-shadow-tint) / 0.1),
209
+ oklch(var(--blocks-shadow-tint) / 0.3)
210
+ ),
211
+ 0 1px 2px -1px
212
+ light-dark(
213
+ oklch(var(--blocks-shadow-tint) / 0.1),
214
+ oklch(var(--blocks-shadow-tint) / 0.3)
215
+ );
216
+ --color-shadow-base:
217
+ 0 4px 6px -1px
218
+ light-dark(
219
+ oklch(var(--blocks-shadow-tint) / 0.1),
220
+ oklch(var(--blocks-shadow-tint) / 0.4)
221
+ ),
222
+ 0 2px 4px -2px
223
+ light-dark(
224
+ oklch(var(--blocks-shadow-tint) / 0.1),
225
+ oklch(var(--blocks-shadow-tint) / 0.4)
226
+ );
227
+ --color-shadow-md:
228
+ 0 10px 15px -3px
229
+ light-dark(
230
+ oklch(var(--blocks-shadow-tint) / 0.1),
231
+ oklch(var(--blocks-shadow-tint) / 0.4)
232
+ ),
233
+ 0 4px 6px -4px
234
+ light-dark(
235
+ oklch(var(--blocks-shadow-tint) / 0.1),
236
+ oklch(var(--blocks-shadow-tint) / 0.4)
237
+ );
238
+ --color-shadow-lg:
239
+ 0 20px 25px -5px
240
+ light-dark(
241
+ oklch(var(--blocks-shadow-tint) / 0.1),
242
+ oklch(var(--blocks-shadow-tint) / 0.5)
243
+ ),
244
+ 0 8px 10px -6px
245
+ light-dark(
246
+ oklch(var(--blocks-shadow-tint) / 0.1),
247
+ oklch(var(--blocks-shadow-tint) / 0.5)
248
+ );
223
249
  }
224
250
 
225
251
  /* Shadow tint — declared on :root rather than inside @theme because
@@ -4,6 +4,19 @@
4
4
  * Generates a Tokens Studio-compatible JSON export from the Urbicon UI
5
5
  * OKLCH design token system. Suitable for Figma plugins like "Tokens Studio
6
6
  * for Figma" (formerly Figma Tokens).
7
+ *
8
+ * The values below mirror the token truth in `../style/foundation.css`
9
+ * (palettes, radii) and `../style/semantic.css` (surface/text/border roles,
10
+ * shadows). They are hardcoded — this module runs in the browser and cannot
11
+ * read the CSS files at runtime — but guarded against drift by the
12
+ * co-located `figma-token-export.test.ts`, which parses both CSS files and
13
+ * compares every value. If you change a token in the CSS, that test fails
14
+ * until the export here is updated to match.
15
+ *
16
+ * Semantic tokens resolve light/dark via CSS `light-dark()`; this export
17
+ * carries the **light-mode** resolution (Figma has no mode-aware token
18
+ * values in plain Tokens Studio JSON). Dark mode swaps at the foundation
19
+ * layer, so the palette ramps below contain every shade both modes use.
7
20
  */
8
21
  export interface FigmaToken {
9
22
  value: string;
@@ -4,10 +4,24 @@
4
4
  * Generates a Tokens Studio-compatible JSON export from the Urbicon UI
5
5
  * OKLCH design token system. Suitable for Figma plugins like "Tokens Studio
6
6
  * for Figma" (formerly Figma Tokens).
7
+ *
8
+ * The values below mirror the token truth in `../style/foundation.css`
9
+ * (palettes, radii) and `../style/semantic.css` (surface/text/border roles,
10
+ * shadows). They are hardcoded — this module runs in the browser and cannot
11
+ * read the CSS files at runtime — but guarded against drift by the
12
+ * co-located `figma-token-export.test.ts`, which parses both CSS files and
13
+ * compares every value. If you change a token in the CSS, that test fails
14
+ * until the export here is updated to match.
15
+ *
16
+ * Semantic tokens resolve light/dark via CSS `light-dark()`; this export
17
+ * carries the **light-mode** resolution (Figma has no mode-aware token
18
+ * values in plain Tokens Studio JSON). Dark mode swaps at the foundation
19
+ * layer, so the palette ramps below contain every shade both modes use.
7
20
  */
8
21
  const foundationColors = {
9
22
  neutral: {
10
23
  '0': 'oklch(1 0 0)',
24
+ '25': 'oklch(0.99 0.002 240)',
11
25
  '50': 'oklch(0.98 0.005 240)',
12
26
  '100': 'oklch(0.95 0.008 240)',
13
27
  '200': 'oklch(0.89 0.012 240)',
@@ -15,8 +29,11 @@ const foundationColors = {
15
29
  '400': 'oklch(0.7 0.015 240)',
16
30
  '500': 'oklch(0.55 0.016 240)',
17
31
  '600': 'oklch(0.42 0.017 240)',
32
+ '650': 'oklch(0.38 0.016 240)',
18
33
  '700': 'oklch(0.32 0.016 240)',
34
+ '750': 'oklch(0.28 0.014 240)',
19
35
  '800': 'oklch(0.23 0.015 240)',
36
+ '850': 'oklch(0.18 0.014 240)',
20
37
  '900': 'oklch(0.15 0.012 240)',
21
38
  '950': 'oklch(0.08 0.008 240)'
22
39
  },
@@ -46,18 +63,33 @@ const foundationColors = {
46
63
  '900': 'oklch(0.25 0.08 280)',
47
64
  '950': 'oklch(0.18 0.05 280)'
48
65
  },
66
+ 'warm-neutral': {
67
+ '50': 'oklch(0.96 0.004 45)',
68
+ '100': 'oklch(0.92 0.006 45)',
69
+ '200': 'oklch(0.86 0.008 45)',
70
+ '300': 'oklch(0.78 0.01 45)',
71
+ '400': 'oklch(0.65 0.012 45)',
72
+ '500': 'oklch(0.5 0.008 45)',
73
+ '600': 'oklch(0.42 0.01 45)',
74
+ '700': 'oklch(0.35 0.012 45)',
75
+ '800': 'oklch(0.28 0.01 45)',
76
+ '900': 'oklch(0.2 0.008 45)',
77
+ '950': 'oklch(0.12 0.006 45)'
78
+ },
79
+ /* success/danger 400–700 are the WCAG-darkened ramps: white text on the
80
+ solid intent backgrounds passes AA (4.5:1). */
49
81
  success: {
50
82
  '50': 'oklch(0.95 0.03 140)',
51
83
  '100': 'oklch(0.9 0.05 140)',
52
84
  '200': 'oklch(0.82 0.08 140)',
53
85
  '300': 'oklch(0.74 0.11 140)',
54
- '400': 'oklch(0.66 0.13 140)',
55
- '500': 'oklch(0.65 0.15 140)',
56
- '600': 'oklch(0.55 0.15 140)',
57
- '700': 'oklch(0.45 0.13 140)',
58
- '800': 'oklch(0.35 0.11 140)',
59
- '900': 'oklch(0.25 0.08 140)',
60
- '950': 'oklch(0.15 0.05 140)'
86
+ '400': 'oklch(0.62 0.14 140)',
87
+ '500': 'oklch(0.5 0.15 140)',
88
+ '600': 'oklch(0.44 0.14 140)',
89
+ '700': 'oklch(0.38 0.12 140)',
90
+ '800': 'oklch(0.3 0.1 140)',
91
+ '900': 'oklch(0.22 0.08 140)',
92
+ '950': 'oklch(0.14 0.05 140)'
61
93
  },
62
94
  warning: {
63
95
  '50': 'oklch(0.95 0.05 80)',
@@ -77,39 +109,67 @@ const foundationColors = {
77
109
  '100': 'oklch(0.9 0.08 25)',
78
110
  '200': 'oklch(0.82 0.1 25)',
79
111
  '300': 'oklch(0.74 0.12 25)',
80
- '400': 'oklch(0.66 0.14 25)',
81
- '500': 'oklch(0.65 0.18 25)',
82
- '600': 'oklch(0.55 0.15 25)',
83
- '700': 'oklch(0.45 0.13 25)',
84
- '800': 'oklch(0.35 0.11 25)',
85
- '900': 'oklch(0.25 0.08 25)',
86
- '950': 'oklch(0.15 0.05 25)'
112
+ '400': 'oklch(0.62 0.16 25)',
113
+ '500': 'oklch(0.5 0.17 25)',
114
+ '600': 'oklch(0.44 0.16 25)',
115
+ '700': 'oklch(0.38 0.14 25)',
116
+ '800': 'oklch(0.3 0.12 25)',
117
+ '900': 'oklch(0.22 0.1 25)',
118
+ '950': 'oklch(0.14 0.07 25)'
119
+ },
120
+ info: {
121
+ '50': 'oklch(0.96 0.025 220)',
122
+ '100': 'oklch(0.92 0.045 220)',
123
+ '200': 'oklch(0.84 0.075 220)',
124
+ '300': 'oklch(0.76 0.105 220)',
125
+ '400': 'oklch(0.66 0.13 220)',
126
+ '500': 'oklch(0.55 0.14 220)',
127
+ '600': 'oklch(0.48 0.13 220)',
128
+ '700': 'oklch(0.4 0.11 220)',
129
+ '800': 'oklch(0.32 0.09 220)',
130
+ '900': 'oklch(0.24 0.07 220)',
131
+ '950': 'oklch(0.16 0.05 220)'
87
132
  }
88
133
  };
134
+ /** Light-mode resolution of the semantic color roles in semantic.css. */
89
135
  const semanticTokens = {
90
136
  surface: {
91
- base: { value: '{color.neutral.0}', description: 'Page background' },
92
- raised: { value: '{color.neutral.50}', description: 'Slightly elevated surface' },
93
- elevated: { value: '{color.neutral.50}', description: 'Elevated surface (cards)' },
94
- overlay: { value: '{color.neutral.0}', description: 'Dialog/popover background' },
137
+ base: { value: '{color.neutral.0}', description: 'L1 — the page itself' },
138
+ quiet: { value: '{color.neutral.25}', description: 'L0 ground beneath the page' },
139
+ elevated: { value: '{color.neutral.50}', description: 'L2 lifted surfaces (popover, menu)' },
140
+ overlay: { value: '{color.neutral.0}', description: 'L3 — dialog/drawer/toast background' },
141
+ interactive: { value: '{color.neutral.100}', description: 'Interactive control background' },
142
+ hover: { value: '{color.neutral.100}', description: 'Hover state background' },
143
+ active: { value: '{color.neutral.200}', description: 'Active/pressed state background' },
144
+ disabled: { value: '{color.neutral.100}', description: 'Disabled surface' },
145
+ selected: { value: '{color.primary.50}', description: 'Selected item background' },
95
146
  subtle: { value: '{color.neutral.50}', description: 'Subtle background' },
96
147
  inverted: { value: '{color.neutral.900}', description: 'Inverted surface' }
97
148
  },
98
149
  text: {
99
150
  primary: { value: '{color.neutral.900}', description: 'Primary text' },
151
+ inverted: { value: '{color.neutral.0}', description: 'Inverted text (on dark bg)' },
100
152
  secondary: { value: '{color.neutral.700}', description: 'Secondary text' },
101
- tertiary: { value: '{color.neutral.500}', description: 'Tertiary text' },
153
+ tertiary: { value: '{color.neutral.600}', description: 'Tertiary text (WCAG AA on base)' },
154
+ quaternary: { value: '{color.neutral.500}', description: 'Quaternary text (lowest emphasis)' },
102
155
  disabled: { value: '{color.neutral.300}', description: 'Disabled text' },
103
- inverted: { value: '{color.neutral.0}', description: 'Inverted text (on dark bg)' },
104
- 'on-primary': { value: '{color.neutral.0}', description: 'Text on primary color bg' }
156
+ 'on-dark': { value: '{color.neutral.0}', description: 'Text on dark surfaces' },
157
+ 'on-primary': { value: '{color.neutral.0}', description: 'Text on primary color bg' },
158
+ 'on-surface': { value: '{color.neutral.900}', description: 'Text on tinted surfaces' }
105
159
  },
106
160
  border: {
161
+ hairline: {
162
+ value: 'rgb(0 0 0 / 0.08)',
163
+ description: 'Quietest structural divider (rows, separators)'
164
+ },
107
165
  subtle: { value: '{color.neutral.200}', description: 'Subtle border' },
108
166
  default: { value: '{color.neutral.300}', description: 'Default border' },
109
167
  emphasis: { value: '{color.neutral.400}', description: 'Emphasized border' },
110
168
  strong: { value: '{color.neutral.500}', description: 'Strong border' }
111
169
  }
112
170
  };
171
+ /* Tailwind 4 default spacing scale (4px per unit) — blocks defines no
172
+ custom spacing tokens. */
113
173
  const spacingTokens = {
114
174
  '0': '0',
115
175
  '1': '4px',
@@ -123,14 +183,24 @@ const spacingTokens = {
123
183
  '12': '48px',
124
184
  '16': '64px'
125
185
  };
186
+ /* Physical radius scale + the semantic 3-tier vocabulary (commit/modify/
187
+ contain, plus the bridge adjacency radius) from foundation.css.
188
+ rem values are exported as px (1rem = 16px) for Figma. */
126
189
  const borderRadiusTokens = {
127
- none: '0',
128
- sm: '2px',
190
+ xs: '2px',
191
+ sm: '4px',
129
192
  md: '6px',
130
193
  lg: '8px',
131
194
  xl: '12px',
132
- full: '9999px'
195
+ '2xl': '16px',
196
+ '3xl': '24px',
197
+ '4xl': '32px',
198
+ commit: { value: '9999px', description: 'Tier: actions, identity, status (pill)' },
199
+ modify: { value: '{borderRadius.sm}', description: 'Tier: editable surfaces, navigation' },
200
+ contain: { value: '{borderRadius.xs}', description: 'Tier: containers, panels, layout' },
201
+ bridge: { value: '{borderRadius.md}', description: 'Adjacency radius: panel anchored to a pill' }
133
202
  };
203
+ /** Light-mode resolution of the shadow tokens (shadow tint = pure black). */
134
204
  const shadowTokens = {
135
205
  xs: '0 1px 2px 0 rgba(0,0,0,0.05)',
136
206
  sm: '0 1px 3px 0 rgba(0,0,0,0.1), 0 1px 2px -1px rgba(0,0,0,0.1)',
@@ -174,8 +244,11 @@ function buildSpacingTokens() {
174
244
  }
175
245
  function buildBorderRadiusTokens() {
176
246
  const result = {};
177
- for (const [name, value] of Object.entries(borderRadiusTokens)) {
178
- result[name] = { value, type: 'borderRadius' };
247
+ for (const [name, def] of Object.entries(borderRadiusTokens)) {
248
+ result[name] =
249
+ typeof def === 'string'
250
+ ? { value: def, type: 'borderRadius' }
251
+ : { value: def.value, type: 'borderRadius', description: def.description };
179
252
  }
180
253
  return result;
181
254
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@urbicon-ui/blocks",
3
- "version": "6.21.2",
3
+ "version": "6.22.0",
4
4
  "description": "Svelte 5 UI component library with Tailwind CSS 4, OKLCH design tokens and zero runtime dependencies",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -91,8 +91,8 @@
91
91
  "@sveltejs/package": "^2.5.8",
92
92
  "@sveltejs/vite-plugin-svelte": "^7.0.0",
93
93
  "@tailwindcss/vite": "^4.3.1",
94
- "@urbicon-ui/i18n": "6.21.2",
95
- "@urbicon-ui/shared-types": "6.21.2",
94
+ "@urbicon-ui/i18n": "6.22.0",
95
+ "@urbicon-ui/shared-types": "6.22.0",
96
96
  "prettier": "^3.8.4",
97
97
  "prettier-plugin-svelte": "^4.1.1",
98
98
  "prettier-plugin-tailwindcss": "^0.8.0",