@juwel-development/design-system 3.9.1 → 3.11.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 (79) hide show
  1. package/README.md +9 -298
  2. package/dist/design-system.js +1070 -605
  3. package/dist/index.css +1 -1
  4. package/dist/types/Arrangement/ColumnLayout/ColumnLayout.d.ts +92 -0
  5. package/dist/types/Arrangement/ColumnLayout/ColumnLayoutCompositionError.d.ts +3 -0
  6. package/dist/types/Arrangement/ColumnLayout/ColumnLayoutConfigurationError.d.ts +3 -0
  7. package/dist/types/Arrangement/FieldRow/FieldRow.d.ts +87 -0
  8. package/dist/types/Arrangement/FieldRow/FieldRowCompositionError.d.ts +3 -0
  9. package/dist/types/Arrangement/FieldRow/FieldRowConfigurationError.d.ts +3 -0
  10. package/dist/types/Arrangement/FieldRow/IControlEdge.d.ts +6 -0
  11. package/dist/types/Arrangement/FieldRow/alignControlEdges.d.ts +7 -0
  12. package/dist/types/Display/Box/Box.d.ts +41 -0
  13. package/dist/types/Display/Brandmark/Brandmark.d.ts +1 -1
  14. package/dist/types/Display/DefinitionList/DefinitionList.d.ts +59 -9
  15. package/dist/types/Display/DefinitionList/DefinitionListConfigurationError.d.ts +3 -0
  16. package/dist/types/Display/Figure/Figure.d.ts +2 -2
  17. package/dist/types/Display/Icon/Icon.d.ts +45 -0
  18. package/dist/types/Display/Table/Table.d.ts +118 -8
  19. package/dist/types/Display/Table/TableConfigurationError.d.ts +3 -0
  20. package/dist/types/Display/Typography/Eyebrow/Eyebrow.d.ts +1 -1
  21. package/dist/types/Display/Typography/H1/H1.d.ts +3 -2
  22. package/dist/types/Display/Typography/H2/H2.d.ts +3 -2
  23. package/dist/types/Display/Typography/H3/H3.d.ts +3 -2
  24. package/dist/types/Display/Typography/H4/H4.d.ts +3 -2
  25. package/dist/types/Display/Typography/H5/H5.d.ts +3 -2
  26. package/dist/types/Display/Typography/H6/H6.d.ts +3 -2
  27. package/dist/types/Display/Typography/Note/Note.d.ts +1 -1
  28. package/dist/types/Display/Typography/P/P.d.ts +3 -2
  29. package/dist/types/Display/Typography/Prose/Prose.d.ts +1 -1
  30. package/dist/types/Interaction/Button/Button.d.ts +25 -3
  31. package/dist/types/Interaction/Tabs/Tabs.d.ts +31 -6
  32. package/dist/types/Layout/Header/Header.d.ts +67 -8
  33. package/dist/types/Layout/ScrollContainer/ScrollContainer.d.ts +37 -0
  34. package/dist/types/Layout/Section/Section.d.ts +1 -1
  35. package/dist/types/Layout/Sidebar/Sidebar.d.ts +4 -0
  36. package/dist/types/Theme/Palette.d.ts +31 -7
  37. package/dist/types/index.d.ts +6 -0
  38. package/package.json +1 -1
  39. package/src/Arrangement/ColumnLayout/ColumnLayout.tsx +249 -0
  40. package/src/Arrangement/ColumnLayout/ColumnLayoutCompositionError.ts +8 -0
  41. package/src/Arrangement/ColumnLayout/ColumnLayoutConfigurationError.ts +6 -0
  42. package/src/Arrangement/FieldRow/FieldRow.tsx +313 -0
  43. package/src/Arrangement/FieldRow/FieldRowCompositionError.ts +6 -0
  44. package/src/Arrangement/FieldRow/FieldRowConfigurationError.ts +6 -0
  45. package/src/Arrangement/FieldRow/IControlEdge.ts +6 -0
  46. package/src/Arrangement/FieldRow/alignControlEdges.ts +35 -0
  47. package/src/Display/Box/Box.tsx +77 -0
  48. package/src/Display/Checklist/Checklist.tsx +1 -1
  49. package/src/Display/DefinitionList/DefinitionList.tsx +164 -22
  50. package/src/Display/DefinitionList/DefinitionListConfigurationError.ts +6 -0
  51. package/src/Display/Icon/Icon.tsx +113 -0
  52. package/src/Display/Table/Table.tsx +434 -44
  53. package/src/Display/Table/TableConfigurationError.ts +6 -0
  54. package/src/Display/Typography/H1/H1.tsx +3 -2
  55. package/src/Display/Typography/H2/H2.tsx +3 -2
  56. package/src/Display/Typography/H3/H3.tsx +3 -2
  57. package/src/Display/Typography/H4/H4.tsx +3 -2
  58. package/src/Display/Typography/H5/H5.tsx +3 -2
  59. package/src/Display/Typography/H6/H6.tsx +3 -2
  60. package/src/Display/Typography/P/P.tsx +3 -2
  61. package/src/Display/Typography/Prose/Prose.tsx +3 -3
  62. package/src/Interaction/Button/Button.tsx +47 -17
  63. package/src/Interaction/Input/Input.tsx +1 -1
  64. package/src/Interaction/MultiSelect/MultiSelect.tsx +1 -1
  65. package/src/Interaction/NumberInput/NumberInput.tsx +1 -1
  66. package/src/Interaction/Select/Select.tsx +1 -1
  67. package/src/Interaction/Tabs/Tabs.tsx +38 -11
  68. package/src/Interaction/TextArea/TextArea.tsx +1 -1
  69. package/src/Layout/Dialog/Dialog.tsx +4 -3
  70. package/src/Layout/Header/Header.tsx +139 -39
  71. package/src/Layout/PageHead/PageHead.tsx +6 -5
  72. package/src/Layout/ScrollContainer/ScrollContainer.tsx +149 -0
  73. package/src/Layout/Sidebar/Sidebar.tsx +8 -4
  74. package/src/Theme/Palette.ts +37 -9
  75. package/src/Theme/renderTokens.ts +101 -5
  76. package/src/index.ts +6 -0
  77. package/src/tokens.css +68 -4
  78. package/src/tokens.dark.css +66 -4
  79. package/src/tokens.light.css +64 -2
@@ -89,8 +89,9 @@ const UNDERLINE = `:root {
89
89
  Tailwind built-in is re-pointed; only new role names. See docs/adr/0004-typography-token-contract.md. */
90
90
  const TYPOGRAPHY = `@theme {
91
91
  /* Both faces default to inherit, so the library ships no @font-face and no face and a one-face
92
- consumer renders as today. --font-primary is carried by content, --font-secondary by labels; a
93
- component sets font-variant-numeric: tabular-nums only on a --font-primary carrying tnum and
92
+ consumer renders as today. --font-primary is the default face of headings, body and controls
93
+ (the three roles below, #120), --font-secondary the face of labels; a component sets
94
+ font-variant-numeric: tabular-nums only on an effective body face carrying tnum and
94
95
  font-variant-caps: small-caps only on a --font-secondary carrying smcp - both fail silently otherwise. */
95
96
  --font-primary: inherit;
96
97
  --font-secondary: inherit;
@@ -136,6 +137,24 @@ const TYPOGRAPHY = `@theme {
136
137
  --tracking-optical: -0.02em;
137
138
  }`;
138
139
 
140
+ /* Three family roles that depart from the primary face on demand (#120): heading for every heading,
141
+ body for reading matter, control for the box a viewer operates. Utilities rather than @theme
142
+ variables, because the fallback has to resolve on the element reading it: a value at :root would
143
+ substitute var(--font-primary) there, so a theme re-pointing primary on a wrapper would move its
144
+ paragraphs and strand its headings. Read this way, a theme re-points a role or primary at any scope
145
+ and the text underneath follows. No value is declared for the three, so the fallback stays live. */
146
+ const FAMILY_ROLES = `@utility font-heading {
147
+ font-family: var(--font-heading, var(--font-primary));
148
+ }
149
+
150
+ @utility font-body {
151
+ font-family: var(--font-body, var(--font-primary));
152
+ }
153
+
154
+ @utility font-control {
155
+ font-family: var(--font-control, var(--font-primary));
156
+ }`;
157
+
139
158
  /* The reading measures are in ch so the character count holds when the body size moves under them:
140
159
  --measure-display narrower because bigger type wants fewer characters per line, --measure-wide a
141
160
  little past the reading column for the page-head standfirst (PageHead #18). --measure-action is
@@ -147,6 +166,17 @@ const MEASURE = `:root {
147
166
  --measure-action: 20rem;
148
167
  }`;
149
168
 
169
+ /* The table's column width roles (#115) are not colours: like the measures they live in :root only,
170
+ so a brand re-points one and every table allocating by that role moves. Four column jobs the
171
+ consumer attests - name, fact, figure, action - and no size ladder (docs/adr/0008, Amendments);
172
+ action holds --control-min-width plus the comfortable insets. Constraint: positive lengths. */
173
+ const TABLE_COLUMN = `:root {
174
+ --table-column-name: 12rem;
175
+ --table-column-fact: 9rem;
176
+ --table-column-figure: 8rem;
177
+ --table-column-action: 12.5rem;
178
+ }`;
179
+
150
180
  /* Three spacing roles, not a ladder: --space-stack is the sibling gap in a stack, --space-region the air
151
181
  around a region of a page - a form's region groups and the shell's bars, above and below the header and
152
182
  the footer and between the header's nav items (#14/#15) - and --space-band the vertical air inside a page
@@ -169,6 +199,44 @@ const COLLECTION_SPACING = `:root {
169
199
  --space-collection-item: 1em;
170
200
  }`;
171
201
 
202
+ /* DefinitionList's spacing and minimum roles (#123): item air per density, in rem like Table's cell padding since
203
+ the members set their own type roles, and the two columns' minimum readable widths, in rem like
204
+ --control-min-width since a column is counted against the root. Theme-overridable; the item air
205
+ accepts any nonnegative length, a minimum any nonnegative length a `calc()` can read. */
206
+ const DEFINITION_SPACING = `:root {
207
+ --space-definition-item: 1.5rem;
208
+ --space-definition-item-compact: 0.5rem;
209
+ --space-definition-column: 3rem;
210
+ --definition-term-min-width: 9rem;
211
+ --definition-description-min-width: 10rem;
212
+ }
213
+
214
+ /* Register the fit value in every token entry point so descriptions inherit a computed fit length. */
215
+ @property --definition-shortfall {
216
+ syntax: "<length>";
217
+ inherits: true;
218
+ initial-value: 1px;
219
+ }`;
220
+
221
+ /* Box's inner padding (#117): one role on all four sides, distinct from a sibling gap, a region's
222
+ air or a page band, so a brand tunes every Box at once and no Box gains a padding prop (ADR 0008,
223
+ the token-role test). In em like --space-collection-item, so it tracks the inherited type.
224
+ Constraint: a nonnegative CSS length. */
225
+ const BOX_INSET = `:root {
226
+ --space-box-inset: 1em;
227
+ }`;
228
+
229
+ /* Table cell insets (#115): one inline/block pair per density, in :root so a brand tunes both
230
+ treatments without Table gaining a measurement prop. comfortable is exactly what px-4 / py-2
231
+ resolved to, so the default moves nothing; compact halves both. In rem: cell type is fixed at the
232
+ small and label roles. Constraint: nonnegative, each compact inset no larger than its comfortable. */
233
+ const TABLE_CELL_INSET = `:root {
234
+ --table-cell-inset-inline: 1rem;
235
+ --table-cell-inset-block: 0.5rem;
236
+ --table-cell-inset-inline-compact: 0.5rem;
237
+ --table-cell-inset-block-compact: 0.25rem;
238
+ }`;
239
+
172
240
  /* The gutter is the horizontal inset holding content off the viewport edge (#9), and the one spacing role
173
241
  measured against the screen rather than the type: it answers to how much room there is, not how large
174
242
  the words are, so it is in rem/vw and never em. A clamp() lets it grow with the viewport with no
@@ -234,6 +302,14 @@ const TAB_MARKER = `:root {
234
302
  --tab-marker-thickness: 2px;
235
303
  }`;
236
304
 
305
+ /* Not a colour: like the tab marker it lives in :root only, so a brand re-points the weight of the
306
+ mark along a selected row's leading edge (#113) without Table gaining a prop. Not the tab marker's
307
+ token: that is a line under a tab, a different position (docs/adr/0008). Constraint: > 0 - zero
308
+ erases the one persistent selection cue. */
309
+ const TABLE_SELECTION_MARKER = `:root {
310
+ --table-selection-marker-thickness: 2px;
311
+ }`;
312
+
237
313
  /* The slider's two dimensions are not colours: like the tick they live in :root only, never @theme
238
314
  inline. Named because both are drawn on vendor pseudo-elements (::-webkit-slider-thumb and kin)
239
315
  no consumer selector can reach - ADR 0004's test. The control takes its height from the thumb, so
@@ -280,7 +356,7 @@ const toKebabCase = (name: string): string =>
280
356
  name.replace(/[A-Z]/g, (char) => `-${char.toLowerCase()}`);
281
357
 
282
358
  const declarations = (
283
- tokens: PaletteTokens,
359
+ tokens: Required<PaletteTokens>,
284
360
  value: (name: string) => string,
285
361
  ): string =>
286
362
  Object.keys(tokens)
@@ -290,7 +366,7 @@ const declarations = (
290
366
  // The library no longer declares --color-ring but still reads it as a fallback, so a consumer's
291
367
  // existing value keeps working; the plain hex in the palette is the default and what the contrast
292
368
  // test checks. See docs/adr/0002-focus-ring-token-contract.md.
293
- const raw = (tokens: PaletteTokens) => (name: string) => {
369
+ const raw = (tokens: Required<PaletteTokens>) => (name: string) => {
294
370
  const value = tokens[name as keyof PaletteTokens];
295
371
  return name === 'focusRing' ? `var(--color-ring, ${value})` : value;
296
372
  };
@@ -330,6 +406,10 @@ ${UNDERLINE}
330
406
  utilities, so it is not carried in @theme inline with the palette. */
331
407
  ${TYPOGRAPHY}
332
408
 
409
+ /* The heading, body and control family roles are utilities with a fallback to the primary face, not
410
+ @theme variables, so a theme re-pointing either name at any scope reaches the text beneath it. */
411
+ ${FAMILY_ROLES}
412
+
333
413
  /* The aspect roles are Tailwind theme namespaces like typography, so they take their own @theme block
334
414
  after it and are not carried in @theme inline with the palette. */
335
415
  ${ASPECT}
@@ -339,6 +419,10 @@ ${ASPECT}
339
419
  of controls rather than a reading line (docs/adr/0008, Amendments). */
340
420
  ${MEASURE}
341
421
 
422
+ /* The table column width roles have no Tailwind namespace either, and sit in :root beside the measures:
423
+ widths a column job needs, counted in rem against the root like the action column. */
424
+ ${TABLE_COLUMN}
425
+
342
426
  /* Spacing has no Tailwind namespace either - --spacing is a single base multiplier ADR 0004 forbids
343
427
  re-pointing - so the three roles sit in :root beside the measure. */
344
428
  ${SPACING}
@@ -346,6 +430,15 @@ ${SPACING}
346
430
  /* Collection's vertical item padding, measured against inherited type. */
347
431
  ${COLLECTION_SPACING}
348
432
 
433
+ /* DefinitionList's item air and column minimums sit in :root beside the collection role (#123). */
434
+ ${DEFINITION_SPACING}
435
+
436
+ /* Box's inner padding, measured against inherited type, beside Collection's. */
437
+ ${BOX_INSET}
438
+
439
+ /* Table's cell insets, one pair per density, beside Box's. */
440
+ ${TABLE_CELL_INSET}
441
+
349
442
  /* The gutter has no Tailwind namespace either, so it sits in :root beside the space roles. */
350
443
  ${GUTTER}
351
444
 
@@ -361,6 +454,9 @@ ${TICK}
361
454
  /* The tab marker's thickness is not a colour either, and sits in :root beside the tick block. */
362
455
  ${TAB_MARKER}
363
456
 
457
+ /* The table selection marker's thickness is not a colour either, and sits in :root beside the tab marker. */
458
+ ${TABLE_SELECTION_MARKER}
459
+
364
460
  ${TAB_INSETS}
365
461
 
366
462
  ${SLIDER}
@@ -403,7 +499,7 @@ ${colourMapAndTail()}`;
403
499
  differ only in header and which palette set lands in `:root`, so both render through here. */
404
500
  const renderSingleTheme = (
405
501
  header: string,
406
- tokens: PaletteTokens,
502
+ tokens: Required<PaletteTokens>,
407
503
  ): string => `${header}
408
504
 
409
505
  :root {
package/src/index.ts CHANGED
@@ -1,14 +1,19 @@
1
1
  import './styles.css';
2
2
 
3
3
  export { Cluster } from 'Arrangement/Cluster/Cluster';
4
+ export { ColumnLayout } from 'Arrangement/ColumnLayout/ColumnLayout';
5
+ export { FieldRow } from 'Arrangement/FieldRow/FieldRow';
4
6
  export { Stack } from 'Arrangement/Stack/Stack';
7
+ export { Box } from 'Display/Box/Box';
5
8
  export { Brandmark } from 'Display/Brandmark/Brandmark';
6
9
  export { Checklist } from 'Display/Checklist/Checklist';
7
10
  export { Collection } from 'Display/Collection/Collection';
8
11
  export { DefinitionList } from 'Display/DefinitionList/DefinitionList';
9
12
  export { Figure } from 'Display/Figure/Figure';
13
+ export { Icon } from 'Display/Icon/Icon';
10
14
  export { Meter } from 'Display/Meter/Meter';
11
15
  export { Rail } from 'Display/Rail/Rail';
16
+ export type { TableColumnAllocation } from 'Display/Table/Table';
12
17
  export { Table } from 'Display/Table/Table';
13
18
  export { Eyebrow } from 'Display/Typography/Eyebrow/Eyebrow';
14
19
  export { H1 } from 'Display/Typography/H1/H1';
@@ -38,6 +43,7 @@ export { Form } from 'Layout/Form/Form';
38
43
  export { Header } from 'Layout/Header/Header';
39
44
  export { Hero } from 'Layout/Hero/Hero';
40
45
  export { PageHead } from 'Layout/PageHead/PageHead';
46
+ export { ScrollContainer } from 'Layout/ScrollContainer/ScrollContainer';
41
47
  export { Section } from 'Layout/Section/Section';
42
48
  export { Sidebar } from 'Layout/Sidebar/Sidebar';
43
49
  export type { PaletteTokens } from 'Theme/Palette';
package/src/tokens.css CHANGED
@@ -33,6 +33,8 @@
33
33
  --color-success: #047857;
34
34
  --color-warning: #b45309;
35
35
  --color-error: #d63384;
36
+ --color-error-hover: #be185d;
37
+ --color-error-foreground: #ffffff;
36
38
  --color-info: #0e7490;
37
39
  }
38
40
 
@@ -50,8 +52,8 @@
50
52
  --color-primary: #8b5cf6;
51
53
  --color-primary-hover: #a78bfa;
52
54
  --color-primary-foreground: #020617;
53
- --color-secondary: #0284c7;
54
- --color-secondary-hover: #0ea5e9;
55
+ --color-secondary: #0ea5e9;
56
+ --color-secondary-hover: #38bdf8;
55
57
  --color-secondary-foreground: #020617;
56
58
  --color-disabled: #475569;
57
59
  --color-disabled-hover: #334155;
@@ -60,6 +62,8 @@
60
62
  --color-success: #34d399;
61
63
  --color-warning: #fbbf24;
62
64
  --color-error: #f48fb1;
65
+ --color-error-hover: #f8bbd0;
66
+ --color-error-foreground: #020617;
63
67
  --color-info: #22d3ee;
64
68
  }
65
69
 
@@ -87,6 +91,8 @@
87
91
  --color-success: var(--color-success);
88
92
  --color-warning: var(--color-warning);
89
93
  --color-error: var(--color-error);
94
+ --color-error-hover: var(--color-error-hover);
95
+ --color-error-foreground: var(--color-error-foreground);
90
96
  --color-info: var(--color-info);
91
97
  }
92
98
 
@@ -137,8 +143,9 @@
137
143
  utilities, so it is not carried in @theme inline with the palette. */
138
144
  @theme {
139
145
  /* Both faces default to inherit, so the library ships no @font-face and no face and a one-face
140
- consumer renders as today. --font-primary is carried by content, --font-secondary by labels; a
141
- component sets font-variant-numeric: tabular-nums only on a --font-primary carrying tnum and
146
+ consumer renders as today. --font-primary is the default face of headings, body and controls
147
+ (the three roles below, #120), --font-secondary the face of labels; a component sets
148
+ font-variant-numeric: tabular-nums only on an effective body face carrying tnum and
142
149
  font-variant-caps: small-caps only on a --font-secondary carrying smcp - both fail silently otherwise. */
143
150
  --font-primary: inherit;
144
151
  --font-secondary: inherit;
@@ -184,6 +191,20 @@
184
191
  --tracking-optical: -0.02em;
185
192
  }
186
193
 
194
+ /* The heading, body and control family roles are utilities with a fallback to the primary face, not
195
+ @theme variables, so a theme re-pointing either name at any scope reaches the text beneath it. */
196
+ @utility font-heading {
197
+ font-family: var(--font-heading, var(--font-primary));
198
+ }
199
+
200
+ @utility font-body {
201
+ font-family: var(--font-body, var(--font-primary));
202
+ }
203
+
204
+ @utility font-control {
205
+ font-family: var(--font-control, var(--font-primary));
206
+ }
207
+
187
208
  /* The aspect roles are Tailwind theme namespaces like typography, so they take their own @theme block
188
209
  after it and are not carried in @theme inline with the palette. */
189
210
  @theme {
@@ -203,6 +224,15 @@
203
224
  --measure-action: 20rem;
204
225
  }
205
226
 
227
+ /* The table column width roles have no Tailwind namespace either, and sit in :root beside the measures:
228
+ widths a column job needs, counted in rem against the root like the action column. */
229
+ :root {
230
+ --table-column-name: 12rem;
231
+ --table-column-fact: 9rem;
232
+ --table-column-figure: 8rem;
233
+ --table-column-action: 12.5rem;
234
+ }
235
+
206
236
  /* Spacing has no Tailwind namespace either - --spacing is a single base multiplier ADR 0004 forbids
207
237
  re-pointing - so the three roles sit in :root beside the measure. */
208
238
  :root {
@@ -216,6 +246,35 @@
216
246
  --space-collection-item: 1em;
217
247
  }
218
248
 
249
+ /* DefinitionList's item air and column minimums sit in :root beside the collection role (#123). */
250
+ :root {
251
+ --space-definition-item: 1.5rem;
252
+ --space-definition-item-compact: 0.5rem;
253
+ --space-definition-column: 3rem;
254
+ --definition-term-min-width: 9rem;
255
+ --definition-description-min-width: 10rem;
256
+ }
257
+
258
+ /* Register the fit value in every token entry point so descriptions inherit a computed fit length. */
259
+ @property --definition-shortfall {
260
+ syntax: "<length>";
261
+ inherits: true;
262
+ initial-value: 1px;
263
+ }
264
+
265
+ /* Box's inner padding, measured against inherited type, beside Collection's. */
266
+ :root {
267
+ --space-box-inset: 1em;
268
+ }
269
+
270
+ /* Table's cell insets, one pair per density, beside Box's. */
271
+ :root {
272
+ --table-cell-inset-inline: 1rem;
273
+ --table-cell-inset-block: 0.5rem;
274
+ --table-cell-inset-inline-compact: 0.5rem;
275
+ --table-cell-inset-block-compact: 0.25rem;
276
+ }
277
+
219
278
  /* The gutter has no Tailwind namespace either, so it sits in :root beside the space roles. */
220
279
  :root {
221
280
  --gutter: clamp(1.5rem, 5vw, 4rem);
@@ -242,6 +301,11 @@
242
301
  --tab-marker-thickness: 2px;
243
302
  }
244
303
 
304
+ /* The table selection marker's thickness is not a colour either, and sits in :root beside the tab marker. */
305
+ :root {
306
+ --table-selection-marker-thickness: 2px;
307
+ }
308
+
245
309
  :root {
246
310
  --tab-inset-inline: 1em;
247
311
  --tab-inset-block: 0.5em;
@@ -18,8 +18,8 @@
18
18
  --color-primary: #8b5cf6;
19
19
  --color-primary-hover: #a78bfa;
20
20
  --color-primary-foreground: #020617;
21
- --color-secondary: #0284c7;
22
- --color-secondary-hover: #0ea5e9;
21
+ --color-secondary: #0ea5e9;
22
+ --color-secondary-hover: #38bdf8;
23
23
  --color-secondary-foreground: #020617;
24
24
  --color-disabled: #475569;
25
25
  --color-disabled-hover: #334155;
@@ -28,6 +28,8 @@
28
28
  --color-success: #34d399;
29
29
  --color-warning: #fbbf24;
30
30
  --color-error: #f48fb1;
31
+ --color-error-hover: #f8bbd0;
32
+ --color-error-foreground: #020617;
31
33
  --color-info: #22d3ee;
32
34
  }
33
35
 
@@ -55,6 +57,8 @@
55
57
  --color-success: var(--color-success);
56
58
  --color-warning: var(--color-warning);
57
59
  --color-error: var(--color-error);
60
+ --color-error-hover: var(--color-error-hover);
61
+ --color-error-foreground: var(--color-error-foreground);
58
62
  --color-info: var(--color-info);
59
63
  }
60
64
 
@@ -105,8 +109,9 @@
105
109
  utilities, so it is not carried in @theme inline with the palette. */
106
110
  @theme {
107
111
  /* Both faces default to inherit, so the library ships no @font-face and no face and a one-face
108
- consumer renders as today. --font-primary is carried by content, --font-secondary by labels; a
109
- component sets font-variant-numeric: tabular-nums only on a --font-primary carrying tnum and
112
+ consumer renders as today. --font-primary is the default face of headings, body and controls
113
+ (the three roles below, #120), --font-secondary the face of labels; a component sets
114
+ font-variant-numeric: tabular-nums only on an effective body face carrying tnum and
110
115
  font-variant-caps: small-caps only on a --font-secondary carrying smcp - both fail silently otherwise. */
111
116
  --font-primary: inherit;
112
117
  --font-secondary: inherit;
@@ -152,6 +157,20 @@
152
157
  --tracking-optical: -0.02em;
153
158
  }
154
159
 
160
+ /* The heading, body and control family roles are utilities with a fallback to the primary face, not
161
+ @theme variables, so a theme re-pointing either name at any scope reaches the text beneath it. */
162
+ @utility font-heading {
163
+ font-family: var(--font-heading, var(--font-primary));
164
+ }
165
+
166
+ @utility font-body {
167
+ font-family: var(--font-body, var(--font-primary));
168
+ }
169
+
170
+ @utility font-control {
171
+ font-family: var(--font-control, var(--font-primary));
172
+ }
173
+
155
174
  /* The aspect roles are Tailwind theme namespaces like typography, so they take their own @theme block
156
175
  after it and are not carried in @theme inline with the palette. */
157
176
  @theme {
@@ -171,6 +190,15 @@
171
190
  --measure-action: 20rem;
172
191
  }
173
192
 
193
+ /* The table column width roles have no Tailwind namespace either, and sit in :root beside the measures:
194
+ widths a column job needs, counted in rem against the root like the action column. */
195
+ :root {
196
+ --table-column-name: 12rem;
197
+ --table-column-fact: 9rem;
198
+ --table-column-figure: 8rem;
199
+ --table-column-action: 12.5rem;
200
+ }
201
+
174
202
  /* Spacing has no Tailwind namespace either - --spacing is a single base multiplier ADR 0004 forbids
175
203
  re-pointing - so the three roles sit in :root beside the measure. */
176
204
  :root {
@@ -184,6 +212,35 @@
184
212
  --space-collection-item: 1em;
185
213
  }
186
214
 
215
+ /* DefinitionList's item air and column minimums sit in :root beside the collection role (#123). */
216
+ :root {
217
+ --space-definition-item: 1.5rem;
218
+ --space-definition-item-compact: 0.5rem;
219
+ --space-definition-column: 3rem;
220
+ --definition-term-min-width: 9rem;
221
+ --definition-description-min-width: 10rem;
222
+ }
223
+
224
+ /* Register the fit value in every token entry point so descriptions inherit a computed fit length. */
225
+ @property --definition-shortfall {
226
+ syntax: "<length>";
227
+ inherits: true;
228
+ initial-value: 1px;
229
+ }
230
+
231
+ /* Box's inner padding, measured against inherited type, beside Collection's. */
232
+ :root {
233
+ --space-box-inset: 1em;
234
+ }
235
+
236
+ /* Table's cell insets, one pair per density, beside Box's. */
237
+ :root {
238
+ --table-cell-inset-inline: 1rem;
239
+ --table-cell-inset-block: 0.5rem;
240
+ --table-cell-inset-inline-compact: 0.5rem;
241
+ --table-cell-inset-block-compact: 0.25rem;
242
+ }
243
+
187
244
  /* The gutter has no Tailwind namespace either, so it sits in :root beside the space roles. */
188
245
  :root {
189
246
  --gutter: clamp(1.5rem, 5vw, 4rem);
@@ -210,6 +267,11 @@
210
267
  --tab-marker-thickness: 2px;
211
268
  }
212
269
 
270
+ /* The table selection marker's thickness is not a colour either, and sits in :root beside the tab marker. */
271
+ :root {
272
+ --table-selection-marker-thickness: 2px;
273
+ }
274
+
213
275
  :root {
214
276
  --tab-inset-inline: 1em;
215
277
  --tab-inset-block: 0.5em;
@@ -28,6 +28,8 @@
28
28
  --color-success: #047857;
29
29
  --color-warning: #b45309;
30
30
  --color-error: #d63384;
31
+ --color-error-hover: #be185d;
32
+ --color-error-foreground: #ffffff;
31
33
  --color-info: #0e7490;
32
34
  }
33
35
 
@@ -55,6 +57,8 @@
55
57
  --color-success: var(--color-success);
56
58
  --color-warning: var(--color-warning);
57
59
  --color-error: var(--color-error);
60
+ --color-error-hover: var(--color-error-hover);
61
+ --color-error-foreground: var(--color-error-foreground);
58
62
  --color-info: var(--color-info);
59
63
  }
60
64
 
@@ -105,8 +109,9 @@
105
109
  utilities, so it is not carried in @theme inline with the palette. */
106
110
  @theme {
107
111
  /* Both faces default to inherit, so the library ships no @font-face and no face and a one-face
108
- consumer renders as today. --font-primary is carried by content, --font-secondary by labels; a
109
- component sets font-variant-numeric: tabular-nums only on a --font-primary carrying tnum and
112
+ consumer renders as today. --font-primary is the default face of headings, body and controls
113
+ (the three roles below, #120), --font-secondary the face of labels; a component sets
114
+ font-variant-numeric: tabular-nums only on an effective body face carrying tnum and
110
115
  font-variant-caps: small-caps only on a --font-secondary carrying smcp - both fail silently otherwise. */
111
116
  --font-primary: inherit;
112
117
  --font-secondary: inherit;
@@ -152,6 +157,20 @@
152
157
  --tracking-optical: -0.02em;
153
158
  }
154
159
 
160
+ /* The heading, body and control family roles are utilities with a fallback to the primary face, not
161
+ @theme variables, so a theme re-pointing either name at any scope reaches the text beneath it. */
162
+ @utility font-heading {
163
+ font-family: var(--font-heading, var(--font-primary));
164
+ }
165
+
166
+ @utility font-body {
167
+ font-family: var(--font-body, var(--font-primary));
168
+ }
169
+
170
+ @utility font-control {
171
+ font-family: var(--font-control, var(--font-primary));
172
+ }
173
+
155
174
  /* The aspect roles are Tailwind theme namespaces like typography, so they take their own @theme block
156
175
  after it and are not carried in @theme inline with the palette. */
157
176
  @theme {
@@ -171,6 +190,15 @@
171
190
  --measure-action: 20rem;
172
191
  }
173
192
 
193
+ /* The table column width roles have no Tailwind namespace either, and sit in :root beside the measures:
194
+ widths a column job needs, counted in rem against the root like the action column. */
195
+ :root {
196
+ --table-column-name: 12rem;
197
+ --table-column-fact: 9rem;
198
+ --table-column-figure: 8rem;
199
+ --table-column-action: 12.5rem;
200
+ }
201
+
174
202
  /* Spacing has no Tailwind namespace either - --spacing is a single base multiplier ADR 0004 forbids
175
203
  re-pointing - so the three roles sit in :root beside the measure. */
176
204
  :root {
@@ -184,6 +212,35 @@
184
212
  --space-collection-item: 1em;
185
213
  }
186
214
 
215
+ /* DefinitionList's item air and column minimums sit in :root beside the collection role (#123). */
216
+ :root {
217
+ --space-definition-item: 1.5rem;
218
+ --space-definition-item-compact: 0.5rem;
219
+ --space-definition-column: 3rem;
220
+ --definition-term-min-width: 9rem;
221
+ --definition-description-min-width: 10rem;
222
+ }
223
+
224
+ /* Register the fit value in every token entry point so descriptions inherit a computed fit length. */
225
+ @property --definition-shortfall {
226
+ syntax: "<length>";
227
+ inherits: true;
228
+ initial-value: 1px;
229
+ }
230
+
231
+ /* Box's inner padding, measured against inherited type, beside Collection's. */
232
+ :root {
233
+ --space-box-inset: 1em;
234
+ }
235
+
236
+ /* Table's cell insets, one pair per density, beside Box's. */
237
+ :root {
238
+ --table-cell-inset-inline: 1rem;
239
+ --table-cell-inset-block: 0.5rem;
240
+ --table-cell-inset-inline-compact: 0.5rem;
241
+ --table-cell-inset-block-compact: 0.25rem;
242
+ }
243
+
187
244
  /* The gutter has no Tailwind namespace either, so it sits in :root beside the space roles. */
188
245
  :root {
189
246
  --gutter: clamp(1.5rem, 5vw, 4rem);
@@ -210,6 +267,11 @@
210
267
  --tab-marker-thickness: 2px;
211
268
  }
212
269
 
270
+ /* The table selection marker's thickness is not a colour either, and sits in :root beside the tab marker. */
271
+ :root {
272
+ --table-selection-marker-thickness: 2px;
273
+ }
274
+
213
275
  :root {
214
276
  --tab-inset-inline: 1em;
215
277
  --tab-inset-block: 0.5em;