@arbor-education/design-system.components 0.13.0 → 0.14.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 (232) hide show
  1. package/.agent-memory/blanche-designspert/MEMORY.md +189 -0
  2. package/.agent-memory/dorothy-fact-checker/MEMORY.md +228 -0
  3. package/.agent-memory/dorothy-fact-checker/numberinput_component.md +53 -0
  4. package/.agent-memory/dorothy-fact-checker/progress_component.md +36 -0
  5. package/.agent-memory/rose-storybookspert/MEMORY.md +105 -0
  6. package/.agent-memory/sophia-componentspert/MEMORY.md +34 -0
  7. package/{.claude/agent-memory → .agent-memory}/sophia-componentspert/components.md +170 -17
  8. package/{.claude → .gather}/agents/blanche-designspert.md +7 -2
  9. package/{.claude → .gather}/agents/dorothy-fact-checker.md +7 -2
  10. package/{.claude → .gather}/agents/rose-storybookspert.md +80 -11
  11. package/{.claude → .gather}/agents/sophia-componentspert.md +9 -4
  12. package/.gather/gather.yaml +9 -0
  13. package/{CLAUDE.md → .gather/instructions/project-overview.md} +42 -9
  14. package/{.claude → .gather}/skills/analyze-design/README.md +5 -0
  15. package/{.claude → .gather}/skills/analyze-design/SKILL.md +1 -1
  16. package/.gather/skills/analyze-design/meta.md +4 -0
  17. package/{.claude → .gather}/skills/create-page/README.md +5 -0
  18. package/{.claude → .gather}/skills/create-page/design-analysis-template.md +5 -0
  19. package/.gather/skills/create-page/meta.md +4 -0
  20. package/{.claude → .gather}/skills/create-page/page-template.scss +5 -0
  21. package/{.claude → .gather}/skills/create-page/page-template.tsx +5 -0
  22. package/{.claude → .gather}/skills/map-legacy/README.md +5 -0
  23. package/.gather/skills/map-legacy/meta.md +4 -0
  24. package/{.claude → .gather}/skills/migrate-page/README.md +5 -0
  25. package/.gather/skills/migrate-page/meta.md +4 -0
  26. package/.gather/skills/write-stories/README.md +157 -0
  27. package/.gather/skills/write-stories/SKILL.md +841 -0
  28. package/.gather/skills/write-stories/meta.md +4 -0
  29. package/.ralph/storybook-upgrade/knowledge.md +308 -0
  30. package/.ralph/storybook-upgrade/prd.json +777 -0
  31. package/.ralph/storybook-upgrade/progress.md +342 -0
  32. package/.storybook/DocsTemplate.tsx +122 -0
  33. package/.storybook/preview.ts +40 -0
  34. package/.stylelintignore +2 -0
  35. package/CHANGELOG.md +14 -0
  36. package/{.claude/component-library.md → component-library.md} +27 -10
  37. package/dist/components/articleCard/ArticleCard.d.ts +30 -0
  38. package/dist/components/articleCard/ArticleCard.d.ts.map +1 -0
  39. package/dist/components/articleCard/ArticleCard.js +24 -0
  40. package/dist/components/articleCard/ArticleCard.js.map +1 -0
  41. package/dist/components/articleCard/ArticleCard.stories.d.ts +18 -0
  42. package/dist/components/articleCard/ArticleCard.stories.d.ts.map +1 -0
  43. package/dist/components/articleCard/ArticleCard.stories.js +112 -0
  44. package/dist/components/articleCard/ArticleCard.stories.js.map +1 -0
  45. package/dist/components/articleCard/ArticleCard.test.d.ts +2 -0
  46. package/dist/components/articleCard/ArticleCard.test.d.ts.map +1 -0
  47. package/dist/components/articleCard/ArticleCard.test.js +49 -0
  48. package/dist/components/articleCard/ArticleCard.test.js.map +1 -0
  49. package/dist/components/badge/Badge.stories.d.ts +85 -6
  50. package/dist/components/badge/Badge.stories.d.ts.map +1 -1
  51. package/dist/components/badge/Badge.stories.js +626 -27
  52. package/dist/components/badge/Badge.stories.js.map +1 -1
  53. package/dist/components/banner/Banner.stories.d.ts +129 -63
  54. package/dist/components/banner/Banner.stories.d.ts.map +1 -1
  55. package/dist/components/banner/Banner.stories.js +855 -39
  56. package/dist/components/banner/Banner.stories.js.map +1 -1
  57. package/dist/components/button/Button.stories.d.ts +148 -8
  58. package/dist/components/button/Button.stories.d.ts.map +1 -1
  59. package/dist/components/button/Button.stories.js +1089 -80
  60. package/dist/components/button/Button.stories.js.map +1 -1
  61. package/dist/components/card/Card.d.ts +41 -12
  62. package/dist/components/card/Card.d.ts.map +1 -1
  63. package/dist/components/card/Card.js +46 -17
  64. package/dist/components/card/Card.js.map +1 -1
  65. package/dist/components/card/Card.stories.d.ts +9 -84
  66. package/dist/components/card/Card.stories.d.ts.map +1 -1
  67. package/dist/components/card/Card.stories.js +15 -73
  68. package/dist/components/card/Card.stories.js.map +1 -1
  69. package/dist/components/card/Card.test.js +50 -152
  70. package/dist/components/card/Card.test.js.map +1 -1
  71. package/dist/components/dot/Dot.stories.d.ts +46 -11
  72. package/dist/components/dot/Dot.stories.d.ts.map +1 -1
  73. package/dist/components/dot/Dot.stories.js +504 -15
  74. package/dist/components/dot/Dot.stories.js.map +1 -1
  75. package/dist/components/dropdown/Dropdown.stories.d.ts +89 -14
  76. package/dist/components/dropdown/Dropdown.stories.d.ts.map +1 -1
  77. package/dist/components/dropdown/Dropdown.stories.js +769 -17
  78. package/dist/components/dropdown/Dropdown.stories.js.map +1 -1
  79. package/dist/components/formField/FormField.stories.d.ts +95 -35
  80. package/dist/components/formField/FormField.stories.d.ts.map +1 -1
  81. package/dist/components/formField/FormField.stories.js +1174 -69
  82. package/dist/components/formField/FormField.stories.js.map +1 -1
  83. package/dist/components/formField/inputs/checkbox/CheckboxInput.stories.d.ts +96 -9
  84. package/dist/components/formField/inputs/checkbox/CheckboxInput.stories.d.ts.map +1 -1
  85. package/dist/components/formField/inputs/checkbox/CheckboxInput.stories.js +717 -10
  86. package/dist/components/formField/inputs/checkbox/CheckboxInput.stories.js.map +1 -1
  87. package/dist/components/formField/inputs/number/NumberInput.stories.d.ts +149 -11
  88. package/dist/components/formField/inputs/number/NumberInput.stories.d.ts.map +1 -1
  89. package/dist/components/formField/inputs/number/NumberInput.stories.js +624 -10
  90. package/dist/components/formField/inputs/number/NumberInput.stories.js.map +1 -1
  91. package/dist/components/formField/inputs/radio/RadioButtonInput.stories.d.ts +74 -1
  92. package/dist/components/formField/inputs/radio/RadioButtonInput.stories.d.ts.map +1 -1
  93. package/dist/components/formField/inputs/radio/RadioButtonInput.stories.js +673 -44
  94. package/dist/components/formField/inputs/radio/RadioButtonInput.stories.js.map +1 -1
  95. package/dist/components/formField/inputs/text/TextInput.stories.d.ts +119 -1
  96. package/dist/components/formField/inputs/text/TextInput.stories.d.ts.map +1 -1
  97. package/dist/components/formField/inputs/text/TextInput.stories.js +549 -10
  98. package/dist/components/formField/inputs/text/TextInput.stories.js.map +1 -1
  99. package/dist/components/formField/inputs/textArea/TextArea.stories.d.ts +129 -4
  100. package/dist/components/formField/inputs/textArea/TextArea.stories.d.ts.map +1 -1
  101. package/dist/components/formField/inputs/textArea/TextArea.stories.js +577 -3
  102. package/dist/components/formField/inputs/textArea/TextArea.stories.js.map +1 -1
  103. package/dist/components/formField/inputs/time/TimeInput.d.ts +1 -1
  104. package/dist/components/formField/inputs/time/TimeInput.stories.d.ts +1 -1
  105. package/dist/components/heading/Heading.stories.d.ts +449 -50
  106. package/dist/components/heading/Heading.stories.d.ts.map +1 -1
  107. package/dist/components/heading/Heading.stories.js +536 -60
  108. package/dist/components/heading/Heading.stories.js.map +1 -1
  109. package/dist/components/icoText/IcoText.d.ts +37 -0
  110. package/dist/components/icoText/IcoText.d.ts.map +1 -0
  111. package/dist/components/icoText/IcoText.js +29 -0
  112. package/dist/components/icoText/IcoText.js.map +1 -0
  113. package/dist/components/icoText/IcoText.stories.d.ts +34 -0
  114. package/dist/components/icoText/IcoText.stories.d.ts.map +1 -0
  115. package/dist/components/icoText/IcoText.stories.js +24 -0
  116. package/dist/components/icoText/IcoText.stories.js.map +1 -0
  117. package/dist/components/icoText/IcoText.test.d.ts +2 -0
  118. package/dist/components/icoText/IcoText.test.d.ts.map +1 -0
  119. package/dist/components/icoText/IcoText.test.js +27 -0
  120. package/dist/components/icoText/IcoText.test.js.map +1 -0
  121. package/dist/components/icon/Icon.stories.d.ts +81 -10
  122. package/dist/components/icon/Icon.stories.d.ts.map +1 -1
  123. package/dist/components/icon/Icon.stories.js +979 -8
  124. package/dist/components/icon/Icon.stories.js.map +1 -1
  125. package/dist/components/kpiCard/KPICard.d.ts +13 -0
  126. package/dist/components/kpiCard/KPICard.d.ts.map +1 -0
  127. package/dist/components/kpiCard/KPICard.js +8 -0
  128. package/dist/components/kpiCard/KPICard.js.map +1 -0
  129. package/dist/components/kpiCard/KPICard.stories.d.ts +9 -0
  130. package/dist/components/kpiCard/KPICard.stories.d.ts.map +1 -0
  131. package/dist/components/kpiCard/KPICard.stories.js +18 -0
  132. package/dist/components/kpiCard/KPICard.stories.js.map +1 -0
  133. package/dist/components/kpiCard/KPICard.test.d.ts +2 -0
  134. package/dist/components/kpiCard/KPICard.test.d.ts.map +1 -0
  135. package/dist/components/kpiCard/KPICard.test.js +37 -0
  136. package/dist/components/kpiCard/KPICard.test.js.map +1 -0
  137. package/dist/components/kvpList/KVPList.d.ts +34 -0
  138. package/dist/components/kvpList/KVPList.d.ts.map +1 -0
  139. package/dist/components/kvpList/KVPList.js +20 -0
  140. package/dist/components/kvpList/KVPList.js.map +1 -0
  141. package/dist/components/kvpList/KVPList.stories.d.ts +27 -0
  142. package/dist/components/kvpList/KVPList.stories.d.ts.map +1 -0
  143. package/dist/components/kvpList/KVPList.stories.js +18 -0
  144. package/dist/components/kvpList/KVPList.stories.js.map +1 -0
  145. package/dist/components/kvpList/KVPList.test.d.ts +2 -0
  146. package/dist/components/kvpList/KVPList.test.d.ts.map +1 -0
  147. package/dist/components/kvpList/KVPList.test.js +29 -0
  148. package/dist/components/kvpList/KVPList.test.js.map +1 -0
  149. package/dist/components/pill/Pill.stories.d.ts +71 -19
  150. package/dist/components/pill/Pill.stories.d.ts.map +1 -1
  151. package/dist/components/pill/Pill.stories.js +573 -14
  152. package/dist/components/pill/Pill.stories.js.map +1 -1
  153. package/dist/components/progress/Progress.stories.d.ts +75 -298
  154. package/dist/components/progress/Progress.stories.d.ts.map +1 -1
  155. package/dist/components/progress/Progress.stories.js +449 -52
  156. package/dist/components/progress/Progress.stories.js.map +1 -1
  157. package/dist/components/separator/Separator.stories.d.ts +58 -5
  158. package/dist/components/separator/Separator.stories.d.ts.map +1 -1
  159. package/dist/components/separator/Separator.stories.js +443 -4
  160. package/dist/components/separator/Separator.stories.js.map +1 -1
  161. package/dist/components/singleUser/SingleUser.d.ts +1 -1
  162. package/dist/components/tabs/TabsItem.stories.d.ts +2 -2
  163. package/dist/components/tag/Tag.stories.d.ts +116 -5
  164. package/dist/components/tag/Tag.stories.d.ts.map +1 -1
  165. package/dist/components/tag/Tag.stories.js +581 -28
  166. package/dist/components/tag/Tag.stories.js.map +1 -1
  167. package/dist/index.css +194 -23
  168. package/dist/index.css.map +1 -1
  169. package/dist/index.d.ts +13 -4
  170. package/dist/index.d.ts.map +1 -1
  171. package/dist/index.js +12 -3
  172. package/dist/index.js.map +1 -1
  173. package/eslint.config.mts +5 -1
  174. package/package.json +3 -3
  175. package/src/components/articleCard/ArticleCard.stories.tsx +132 -0
  176. package/src/components/articleCard/ArticleCard.test.tsx +121 -0
  177. package/src/components/articleCard/ArticleCard.tsx +100 -0
  178. package/src/components/articleCard/articleCard.scss +39 -0
  179. package/src/components/badge/Badge.stories.tsx +869 -42
  180. package/src/components/banner/Banner.stories.tsx +1081 -63
  181. package/src/components/button/Button.stories.tsx +1394 -99
  182. package/src/components/card/Card.stories.tsx +35 -79
  183. package/src/components/card/Card.test.tsx +72 -190
  184. package/src/components/card/Card.tsx +117 -58
  185. package/src/components/card/card.scss +18 -31
  186. package/src/components/dot/Dot.stories.tsx +723 -32
  187. package/src/components/dropdown/Dropdown.stories.tsx +1174 -35
  188. package/src/components/formField/FormField.stories.tsx +1522 -105
  189. package/src/components/formField/inputs/checkbox/CheckboxInput.stories.tsx +1020 -15
  190. package/src/components/formField/inputs/number/NumberInput.stories.tsx +908 -15
  191. package/src/components/formField/inputs/radio/RadioButtonInput.stories.tsx +932 -51
  192. package/src/components/formField/inputs/text/TextInput.stories.tsx +773 -13
  193. package/src/components/formField/inputs/textArea/TextArea.stories.tsx +756 -8
  194. package/src/components/heading/Heading.stories.tsx +752 -120
  195. package/src/components/icoText/IcoText.stories.tsx +47 -0
  196. package/src/components/icoText/IcoText.test.tsx +41 -0
  197. package/src/components/icoText/IcoText.tsx +93 -0
  198. package/src/components/icoText/icoText.scss +34 -0
  199. package/src/components/icon/Icon.stories.tsx +1446 -12
  200. package/src/components/kpiCard/KPICard.stories.tsx +47 -0
  201. package/src/components/kpiCard/KPICard.test.tsx +60 -0
  202. package/src/components/kpiCard/KPICard.tsx +45 -0
  203. package/src/components/kpiCard/kpiCard.scss +35 -0
  204. package/src/components/kvpList/KVPList.stories.tsx +51 -0
  205. package/src/components/kvpList/KVPList.test.tsx +66 -0
  206. package/src/components/kvpList/KVPList.tsx +109 -0
  207. package/src/components/kvpList/kvpList.scss +64 -0
  208. package/src/components/pill/Pill.stories.tsx +867 -21
  209. package/src/components/progress/Progress.stories.tsx +625 -58
  210. package/src/components/separator/Separator.stories.tsx +730 -8
  211. package/src/components/separator/separator.scss +12 -3
  212. package/src/components/tag/Tag.stories.tsx +755 -53
  213. package/src/index.scss +4 -0
  214. package/src/index.ts +13 -4
  215. package/src/tokens.scss +6 -0
  216. package/tokens/json/Arbor.json +30 -0
  217. package/.claude/agent-memory/blanche-designspert/MEMORY.md +0 -64
  218. package/.claude/agent-memory/dorothy-fact-checker/MEMORY.md +0 -129
  219. package/.claude/agent-memory/rose-storybookspert/MEMORY.md +0 -29
  220. package/.claude/agent-memory/sophia-componentspert/MEMORY.md +0 -14
  221. package/.claude/design-assessment-daily-attendance-2026-04-10.md +0 -566
  222. package/.claude/figma-assessment-7154-58899.md +0 -404
  223. package/.claude/figma-assessment-UKQfcxnT4rlHHNuiumt4o1-11086-97537.md +0 -392
  224. package/.claude/figma-assessment-UKQfcxnT4rlHHNuiumt4o1-551-41974.md +0 -474
  225. package/.claude/figma-assessment-UKQfcxnT4rlHHNuiumt4o1-551-43094.md +0 -462
  226. package/.claude/figma-assessment-fcFK4CGzkz2fVyY3koX8ZE-7154-59061.md +0 -440
  227. package/.claude/migration-report-custom-report-writer-2026-02-19.md +0 -591
  228. /package/{.claude/agent-memory → .agent-memory}/blanche-designspert/token-review-patterns.md +0 -0
  229. /package/{.claude/agent-memory → .agent-memory}/rose-storybookspert/patterns.md +0 -0
  230. /package/{.claude → .gather}/skills/create-page/SKILL.md +0 -0
  231. /package/{.claude → .gather}/skills/map-legacy/SKILL.md +0 -0
  232. /package/{.claude → .gather}/skills/migrate-page/SKILL.md +0 -0
@@ -2,7 +2,7 @@
2
2
 
3
3
  > Auto-generated reference for AI agents (Sophia, analyze-design, etc.)
4
4
  > Source: `src/components/` · Public API: `src/index.ts`
5
- > Last updated: 2026-04-17
5
+ > Last updated: 2026-04-22
6
6
 
7
7
  ---
8
8
 
@@ -331,7 +331,7 @@ Component-scoped tokens follow: `--{component}-{state}-{property}` (e.g. `--butt
331
331
 
332
332
  ### 9. FormField
333
333
 
334
- **File:** `src/components/formField/FormField.tsx` · **Public export:** No (internal)
334
+ **File:** `src/components/formField/FormField.tsx` · **Public export:** Yes
335
335
 
336
336
  **Use case:** Complete form field wrapper combining label, description, input, error text, and helper link. The preferred way to render any form input with consistent layout and accessibility wiring.
337
337
 
@@ -339,7 +339,7 @@ Component-scoped tokens follow: `--{component}-{state}-{property}` (e.g. `--butt
339
339
  |---|---|---|---|---|
340
340
  | `label` | `string` | No | — | Field label |
341
341
  | `id` | `string` | No | — | Associates label and input |
342
- | `inputType` | `'text' \| 'textarea' \| 'number' \| 'colourPicker' \| 'selectDropdown' \| 'datePicker'` | No | `'text'` | Which input to render |
342
+ | `inputType` | `'text' \| 'textarea' \| 'number' \| 'time' \| 'colourPicker' \| 'selectDropdown' \| 'datePicker' \| 'combobox'` | No | `'text'` | Which input to render |
343
343
  | `inputProps` | Varies by `inputType` | No | — | Props forwarded to the input |
344
344
  | `fieldDescription` | `ReactNode` | No | — | Descriptive text below label |
345
345
  | `helperLinkText` | `string` | No | — | Helper link label |
@@ -742,7 +742,7 @@ Component-scoped tokens follow: `--{component}-{state}-{property}` (e.g. `--butt
742
742
  ### 30. Table
743
743
 
744
744
  **File:** `src/components/table/Table.tsx` · **Public export:** Yes
745
- **Also exports:** `GridApiContext`, `DSDefaultColDef`, `DefaultCellRenderer`, `BooleanCellRenderer`
745
+ **Also exports:** `GridApiContext`, `DSDefaultColDef`, `DefaultCellRenderer`, `BooleanCellRenderer`, `CheckboxCellRenderer`, `TableSettingsContext`, `TABLE_SPACING`
746
746
 
747
747
  **Use case:** Full-featured enterprise data grid wrapping AG Grid Enterprise with design system theming, search, pagination, column visibility, bulk actions, row selection, and table settings — all pre-wired.
748
748
 
@@ -772,12 +772,14 @@ Component-scoped tokens follow: `--{component}-{state}-{property}` (e.g. `--butt
772
772
  | `Table.HideColumnsDropdown` | Multi-select to toggle column visibility |
773
773
  | `Table.ButtonCellRenderer` | Renders a `Button` in a cell (ref: `dsButtonCellRenderer`) |
774
774
  | `Table.TableSettingsDropdown` | Settings dropdown (spacing, borders, cell colors) |
775
+ | `Table.TableControls` | Composed header bar: search, bulk actions, hide columns, settings, undo/redo, expand, download, help — all wired up |
775
776
 
776
777
  **Auto-registered cell renderers:**
777
778
  - `dsButtonCellRenderer` → `ButtonCellRenderer`
778
779
  - `dsInlineTextCellRenderer` → `InlineTextCellRenderer` (editable text in cell)
779
780
  - `dsSelectDropdownCellRenderer` → `SelectDropdownCellRenderer` (dropdown in cell)
780
781
  - `dsBooleanCellRenderer` → `BooleanCellRenderer` (check-solid icon for `true`, x-solid for `false`, null otherwise; also exported directly as `BooleanCellRenderer`)
782
+ - `dsCheckboxCellRenderer` → `CheckboxCellRenderer` (checkbox for editable boolean cells; also exported directly as `CheckboxCellRenderer`)
781
783
 
782
784
  **Auto-registered column filters:**
783
785
  - `dsBooleanFilter` → `BooleanFilter`
@@ -819,18 +821,32 @@ Component-scoped tokens follow: `--{component}-{state}-{property}` (e.g. `--butt
819
821
  ### 32. Tag
820
822
 
821
823
  **File:** `src/components/tag/Tag.tsx` · **Public export:** Yes
824
+ **Also exports:** `TagColor`, `TagProps` types
822
825
 
823
- **Use case:** Non-interactive label/badge for categorization, status indicators, or metadata display.
826
+ **Use case:** Non-interactive label for metadata, categories, and status indicators. Used standalone for purely informational display; also used inside Combobox as removable selection chips (the only legitimate use of `onRemove`).
827
+
828
+ > **MANIFEST CORRECTION (2026-04-17):** Component was rewritten. Old props `text` (string), `dotColour` are GONE. Current API uses `children` (ReactNode) + `slotStart`/`slotEnd` for slot composition.
824
829
 
825
830
  | Prop | Type | Required | Default | Description |
826
831
  |---|---|---|---|---|
827
- | `text` | `string` | Yes | — | Tag label |
832
+ | `children` | `ReactNode` | Yes | — | Tag label content |
828
833
  | `color` | `TagColor` | No | `'neutral'` | Color variant |
829
- | `dotColour` | `DotColour` | No | | Optional colored dot prefix |
834
+ | `selected` | `boolean` | No | `false` | Selected state overrides colour bg/border with selection tokens |
835
+ | `slotStart` | `ReactNode` | No | — | Leading slot (e.g. Dot, Icon, Avatar) |
836
+ | `slotEnd` | `ReactNode` | No | — | Trailing slot (e.g. chevron, badge count) |
837
+ | `onRemove` | `() => void` | No | — | When provided, renders an X remove button. FOR COMPOSITE CONTEXTS ONLY (e.g. Combobox selection chips). Do not use for standalone tags. |
838
+ | `removeLabel` | `string` | No | `'Remove'` | Accessible aria-label for the remove button |
839
+ | `removeButtonTabIndex` | `0 \| -1` | No | `0` | Pass `-1` when a composite parent (e.g. Combobox) manages focus with roving tabindex |
830
840
 
831
841
  **`TagColor` values:** `'neutral'` · `'orange'` · `'blue'` · `'green'` · `'purple'` · `'teal'` · `'salmon'` · `'yellow'`
832
842
 
833
- **`DotColour` values:** `'purple'` · `'salmon'` · `'teal'` · `'yellow'` · `'green'` · `'orange'` · `'blue'`
843
+ **Key behaviours:**
844
+ - Renders as `<span>` — no interactive role; non-interactive tags have no keyboard focus
845
+ - `selected` state overrides `color` bg/border with `--tag-selected-color-background/border` tokens; text remains neutral colour
846
+ - Label (`ds-tag__label`) has `max-width: 100%`, `white-space: nowrap`, `overflow: hidden`, `text-overflow: ellipsis`
847
+ - `slotStart` = canonical way to prefix a Dot (replace old `dotColour` prop) or Icon
848
+ - Remove button: `aria-label={removeLabel}`, `e.stopPropagation()` on click, uses `Icon name="x" size={12}`
849
+ - Dot in `slotStart` is `aria-hidden` when no `label` prop passed to Dot
834
850
 
835
851
  **Key features:**
836
852
  - Purely presentational `<span>` — no click handling
@@ -1052,9 +1068,10 @@ Component-scoped tokens follow: `--{component}-{state}-{property}` (e.g. `--butt
1052
1068
  | `DefaultCellRenderer` | `src/components/table/cellRenderers/DefaultCellRenderer.tsx` | Standard AG Grid cell renderer |
1053
1069
  | `BooleanCellRenderer` | `src/components/table/cellRenderers/BooleanCellRenderer.tsx` | Shows check icon (true), x icon (false), or null — also registered as `'dsBooleanCellRenderer'` string |
1054
1070
 
1071
+ | `PopupParentContext` | `src/utils/PopupParentContext.ts` | React context (`RefObject<HTMLElement \| null>`) controlling where portal-based floating elements render. Default: `getDefaultPopupParent()`. Consumed by Dropdown, Modal, Tooltip, DatePicker, DateTimePicker, Combobox, UserDropdown, SlideoverManager, and Table column filters (TimeFilter, BooleanFilter). Wrap with `<PopupParentContext.Provider value={containerRef}>` when floating elements are inside containers with `overflow: hidden` or custom z-index stacking contexts. |
1072
+
1055
1073
  **Not exported but notable:**
1056
1074
  - `ModalUtils` — `addModal()`, `removeModal()`, `removeAllModals()` (mount `ModalManager` to use)
1057
- - `PopupParentContext` — React context for portal container (used by Modal, Slideover, Dropdown, Tooltip, DatePicker)
1058
1075
  - `PubSub` — lightweight pub/subscribe for imperative modal/slideover control
1059
1076
 
1060
1077
  ---
@@ -1073,7 +1090,7 @@ Component-scoped tokens follow: `--{component}-{state}-{property}` (e.g. `--butt
1073
1090
  | `DatePicker` | Yes | any date-fns format; error state | Radix Popover, react-day-picker |
1074
1091
  | `Dropdown` | Yes | compound: Trigger/Content/Item/SelectItem/Separator/Group | Radix DropdownMenu |
1075
1092
  | `EditableText` | Yes | single-line/multiline; controlled editing | — |
1076
- | `FormField` | No | 6 inputType values; error/helper/description | — |
1093
+ | `FormField` | Yes | 8 inputType values; error/helper/description; sharedProps a11y wiring | — |
1077
1094
  | `Fieldset` | Yes | with/without legend; native disabled | — |
1078
1095
  | `TextInput` | Yes | size: M/S; error state | — |
1079
1096
  | `TextArea` | Yes | autoSize; error state | — |
@@ -0,0 +1,30 @@
1
+ import type { IcoTextIconProps } from '../icoText/IcoText';
2
+ import type { TagColor } from '../tag/Tag';
3
+ import type { IconName } from '../icon/allowedIcons';
4
+ import { Card } from '../card/Card';
5
+ type ArticleCardBaseProps = {
6
+ className?: string;
7
+ paragraph?: React.ReactNode;
8
+ icon?: IconName;
9
+ iconColor?: IcoTextIconProps['color'];
10
+ disabled?: boolean;
11
+ tagText?: string;
12
+ tagColor?: TagColor;
13
+ iconScreenReaderText?: string;
14
+ };
15
+ type ArticleCardLinkedProps = {
16
+ 'href': string;
17
+ 'title': React.ReactNode;
18
+ 'onClick'?: undefined;
19
+ 'onKeyDown'?: undefined;
20
+ 'aria-label'?: string;
21
+ 'aria-labelledby'?: string;
22
+ };
23
+ type ArticleCardCardShellProps = {
24
+ href?: undefined;
25
+ title?: React.ReactNode;
26
+ } & Card.InteractionProps;
27
+ export type ArticleCardProps = ArticleCardBaseProps & (ArticleCardLinkedProps | ArticleCardCardShellProps);
28
+ export declare const ArticleCard: (props: ArticleCardProps) => React.JSX.Element;
29
+ export {};
30
+ //# sourceMappingURL=ArticleCard.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ArticleCard.d.ts","sourceRoot":"","sources":["../../../src/components/articleCard/ArticleCard.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AACnE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAEnD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,8BAA8B,CAAC;AAC7D,OAAO,EAAE,IAAI,EAA2B,MAAM,sBAAsB,CAAC;AAGrE,KAAK,oBAAoB,GAAG;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC5B,IAAI,CAAC,EAAE,QAAQ,CAAC;IAChB,SAAS,CAAC,EAAE,gBAAgB,CAAC,OAAO,CAAC,CAAC;IACtC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB,oBAAoB,CAAC,EAAE,MAAM,CAAC;CAC/B,CAAC;AAEF,KAAK,sBAAsB,GAAG;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,KAAK,CAAC,SAAS,CAAC;IACzB,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB,WAAW,CAAC,EAAE,SAAS,CAAC;IACxB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B,CAAC;AAEF,KAAK,yBAAyB,GAAG;IAC/B,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,KAAK,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CACzB,GAAG,IAAI,CAAC,gBAAgB,CAAC;AAE1B,MAAM,MAAM,gBAAgB,GAAG,oBAAoB,GAAG,CAAC,sBAAsB,GAAG,yBAAyB,CAAC,CAAC;AAE3G,eAAO,MAAM,WAAW,GAAI,OAAO,gBAAgB,KAAG,KAAK,CAAC,GAAG,CAAC,OAgE/D,CAAC"}
@@ -0,0 +1,24 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import classNames from 'classnames';
3
+ import { Tag } from '../tag/Tag';
4
+ import { Card, getCardInteractionProps } from '../card/Card';
5
+ import { IcoText } from '../icoText/IcoText';
6
+ export const ArticleCard = (props) => {
7
+ const { className, href, title, paragraph, icon, iconColor, iconScreenReaderText, disabled = false, tagText, tagColor, } = props;
8
+ const hasPrimaryLink = Boolean(href && title && !disabled);
9
+ const cardClassName = classNames({
10
+ 'ds-card__container--article-link': hasPrimaryLink,
11
+ }, className);
12
+ const cardInteractionProps = hasPrimaryLink
13
+ ? getCardInteractionProps({
14
+ 'onKeyDown': undefined,
15
+ 'aria-label': props['aria-label'],
16
+ 'aria-labelledby': props['aria-labelledby'],
17
+ })
18
+ : getCardInteractionProps(props);
19
+ const content = (_jsx("article", { className: "ds-article-card", children: _jsxs(IcoText, { children: [icon && (_jsx(IcoText.Icon, { color: iconColor, name: icon, screenReaderText: iconScreenReaderText })), title && (_jsx(IcoText.Heading, { children: hasPrimaryLink
20
+ ? (_jsx("a", { className: "ds-article-card__primary-link", href: href, children: title }))
21
+ : title })), paragraph && _jsx(IcoText.Paragraph, { children: paragraph }), tagText && _jsx(Tag, { color: tagColor, children: tagText })] }) }));
22
+ return (_jsx(Card, { ...cardInteractionProps, className: cardClassName, disabled: disabled, spacing: "default", children: content }));
23
+ };
24
+ //# sourceMappingURL=ArticleCard.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ArticleCard.js","sourceRoot":"","sources":["../../../src/components/articleCard/ArticleCard.tsx"],"names":[],"mappings":";AAAA,OAAO,UAAU,MAAM,YAAY,CAAC;AAGpC,OAAO,EAAE,GAAG,EAAE,MAAM,oBAAoB,CAAC;AAEzC,OAAO,EAAE,IAAI,EAAE,uBAAuB,EAAE,MAAM,sBAAsB,CAAC;AACrE,OAAO,EAAE,OAAO,EAAE,MAAM,4BAA4B,CAAC;AA6BrD,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,KAAuB,EAAqB,EAAE;IACxE,MAAM,EACJ,SAAS,EACT,IAAI,EACJ,KAAK,EACL,SAAS,EACT,IAAI,EACJ,SAAS,EACT,oBAAoB,EACpB,QAAQ,GAAG,KAAK,EAChB,OAAO,EACP,QAAQ,GACT,GAAG,KAAK,CAAC;IACV,MAAM,cAAc,GAAG,OAAO,CAAC,IAAI,IAAI,KAAK,IAAI,CAAC,QAAQ,CAAC,CAAC;IAE3D,MAAM,aAAa,GAAG,UAAU,CAAC;QAC/B,kCAAkC,EAAE,cAAc;KACnD,EAAE,SAAS,CAAC,CAAC;IAEd,MAAM,oBAAoB,GAAG,cAAc;QACzC,CAAC,CAAC,uBAAuB,CAAC;YACtB,WAAW,EAAE,SAAS;YACtB,YAAY,EAAE,KAAK,CAAC,YAAY,CAAC;YACjC,iBAAiB,EAAE,KAAK,CAAC,iBAAiB,CAAC;SAC5C,CAAC;QACJ,CAAC,CAAC,uBAAuB,CAAC,KAAK,CAAC,CAAC;IAEnC,MAAM,OAAO,GAAG,CACd,kBAAS,SAAS,EAAC,iBAAiB,YAClC,MAAC,OAAO,eACL,IAAI,IAAI,CACP,KAAC,OAAO,CAAC,IAAI,IACX,KAAK,EAAE,SAAS,EAChB,IAAI,EAAE,IAAI,EACV,gBAAgB,EAAE,oBAAoB,GACtC,CACH,EACA,KAAK,IAAI,CACR,KAAC,OAAO,CAAC,OAAO,cACb,cAAc;wBACb,CAAC,CAAC,CACE,YAAG,SAAS,EAAC,+BAA+B,EAAC,IAAI,EAAE,IAAI,YACpD,KAAK,GACJ,CACL;wBACH,CAAC,CAAC,KAAK,GACO,CACnB,EACA,SAAS,IAAI,KAAC,OAAO,CAAC,SAAS,cAAE,SAAS,GAAqB,EAC/D,OAAO,IAAI,KAAC,GAAG,IAAC,KAAK,EAAE,QAAQ,YAAG,OAAO,GAAO,IACzC,GACF,CACX,CAAC;IAEF,OAAO,CACL,KAAC,IAAI,OACC,oBAAoB,EACxB,SAAS,EAAE,aAAa,EACxB,QAAQ,EAAE,QAAQ,EAClB,OAAO,EAAC,SAAS,YAEhB,OAAO,GACH,CACR,CAAC;AACJ,CAAC,CAAC"}
@@ -0,0 +1,18 @@
1
+ import type { StoryObj } from '@storybook/react-vite';
2
+ declare const meta: {
3
+ title: string;
4
+ component: (props: import("./ArticleCard").ArticleCardProps) => React.JSX.Element;
5
+ };
6
+ type Story = StoryObj<typeof meta>;
7
+ export declare const CardWithTitleAndParagraph: Story;
8
+ export declare const CardWithTitleParagraphAndIcon: Story;
9
+ export declare const TheEverythingCard: Story;
10
+ export declare const CardWithTitleParagraphAndTag: Story;
11
+ export declare const CardWithTitleAndIcon: Story;
12
+ export declare const CardWithParagraph: Story;
13
+ export declare const ClickableDisabledCard: Story;
14
+ export declare const UnclickableCard: Story;
15
+ export declare const TextOnly: Story;
16
+ export declare const LinkedArticle: Story;
17
+ export default meta;
18
+ //# sourceMappingURL=ArticleCard.stories.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ArticleCard.stories.d.ts","sourceRoot":"","sources":["../../../src/components/articleCard/ArticleCard.stories.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAQ,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAI5D,QAAA,MAAM,IAAI;;;CAG0B,CAAC;AAErC,KAAK,KAAK,GAAG,QAAQ,CAAC,OAAO,IAAI,CAAC,CAAC;AAEnC,eAAO,MAAM,yBAAyB,EAAE,KASvC,CAAC;AAEF,eAAO,MAAM,6BAA6B,EAAE,KAU3C,CAAC;AAEF,eAAO,MAAM,iBAAiB,EAAE,KAY/B,CAAC;AAEF,eAAO,MAAM,4BAA4B,EAAE,KAW1C,CAAC;AAEF,eAAO,MAAM,oBAAoB,EAAE,KASlC,CAAC;AAEF,eAAO,MAAM,iBAAiB,EAAE,KAQ/B,CAAC;AAEF,eAAO,MAAM,qBAAqB,EAAE,KAYnC,CAAC;AAEF,eAAO,MAAM,eAAe,EAAE,KAQ7B,CAAC;AAEF,eAAO,MAAM,QAAQ,EAAE,KAKtB,CAAC;AAEF,eAAO,MAAM,aAAa,EAAE,KAgB3B,CAAC;AAEF,eAAe,IAAI,CAAC"}
@@ -0,0 +1,112 @@
1
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { fn } from 'storybook/test';
3
+ import { ArticleCard } from './ArticleCard';
4
+ const meta = {
5
+ title: 'Components/Card/ArticleCard',
6
+ component: ArticleCard,
7
+ };
8
+ export const CardWithTitleAndParagraph = {
9
+ args: {
10
+ 'title': 'Title of Card',
11
+ 'paragraph': 'Lorem ipsum dolor sit amet consectetur adipiscing elit.',
12
+ 'disabled': false,
13
+ 'onClick': fn(),
14
+ 'onKeyDown': fn(),
15
+ 'aria-label': 'Clickable article card with title and paragraph',
16
+ },
17
+ };
18
+ export const CardWithTitleParagraphAndIcon = {
19
+ args: {
20
+ 'title': 'Title of Card',
21
+ 'paragraph': 'Lorem ipsum dolor sit amet consectetur adipiscing elit.',
22
+ 'icon': 'eye',
23
+ 'disabled': false,
24
+ 'onClick': fn(),
25
+ 'onKeyDown': fn(),
26
+ 'aria-label': 'Clickable article card with title paragraph and icon',
27
+ },
28
+ };
29
+ export const TheEverythingCard = {
30
+ args: {
31
+ 'title': 'Title of Card',
32
+ 'paragraph': 'Lorem ipsum dolor sit amet consectetur adipiscing elit.',
33
+ 'icon': 'eye',
34
+ 'disabled': false,
35
+ 'tagText': 'argle bargle',
36
+ 'tagColor': 'orange',
37
+ 'onClick': fn(),
38
+ 'onKeyDown': fn(),
39
+ 'aria-label': 'Clickable article card with all content',
40
+ },
41
+ };
42
+ export const CardWithTitleParagraphAndTag = {
43
+ args: {
44
+ 'title': 'Title of Card',
45
+ 'paragraph': 'Lorem ipsum dolor sit amet consectetur adipiscing elit.',
46
+ 'disabled': false,
47
+ 'tagText': 'argle bargle',
48
+ 'tagColor': 'orange',
49
+ 'onClick': fn(),
50
+ 'onKeyDown': fn(),
51
+ 'aria-label': 'Clickable article card with title paragraph and tag',
52
+ },
53
+ };
54
+ export const CardWithTitleAndIcon = {
55
+ args: {
56
+ 'title': 'Title of Card',
57
+ 'icon': 'eye',
58
+ 'disabled': false,
59
+ 'onClick': fn(),
60
+ 'onKeyDown': fn(),
61
+ 'aria-label': 'Clickable article card with title and icon',
62
+ },
63
+ };
64
+ export const CardWithParagraph = {
65
+ args: {
66
+ 'paragraph': 'Lorem ipsum dolor sit amet consectetur adipiscing elit.',
67
+ 'disabled': false,
68
+ 'onClick': fn(),
69
+ 'onKeyDown': fn(),
70
+ 'aria-label': 'Clickable article card with paragraph',
71
+ },
72
+ };
73
+ export const ClickableDisabledCard = {
74
+ args: {
75
+ 'title': 'Title of Card',
76
+ 'paragraph': 'Lorem ipsum dolor sit amet consectetur adipiscing elit.',
77
+ 'icon': 'eye',
78
+ 'tagText': 'argle bargle',
79
+ 'tagColor': 'orange',
80
+ 'disabled': true,
81
+ 'onClick': fn(),
82
+ 'onKeyDown': fn(),
83
+ 'aria-label': 'Disabled clickable article card',
84
+ },
85
+ };
86
+ export const UnclickableCard = {
87
+ args: {
88
+ title: 'Title of Card',
89
+ paragraph: 'Lorem ipsum dolor sit amet consectetur adipiscing elit.',
90
+ icon: 'eye',
91
+ tagText: 'argle bargle',
92
+ tagColor: 'orange',
93
+ },
94
+ };
95
+ export const TextOnly = {
96
+ args: {
97
+ title: 'Text-only article card',
98
+ paragraph: 'A compact way to present article-style content in the shared shell.',
99
+ },
100
+ };
101
+ export const LinkedArticle = {
102
+ args: {
103
+ title: 'Primary article link',
104
+ href: '/articles/primary-article-link',
105
+ paragraph: (_jsxs(_Fragment, { children: ["Read the full article or visit the", ' ', _jsx("a", { href: "/authors/design-system", children: "author page" }), "."] })),
106
+ icon: 'eye',
107
+ tagText: 'Featured',
108
+ tagColor: 'green',
109
+ },
110
+ };
111
+ export default meta;
112
+ //# sourceMappingURL=ArticleCard.stories.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ArticleCard.stories.js","sourceRoot":"","sources":["../../../src/components/articleCard/ArticleCard.stories.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import '@testing-library/jest-dom/vitest';
2
+ //# sourceMappingURL=ArticleCard.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ArticleCard.test.d.ts","sourceRoot":"","sources":["../../../src/components/articleCard/ArticleCard.test.tsx"],"names":[],"mappings":"AACA,OAAO,kCAAkC,CAAC"}
@@ -0,0 +1,49 @@
1
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { fireEvent, render, screen } from '@testing-library/react';
3
+ import '@testing-library/jest-dom/vitest';
4
+ import { describe, expect, test, vi } from 'vitest';
5
+ import { ArticleCard } from './ArticleCard';
6
+ describe('ArticleCard', () => {
7
+ test('renders the legacy card content composition', () => {
8
+ const { container } = render(_jsx(ArticleCard, { icon: "eye", paragraph: "Helpful supporting copy", tagColor: "green", tagText: "Live", title: "Article summary" }));
9
+ expect(screen.getByRole('article')).toBeInTheDocument();
10
+ expect(screen.getByRole('heading', { level: 4 })).toHaveTextContent('Article summary');
11
+ expect(screen.getByText('Helpful supporting copy')).toBeInTheDocument();
12
+ expect(screen.getByText('Live')).toBeInTheDocument();
13
+ expect(container.querySelector('.ds-icon-eye')).toBeInTheDocument();
14
+ });
15
+ test('renders content without an icon', () => {
16
+ const { container } = render(_jsx(ArticleCard, { paragraph: "Helpful supporting copy", title: "Article summary" }));
17
+ expect(screen.getByRole('heading', { level: 4 })).toHaveTextContent('Article summary');
18
+ expect(container.querySelector('.ds-ico-text__icon')).not.toBeInTheDocument();
19
+ });
20
+ test('renders a tag when provided', () => {
21
+ render(_jsx(ArticleCard, { paragraph: "Helpful supporting copy", tagColor: "orange", tagText: "Pinned", title: "Article summary" }));
22
+ expect(screen.getByText('Pinned')).toBeInTheDocument();
23
+ });
24
+ test('renders a primary title link without button semantics when href is provided', () => {
25
+ const { container } = render(_jsx(ArticleCard, { href: "/articles/linked-article", paragraph: (_jsxs(_Fragment, { children: ["By", ' ', _jsx("a", { href: "/authors/design-system", children: "Design System Team" })] })), title: "Linked article" }));
26
+ expect(screen.getByRole('link', { name: 'Linked article' })).toHaveAttribute('href', '/articles/linked-article');
27
+ expect(screen.getByRole('link', { name: 'Design System Team' })).toHaveAttribute('href', '/authors/design-system');
28
+ expect(container.querySelector('figure')).not.toHaveAttribute('role', 'button');
29
+ });
30
+ test('suppresses the primary link when disabled even if href is provided', () => {
31
+ const { container } = render(_jsx(ArticleCard, { disabled: true, href: "/articles/linked-article", paragraph: "Helpful supporting copy", title: "Linked article" }));
32
+ expect(screen.queryByRole('link', { name: 'Linked article' })).not.toBeInTheDocument();
33
+ expect(container.querySelector('figure')).not.toHaveAttribute('role', 'button');
34
+ });
35
+ test('uses the shared card shell for interactivity', () => {
36
+ const handleClick = vi.fn();
37
+ render(_jsx(ArticleCard, { "aria-label": "Clickable article card", onClick: handleClick, paragraph: "Helpful supporting copy", title: "Clickable article" }));
38
+ const card = screen.getByRole('button', { name: 'Clickable article card' });
39
+ fireEvent.click(card);
40
+ expect(handleClick).toHaveBeenCalledTimes(1);
41
+ });
42
+ test('renders as a static figure when not clickable', () => {
43
+ const { container } = render(_jsx(ArticleCard, { paragraph: "Helpful supporting copy", title: "Static article" }));
44
+ const card = container.querySelector('figure');
45
+ expect(card).toBeInTheDocument();
46
+ expect(card).not.toHaveAttribute('role', 'button');
47
+ });
48
+ });
49
+ //# sourceMappingURL=ArticleCard.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ArticleCard.test.js","sourceRoot":"","sources":["../../../src/components/articleCard/ArticleCard.test.tsx"],"names":[],"mappings":"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"}
@@ -1,10 +1,89 @@
1
- import type { Meta, StoryObj } from '@storybook/react-vite';
1
+ import type { StoryObj } from '@storybook/react-vite';
2
2
  import { Badge } from './Badge';
3
- declare const meta: Meta<typeof Badge>;
3
+ declare function BadgeDocsPage(): import("react/jsx-runtime").JSX.Element;
4
+ declare const meta: {
5
+ title: string;
6
+ component: ({ children, a11yLabel, className, size, colour, }: import("./Badge").BadgeProps) => React.JSX.Element;
7
+ parameters: {
8
+ layout: string;
9
+ docs: {
10
+ page: typeof BadgeDocsPage;
11
+ };
12
+ };
13
+ tags: string[];
14
+ argTypes: {
15
+ children: {
16
+ control: "text";
17
+ description: string;
18
+ table: {
19
+ type: {
20
+ summary: string;
21
+ };
22
+ };
23
+ };
24
+ size: {
25
+ control: "select";
26
+ options: string[];
27
+ description: string;
28
+ table: {
29
+ type: {
30
+ summary: string;
31
+ };
32
+ defaultValue: {
33
+ summary: string;
34
+ };
35
+ };
36
+ };
37
+ colour: {
38
+ control: "select";
39
+ options: (import("../dot/Dot").DotColour | undefined)[];
40
+ description: string;
41
+ table: {
42
+ type: {
43
+ summary: string;
44
+ };
45
+ defaultValue: {
46
+ summary: string;
47
+ };
48
+ };
49
+ };
50
+ a11yLabel: {
51
+ control: "text";
52
+ description: string;
53
+ table: {
54
+ type: {
55
+ summary: string;
56
+ };
57
+ defaultValue: {
58
+ summary: string;
59
+ };
60
+ };
61
+ };
62
+ className: {
63
+ control: false;
64
+ description: string;
65
+ table: {
66
+ type: {
67
+ summary: string;
68
+ };
69
+ defaultValue: {
70
+ summary: string;
71
+ };
72
+ };
73
+ };
74
+ };
75
+ };
4
76
  export default meta;
5
77
  type Story = StoryObj<typeof Badge>;
6
- export declare const Count: Story;
7
- export declare const WithA11yLabel: Story;
8
- export declare const Sizes: Story;
9
- export declare const Colours: Story;
78
+ export declare const Default: Story;
79
+ export declare const SingleDigit: Story;
80
+ export declare const DoubleDigit: Story;
81
+ export declare const Overflow: Story;
82
+ export declare const Zero: Story;
83
+ export declare const WithIcon: Story;
84
+ export declare const InlineWithText: Story;
85
+ export declare const AllSizes: Story;
86
+ export declare const AllColours: Story;
87
+ export declare const AllVariants: Story;
88
+ export declare const A11yWithLabel: Story;
10
89
  //# sourceMappingURL=Badge.stories.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"Badge.stories.d.ts","sourceRoot":"","sources":["../../../src/components/badge/Badge.stories.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,EAAE,KAAK,EAAoB,MAAM,SAAS,CAAC;AAYlD,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,OAAO,KAAK,CAQ5B,CAAC;AAEF,eAAe,IAAI,CAAC;AAEpB,KAAK,KAAK,GAAG,QAAQ,CAAC,OAAO,KAAK,CAAC,CAAC;AAepC,eAAO,MAAM,KAAK,EAAE,KAIoD,CAAC;AAEzE,eAAO,MAAM,aAAa,EAAE,KAK2D,CAAC;AAExF,eAAO,MAAM,KAAK,EAAE,KAQ4C,CAAC;AAEjE,eAAO,MAAM,OAAO,EAAE,KAU0C,CAAC"}
1
+ {"version":3,"file":"Badge.stories.d.ts","sourceRoot":"","sources":["../../../src/components/badge/Badge.stories.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAQ,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAW5D,OAAO,EAAE,KAAK,EAAoB,MAAM,SAAS,CAAC;AAiGlD,iBAAS,aAAa,4CAmBrB;AAYD,QAAA,MAAM,IAAI;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA2EoB,CAAC;AAE/B,eAAe,IAAI,CAAC;AAIpB,KAAK,KAAK,GAAG,QAAQ,CAAC,OAAO,KAAK,CAAC,CAAC;AA+PpC,eAAO,MAAM,OAAO,EAAE,KAUrB,CAAC;AAEF,eAAO,MAAM,WAAW,EAAE,KAqBzB,CAAC;AAEF,eAAO,MAAM,WAAW,EAAE,KAqBzB,CAAC;AAEF,eAAO,MAAM,QAAQ,EAAE,KAqBtB,CAAC;AAEF,eAAO,MAAM,IAAI,EAAE,KAqBlB,CAAC;AAEF,eAAO,MAAM,QAAQ,EAAE,KAwCtB,CAAC;AAEF,eAAO,MAAM,cAAc,EAAE,KAiD5B,CAAC;AAEF,eAAO,MAAM,QAAQ,EAAE,KA0DtB,CAAC;AAEF,eAAO,MAAM,UAAU,EAAE,KAgDxB,CAAC;AAEF,eAAO,MAAM,WAAW,EAAE,KAmDzB,CAAC;AAEF,eAAO,MAAM,aAAa,EAAE,KAiE3B,CAAC"}