@platned/ui 0.1.4 → 0.5.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.
@@ -0,0 +1,349 @@
1
+ /** @type {import('tailwindcss').Config} */
2
+ module.exports = {
3
+ theme: {
4
+ extend: {
5
+ backgroundColor: {
6
+ // ── Brand ────────────────────────────────────────────────────────────
7
+ 'brand': 'var(--color-background-brand-default)',
8
+ 'brand-hover': 'var(--color-background-brand-hover)',
9
+ 'brand-secondary': 'var(--color-background-brand-secondary)',
10
+ 'brand-secondary-hover': 'var(--color-background-brand-secondary-hover)',
11
+ 'brand-tertiary': 'var(--color-background-brand-tertiary)',
12
+ 'brand-tertiary-hover': 'var(--color-background-brand-tertiary-hover)',
13
+ // ── Default / Neutral ─────────────────────────────────────────────────
14
+ 'default': 'var(--color-background-default-default)',
15
+ 'default-hover': 'var(--color-background-default-default-hover)',
16
+ 'default-secondary': 'var(--color-background-default-secondary)',
17
+ 'default-secondary-hover': 'var(--color-background-default-secondary-hover)',
18
+ 'default-tertiary': 'var(--color-background-default-tertiary)',
19
+ // `neutral` was missing through 0.4.0 while `text-neutral` existed, so
20
+ // `StatusDot tone="neutral"` and `ProgressBar tone="neutral"` referenced an
21
+ // undefined class, emitted no CSS, and rendered as invisible elements.
22
+ 'neutral': 'var(--color-background-neutral-default)',
23
+ 'neutral-hover': 'var(--color-background-neutral-hover)',
24
+ 'neutral-secondary': 'var(--color-background-neutral-secondary)',
25
+ 'neutral-tertiary': 'var(--color-background-neutral-tertiary)',
26
+ 'neutral-tertiary-hover': 'var(--color-background-neutral-tertiary-hover)',
27
+ // ── Danger ───────────────────────────────────────────────────────────
28
+ 'danger': 'var(--color-background-danger-default)',
29
+ 'danger-hover': 'var(--color-background-danger-hover)',
30
+ 'danger-secondary': 'var(--color-background-danger-secondary)',
31
+ 'danger-tertiary': 'var(--color-background-danger-tertiary)',
32
+ 'danger-tertiary-hover': 'var(--color-background-danger-tertiary-hover)',
33
+ // ── Positive / Warning ────────────────────────────────────────────────
34
+ 'positive': 'var(--color-background-positive-default)',
35
+ 'positive-tertiary': 'var(--color-background-positive-tertiary)',
36
+ 'warning': 'var(--color-background-warning-default)',
37
+ 'warning-tertiary': 'var(--color-background-warning-tertiary)',
38
+ // ── Disabled ──────────────────────────────────────────────────────────
39
+ 'disabled': 'var(--color-background-disabled-default)',
40
+ // ── Overlay utilities (scrims behind modals / drawers) ─────────────────
41
+ 'scrim': 'var(--color-background-utilities-scrim)',
42
+ 'blanket': 'var(--color-background-utilities-blanket)',
43
+ 'overlay': 'var(--color-background-utilities-overlay)',
44
+ // Hairline dividers drawn as a filled element rather than a border
45
+ 'divider': 'var(--color-border-default-default)',
46
+ // ── Status tones ──────────────────────────────────────────────────────
47
+ 'status-neutral': 'var(--status-neutral-bg)',
48
+ 'status-info': 'var(--status-info-bg)',
49
+ 'status-warning': 'var(--status-warning-bg)',
50
+ 'status-caution': 'var(--status-caution-bg)',
51
+ 'status-accent': 'var(--status-accent-bg)',
52
+ 'status-positive': 'var(--status-positive-bg)',
53
+ 'status-danger': 'var(--status-danger-bg)',
54
+ // ── Status tone leading dots ───────────────────────────────────────────
55
+ 'status-dot-neutral': 'var(--status-neutral-dot)',
56
+ 'status-dot-info': 'var(--status-info-dot)',
57
+ 'status-dot-warning': 'var(--status-warning-dot)',
58
+ 'status-dot-caution': 'var(--status-caution-dot)',
59
+ 'status-dot-accent': 'var(--status-accent-dot)',
60
+ 'status-dot-positive': 'var(--status-positive-dot)',
61
+ 'status-dot-danger': 'var(--status-danger-dot)',
62
+ // ── Compliance check indicator ─────────────────────────────────────────
63
+ 'status-check-passed': 'var(--status-check-passed-bg)',
64
+ 'status-check-progress': 'var(--status-check-progress-bg)',
65
+ 'status-check-failed': 'var(--status-check-failed-bg)',
66
+ 'status-check-pending': 'var(--status-check-pending-bg)',
67
+ // ── Badge ─────────────────────────────────────────────────────────────
68
+ 'badge-gray': 'var(--badge-gray-bg)',
69
+ 'badge-red': 'var(--badge-red-bg)',
70
+ 'badge-yellow': 'var(--badge-yellow-bg)',
71
+ 'badge-lime': 'var(--badge-lime-bg)',
72
+ 'badge-green': 'var(--badge-green-bg)',
73
+ 'badge-teal': 'var(--badge-teal-bg)',
74
+ 'badge-blue': 'var(--badge-blue-bg)',
75
+ 'badge-pink': 'var(--badge-pink-bg)',
76
+ 'badge-slate': 'var(--badge-slate-bg)',
77
+ },
78
+
79
+ borderColor: {
80
+ // ── Badge (subtle variant uses the badge bg color as its border) ──────
81
+ 'badge-gray': 'var(--color-border-default-default)',
82
+ 'badge-red': 'var(--badge-red-bg)',
83
+ 'badge-yellow': 'var(--badge-yellow-bg)',
84
+ 'badge-lime': 'var(--badge-lime-bg)',
85
+ 'badge-green': 'var(--badge-green-bg)',
86
+ 'badge-teal': 'var(--badge-teal-bg)',
87
+ 'badge-blue': 'var(--badge-blue-bg)',
88
+ 'badge-pink': 'var(--badge-pink-bg)',
89
+ 'badge-slate': 'var(--badge-slate-bg)',
90
+ 'default': 'var(--color-border-default-default)',
91
+ 'default-secondary': 'var(--color-border-default-secondary)',
92
+ 'brand': 'var(--color-border-brand-default)',
93
+ 'brand-secondary': 'var(--color-border-brand-secondary)',
94
+ 'brand-tertiary': 'var(--color-border-brand-tertiary)',
95
+ // The brand *fill* colour, one step darker than border-brand. For edges that
96
+ // must match a bg-brand surface exactly (checked checkbox, active tab rule) —
97
+ // border-brand would leave a visibly lighter 1px halo against the fill.
98
+ 'brand-emphasis': 'var(--color-background-brand-default)',
99
+ 'danger': 'var(--color-border-danger-default)',
100
+ 'danger-secondary': 'var(--color-border-danger-secondary)',
101
+ 'danger-tertiary': 'var(--color-border-danger-tertiary)',
102
+ 'positive-tertiary': 'var(--color-border-positive-tertiary)',
103
+ 'warning-tertiary': 'var(--color-border-warning-tertiary)',
104
+ 'disabled': 'var(--color-border-disabled-default)',
105
+ // ── Compliance check indicator rings ───────────────────────────────────
106
+ 'status-check-passed': 'var(--status-check-passed-ring)',
107
+ 'status-check-progress': 'var(--status-check-progress-ring)',
108
+ 'status-check-failed': 'var(--status-check-failed-ring)',
109
+ 'status-check-pending': 'var(--status-check-pending-ring)',
110
+ },
111
+
112
+ // divideColor is its own Tailwind namespace — extending borderColor does NOT
113
+ // populate it, so `divide-default` emitted no CSS and every divided list had to
114
+ // escape to `divide-[color:var(--color-border-default-default)]`.
115
+ divideColor: {
116
+ 'default': 'var(--color-border-default-default)',
117
+ 'default-secondary': 'var(--color-border-default-secondary)',
118
+ 'brand-tertiary': 'var(--color-border-brand-tertiary)',
119
+ 'danger-tertiary': 'var(--color-border-danger-tertiary)',
120
+ },
121
+
122
+ // ringColor mirrors borderColor — focus rings use the same border token values
123
+ ringColor: {
124
+ 'default': 'var(--color-border-default-default)',
125
+ 'default-secondary': 'var(--color-border-default-secondary)',
126
+ 'brand': 'var(--color-border-brand-default)',
127
+ 'brand-secondary': 'var(--color-border-brand-secondary)',
128
+ 'brand-tertiary': 'var(--color-border-brand-tertiary)',
129
+ 'danger': 'var(--color-border-danger-default)',
130
+ 'danger-secondary': 'var(--color-border-danger-secondary)',
131
+ 'danger-tertiary': 'var(--color-border-danger-tertiary)',
132
+ 'disabled': 'var(--color-border-disabled-default)',
133
+ },
134
+
135
+ // outlineColor is its own Tailwind namespace — it does NOT read borderColor or
136
+ // ringColor. Table rows need it because `ring-*` compiles to box-shadow, which
137
+ // browsers do not paint on a <tr> under `border-collapse: collapse`.
138
+ outlineColor: {
139
+ 'default': 'var(--color-border-default-default)',
140
+ 'brand': 'var(--color-border-brand-default)',
141
+ 'danger': 'var(--color-border-danger-default)',
142
+ },
143
+
144
+ textColor: {
145
+ 'default': 'var(--color-text-default-default)',
146
+ 'default-secondary': 'var(--color-text-default-secondary)',
147
+ 'default-tertiary': 'var(--color-text-default-tertiary)',
148
+ 'brand': 'var(--color-text-brand-default)',
149
+ 'brand-on-brand': 'var(--color-text-brand-on-brand)',
150
+ // Matches a bg-brand fill — see border-brand-emphasis for the rationale.
151
+ 'brand-emphasis': 'var(--color-background-brand-default)',
152
+ 'neutral': 'var(--color-text-neutral-default)',
153
+ // The neutral ramp's quieter steps, for the sidebar's group headings. Note
154
+ // `text-default-tertiary` is #B3B3B3 — 1.9:1 on the #F5F5F5 rail, a WCAG failure at
155
+ // any size. These are #5A5A5A / 6.3:1 and #767676 / 4.2:1.
156
+ 'neutral-secondary': 'var(--color-text-neutral-secondary)',
157
+ 'neutral-tertiary': 'var(--color-text-neutral-tertiary)',
158
+ 'positive': 'var(--color-text-positive-default)',
159
+ 'warning': 'var(--color-text-warning-default)',
160
+ 'danger': 'var(--color-text-danger-default)',
161
+ 'danger-on-danger': 'var(--color-text-danger-on-danger)',
162
+ 'disabled': 'var(--color-text-disabled-default)',
163
+ 'disabled-on-disabled': 'var(--color-text-disabled-on-disabled)',
164
+ // ── Icon (SVG currentColor) ───────────────────────────────────────────
165
+ 'icon-default': 'var(--color-icon-default-default)',
166
+ 'icon-default-secondary': 'var(--color-icon-default-secondary)',
167
+ 'icon-brand': 'var(--color-icon-brand-default)',
168
+ 'icon-brand-on-brand': 'var(--color-icon-brand-on-brand)',
169
+ 'icon-disabled': 'var(--color-icon-disabled-default)',
170
+ 'icon-danger': 'var(--color-icon-danger-default)',
171
+ 'icon-positive': 'var(--color-icon-positive-default)',
172
+ 'icon-neutral': 'var(--color-icon-neutral-default)',
173
+ 'icon-warning': 'var(--color-icon-warning-default)',
174
+ // ── Status tones ──────────────────────────────────────────────────────
175
+ 'status-neutral': 'var(--status-neutral-text)',
176
+ 'status-info': 'var(--status-info-text)',
177
+ 'status-warning': 'var(--status-warning-text)',
178
+ 'status-caution': 'var(--status-caution-text)',
179
+ 'status-accent': 'var(--status-accent-text)',
180
+ 'status-positive': 'var(--status-positive-text)',
181
+ 'status-danger': 'var(--status-danger-text)',
182
+ // ── Compliance check indicator (glyph shares the ring colour) ──────────
183
+ 'status-check-passed': 'var(--status-check-passed-ring)',
184
+ 'status-check-progress': 'var(--status-check-progress-ring)',
185
+ 'status-check-failed': 'var(--status-check-failed-ring)',
186
+ 'status-check-pending': 'var(--status-check-pending-ring)',
187
+ // ── Badge ─────────────────────────────────────────────────────────────
188
+ 'badge-gray': 'var(--badge-gray-text)',
189
+ 'badge-red': 'var(--badge-red-text)',
190
+ 'badge-yellow': 'var(--badge-yellow-text)',
191
+ 'badge-lime': 'var(--badge-lime-text)',
192
+ 'badge-green': 'var(--badge-green-text)',
193
+ 'badge-teal': 'var(--badge-teal-text)',
194
+ 'badge-blue': 'var(--badge-blue-text)',
195
+ 'badge-pink': 'var(--badge-pink-text)',
196
+ 'badge-slate': 'var(--badge-slate-text)',
197
+ },
198
+
199
+ fontSize: {
200
+ // ── Body ─────────────────────────────────────────────────────────────
201
+ // Below `--typo-scale-01` (11px), which is the smallest step the Figma type scale
202
+ // defines. For uppercase labels that need to sit well under the content they label —
203
+ // the sidebar's group headings — and for nothing that has to be read as prose.
204
+ 'body-micro': ['8px', { lineHeight: '1.4' }],
205
+ 'body-tiny': ['11px', { lineHeight: '1.4' }],
206
+ 'body-xs': ['13px', { lineHeight: '1.4' }],
207
+ 'body-sm': ['14px', { lineHeight: '1.4' }],
208
+ 'body': ['16px', { lineHeight: '1.4' }],
209
+ 'body-lg': ['20px', { lineHeight: '1.4' }],
210
+ // ── Heading ──────────────────────────────────────────────────────────
211
+ 'heading-sm': ['20px', { lineHeight: '1.3' }],
212
+ 'heading': ['24px', { lineHeight: '1.3' }],
213
+ 'heading-lg': ['32px', { lineHeight: '1.3' }],
214
+ // ── Subheading ───────────────────────────────────────────────────────
215
+ 'subheading-sm': ['16px', { lineHeight: '1.4' }],
216
+ 'subheading': ['20px', { lineHeight: '1.4' }],
217
+ 'subheading-lg': ['24px', { lineHeight: '1.4' }],
218
+ // ── Subtitle ─────────────────────────────────────────────────────────
219
+ 'subtitle-sm': ['24px', { lineHeight: '1.2' }],
220
+ 'subtitle': ['32px', { lineHeight: '1.2' }],
221
+ 'subtitle-lg': ['40px', { lineHeight: '1.2' }],
222
+ // ── Title ────────────────────────────────────────────────────────────
223
+ 'title-sm': ['40px', { lineHeight: '1.2' }],
224
+ 'title': ['48px', { lineHeight: '1.2' }],
225
+ 'title-lg': ['64px', { lineHeight: '1.2' }],
226
+ 'title-hero': ['72px', { lineHeight: '1.2' }],
227
+
228
+ // ── Raw scale ────────────────────────────────────────────────────────
229
+ // The unopinionated size ramp, matching Figma's `Typography Primitives`
230
+ // (`Scale 02`…`Scale 12`) and `--typo-scale-*` in styles/tokens/typography.css.
231
+ // These carry no line-height, so `leading-*` stays the caller's decision.
232
+ //
233
+ // Their absence was a real bug, not a gap: `StatNumber` referenced
234
+ // `text-scale-07/08/09` at every size and the preset defined none of them, so an
235
+ // undefined class emitted no CSS and the component shipped with no font-size at
236
+ // all. Same for `RiskScore size="2xl"` and `WidgetTitle size="lg"` (0.3.0
237
+ // CHANGELOG). Prefer the semantic names above; use these when a one-off needs a
238
+ // step off the semantic ladder.
239
+ 'scale-01': 'var(--typo-scale-01)', // 11px
240
+ 'scale-02': 'var(--typo-scale-02)', // 13px
241
+ 'scale-03': 'var(--typo-scale-03)', // 14px
242
+ 'scale-04': 'var(--typo-scale-04)', // 16px
243
+ 'scale-05': 'var(--typo-scale-05)', // 20px
244
+ 'scale-06': 'var(--typo-scale-06)', // 24px
245
+ 'scale-07': 'var(--typo-scale-07)', // 32px
246
+ 'scale-08': 'var(--typo-scale-08)', // 40px
247
+ 'scale-09': 'var(--typo-scale-09)', // 48px
248
+ 'scale-10': 'var(--typo-scale-10)', // 64px
249
+ 'scale-12': 'var(--typo-scale-12)', // 72px
250
+ },
251
+ fontWeight: {
252
+ regular: '400',
253
+ },
254
+ // Brand directional gradients — bg-gradient-brand-{direction}
255
+ backgroundImage: {
256
+ 'gradient-brand-n-s': 'var(--gradient-brand-n-s)',
257
+ 'gradient-brand-ne-sw': 'var(--gradient-brand-ne-sw)',
258
+ 'gradient-brand-e-w': 'var(--gradient-brand-e-w)',
259
+ 'gradient-brand-se-nw': 'var(--gradient-brand-se-nw)',
260
+ 'gradient-brand-s-n': 'var(--gradient-brand-s-n)',
261
+ 'gradient-brand-sw-ne': 'var(--gradient-brand-sw-ne)',
262
+ 'gradient-brand-w-e': 'var(--gradient-brand-w-e)',
263
+ 'gradient-brand-nw-se': 'var(--gradient-brand-nw-se)',
264
+ },
265
+
266
+ // gradientColorStops mirrors backgroundColor — from-*/to-*/via-* utilities use `colors`, not backgroundColor
267
+ gradientColorStops: {
268
+ 'brand': 'var(--color-background-brand-default)',
269
+ 'brand-hover': 'var(--color-background-brand-hover)',
270
+ 'brand-secondary': 'var(--color-background-brand-secondary)',
271
+ 'brand-tertiary': 'var(--color-background-brand-tertiary)',
272
+ 'brand-tertiary-hover': 'var(--color-background-brand-tertiary-hover)',
273
+ 'default': 'var(--color-background-default-default)',
274
+ 'default-hover': 'var(--color-background-default-default-hover)',
275
+ 'default-secondary': 'var(--color-background-default-secondary)',
276
+ 'default-tertiary': 'var(--color-background-default-tertiary)',
277
+ 'danger': 'var(--color-background-danger-default)',
278
+ 'danger-secondary': 'var(--color-background-danger-secondary)',
279
+ 'danger-tertiary': 'var(--color-background-danger-tertiary)',
280
+ 'positive-tertiary': 'var(--color-background-positive-tertiary)',
281
+ 'warning-tertiary': 'var(--color-background-warning-tertiary)',
282
+ },
283
+ // The elevation ramp from styles/tokens/effects.css, which matches the 15 effect
284
+ // styles in Figma one-for-one. Until 0.4.0 only `panel` was exposed here, so the
285
+ // twelve shadow tokens were unreachable and components reached for stock Tailwind
286
+ // (`shadow-lg`/`xl`/`2xl`) instead — untokenised, and invisible to a theme change.
287
+ boxShadow: {
288
+ panel: '0 2px 16px 0 rgba(0,0,0,0.08)',
289
+ 100: 'var(--effect-shadow-100)',
290
+ 200: 'var(--effect-shadow-200)',
291
+ 300: 'var(--effect-shadow-300)',
292
+ 400: 'var(--effect-shadow-400)',
293
+ 500: 'var(--effect-shadow-500)',
294
+ 600: 'var(--effect-shadow-600)',
295
+ 'inner-100': 'var(--effect-inner-shadow-100)',
296
+ 'inner-200': 'var(--effect-inner-shadow-200)',
297
+ 'inner-300': 'var(--effect-inner-shadow-300)',
298
+ 'inner-400': 'var(--effect-inner-shadow-400)',
299
+ 'inner-500': 'var(--effect-inner-shadow-500)',
300
+ 'inner-600': 'var(--effect-inner-shadow-600)',
301
+ },
302
+
303
+ // `ring-offset-*` reads this namespace, and nothing else does. Without it the
304
+ // offset falls back to Tailwind's `#fff`, so the six components using
305
+ // `ring-offset-1` drew a white halo on every non-white surface — the sidebar, a
306
+ // toned Card, a secondary-background filter bar.
307
+ ringOffsetColor: {
308
+ 'default': 'var(--color-background-default-default)',
309
+ 'default-secondary': 'var(--color-background-default-secondary)',
310
+ 'default-tertiary': 'var(--color-background-default-tertiary)',
311
+ 'brand': 'var(--color-background-brand-default)',
312
+ 'danger': 'var(--color-background-danger-default)',
313
+ },
314
+
315
+ // Named layers, so a consumer's own z-index cannot land between a Modal and its
316
+ // close button. Overlays previously used bare z-50/z-20/z-10 with no scale.
317
+ zIndex: {
318
+ base: '0',
319
+ raised: '10',
320
+ sticky: '20',
321
+ dropdown: '30',
322
+ overlay: '40',
323
+ modal: '50',
324
+ popover: '60',
325
+ tooltip: '70',
326
+ toast: '80',
327
+ },
328
+ },
329
+ },
330
+ plugins: [
331
+ // `motion-reduce:` ships with Tailwind, but nothing in the library used it — there
332
+ // was no `prefers-reduced-motion` handling anywhere, including an infinite
333
+ // `animate-pulse`. This adds the inverse-of-inverse escape hatch components need:
334
+ // `motion-safe:animate-pulse` for opt-in motion, and `animate-none` under
335
+ // `motion-reduce` for anything already animating.
336
+ function reducedMotion({ addBase }) {
337
+ addBase({
338
+ '@media (prefers-reduced-motion: reduce)': {
339
+ '*, *::before, *::after': {
340
+ animationDuration: '0.01ms !important',
341
+ animationIterationCount: '1 !important',
342
+ transitionDuration: '0.01ms !important',
343
+ scrollBehavior: 'auto !important',
344
+ },
345
+ },
346
+ });
347
+ },
348
+ ],
349
+ }
@@ -1,124 +0,0 @@
1
- /** @type {import('tailwindcss').Config} */
2
- module.exports = {
3
- theme: {
4
- extend: {
5
- backgroundColor: {
6
- // ── Brand ────────────────────────────────────────────────────────────
7
- 'brand': 'var(--color-background-brand-default)',
8
- 'brand-hover': 'var(--color-background-brand-hover)',
9
- 'brand-secondary': 'var(--color-background-brand-secondary)',
10
- 'brand-secondary-hover': 'var(--color-background-brand-secondary-hover)',
11
- 'brand-tertiary': 'var(--color-background-brand-tertiary)',
12
- 'brand-tertiary-hover': 'var(--color-background-brand-tertiary-hover)',
13
- // ── Default / Neutral ─────────────────────────────────────────────────
14
- 'default': 'var(--color-background-default-default)',
15
- 'default-hover': 'var(--color-background-default-default-hover)',
16
- 'default-secondary': 'var(--color-background-default-secondary)',
17
- 'default-secondary-hover': 'var(--color-background-default-secondary-hover)',
18
- 'default-tertiary': 'var(--color-background-default-tertiary)',
19
- 'neutral-tertiary': 'var(--color-background-neutral-tertiary)',
20
- 'neutral-tertiary-hover': 'var(--color-background-neutral-tertiary-hover)',
21
- // ── Danger ───────────────────────────────────────────────────────────
22
- 'danger': 'var(--color-background-danger-default)',
23
- 'danger-hover': 'var(--color-background-danger-hover)',
24
- 'danger-secondary': 'var(--color-background-danger-secondary)',
25
- 'danger-tertiary': 'var(--color-background-danger-tertiary)',
26
- 'danger-tertiary-hover': 'var(--color-background-danger-tertiary-hover)',
27
- // ── Positive / Warning ────────────────────────────────────────────────
28
- 'positive-tertiary': 'var(--color-background-positive-tertiary)',
29
- 'warning-tertiary': 'var(--color-background-warning-tertiary)',
30
- // ── Disabled ──────────────────────────────────────────────────────────
31
- 'disabled': 'var(--color-background-disabled-default)',
32
- },
33
-
34
- borderColor: {
35
- 'default': 'var(--color-border-default-default)',
36
- 'default-secondary': 'var(--color-border-default-secondary)',
37
- 'brand': 'var(--color-border-brand-default)',
38
- 'brand-secondary': 'var(--color-border-brand-secondary)',
39
- 'brand-tertiary': 'var(--color-border-brand-tertiary)',
40
- 'danger': 'var(--color-border-danger-default)',
41
- 'danger-secondary': 'var(--color-border-danger-secondary)',
42
- 'disabled': 'var(--color-border-disabled-default)',
43
- },
44
-
45
- // ringColor mirrors borderColor — focus rings use the same border token values
46
- ringColor: {
47
- 'default': 'var(--color-border-default-default)',
48
- 'default-secondary': 'var(--color-border-default-secondary)',
49
- 'brand': 'var(--color-border-brand-default)',
50
- 'brand-secondary': 'var(--color-border-brand-secondary)',
51
- 'brand-tertiary': 'var(--color-border-brand-tertiary)',
52
- 'danger': 'var(--color-border-danger-default)',
53
- 'danger-secondary': 'var(--color-border-danger-secondary)',
54
- 'disabled': 'var(--color-border-disabled-default)',
55
- },
56
-
57
- textColor: {
58
- 'default': 'var(--color-text-default-default)',
59
- 'default-secondary': 'var(--color-text-default-secondary)',
60
- 'default-tertiary': 'var(--color-text-default-tertiary)',
61
- 'brand': 'var(--color-text-brand-default)',
62
- 'brand-on-brand': 'var(--color-text-brand-on-brand)',
63
- 'neutral': 'var(--color-text-neutral-default)',
64
- 'positive': 'var(--color-text-positive-default)',
65
- 'danger': 'var(--color-text-danger-default)',
66
- 'danger-on-danger': 'var(--color-text-danger-on-danger)',
67
- 'disabled': 'var(--color-text-disabled-default)',
68
- 'disabled-on-disabled': 'var(--color-text-disabled-on-disabled)',
69
- // ── Icon (SVG currentColor) ───────────────────────────────────────────
70
- 'icon-default': 'var(--color-icon-default-default)',
71
- 'icon-default-secondary': 'var(--color-icon-default-secondary)',
72
- 'icon-brand': 'var(--color-icon-brand-default)',
73
- 'icon-brand-on-brand': 'var(--color-icon-brand-on-brand)',
74
- 'icon-disabled': 'var(--color-icon-disabled-default)',
75
- 'icon-danger': 'var(--color-icon-danger-default)',
76
- 'icon-positive': 'var(--color-icon-positive-default)',
77
- },
78
-
79
- fontSize: {
80
- 'body-tiny': ['11px', { lineHeight: '1.4' }],
81
- 'body-xs': ['13px', { lineHeight: '1.4' }],
82
- 'body-sm': ['14px', { lineHeight: '1.5' }],
83
- 'body': ['16px', { lineHeight: '1.5' }],
84
- 'heading-sm': ['20px', { lineHeight: '1.3' }],
85
- 'heading': ['24px', { lineHeight: '1.3' }],
86
- },
87
- fontWeight: {
88
- regular: '400',
89
- },
90
- // Brand directional gradients — bg-gradient-brand-{direction}
91
- backgroundImage: {
92
- 'gradient-brand-n-s': 'var(--gradient-brand-n-s)',
93
- 'gradient-brand-ne-sw': 'var(--gradient-brand-ne-sw)',
94
- 'gradient-brand-e-w': 'var(--gradient-brand-e-w)',
95
- 'gradient-brand-se-nw': 'var(--gradient-brand-se-nw)',
96
- 'gradient-brand-s-n': 'var(--gradient-brand-s-n)',
97
- 'gradient-brand-sw-ne': 'var(--gradient-brand-sw-ne)',
98
- 'gradient-brand-w-e': 'var(--gradient-brand-w-e)',
99
- 'gradient-brand-nw-se': 'var(--gradient-brand-nw-se)',
100
- },
101
-
102
- // gradientColorStops mirrors backgroundColor — from-*/to-*/via-* utilities use `colors`, not backgroundColor
103
- gradientColorStops: {
104
- 'brand': 'var(--color-background-brand-default)',
105
- 'brand-hover': 'var(--color-background-brand-hover)',
106
- 'brand-secondary': 'var(--color-background-brand-secondary)',
107
- 'brand-tertiary': 'var(--color-background-brand-tertiary)',
108
- 'brand-tertiary-hover': 'var(--color-background-brand-tertiary-hover)',
109
- 'default': 'var(--color-background-default-default)',
110
- 'default-hover': 'var(--color-background-default-default-hover)',
111
- 'default-secondary': 'var(--color-background-default-secondary)',
112
- 'default-tertiary': 'var(--color-background-default-tertiary)',
113
- 'danger': 'var(--color-background-danger-default)',
114
- 'danger-secondary': 'var(--color-background-danger-secondary)',
115
- 'danger-tertiary': 'var(--color-background-danger-tertiary)',
116
- 'positive-tertiary': 'var(--color-background-positive-tertiary)',
117
- 'warning-tertiary': 'var(--color-background-warning-tertiary)',
118
- },
119
- boxShadow: {
120
- panel: '0 2px 16px 0 rgba(0,0,0,0.08)',
121
- },
122
- },
123
- },
124
- }