@pnx-mixtape/mxds 0.1.0-rc.1 → 0.1.0-rc.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 (198) hide show
  1. package/.storybook/decorators.ts +15 -0
  2. package/.storybook/preview.ts +4 -1
  3. package/.storybook/themes/campus-vibrant.css +181 -0
  4. package/.storybook/themes/civic-formal.css +246 -0
  5. package/.storybook/{theme-demo.css → themes/demo.css} +14 -7
  6. package/.storybook/themes/health-services.css +255 -0
  7. package/.storybook/themes/research-faculty.css +169 -0
  8. package/dist/build/accordion.css +1 -1
  9. package/dist/build/base.css +1 -1
  10. package/dist/build/button.css +1 -1
  11. package/dist/build/chunks/DropMenu-1baQc8Yc.js +1 -0
  12. package/dist/build/chunks/InPageNavigation-CVieEl9u.js +1 -0
  13. package/dist/build/chunks/Popover-Cxg-s5Jn.js +1 -0
  14. package/dist/build/chunks/Sticky-cWUVSOXN.js +1 -0
  15. package/dist/build/chunks/{Tabs-Dm8g301e.js → Tabs-DA_Ez8pv.js} +2 -2
  16. package/dist/build/chunks/polyfills-C7pRt54M.js +1 -0
  17. package/dist/build/constants.css +1 -1
  18. package/dist/build/drop-menu.entry.js +1 -1
  19. package/dist/build/elements.js +1 -1
  20. package/dist/build/form.css +1 -1
  21. package/dist/build/grid.css +1 -1
  22. package/dist/build/in-page-alert.css +1 -1
  23. package/dist/build/in-page-navigation.entry.js +1 -1
  24. package/dist/build/navigation.css +1 -1
  25. package/dist/build/popover.entry.js +1 -1
  26. package/dist/build/print.css +1 -1
  27. package/dist/build/progress-indicator.css +1 -0
  28. package/dist/build/react.js +1 -1
  29. package/dist/build/sidebar.css +1 -1
  30. package/dist/build/sticky.entry.js +1 -1
  31. package/dist/build/tabs.entry.js +1 -1
  32. package/dist/build/tag.css +1 -1
  33. package/dist/build/utilities.css +1 -1
  34. package/dist/types/Atom/DefinitionList/DefinitionList.d.ts +3 -2
  35. package/dist/types/Atom/DefinitionList/DefinitionList.d.ts.map +1 -1
  36. package/dist/types/Atom/Heading/Heading.d.ts.map +1 -1
  37. package/dist/types/Atom/List/List.d.ts +10 -0
  38. package/dist/types/Atom/List/List.d.ts.map +1 -0
  39. package/dist/types/Component/DropMenu/Elements/DropMenu.d.ts.map +1 -1
  40. package/dist/types/Component/InPageNavigation/Elements/InPageNavigation.d.ts +2 -2
  41. package/dist/types/Component/InPageNavigation/Elements/InPageNavigation.d.ts.map +1 -1
  42. package/dist/types/Component/InPageNavigation/Hooks/useInPageNavigation.d.ts.map +1 -1
  43. package/dist/types/Component/ProgressIndicator/ProgressIndicator.d.ts +9 -0
  44. package/dist/types/Component/ProgressIndicator/ProgressIndicator.d.ts.map +1 -0
  45. package/dist/types/Component/Tabs/Elements/Tabs.d.ts.map +1 -1
  46. package/dist/types/Component/Tag/Tag.d.ts +4 -2
  47. package/dist/types/Component/Tag/Tag.d.ts.map +1 -1
  48. package/dist/types/Form/Autocomplete/Autocomplete.d.ts.map +1 -1
  49. package/dist/types/Form/Checkbox/FormCheckbox.d.ts.map +1 -1
  50. package/dist/types/Form/CheckboxCard/CheckboxCard.d.ts +23 -0
  51. package/dist/types/Form/CheckboxCard/CheckboxCard.d.ts.map +1 -0
  52. package/dist/types/Form/Radio/FormRadio.d.ts.map +1 -1
  53. package/dist/types/Form/RadioCard/RadioCard.d.ts +16 -0
  54. package/dist/types/Form/RadioCard/RadioCard.d.ts.map +1 -0
  55. package/dist/types/Form/Select/FormSelect.d.ts.map +1 -1
  56. package/dist/types/Form/TextInput/FormText.d.ts.map +1 -1
  57. package/dist/types/Form/Textarea/FormTextarea.d.ts.map +1 -1
  58. package/dist/types/enums.d.ts +15 -0
  59. package/dist/types/enums.d.ts.map +1 -1
  60. package/dist/types/react.d.ts +4 -0
  61. package/dist/types/react.d.ts.map +1 -1
  62. package/package.json +7 -7
  63. package/src/Atom/Background/_background.css +2 -2
  64. package/src/Atom/Blockquote/_blockquote.css +9 -2
  65. package/src/Atom/Button/README.md +1 -0
  66. package/src/Atom/Button/_buttons-styles.css +6 -6
  67. package/src/Atom/Button/_buttons.css +5 -3
  68. package/src/Atom/DefinitionList/DefinitionList.stories.ts +39 -2
  69. package/src/Atom/DefinitionList/DefinitionList.stories.tsx +36 -0
  70. package/src/Atom/DefinitionList/DefinitionList.tsx +4 -1
  71. package/src/Atom/DefinitionList/DefinitionListItem.stories.ts +1 -1
  72. package/src/Atom/DefinitionList/README.md +43 -0
  73. package/src/Atom/DefinitionList/__snapshots__/DefinitionList.stories.ts.snap +37 -3
  74. package/src/Atom/DefinitionList/__snapshots__/DefinitionList.stories.tsx.snap +2 -0
  75. package/src/Atom/DefinitionList/__snapshots__/DefinitionListItem.stories.ts.snap +3 -3
  76. package/src/Atom/DefinitionList/definition-list-item.twig +1 -0
  77. package/src/Atom/DefinitionList/definition-list.twig +6 -1
  78. package/src/Atom/Heading/Heading.tsx +6 -0
  79. package/src/Atom/Heading/_headings.css +2 -1
  80. package/src/Atom/Icon/_extended-set.css +30 -30
  81. package/src/Atom/Icon/_icon.css +36 -36
  82. package/src/Atom/Image/README.md +2 -2
  83. package/src/Atom/Image/_image.css +12 -6
  84. package/src/Atom/List/List.stories.ts +102 -0
  85. package/src/Atom/List/List.stories.tsx +103 -0
  86. package/src/Atom/List/List.tsx +22 -0
  87. package/src/Atom/List/README.md +150 -0
  88. package/src/Atom/List/__snapshots__/List.stories.ts.snap +43 -0
  89. package/src/Atom/List/__snapshots__/List.stories.tsx.snap +13 -0
  90. package/src/Atom/List/_list.css +123 -0
  91. package/src/Atom/List/list.twig +5 -0
  92. package/src/Atom/Media/Media.stories.ts +1 -1
  93. package/src/Atom/Media/__snapshots__/Media.stories.ts.snap +2 -2
  94. package/src/Atom/Spacing/_spacing.css +24 -24
  95. package/src/Atom/Table/__snapshots__/Table.stories.ts.snap +24 -4
  96. package/src/Atom/Table/_table.css +15 -3
  97. package/src/Atom/Table/table.twig +6 -1
  98. package/src/Atom/Text/__snapshots__/Text.stories.ts.snap +3 -2
  99. package/src/Atom/Text/_text-styles.css +21 -1
  100. package/src/Atom/Text/twig/text-styles-example.twig +3 -2
  101. package/src/Atom/_base.css +6 -0
  102. package/src/Atom/_flow.css +1 -1
  103. package/src/Atom/_generic.css +18 -11
  104. package/src/Component/Accordion/accordion.css +2 -0
  105. package/src/Component/Card/__snapshots__/Card.stories.ts.snap +2 -2
  106. package/src/Component/Card/card.twig +1 -1
  107. package/src/Component/Carousel/Carousel.stories.ts +46 -23
  108. package/src/Component/DropMenu/Elements/DropMenu.ts +10 -1
  109. package/src/Component/InPageAlert/in-page-alert.css +2 -1
  110. package/src/Component/InPageNavigation/Elements/InPageNavigation.ts +10 -5
  111. package/src/Component/InPageNavigation/Hooks/useInPageNavigation.ts +10 -5
  112. package/src/Component/InPageNavigation/InPageNavigation.stories.ts +33 -0
  113. package/src/Component/InPageNavigation/InPageNavigation.stories.tsx +52 -0
  114. package/src/Component/InPageNavigation/__snapshots__/InPageNavigation.stories.ts.snap +26 -0
  115. package/src/Component/InPageNavigation/__snapshots__/InPageNavigation.stories.tsx.snap +2 -0
  116. package/src/Component/InPageNavigation/twig/content-example-duplicate-headings.twig +20 -0
  117. package/src/Component/InPageNavigation/twig/in-page-navigation-story-duplicate-headings.twig +2 -0
  118. package/src/Component/ListItem/__snapshots__/ListItem.stories.ts.snap +4 -4
  119. package/src/Component/ListItem/list-item.twig +2 -2
  120. package/src/Component/Navigation/_navigation.css +1 -1
  121. package/src/Component/Pagination/Pagination.stories.ts +8 -4
  122. package/src/Component/Pagination/pagination.css +2 -2
  123. package/src/Component/ProgressIndicator/ProgressIndicator.stories.ts +36 -0
  124. package/src/Component/ProgressIndicator/ProgressIndicator.stories.tsx +30 -0
  125. package/src/Component/ProgressIndicator/ProgressIndicator.tsx +60 -0
  126. package/src/Component/ProgressIndicator/README.md +111 -0
  127. package/src/Component/ProgressIndicator/__snapshots__/ProgressIndicator.stories.ts.snap +67 -0
  128. package/src/Component/ProgressIndicator/__snapshots__/ProgressIndicator.stories.tsx.snap +7 -0
  129. package/src/Component/ProgressIndicator/progress-indicator.css +59 -0
  130. package/src/Component/ProgressIndicator/progress-indicator.twig +22 -0
  131. package/src/Component/Sticky/Elements/Sticky.ts +1 -1
  132. package/src/Component/Sticky/sticky.css +3 -3
  133. package/src/Component/Tabs/Elements/Tabs.ts +3 -1
  134. package/src/Component/Tabs/Tabs.stories.ts +55 -21
  135. package/src/Component/Tabs/__snapshots__/Tabs.stories.ts.snap +2 -2
  136. package/src/Component/Tag/README.md +52 -26
  137. package/src/Component/Tag/Tag.stories.tsx +24 -0
  138. package/src/Component/Tag/Tag.tsx +12 -2
  139. package/src/Component/Tag/TagItem.stories.ts +25 -0
  140. package/src/Component/Tag/__snapshots__/Tag.stories.ts.snap +2 -2
  141. package/src/Component/Tag/__snapshots__/Tag.stories.tsx.snap +2 -0
  142. package/src/Component/Tag/tag-item.twig +2 -2
  143. package/src/Component/Tag/tag.css +76 -2
  144. package/src/Form/Autocomplete/Autocomplete.stories.ts +8 -3
  145. package/src/Form/Autocomplete/Autocomplete.tsx +1 -4
  146. package/src/Form/Autocomplete/README.md +26 -26
  147. package/src/Form/Autocomplete/__snapshots__/Autocomplete.stories.ts.snap +1 -1
  148. package/src/Form/Autocomplete/__snapshots__/Autocomplete.stories.tsx.snap +1 -1
  149. package/src/Form/Autocomplete/autocomplete.twig +0 -2
  150. package/src/Form/Checkbox/FormCheckbox.tsx +2 -8
  151. package/src/Form/Checkbox/README.md +23 -18
  152. package/src/Form/Checkbox/input-checkbox.twig +0 -2
  153. package/src/Form/CheckboxCard/CheckboxCard.stories.ts +90 -0
  154. package/src/Form/CheckboxCard/CheckboxCard.stories.tsx +43 -0
  155. package/src/Form/CheckboxCard/CheckboxCard.tsx +102 -0
  156. package/src/Form/CheckboxCard/README.md +163 -0
  157. package/src/Form/CheckboxCard/__snapshots__/CheckboxCard.stories.ts.snap +63 -0
  158. package/src/Form/CheckboxCard/__snapshots__/CheckboxCard.stories.tsx.snap +7 -0
  159. package/src/Form/CheckboxCard/checkbox-card.twig +29 -0
  160. package/src/Form/FormItem/__snapshots__/FormItem.stories.ts.snap +2 -2
  161. package/src/Form/README.md +65 -13
  162. package/src/Form/Radio/FormRadio.tsx +1 -4
  163. package/src/Form/Radio/input-radio.twig +0 -2
  164. package/src/Form/RadioCard/README.md +146 -0
  165. package/src/Form/RadioCard/RadioCard.stories.ts +95 -0
  166. package/src/Form/RadioCard/RadioCard.stories.tsx +26 -0
  167. package/src/Form/RadioCard/RadioCard.tsx +59 -0
  168. package/src/Form/RadioCard/__snapshots__/RadioCard.stories.ts.snap +69 -0
  169. package/src/Form/RadioCard/__snapshots__/RadioCard.stories.tsx.snap +3 -0
  170. package/src/Form/RadioCard/radio-card.twig +20 -0
  171. package/src/Form/Select/FormSelect.tsx +1 -4
  172. package/src/Form/Select/input-select.twig +0 -2
  173. package/src/Form/TextInput/FormText.stories.tsx +14 -0
  174. package/src/Form/TextInput/FormText.tsx +1 -4
  175. package/src/Form/TextInput/__snapshots__/FormText.stories.tsx.snap +2 -0
  176. package/src/Form/TextInput/input-text.twig +0 -2
  177. package/src/Form/Textarea/FormTextarea.tsx +1 -4
  178. package/src/Form/Textarea/input-textarea.twig +0 -2
  179. package/src/Form/Validation.stories.ts +153 -0
  180. package/src/Form/__snapshots__/Validation.stories.ts.snap +130 -0
  181. package/src/Form/form.css +155 -28
  182. package/src/Layout/Grid/grid.css +4 -4
  183. package/src/Layout/Sidebar/__snapshots__/Sidebar.stories.ts.snap +5 -5
  184. package/src/Layout/Sidebar/sidebar.css +1 -0
  185. package/src/Layout/Sidebar/sidebar.twig +1 -1
  186. package/src/Utility/_layout-utils.css +8 -0
  187. package/src/Utility/print.css +50 -28
  188. package/src/Utility/utilities.css +2 -2
  189. package/src/constants.css +12 -2
  190. package/src/enums.ts +17 -0
  191. package/src/react.ts +4 -0
  192. package/tools/lib/extract-classnames.mjs +0 -0
  193. package/tools/lint-classnames.mjs +1 -1
  194. package/dist/build/chunks/DropMenu-Co9jZZ4S.js +0 -1
  195. package/dist/build/chunks/InPageNavigation-CzR_KZaz.js +0 -1
  196. package/dist/build/chunks/Popover-De_CQqcd.js +0 -1
  197. package/dist/build/chunks/Sticky-Kyjykb36.js +0 -1
  198. package/dist/build/chunks/polyfills-Dokbkxxk.js +0 -1
package/src/Form/form.css CHANGED
@@ -66,14 +66,6 @@
66
66
  opacity: var(--disabled-opacity, 0.6);
67
67
  cursor: not-allowed;
68
68
  }
69
-
70
- &.error {
71
- border-color: var(--error-foreground, var(--colour-error));
72
- }
73
-
74
- &.success {
75
- border-color: var(--success-foreground, var(--colour-success));
76
- }
77
69
  }
78
70
 
79
71
  .mx-input--small {
@@ -123,12 +115,12 @@
123
115
  background-color: transparent;
124
116
  }
125
117
 
126
- &:has(.error)::before {
127
- background-color: var(--error-foreground, var(--colour-error));
118
+ &:has(.mx-validate:user-valid)::before {
119
+ background-color: var(--success-foreground, var(--colour-success));
128
120
  }
129
121
 
130
- &:has(.success)::before {
131
- background-color: var(--success-foreground, var(--colour-success));
122
+ &:has(:is(.mx-validate:user-invalid, [aria-invalid="true"]))::before {
123
+ background-color: var(--error-foreground, var(--colour-error));
132
124
  }
133
125
  }
134
126
  }
@@ -153,6 +145,17 @@
153
145
  outline-offset: calc(var(--line-width, 2px) * -1);
154
146
  }
155
147
 
148
+ &:has(.mx-validate:user-valid),
149
+ .mx-validate &:has(:user-valid) {
150
+ border-color: var(--success-foreground, var(--colour-success));
151
+ }
152
+
153
+ &:has(.mx-validate:user-invalid),
154
+ .mx-validate &:has(:user-invalid),
155
+ &:has([aria-invalid="true"]) {
156
+ border-color: var(--error-foreground, var(--colour-error));
157
+ }
158
+
156
159
  & .mx-input__text {
157
160
  background-color: transparent;
158
161
  border: 0;
@@ -200,6 +203,7 @@
200
203
  background-color: var(--background, var(--colour-background));
201
204
  border: var(--line-width, 2px) solid var(--line-colour, var(--colour-border));
202
205
  border-radius: var(--border-radius);
206
+ font-size: 1rem;
203
207
 
204
208
  @media (pointer: coarse) {
205
209
  --control-size: 2rem;
@@ -227,14 +231,6 @@
227
231
  cursor: not-allowed;
228
232
  }
229
233
  }
230
-
231
- &.error {
232
- border-color: var(--error-foreground, var(--colour-error));
233
- }
234
-
235
- &.success {
236
- border-color: var(--success-foreground, var(--colour-success));
237
- }
238
234
  }
239
235
  }
240
236
 
@@ -256,6 +252,7 @@
256
252
  background-color: var(--background, var(--colour-background));
257
253
  border: var(--line-width, 2px) solid var(--line-colour, var(--colour-border));
258
254
  border-radius: 50%;
255
+ font-size: 1rem;
259
256
 
260
257
  @media (pointer: coarse) {
261
258
  --control-size: 2rem;
@@ -289,14 +286,6 @@
289
286
  cursor: not-allowed;
290
287
  }
291
288
  }
292
-
293
- &.error {
294
- border-color: var(--error-foreground, var(--colour-error));
295
- }
296
-
297
- &.success {
298
- border-color: var(--success-foreground, var(--colour-success));
299
- }
300
289
  }
301
290
 
302
291
  :is(.mx-radio, .mx-checkbox) {
@@ -337,6 +326,96 @@
337
326
  }
338
327
  }
339
328
 
329
+ /**
330
+ * Choice cards.
331
+ */
332
+
333
+ @layer design-system.components {
334
+ .mx-choice-card {
335
+ /* @public --choice-padding-block --choice-padding-inline --choice-colour-active */
336
+ display: block;
337
+ position: relative;
338
+ border: var(--line-width, 2px) solid var(--line-colour, var(--colour-border));
339
+ border-radius: var(--border-radius);
340
+ background-color: var(--background, var(--colour-background));
341
+ transition:
342
+ border-color 0.12s linear,
343
+ background-color 0.12s linear;
344
+
345
+ & label {
346
+ display: grid;
347
+ gap: var(--spacing-xxxs);
348
+ padding-block: var(--choice-padding-block, var(--spacing-s));
349
+ padding-inline: calc(
350
+ var(--control-size, var(--spacing-m)) + var(--choice-padding-inline, var(--spacing-m)) * 2
351
+ )
352
+ var(--choice-padding-inline, var(--spacing-m));
353
+ min-block-size: calc(
354
+ var(--control-size, var(--spacing-m)) + var(--choice-padding-block, var(--spacing-s)) * 2
355
+ );
356
+ cursor: pointer;
357
+ font-weight: var(--font-weight-bold);
358
+ }
359
+
360
+ & input {
361
+ position: absolute;
362
+ inset-block-start: var(--choice-padding-block, var(--spacing-s));
363
+ inset-inline-start: var(--choice-padding-inline, var(--spacing-m));
364
+ }
365
+
366
+ &:has(input:checked) {
367
+ border-color: var(--choice-colour-active, var(--colour-primary));
368
+ background-color: color-mix(
369
+ in oklch,
370
+ var(--choice-colour-active, var(--colour-primary)),
371
+ white 95%
372
+ );
373
+ }
374
+
375
+ &:hover {
376
+ border-color: var(--choice-colour-active, var(--colour-primary));
377
+ }
378
+
379
+ &:has(.mx-validate:user-valid),
380
+ .mx-validate &:has(:user-valid) {
381
+ border-color: var(--success-foreground, var(--colour-success));
382
+ }
383
+
384
+ &:has(.mx-validate:user-invalid),
385
+ .mx-validate &:has(:user-invalid),
386
+ &:has([aria-invalid="true"]) {
387
+ border-color: var(--error-foreground, var(--colour-error));
388
+ }
389
+ }
390
+
391
+ .mx-choice-divider {
392
+ display: flex;
393
+ align-items: center;
394
+ gap: var(--spacing-xs);
395
+ font-size: var(--font-size-s);
396
+ color: var(--colour-foreground-alt);
397
+ margin-block-end: var(--spacing-xxxs);
398
+
399
+ &::before,
400
+ &::after {
401
+ content: "";
402
+ flex: 1;
403
+ block-size: 1px;
404
+ background-color: var(--colour-border);
405
+ }
406
+ }
407
+
408
+ .mx-choice-card__hint {
409
+ font-weight: var(--font-weight-normal);
410
+ font-size: var(--font-size-s);
411
+ color: var(--colour-foreground-alt);
412
+ }
413
+
414
+ .mx-description + .mx-choice-card {
415
+ margin-block-start: var(--spacing-xxxs);
416
+ }
417
+ }
418
+
340
419
  /**
341
420
  * Select
342
421
  */
@@ -534,3 +613,51 @@
534
613
  background-color: var(--success-foreground, var(--colour-success));
535
614
  }
536
615
  }
616
+
617
+ /**
618
+ * Validation state
619
+ *
620
+ * Two separate hooks, deliberately:
621
+ *
622
+ * 1. .mx-validate — opt in to *live* native validation. :user-valid /
623
+ * :user-invalid fire on their own as the user types, so without this class
624
+ * a control is never coloured automatically (filling in an unmarked field
625
+ * doesn't turn it green).
626
+ *
627
+ * Put it on the control itself, or on a .mx-checkbox / .mx-radio /
628
+ * .mx-autocomplete wrapper — those three components put `className` and
629
+ * Drupal `attributes` on the wrapper, not the input, so the wrapper is the
630
+ * only reachable spot. The wrapper half is scoped to those class names on
631
+ * purpose: a bare descendant selector would leak, styling checkboxes
632
+ * inside any .mx-validate ancestor while leaving text inputs alone.
633
+ *
634
+ * 2. [aria-invalid="true"] — an *explicit* error, no opt-in: server-rendered
635
+ * (Drupal) or async failures the browser can't see. The consumer has
636
+ * already decided the field is wrong, so there's nothing to opt into.
637
+ *
638
+ * :user-* is used rather than :valid / :invalid so a blank required field
639
+ * isn't red on page load.
640
+ *
641
+ * Explicit errors are excluded from live success styling so they stay red.
642
+ */
643
+
644
+ @layer design-system.atoms {
645
+ .mx-validate,
646
+ :is(.mx-checkbox, .mx-radio, .mx-autocomplete).mx-validate :is(input, select, textarea) {
647
+ &:user-valid:not([aria-invalid="true"]) {
648
+ border-color: var(--success-foreground, var(--colour-success));
649
+ }
650
+
651
+ &:user-invalid {
652
+ border-color: var(--error-foreground, var(--colour-error));
653
+ }
654
+ }
655
+
656
+ .mx-input__text[aria-invalid="true"],
657
+ .mx-input__select[aria-invalid="true"],
658
+ .mx-input__textarea[aria-invalid="true"],
659
+ .mx-checkbox [type="checkbox"][aria-invalid="true"],
660
+ .mx-radio [type="radio"][aria-invalid="true"] {
661
+ border-color: var(--error-foreground, var(--colour-error));
662
+ }
663
+ }
@@ -4,11 +4,11 @@
4
4
 
5
5
  @layer design-system.layouts {
6
6
  .mx-grid {
7
- --grid-repeat: auto-fit;
8
- --grid-min: 20ch;
9
-
10
7
  display: grid;
11
- grid-template-columns: repeat(var(--grid-repeat), minmax(min(100%, var(--grid-min)), 1fr));
8
+ grid-template-columns: repeat(
9
+ var(--grid-repeat, auto-fit),
10
+ minmax(min(100%, var(--grid-min, 20ch)), 1fr)
11
+ );
12
12
  grid-template-rows: 1fr;
13
13
  gap: var(--grid-gap, var(--gap));
14
14
 
@@ -4,7 +4,7 @@ exports[`No Sidebar 1`] = `
4
4
  "
5
5
 
6
6
  <div class="mx-grid--sidebar">
7
- <section class="js-content mx-vertical-flow-grid">
7
+ <section class="js-content mx-vertical-flow-grid gap--xl">
8
8
  Main content
9
9
  </section>
10
10
  </div>
@@ -15,7 +15,7 @@ exports[`Reverse Large 1`] = `
15
15
  "
16
16
 
17
17
  <div class="mx-grid--sidebar mx-grid--sidebar-rev-lg">
18
- <section class="js-content mx-vertical-flow-grid">
18
+ <section class="js-content mx-vertical-flow-grid gap--xl">
19
19
  Main content
20
20
  </section>
21
21
  <aside class="mx-vertical-flow-grid">
@@ -30,7 +30,7 @@ exports[`Revserse Medium 1`] = `
30
30
  "
31
31
 
32
32
  <div class="mx-grid--sidebar mx-grid--sidebar-rev">
33
- <section class="js-content mx-vertical-flow-grid">
33
+ <section class="js-content mx-vertical-flow-grid gap--xl">
34
34
  Main content
35
35
  </section>
36
36
  <aside class="mx-vertical-flow-grid">
@@ -45,7 +45,7 @@ exports[`Sidebar 1`] = `
45
45
  "
46
46
 
47
47
  <div class="mx-grid--sidebar">
48
- <section class="js-content mx-vertical-flow-grid">
48
+ <section class="js-content mx-vertical-flow-grid gap--xl">
49
49
  Main content
50
50
  </section>
51
51
  <aside class="mx-vertical-flow-grid">
@@ -64,7 +64,7 @@ exports[`Sidebar First 1`] = `
64
64
  Sidebar content
65
65
  </aside>
66
66
 
67
- <section class="js-content mx-vertical-flow-grid">
67
+ <section class="js-content mx-vertical-flow-grid gap--xl">
68
68
  Main content
69
69
  </section>
70
70
  </div>
@@ -20,6 +20,7 @@
20
20
 
21
21
  & > aside {
22
22
  flex-grow: 1;
23
+ align-content: start;
23
24
 
24
25
  @media (--medium-up) {
25
26
  max-inline-size: var(--sidebar-width, 24ch);
@@ -8,7 +8,7 @@
8
8
  {% endfor %}
9
9
  {% set attributes = (attributes ?? create_attribute()).addClass(classes) %}
10
10
  {% set sidebarAttributes = (sidebarAttributes ?? create_attribute()).addClass('mx-vertical-flow-grid') %}
11
- {% set contentAttributes = (contentAttributes ?? create_attribute()).addClass('js-content', 'mx-vertical-flow-grid') %}
11
+ {% set contentAttributes = (contentAttributes ?? create_attribute()).addClass('js-content', 'mx-vertical-flow-grid', 'gap--xl') %}
12
12
 
13
13
  {% if sidebarContent is not empty %}
14
14
  {% set sidebar %}
@@ -12,6 +12,14 @@
12
12
  display: flex;
13
13
  }
14
14
 
15
+ .grid {
16
+ display: grid;
17
+ }
18
+
19
+ .spacer {
20
+ flex: 1;
21
+ }
22
+
15
23
  .place--center {
16
24
  place-content: center;
17
25
  }
@@ -40,7 +40,6 @@
40
40
  *,
41
41
  *::before,
42
42
  *::after {
43
- background: var(--colour-background);
44
43
  color: var(--colour-foreground);
45
44
  box-shadow: none;
46
45
  text-shadow: none;
@@ -64,8 +63,7 @@
64
63
  .mx-accordions__toggle-all,
65
64
  .mx-hero-banner__aside-image,
66
65
  .mx-card__media,
67
- .mx-results-bar__sort,
68
- .mx-icon
66
+ .mx-results-bar__sort
69
67
  ) {
70
68
  display: none;
71
69
  }
@@ -79,6 +77,10 @@
79
77
  display: none;
80
78
  }
81
79
 
80
+ /**
81
+ * Override grid layouts and add spacing.
82
+ */
83
+
82
84
  :is(
83
85
  .mx-grid,
84
86
  .mx-page,
@@ -108,6 +110,18 @@
108
110
  padding-block: var(--spacing-uul) 0;
109
111
  }
110
112
 
113
+ .mx-vertical-flow-grid > *:not(:first-child) {
114
+ margin-block-start: var(--gap);
115
+ }
116
+
117
+ :is(mx-accordion, .mx-carousel__scrollable li, .mx-tabs__panel):not(:first-child) {
118
+ margin-block-start: var(--spacing-m);
119
+ }
120
+
121
+ /**
122
+ * Add dividers to separate header, hero, sidebar and footer content.
123
+ */
124
+
111
125
  .mx-header {
112
126
  border-block-end: 2px solid currentcolor;
113
127
  }
@@ -140,23 +154,9 @@
140
154
  }
141
155
  }
142
156
 
143
- .mx-nav--breadcrumbs {
144
- & ul {
145
- gap: 0;
146
- }
147
-
148
- & li:not(:last-child)::after {
149
- content: "/";
150
- mask: unset;
151
- margin-inline: 1ch;
152
- inline-size: unset;
153
- }
154
- }
155
-
156
- .mx-footer__aoc {
157
- padding-block-end: unset;
158
- font-size: var(--font-size-s);
159
- }
157
+ /**
158
+ * Page breaks and typography.
159
+ */
160
160
 
161
161
  :is(pre, blockquote, tr, img, p, li, .mx-hero-banner) {
162
162
  break-inside: avoid;
@@ -203,6 +203,34 @@
203
203
  }
204
204
  }
205
205
 
206
+ /**
207
+ * General style fixes.
208
+ */
209
+
210
+ .mx-icon {
211
+ /* mask-image in print is treated the same background-image and is invisible, so we override it. */
212
+ print-color-adjust: exact;
213
+ }
214
+
215
+ .mx-nav--breadcrumbs {
216
+ & ul {
217
+ gap: 0;
218
+ }
219
+
220
+ /* Forward slash separator for breadcrumbs */
221
+ & li:not(:last-child)::after {
222
+ content: "/";
223
+ mask: unset;
224
+ margin-inline: 1ch;
225
+ inline-size: unset;
226
+ }
227
+ }
228
+
229
+ .mx-footer__aoc {
230
+ padding-block-end: unset;
231
+ font-size: var(--font-size-s);
232
+ }
233
+
206
234
  .mx-rich-text {
207
235
  max-inline-size: unset;
208
236
  }
@@ -216,6 +244,7 @@
216
244
  }
217
245
 
218
246
  :is(.mx-card--block a) {
247
+ /* Show card links */
219
248
  & .sr-only:only-child {
220
249
  clip-path: unset;
221
250
  inline-size: unset;
@@ -253,14 +282,6 @@
253
282
  border: unset;
254
283
  }
255
284
 
256
- .mx-vertical-flow-grid > *:not(:first-child) {
257
- margin-block-start: var(--gap);
258
- }
259
-
260
- :is(mx-accordion, .mx-carousel__scrollable li, .mx-tabs__panel):not(:first-child) {
261
- margin-block-start: var(--spacing-m);
262
- }
263
-
264
285
  .mx-accordion {
265
286
  &.mx-accordion--divided {
266
287
  border-block-end: unset;
@@ -312,6 +333,7 @@
312
333
  }
313
334
 
314
335
  .mx-video {
336
+ /* Show video url */
315
337
  &::after {
316
338
  content: "Video: " attr(data-title) " (" attr(data-src) ")";
317
339
  display: block;
@@ -5,12 +5,12 @@
5
5
  .hidden,
6
6
  .visually-hidden,
7
7
  .sr-only {
8
- @mixin sr-only;
8
+ @add-mixin sr-only;
9
9
  }
10
10
 
11
11
  .visually-hidden.visually-hidden--focussable:focus,
12
12
  .sr-only.sr-only--focussable:focus {
13
- @mixin sr-undo;
13
+ @add-mixin sr-undo;
14
14
  }
15
15
 
16
16
  [hidden] {
package/src/constants.css CHANGED
@@ -16,17 +16,27 @@
16
16
  initial-value: black;
17
17
  }
18
18
 
19
+ @property --colour-primary {
20
+ syntax: "<color>";
21
+ inherits: true;
22
+ initial-value: token("colour.primary.colour");
23
+ }
24
+
25
+ @property --colour-accent {
26
+ syntax: "<color>";
27
+ inherits: true;
28
+ initial-value: token("colour.accent.colour");
29
+ }
30
+
19
31
  @layer design-system.defaults {
20
32
  :root {
21
33
  /* Brand colors */
22
- --colour-primary: token("colour.primary.colour");
23
34
  --colour-primary-light: color-mix(in oklch, var(--colour-primary), white 90%);
24
35
  --colour-primary-lighter: color-mix(in oklch, var(--colour-primary), white 20%);
25
36
  --colour-primary-darker: color-mix(in oklch, var(--colour-primary), black 20%);
26
37
  --colour-primary-dark: color-mix(in oklch, var(--colour-primary), black 40%);
27
38
  --colour-primary-darkest: color-mix(in oklch, var(--colour-primary), black 50%);
28
39
  --colour-primary-scheme: token("colour.primary.scheme");
29
- --colour-accent: token("colour.accent.colour");
30
40
  --colour-accent-light: color-mix(in oklch, var(--colour-accent), white 90%);
31
41
  --colour-accent-lighter: color-mix(in oklch, var(--colour-accent), white 20%);
32
42
  --colour-accent-darker: color-mix(in oklch, var(--colour-accent), black 10%);
package/src/enums.ts CHANGED
@@ -45,11 +45,20 @@ export enum TextStyles {
45
45
  S = "mx-text--s",
46
46
  XS = "mx-text--xs",
47
47
  LEDE = "mx-text--lede",
48
+ META = "mx-text--meta",
48
49
  PRIMARY = "mx-text--primary",
49
50
  ACCENT = "mx-text--accent",
50
51
  ALT = "mx-text--alt",
51
52
  }
52
53
 
54
+ export enum ListStyles {
55
+ NOTES = "mx-list--notes",
56
+ REFS = "mx-list--refs",
57
+ STATS = "mx-list--stats",
58
+ COLUMNS = "mx-list--columns",
59
+ SUMMARY = "mx-list--summary",
60
+ }
61
+
53
62
  export enum Icons {
54
63
  ARROW_DOWN = "arrow-down",
55
64
  ARROW_LEFT = "arrow-left",
@@ -141,6 +150,14 @@ export enum FormStatus {
141
150
  INVALID = "invalid",
142
151
  }
143
152
 
153
+ export enum TagVariants {
154
+ INFO = "info",
155
+ SUCCESS = "success",
156
+ WARNING = "warning",
157
+ ERROR = "error",
158
+ FEATURED = "featured",
159
+ }
160
+
144
161
  export enum TabStyles {
145
162
  DEFAULT = "default",
146
163
  CENTERED = "centered",
package/src/react.ts CHANGED
@@ -40,6 +40,7 @@ export { default as FormItem } from "./Form/FormItem/FormItem"
40
40
  export { default as FormTitle } from "./Form/Form/FormTitle"
41
41
  export { default as Form } from "./Form/Form/Form"
42
42
  export { default as Icon } from "./Atom/Icon/Icon"
43
+ export { default as List } from "./Atom/List/List"
43
44
  export { default as Grid } from "./Layout/Grid/Grid"
44
45
  export { default as Page } from "./Layout/Page/Page"
45
46
  export { default as HeroBanner } from "./Component/HeroBanner/HeroBanner"
@@ -87,8 +88,11 @@ export { default as SideNavigationTree } from "./Component/SideNavigation/Compon
87
88
  export { default as CookieConsent } from "./Component/CookieConsent/CookieConsent"
88
89
  export { default as Gallery } from "./Component/Gallery/Gallery"
89
90
  export { default as GalleryTrigger } from "./Component/Gallery/Components/GalleryTrigger"
91
+ export { default as ProgressIndicator } from "./Component/ProgressIndicator/ProgressIndicator"
90
92
  export { default as FormSearch } from "./Form/Search/FormSearch"
91
93
  export { default as Autocomplete } from "./Form/Autocomplete/Autocomplete"
94
+ export { default as CheckboxCard } from "./Form/CheckboxCard/CheckboxCard"
95
+ export { default as RadioCard } from "./Form/RadioCard/RadioCard"
92
96
  export { default as Masthead } from "./Layout/Masthead/Masthead"
93
97
  export { default as Sidebar } from "./Layout/Sidebar/Sidebar"
94
98
  export { default as Footer } from "./Layout/Footer/Footer"
Binary file
@@ -73,7 +73,7 @@ function collect() {
73
73
  const usages = [] // { className, file, line } | { prefix, suffix, file, line, raw }
74
74
 
75
75
  // postcss-mixins can generate whole class families at build time (e.g.
76
- // `@mixin icon chevron-left;` -> `.mx-icon--chevron-left`) that never
76
+ // `@add-mixin icon chevron-left;` -> `.mx-icon--chevron-left`) that never
77
77
  // appear as literal selector text — collect templates + invocations across
78
78
  // ALL css files first (a definition and its invocations can live in
79
79
  // different files) and synthesize the resulting classes before the normal
@@ -1 +0,0 @@
1
- import{t as e}from"./Popover-De_CQqcd.js";var t=class extends e{controller;closeOnClick;constructor(){super(),this.controller=new AbortController}async connectedCallback(){if(await super.connectedCallback(),!this.container||!this.trigger)return;this.closeOnClick=this.hasAttribute(`closeonclick`);let{signal:e}=this.controller;document.addEventListener(`click`,e=>{let t=e.target,n=t.closest(`a, button`);t!==this.container&&![...this.items].includes(n)||(this.handleSelect(e),e.preventDefault())},{signal:e}),document.addEventListener(`keydown`,e=>{let{target:t,key:n}=e;if(!(t!==this.container&&![...this.items].includes(t)))switch(n){case`Enter`:e.preventDefault(),this.handleSelect(e);break;case`ArrowDown`:case`ArrowRight`:e.preventDefault(),this.moveFocus(t,1);break;case`ArrowUp`:case`ArrowLeft`:e.preventDefault(),this.moveFocus(t,-1)}},{signal:e})}disconnectedCallback(){this.controller.abort()}handleSelect=e=>{let t=e.target;this.items?.forEach(e=>{e instanceof HTMLButtonElement&&e.setAttribute(`aria-checked`,String(e===t))});let n=new CustomEvent(`drop-menu-select`,{bubbles:!0,cancelable:!0,detail:{event:e,target:t}});this.container.dispatchEvent(n),this.closeOnClick&&this.container.togglePopover()};moveFocus=(e,t)=>{let n=[...this.items],r=n.indexOf(e);if(r===-1)return;let i=r;for(let e=0;e<n.length&&(i=(i+t+n.length)%n.length,n[i].getAttribute(`tabindex`)===`-1`);e+=1);n[i]?.focus()};get items(){return this.container.querySelectorAll(`a, button`)}};customElements.get(`mx-dropmenu`)||customElements.define(`mx-dropmenu`,t);export{t};
@@ -1 +0,0 @@
1
- import{s as e,t}from"./utilities-C5dAO2YA.js";var n=class extends HTMLElement{internals_;controller;headingLevels;title;titleClass=`is-excluded mx-heading--m`;items;active;constructor(){super(),this.internals_=this.attachInternals(),this.controller=new AbortController,this.headingLevels=this.dataset?.levels||`h2`,this.title=this.dataset?.title||`On this page`,this.items=[]}connectedCallback(){if(!this.menu||!this.headings)return;if(this.links.length)this.links.forEach(e=>{let t=this.container.querySelector(e.hash);t&&this.items.push({link:e,heading:t})});else{let e=t(`<h2 class="${this.titleClass}">${this.title}</h2>`);this.nav.insertBefore(e,this.menu),this.headings.forEach(e=>{let t=this.generateListItem(e),n=this.generateAnchor(e);this.items.push({link:n,heading:e}),t.appendChild(n),this.menu?.appendChild(t)})}let{signal:e}=this.controller;this.menu.addEventListener(`click`,e=>{let{target:t}=e;t instanceof HTMLAnchorElement&&this.handleClick(t)},{signal:e})}disconnectedCallback(){!this.menu||!this.headings||(this.menu.textContent=``,this.items=[],this.controller.abort())}handleClick=e=>{this.active=this.items.find(t=>t.link===e),!(!this.links||!this.active)&&(this.links.forEach(e=>e.classList.remove(`is-active`)),this.active.link.classList.add(`is-active`))};get menu(){let e=this.querySelector(`ul, ol`);if(e)return e;if(!this.nav)throw Error(`${this.localName} must contain a <nav> element.`);if(this.items?.length===0&&this.headings?.length===0)return null;let t=document.createElement(`ul`);return this.nav.appendChild(t),t}get nav(){return this.querySelector(`nav`)}get container(){let e=this.getAttribute(`data-content`);if(!e)throw Error(`${this.localName} must have a [data-content] attribute that contains the content selector.`);return this.closest(e)||this.parentElement.querySelector(e)||document.querySelector(e)}get headings(){return this.container?.querySelectorAll(`:is(${this.headingLevels}):not(.is-excluded)`)}get links(){return this.menu?.querySelectorAll(`a`)}generatedId(t){let n=t?.textContent?.trim();return n?e(n):``}generateAnchor(e){let{textContent:n,id:r}=e,i=e.getAttribute(`data-in-page-navigation-title`)||n,a=r||this.generatedId(e);return r||(e.id=a),t(`<a href="#${a}"><span class="mx-icon mx-icon--chevron-right"></span><span>${i}</span></a>`)}generateListItem(e){let{tagName:n}=e;return t(`<li class="mx-in-page-navigation__level--${n.toLowerCase()}"></li>`)}};customElements.get(`mx-in-page-navigation`)||customElements.define(`mx-in-page-navigation`,n);export{n as t};
@@ -1 +0,0 @@
1
- var e=class extends HTMLElement{internals_;polyfills;constructor(){super(),this.internals_=this.attachInternals()}async connectedCallback(){if(!(!this.container||!this.trigger)&&(!(`anchorName`in document.documentElement.style)||!(`popover`in HTMLElement.prototype))){let{default:e}=await import(`./polyfills-Dokbkxxk.js`);this.polyfills=new e(this.container)}}disconnectedCallback(){this.polyfills?.destroy()}get container(){let e=this.querySelector(`[popover]`);if(!e)throw Error(`${this.localName} must contain a <div popover> element.`);return e}get trigger(){let e=this.querySelector(`[popovertarget=${this.container?.id}]`);if(!e)throw Error(`${this.localName} must contain a <button popovertarget="${this.container.id}">`);return e}};customElements.get(`mx-popover`)||customElements.define(`mx-popover`,e);export{e as t};
@@ -1 +0,0 @@
1
- import{t as e}from"./utilities-C5dAO2YA.js";var t=class extends HTMLElement{internals_;iO;rO;offsetPropName;root=null;rootMargin=`0px 0px 0px 0px`;thresholds=[0];constructor(){super(),this.internals_=this.attachInternals()}connectedCallback(){this.offsetPropName=this.getAttribute(`offsetpropname`);let e={root:this.root,rootMargin:this.rootMargin,thresholds:this.thresholds};this.iO=new IntersectionObserver(([{boundingClientRect:t}])=>{let n=t.y<0;this.classList.toggle(`is-stuck`,n);let r=new CustomEvent(`sticky-toggle`,{bubbles:!0,cancelable:!0,detail:{isSticky:n,options:e,target:this}});this.dispatchEvent(r)},e),this.iO.observe(this.trigger),this.offsetPropName&&(this.rO=new ResizeObserver(e=>{e.forEach(({borderBoxSize:e})=>{let[{blockSize:t}]=e;document.body.style.setProperty(this.offsetPropName,`${t.toFixed(1)}px`)})}),this.rO.observe(this))}disconnectedCallback(){this.iO.disconnect(),this.rO?.disconnect()}get trigger(){let t=this.querySelector(`.mx-sticky__trigger`);return t||(t=e(`<div class="mx-sticky__trigger"></div>`),this.insertAdjacentElement(`beforebegin`,t)),t}};customElements.get(`mx-sticky`)||customElements.define(`mx-sticky`,t);export{t};
@@ -1 +0,0 @@
1
- var e,t=class{constructor(e){this.popover=e,this.trigger=document.querySelector(`[popovertarget="${e.getAttribute(`id`)}"]`),this.init()}init=async()=>{!this.trigger||!this.popover||(this.supportsPopover()||await this.ensurePopoverPolyfill(),this.supportsAnchor()||(this.controller=new AbortController,this.popover.addEventListener(`toggle`,this.positionPopover,{signal:this.controller.signal})))};supportsAnchor=()=>`anchorName`in document.documentElement.style;supportsPopover=()=>`popover`in HTMLElement.prototype;ensurePopoverPolyfill=()=>(e||=import(`@oddbird/popover-polyfill`),e);positionPopover=async({newState:e})=>{if(e===`open`){let{computePosition:e,flip:t,shift:n}=await import(`@floating-ui/dom`);requestAnimationFrame(()=>{e(this.trigger,this.popover,{placement:this.placement||`top`,middleware:[t({padding:10}),n({padding:10})]}).then(({x:e,y:t})=>{this.popover.style.insetInlineStart=`${e}px`,this.popover.style.insetBlockStart=`${t}px`})})}};destroy(){this.controller.abort()}get placement(){return this.popover.getAttribute(`data-placement`)}};export{t as default};