@scottish-government/designsystem-react 0.12.1 → 0.13.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 (227) hide show
  1. package/.storybook/main.ts +6 -6
  2. package/.storybook/sgdsArgTypes.ts +84 -43
  3. package/CHANGELOG.md +26 -0
  4. package/eslint.config.mjs +32 -0
  5. package/package.json +8 -3
  6. package/src/common/AbstractNotificationBanner/AbstractNotificationBanner.tsx +5 -4
  7. package/src/common/AbstractNotificationBanner/types.ts +15 -0
  8. package/src/common/ActionLink/ActionLink.tsx +3 -1
  9. package/src/common/ActionLink/types.ts +8 -0
  10. package/src/common/ConditionalWrapper/ConditionalWrapper.tsx +10 -2
  11. package/src/common/ConditionalWrapper/types.ts +4 -0
  12. package/src/common/FileIcon/FileIcon.tsx +2 -1
  13. package/src/common/FileIcon/types.ts +7 -0
  14. package/src/common/HintText/HintText.test.tsx +3 -15
  15. package/src/common/HintText/HintText.tsx +4 -4
  16. package/src/common/HintText/types.ts +4 -0
  17. package/src/common/Icon/Icon.tsx +2 -1
  18. package/src/common/Icon/types.ts +9 -0
  19. package/src/common/ScreenReaderText/ScreenReaderText.tsx +1 -1
  20. package/src/common/WrapperTag/WrapperTag.tsx +5 -3
  21. package/src/common/WrapperTag/types.ts +3 -0
  22. package/src/components/Accordion/Accordion.Item.stories.tsx +1 -5
  23. package/src/components/Accordion/Accordion.stories.tsx +5 -5
  24. package/src/components/Accordion/Accordion.tsx +5 -4
  25. package/src/components/Accordion/types.ts +13 -0
  26. package/src/components/AspectBox/AspectBox.stories.tsx +1 -2
  27. package/src/components/AspectBox/AspectBox.tsx +5 -4
  28. package/src/components/AspectBox/types.ts +3 -0
  29. package/src/components/BackToTop/BackToTop.tsx +3 -2
  30. package/src/components/BackToTop/types.ts +3 -0
  31. package/src/components/Breadcrumbs/Breadcrumbs.tsx +4 -2
  32. package/src/components/Breadcrumbs/types.ts +6 -0
  33. package/src/components/Button/Button.tsx +2 -1
  34. package/src/components/Button/ButtonGroup.tsx +3 -1
  35. package/src/components/Button/types.ts +21 -0
  36. package/src/components/CategoryItem/CategoryItem.tsx +7 -4
  37. package/src/components/CategoryItem/types.ts +10 -0
  38. package/src/components/CategoryList/CategoryList.tsx +4 -2
  39. package/src/components/CategoryList/types.ts +5 -0
  40. package/src/components/Checkbox/Checkbox.stories.tsx +3 -3
  41. package/src/components/Checkbox/Checkbox.tsx +5 -4
  42. package/src/components/Checkbox/CheckboxGroup.tsx +3 -3
  43. package/src/components/Checkbox/types.ts +9 -0
  44. package/src/components/ConfirmationMessage/ConfirmationMessage.tsx +2 -1
  45. package/src/components/ConfirmationMessage/types.ts +7 -0
  46. package/src/components/ContentsNav/ContentsNav.stories.tsx +5 -1
  47. package/src/components/ContentsNav/ContentsNav.tsx +3 -2
  48. package/src/components/ContentsNav/types.ts +11 -0
  49. package/src/components/CookieBanner/CookieBanner.Buttons.stories.tsx +3 -3
  50. package/src/components/CookieBanner/CookieBanner.stories.tsx +6 -6
  51. package/src/components/CookieBanner/CookieBanner.test.tsx +6 -0
  52. package/src/components/CookieBanner/CookieBanner.tsx +13 -3
  53. package/src/components/DatePicker/DatePicker.test.tsx +0 -5
  54. package/src/components/DatePicker/DatePicker.tsx +3 -2
  55. package/src/components/DatePicker/types.ts +20 -0
  56. package/src/components/Details/Details.stories.tsx +1 -1
  57. package/src/components/Details/Details.tsx +3 -1
  58. package/src/components/Details/types.ts +4 -0
  59. package/src/components/ErrorMessage/ErrorMessage.tsx +3 -1
  60. package/src/components/ErrorMessage/types.ts +3 -0
  61. package/src/components/ErrorSummary/ErrorSummary.test.tsx +1 -1
  62. package/src/components/ErrorSummary/ErrorSummary.tsx +3 -2
  63. package/src/components/ErrorSummary/types.ts +11 -0
  64. package/src/components/FileDownload/FileDownload.tsx +2 -1
  65. package/src/components/FileDownload/types.ts +11 -0
  66. package/src/components/HideThisPage/HideThisPage.tsx +3 -2
  67. package/src/components/HideThisPage/types.ts +3 -0
  68. package/src/components/InsetText/InsetText.tsx +1 -1
  69. package/src/components/NotificationBanner/NotificationBanner.stories.tsx +2 -2
  70. package/src/components/NotificationBanner/NotificationBanner.tsx +5 -4
  71. package/src/components/NotificationPanel/NotificationPanel.tsx +2 -1
  72. package/src/components/NotificationPanel/types.ts +7 -0
  73. package/src/components/PageHeader/PageHeader.tsx +3 -1
  74. package/src/components/PageHeader/types.ts +5 -0
  75. package/src/components/PageMetadata/PageMetadata.stories.tsx +1 -1
  76. package/src/components/PageMetadata/PageMetadata.tsx +5 -3
  77. package/src/components/PageMetadata/types.ts +7 -0
  78. package/src/components/Pagination/Pagination.tsx +5 -3
  79. package/src/components/Pagination/types.ts +20 -0
  80. package/src/components/PhaseBanner/PhaseBanner.stories.tsx +1 -4
  81. package/src/components/PhaseBanner/PhaseBanner.tsx +2 -1
  82. package/src/components/PhaseBanner/types.ts +3 -0
  83. package/src/components/Question/Question.tsx +3 -2
  84. package/src/components/Question/types.ts +9 -0
  85. package/src/components/RadioButton/RadioButton.tsx +5 -4
  86. package/src/components/RadioButton/RadioGroup.tsx +2 -1
  87. package/src/components/RadioButton/types.ts +12 -0
  88. package/src/components/SearchFacets/SearchFacets.Group.stories.tsx +2 -3
  89. package/src/components/SearchFacets/SearchFacets.stories.tsx +1 -1
  90. package/src/components/SearchFacets/SearchFacets.tsx +7 -6
  91. package/src/components/SearchFacets/types.ts +14 -0
  92. package/src/components/SearchFilters/SearchFilters.Panel.stories.tsx +18 -7
  93. package/src/components/SearchFilters/SearchFilters.stories.tsx +1 -1
  94. package/src/components/SearchFilters/SearchFilters.tsx +4 -3
  95. package/src/components/SearchFilters/types.ts +14 -0
  96. package/src/components/SearchResult/SearchResult.stories.tsx +9 -10
  97. package/src/components/SearchResult/SearchResult.tsx +9 -8
  98. package/src/components/SearchResult/types.ts +13 -0
  99. package/src/components/SearchSort/SearchSort.stories.tsx +2 -1
  100. package/src/components/SearchSort/SearchSort.tsx +2 -1
  101. package/src/components/SearchSort/types.ts +7 -0
  102. package/src/components/Select/Select.tsx +5 -4
  103. package/src/components/Select/types.ts +7 -0
  104. package/src/components/SequentialNavigation/SequentialNavigation.tsx +6 -4
  105. package/src/components/SequentialNavigation/types.ts +12 -0
  106. package/src/components/SideNavigation/SideNavigation.tsx +5 -4
  107. package/src/components/SideNavigation/types.ts +16 -0
  108. package/src/components/SiteFooter/SiteFooter.tsx +7 -6
  109. package/src/components/SiteFooter/types.ts +20 -0
  110. package/src/components/SiteHeader/SiteHeader.stories.tsx +4 -3
  111. package/src/components/SiteHeader/SiteHeader.tsx +10 -9
  112. package/src/components/SiteHeader/types.ts +22 -0
  113. package/src/components/SiteNavigation/SiteNavigation.tsx +4 -2
  114. package/src/components/SiteNavigation/types.ts +11 -0
  115. package/src/components/SiteSearch/SiteSearch.stories.tsx +4 -2
  116. package/src/components/SiteSearch/SiteSearch.tsx +6 -5
  117. package/src/components/SiteSearch/types.ts +13 -0
  118. package/src/components/SkipLinks/SkipLinks.stories.tsx +3 -3
  119. package/src/components/SkipLinks/SkipLinks.tsx +4 -4
  120. package/src/components/SkipLinks/types.ts +9 -0
  121. package/src/components/SummaryCard/SummaryCard.test.tsx +0 -11
  122. package/src/components/SummaryCard/SummaryCard.tsx +6 -4
  123. package/src/components/SummaryCard/types.ts +6 -0
  124. package/src/components/SummaryList/SummaryList.Item.stories.tsx +5 -5
  125. package/src/components/SummaryList/SummaryList.stories.tsx +1 -1
  126. package/src/components/SummaryList/SummaryList.test.tsx +1 -6
  127. package/src/components/SummaryList/SummaryList.tsx +8 -6
  128. package/src/components/SummaryList/types.ts +7 -0
  129. package/src/components/Table/Table.tsx +3 -2
  130. package/src/components/Table/types.ts +6 -0
  131. package/src/components/Tabs/Tabs.Item.stories.tsx +7 -7
  132. package/src/components/Tabs/Tabs.stories.tsx +3 -3
  133. package/src/components/Tabs/Tabs.tsx +7 -5
  134. package/src/components/Tabs/types.ts +19 -0
  135. package/src/components/Tag/Tag.tsx +3 -1
  136. package/src/components/Tag/types.ts +5 -0
  137. package/src/components/TaskList/TaskList.Group.stories.tsx +0 -5
  138. package/src/components/TaskList/TaskList.stories.tsx +0 -1
  139. package/src/components/TaskList/TaskList.tsx +12 -9
  140. package/src/components/TaskList/types.ts +20 -0
  141. package/src/components/TextInput/TextInput.tsx +6 -6
  142. package/src/components/TextInput/types.ts +12 -0
  143. package/src/components/Textarea/Textarea.tsx +6 -5
  144. package/src/components/WarningText/WarningText.tsx +1 -1
  145. package/src/hooks/useTracking/useTracking.test.tsx +5 -7
  146. package/src/hooks/useTracking/useTracking.ts +1 -1
  147. package/src/images/icons/arrow_upward.tsx +10 -10
  148. package/src/images/icons/calendar_today.tsx +10 -10
  149. package/src/images/icons/cancel.tsx +8 -8
  150. package/src/images/icons/check_circle.tsx +10 -10
  151. package/src/images/icons/chevron_left.tsx +10 -10
  152. package/src/images/icons/chevron_right.tsx +10 -10
  153. package/src/images/icons/close.tsx +10 -10
  154. package/src/images/icons/description.tsx +10 -10
  155. package/src/images/icons/double_chevron_left.tsx +8 -8
  156. package/src/images/icons/double_chevron_right.tsx +8 -8
  157. package/src/images/icons/error.tsx +10 -10
  158. package/src/images/icons/expand_less.tsx +10 -10
  159. package/src/images/icons/expand_more.tsx +10 -10
  160. package/src/images/icons/list.tsx +13 -13
  161. package/src/images/icons/menu.tsx +10 -10
  162. package/src/images/icons/priority_high.tsx +11 -11
  163. package/src/images/icons/search.tsx +10 -10
  164. package/src/shared-types.ts +40 -0
  165. package/vite.config.ts +2 -1
  166. package/@types/common/AbstractNotificationBanner.d.ts +0 -17
  167. package/@types/common/ActionLink.d.ts +0 -8
  168. package/@types/common/ConditionalWrapper.d.ts +0 -6
  169. package/@types/common/FileIcon.d.ts +0 -7
  170. package/@types/common/HintText.d.ts +0 -6
  171. package/@types/common/Icon.d.ts +0 -9
  172. package/@types/common/ScreenReaderText.d.ts +0 -4
  173. package/@types/common/WrapperTag.d.ts +0 -5
  174. package/@types/components/Accordion.d.ts +0 -15
  175. package/@types/components/AspectBox.d.ts +0 -5
  176. package/@types/components/BackToTop.d.ts +0 -5
  177. package/@types/components/Breadcrumbs.d.ts +0 -11
  178. package/@types/components/Button.d.ts +0 -17
  179. package/@types/components/ButtonGroup.d.ts +0 -5
  180. package/@types/components/CategoryItem.d.ts +0 -10
  181. package/@types/components/CategoryList.d.ts +0 -7
  182. package/@types/components/Checkbox.d.ts +0 -11
  183. package/@types/components/ConfirmationMessage.d.ts +0 -7
  184. package/@types/components/ContentsNav.d.ts +0 -13
  185. package/@types/components/DatePicker.d.ts +0 -20
  186. package/@types/components/Details.d.ts +0 -6
  187. package/@types/components/ErrorMessage.d.ts +0 -5
  188. package/@types/components/ErrorSummary.d.ts +0 -12
  189. package/@types/components/FileDownload.d.ts +0 -11
  190. package/@types/components/HideThisPage.d.ts +0 -5
  191. package/@types/components/InsetText.d.ts +0 -5
  192. package/@types/components/Metadata.d.ts +0 -11
  193. package/@types/components/NotificationPanel.d.ts +0 -7
  194. package/@types/components/PageHeader.d.ts +0 -7
  195. package/@types/components/Pagination.d.ts +0 -22
  196. package/@types/components/PhaseBanner.d.ts +0 -5
  197. package/@types/components/Question.d.ts +0 -11
  198. package/@types/components/RadioButton.d.ts +0 -14
  199. package/@types/components/SearchFacets.d.ts +0 -18
  200. package/@types/components/SearchFilters.d.ts +0 -14
  201. package/@types/components/SearchResult.d.ts +0 -30
  202. package/@types/components/SearchSort.d.ts +0 -9
  203. package/@types/components/Select.d.ts +0 -7
  204. package/@types/components/SequentialNavigation.d.ts +0 -14
  205. package/@types/components/SideNavigation.d.ts +0 -18
  206. package/@types/components/SiteFooter.d.ts +0 -25
  207. package/@types/components/SiteHeader.d.ts +0 -20
  208. package/@types/components/SiteNavigation.d.ts +0 -13
  209. package/@types/components/SiteSearch.d.ts +0 -14
  210. package/@types/components/SkipLinks.d.ts +0 -13
  211. package/@types/components/SummaryCard.d.ts +0 -6
  212. package/@types/components/SummaryList.d.ts +0 -14
  213. package/@types/components/Table.d.ts +0 -8
  214. package/@types/components/Tabs.d.ts +0 -21
  215. package/@types/components/Tag.d.ts +0 -5
  216. package/@types/components/TaskList.d.ts +0 -22
  217. package/@types/components/TextInput.d.ts +0 -12
  218. package/@types/components/Textarea.d.ts +0 -4
  219. package/@types/components/WarningText.d.ts +0 -5
  220. package/@types/global.d.ts +0 -1
  221. package/@types/sgds.d.ts +0 -49
  222. package/dist/index.d.ts +0 -4
  223. package/dist/index.js +0 -40
  224. package/dist/tsconfig.tsbuildinfo +0 -1
  225. package/src/components/FeatureHeader/FeatureHeader.stories.tsx +0 -60
  226. package/src/components/FeatureHeader/FeatureHeader.tsx +0 -94
  227. package/src/components/FeatureHeader/index.ts +0 -1
@@ -1,20 +1,20 @@
1
1
  import type { StorybookConfig } from '@storybook/react-vite';
2
2
 
3
3
  const config: StorybookConfig = {
4
- "stories": [
4
+ stories: [
5
5
  "../src/**/*.mdx",
6
6
  "../src/**/*.stories.@(js|jsx|mjs|ts|tsx)"
7
7
  ],
8
- "addons": [
8
+ addons: [
9
9
  "@chromatic-com/storybook",
10
10
  "@storybook/addon-docs",
11
11
  "@storybook/addon-onboarding",
12
12
  "@storybook/addon-a11y",
13
13
  "@storybook/addon-vitest"
14
14
  ],
15
- "framework": {
16
- "name": "@storybook/react-vite",
17
- "options": {}
15
+ framework: {
16
+ name: "@storybook/react-vite",
17
+ options: {}
18
18
  }
19
19
  };
20
- export default config;
20
+ export default config;
@@ -1,141 +1,182 @@
1
+ import { InputType } from "storybook/internal/csf";
2
+
3
+ type OptionsControlType = 'radio' | 'inline-radio' | 'check' | 'inline-check' | 'select' | 'multi-select';
4
+
5
+ type Conditional = (
6
+ { arg: string; }
7
+ | { global: string; }) & ({ truthy?: boolean | undefined; }
8
+ | { exists: boolean; }
9
+ | { eq: () => void; }
10
+ | { neq: () => void; }
11
+ );
12
+
13
+ type ControlType =
14
+ | 'array'
15
+ | 'boolean'
16
+ | 'color'
17
+ | 'date'
18
+ | 'number'
19
+ | 'range'
20
+ | 'object'
21
+ | OptionsControlType
22
+ | 'text';
23
+
24
+ interface ArgType {
25
+ control?: ControlType | { type: ControlType };
26
+ defaultValue?: string | number | boolean | object | null;
27
+ description?: string;
28
+ if?: Conditional;
29
+ mapping?: { [key: string]: { [option: string]: string | object } };
30
+ name?: string;
31
+ options?: string[];
32
+ table?: {
33
+ category?: string;
34
+ defaultValue?: { summary: string; detail?: string };
35
+ subcategory?: string;
36
+ type?: { summary?: string; detail?: string };
37
+ disable?: boolean;
38
+ };
39
+ type?: string | { name: string; required?: boolean };
40
+ }
41
+
1
42
  const SGDSArgTypes = {
2
- ariaLabel: (options?: any) => {
43
+ ariaLabel: (options?: ArgType) => {
3
44
  return Object.assign({
4
45
  type: 'string'
5
- }, options);
46
+ }, options) as InputType;
6
47
  },
7
- ariaLive: (options?: any) => {
48
+ ariaLive: (options?: ArgType) => {
8
49
  return Object.assign({
9
50
  options: ['off', 'polite', 'assertive'],
10
51
  control: { type: 'select' },
11
52
  type: 'string'
12
- }, options);
53
+ }, options) as InputType;
13
54
  },
14
- children: (options?: any) => {
55
+ children: (options?: ArgType) => {
15
56
  return Object.assign({
16
57
  control: false
17
- }, options);
58
+ }, options) as InputType;
18
59
  },
19
- countThreshold: (options?: any) => {
60
+ countThreshold: (options?: ArgType) => {
20
61
  return Object.assign({
21
62
  control: {
22
63
  type: 'number', min: 1, max: 100, step: 1
23
64
  },
24
65
  description: 'Percentage threshold to show the character count at',
25
66
  type: 'number'
26
- }, options);
67
+ }, options) as InputType;
27
68
  },
28
- errorMessage: (options?: any) => {
69
+ errorMessage: (options?: ArgType) => {
29
70
  return Object.assign({
30
71
  description: 'Text to use for an error message',
31
72
  type: 'string'
32
- }, options);
73
+ }, options) as InputType;
33
74
  },
34
- hasError: (options?: any) => {
75
+ hasError: (options?: ArgType) => {
35
76
  return Object.assign({
36
77
  control: 'boolean',
37
78
  description: 'Whether the field is in an error state'
38
- }, options);
79
+ }, options) as InputType;
39
80
  },
40
- headingLevel: (options?: any) => {
81
+ headingLevel: (options?: ArgType) => {
41
82
  return Object.assign({
42
83
  description: 'Heading level for the component\'s title',
43
84
  options: ['h1', 'h2', 'h3', 'h4', 'h5', 'h6'],
44
85
  control: { type: 'select' },
45
86
  type: 'string'
46
- }, options);
87
+ }, options) as InputType;
47
88
  },
48
- hintText: (options?: any) => {
89
+ hintText: (options?: ArgType) => {
49
90
  return Object.assign({
50
91
  description: 'Text to use for the field\'s hint text',
51
92
  type: 'string'
52
- }, options);
93
+ }, options) as InputType;
53
94
  },
54
- href: (options?: any) => {
95
+ href: (options?: ArgType) => {
55
96
  return Object.assign({
56
97
  type: 'string'
57
- }, options);
98
+ }, options) as InputType
58
99
  },
59
- id: (options?: any) => {
100
+ id: (options?: ArgType) => {
60
101
  return Object.assign({
61
102
  type: {
62
103
  required: true,
63
104
  name: 'string'
64
105
  }
65
- }, options);
106
+ }, options) as InputType
66
107
  },
67
- inputWidth: (options?: any) => {
108
+ inputWidth: (options?: ArgType) => {
68
109
  return Object.assign({
69
110
  control: { type: 'select' },
70
111
  options: [undefined, 'fixed-20', 'fixed-10', 'fixed-5', 'fixed-4', 'fixed-3', 'fixed-2', 'fluid-three-quarters', 'fluid-two-thirds', 'fluid-half', 'fluid-one-third', 'fluid-one-quarter'],
71
112
  type: 'string'
72
- }, options);
113
+ }, options) as InputType
73
114
  },
74
- isCurrent: (options?: any) => {
115
+ isCurrent: (options?: ArgType) => {
75
116
  return Object.assign({
76
117
  control: 'boolean',
77
118
  description: 'Whether the component is for the current page'
78
- }, options);
119
+ }, options) as InputType
79
120
  },
80
- isSmall: (options?: any) => {
121
+ isSmall: (options?: ArgType) => {
81
122
  return Object.assign({
82
123
  control: 'boolean',
83
- description: 'Whether to use the small input control variant'
84
- }, options);
124
+ description: 'Whether to use the \'small\' input control variant'
125
+ }, options) as InputType
85
126
  },
86
- label: (options?: any) => {
127
+ label: (options?: ArgType) => {
87
128
  return Object.assign({
88
129
  description: 'Text to use for the field\'s associated label',
89
130
  type: {
90
131
  required: true,
91
132
  name: 'string'
92
133
  }
93
- }, options);
134
+ }, options) as InputType;
94
135
  },
95
- linkComponent: (options?: any) => {
136
+ linkComponent: (options?: ArgType) => {
96
137
  return Object.assign({
97
138
  control: false,
98
139
  description: 'Function that returns an element, to customise the output',
99
140
  type: 'function'
100
- }, options);
141
+ }, options) as InputType;
101
142
  },
102
- maxlength: (options?: any) => {
143
+ maxlength: (options?: ArgType) => {
103
144
  return Object.assign({
104
145
  description: 'Maximum number of characters permitted',
105
146
  type: 'number'
106
- }, options);
147
+ }, options) as InputType;
107
148
  },
108
- noBorder: (options?: any) => {
149
+ noBorder: (options?: ArgType) => {
109
150
  return Object.assign({
110
151
  control: 'boolean',
111
152
  description: 'Use the borderless display variant'
112
- }, options);
153
+ }, options) as InputType;
113
154
  },
114
- onBlur: (options?: any) => {
155
+ onBlur: (options?: ArgType) => {
115
156
  return Object.assign({
116
157
  description: 'Function to fire in response to a blur event',
117
158
  type: 'function'
118
- }, options);
159
+ }, options) as InputType;
119
160
  },
120
- onChange: (options?: any) => {
161
+ onChange: (options?: ArgType) => {
121
162
  return Object.assign({
122
163
  description: 'Function to fire in response to a change event',
123
164
  type: 'function'
124
- }, options);
165
+ }, options) as InputType;
125
166
  },
126
- onClick: (options?: any) => {
167
+ onClick: (options?: ArgType) => {
127
168
  return Object.assign({
128
169
  description: 'Function to fire in response to a click event',
129
170
  type: 'function'
130
- }, options);
171
+ }, options) as InputType;
131
172
  },
132
- tagColour: (options?: any) => {
173
+ tagColour: (options?: ArgType) => {
133
174
  return Object.assign({
134
175
  control: { type: 'select' },
135
176
  description: 'The tag colour to use',
136
177
  options: ['', 'blue', 'green', 'grey', 'orange', 'pink', 'purple', 'red', 'teal', 'yellow'],
137
178
  type: 'string'
138
- }, options);
179
+ }, options) as InputType;
139
180
  }
140
181
  }
141
182
 
package/CHANGELOG.md CHANGED
@@ -6,6 +6,32 @@ Changes are grouped under the labels: `Added`, `Changed`, `Deprecated`, `Fixed`,
6
6
  `Removed` and `Security`.
7
7
 
8
8
  ---
9
+ ## [0.13.0] - 2025-12-19
10
+
11
+ ### Added
12
+ - eslint added to build task
13
+ ### Changed
14
+ - Types moved from .d.ts files in @types folder to types.ts files in each component's folder
15
+ - HintText no longer allows content to be added with a 'text' prop -- use children instead
16
+ - NotificationBanner title (visually hidden) is customisable via a 'title' prop
17
+ ### Fixed
18
+ - Checkbox stories updated to use 'isSmall' and 'isExclusive' (see v0.10.0).
19
+ - CookieBanner now fires the SG Design System cookie notification JS
20
+ ### Removed
21
+ - 'SGDS' namespace no longer used for types etc
22
+ ### Security
23
+ - Storybook version updated to address vulnerabilities
24
+
25
+ ## [0.12.1] - 2025-11-19
26
+
27
+ ### Added
28
+ - 'Barrel' index files
29
+ - 'main' and typings added to package.json
30
+ ### Changed
31
+ - Move hooks and common components and to subfolders to match structure of the main components
32
+ ### Security
33
+ - Update dependencies
34
+
9
35
  ## [0.12.0] - 2025-11-12
10
36
 
11
37
  ### Added
@@ -0,0 +1,32 @@
1
+ // import eslint from "@eslint";
2
+ import globals from "globals";
3
+ import tseslint from "typescript-eslint";
4
+ import react from "eslint-plugin-react";
5
+ import { defineConfig } from "eslint/config";
6
+
7
+ export default defineConfig([
8
+ {
9
+ files: ["**/*.{js,mjs,cjs,ts,mts,cts,jsx,tsx}"],
10
+ plugins: { react },
11
+ languageOptions: { globals: globals.browser },
12
+ settings: {
13
+ react: {
14
+ version: "detect"
15
+ }
16
+ }
17
+ },
18
+ tseslint.configs.recommended,
19
+ react.configs.flat.recommended,
20
+ {
21
+ rules: {
22
+ "react/react-in-jsx-scope": "off"
23
+ }
24
+ },
25
+ {
26
+ ignores: [
27
+ "coverage/**",
28
+ "dist/**",
29
+ "node_modules/**"
30
+ ]
31
+ }
32
+ ]);
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@scottish-government/designsystem-react",
3
3
  "description": "A React/JSX implementation of the Scottish Government Design System",
4
- "version": "0.12.1",
4
+ "version": "0.13.0",
5
5
  "license": "MIT",
6
6
  "author": {
7
7
  "name": "Scottish Government Digital Design System team",
@@ -11,7 +11,7 @@
11
11
  "typings": "dist/index.d.ts",
12
12
  "main": "dist/index.js",
13
13
  "scripts": {
14
- "build": "npm run svgr && npm run tsc",
14
+ "build": "npx eslint && npm run svgr && npm run tsc",
15
15
  "coverage": "vitest test.tsx run --coverage",
16
16
  "svgr": "npx @svgr/cli node_modules/@scottish-government/design-system/src/images/icons/svg --config-file .svgrrc",
17
17
  "svgr_documents": "npx @svgr/cli node_modules/@scottish-government/design-system/src/images/documents/svg --config-file .svgrrc_documents",
@@ -25,6 +25,7 @@
25
25
  },
26
26
  "devDependencies": {
27
27
  "@chromatic-com/storybook": "^4.1.3",
28
+ "@eslint/js": "^9.39.1",
28
29
  "@storybook/addon-a11y": "^10.0.8",
29
30
  "@storybook/addon-docs": "^10.0.8",
30
31
  "@storybook/addon-onboarding": "^10.0.8",
@@ -42,11 +43,15 @@
42
43
  "@vitest/browser": "4.0.10",
43
44
  "@vitest/browser-playwright": "^4.0.10",
44
45
  "@vitest/coverage-v8": "^4.0.10",
46
+ "eslint": "^9.39.1",
47
+ "eslint-plugin-react": "^7.37.5",
48
+ "globals": "^16.5.0",
45
49
  "jsdom": "^27.2.0",
46
50
  "react": "^19.2.0",
47
51
  "react-dom": "^19.2.0",
48
- "storybook": "^10.0.8",
52
+ "storybook": "^10.1.10",
49
53
  "typescript": "^5.9.3",
54
+ "typescript-eslint": "^8.47.0",
50
55
  "vitest": "^4.0.10"
51
56
  }
52
57
  }
@@ -1,12 +1,13 @@
1
1
  import { Children } from 'react';
2
2
  import Icon from '../Icon';
3
3
  import ScreenReaderText from '../ScreenReaderText';
4
+ import { AbstractNotificationBannerProps, AbstractNotificationBannerButtonsProps } from './types';
4
5
 
5
6
  const Buttons = ({
6
7
  children
7
- }: SGDS.Common.AbstractNotificationBanner.Buttons) => {
8
+ }: AbstractNotificationBannerButtonsProps) => {
8
9
  return (<div className="ds_button-group">{children}</div>);
9
- }
10
+ };
10
11
 
11
12
  const AbstractNotificationBanner = ({
12
13
  children,
@@ -17,8 +18,8 @@ const AbstractNotificationBanner = ({
17
18
  isDismissable,
18
19
  title = 'Information',
19
20
  ...props
20
- }: SGDS.Common.AbstractNotificationBanner) => {
21
- let content: any[] = [];
21
+ }: AbstractNotificationBannerProps) => {
22
+ const content: React.ReactElement[] = [];
22
23
  let buttons;
23
24
 
24
25
  Children.forEach(children, (child) => {
@@ -0,0 +1,15 @@
1
+ import { IconName } from '../../shared-types';
2
+
3
+ export interface AbstractNotificationBannerProps extends React.AllHTMLAttributes<HTMLDivElement> {
4
+ hasIcon?: boolean;
5
+ hasColourIcon?: boolean;
6
+ hasInverseIcon?: boolean;
7
+ icon?: IconName;
8
+ isDismissable?: boolean;
9
+ title?: string;
10
+ ref?: React.Ref<HTMLDivElement>;
11
+ }
12
+
13
+ export interface AbstractNotificationBannerButtonsProps extends React.AllHTMLAttributes<HTMLDivElement> {
14
+ children: React.ReactNode;
15
+ }
@@ -1,10 +1,12 @@
1
+ import { ActionLinkProps } from './types';
2
+
1
3
  const ActionLink = ({
2
4
  children,
3
5
  describedby,
4
6
  href,
5
7
  linkComponent,
6
8
  onclick
7
- }: SGDS.Common.ActionLink) => {
9
+ }: ActionLinkProps) => {
8
10
  const CLASSNAME = 'ds_link';
9
11
 
10
12
  function processChildren(children: React.ReactNode) {
@@ -0,0 +1,8 @@
1
+ import { LinkComponent } from '../../shared-types';
2
+
3
+ export interface ActionLinkProps extends React.AllHTMLAttributes<HTMLElement> {
4
+ describedby?: string;
5
+ href?: string;
6
+ linkComponent?: LinkComponent;
7
+ onclick?: React.EventHandler<React.MouseEvent>;
8
+ }
@@ -1,8 +1,16 @@
1
1
  /**
2
2
  * Wraps all children in a specified HTML tag if a condition is met.
3
3
  */
4
- const ConditionalWrapper = ({ condition, wrapper, children }:SGDS.Common.ConditionalWrapper) =>
5
- condition ? wrapper(children) : children;
4
+
5
+ import { ConditionalWrapperProps } from "./types";
6
+
7
+ const ConditionalWrapper = ({
8
+ condition,
9
+ wrapper,
10
+ children
11
+ }: ConditionalWrapperProps) => {
12
+ return condition ? wrapper(children as React.JSX.Element) : children;
13
+ };
6
14
 
7
15
  ConditionalWrapper.displayName = 'ConditionalWrapper';
8
16
 
@@ -0,0 +1,4 @@
1
+ export interface ConditionalWrapperProps extends React.AllHTMLAttributes<HTMLElement> {
2
+ condition: boolean;
3
+ wrapper: (children: React.JSX.Element) => React.JSX.Element;
4
+ }
@@ -1,11 +1,12 @@
1
1
  import React from 'react';
2
2
  import * as FileIcons from '../../images/documents';
3
+ import { FileIconProps } from './types';
3
4
 
4
5
  const FileIcon = ({
5
6
  ariaLabel = '',
6
7
  className,
7
8
  icon
8
- }: SGDS.Common.FileIcon) => {
9
+ }: FileIconProps) => {
9
10
  const FileIconComponent = FileIcons[icon];
10
11
 
11
12
  return (
@@ -0,0 +1,7 @@
1
+ import { DocumentIconName } from '../../shared-types';
2
+
3
+ export interface FileIconProps extends React.AllHTMLAttributes<SVGSVGElement> {
4
+ ariaLabel?: React.AriaAttributes['aria-label'];
5
+ className?: string;
6
+ icon: DocumentIconName;
7
+ }
@@ -9,8 +9,9 @@ test('hint test renders correctly', () => {
9
9
  render(
10
10
  <HintText data-testid="hint-text"
11
11
  id={HINT_TEXT_ID}
12
- text={HINT_TEXT_CONTENT}
13
- />
12
+ >
13
+ {HINT_TEXT_CONTENT}
14
+ </HintText>
14
15
  );
15
16
 
16
17
  const hintText = screen.getByTestId('hint-text');
@@ -20,19 +21,6 @@ test('hint test renders correctly', () => {
20
21
  expect(hintText.textContent).toEqual(HINT_TEXT_CONTENT);
21
22
  });
22
23
 
23
- test('hint test with children instead of text', () => {
24
- render(
25
- <HintText data-testid="hint-text"
26
- id={HINT_TEXT_ID}
27
- >
28
- <span>{HINT_TEXT_CONTENT}</span>
29
- </HintText>
30
- );
31
-
32
- const hintText = screen.getByTestId('hint-text');
33
- expect(hintText.innerHTML).toEqual(`<span>${HINT_TEXT_CONTENT}</span>`);
34
- });
35
-
36
24
  test('passing additional props', () => {
37
25
  render(
38
26
  <HintText data-testid="hint-text"
@@ -1,17 +1,17 @@
1
+ import { HintTextProps } from "./types";
2
+
1
3
  const HintText = ({
2
4
  children,
3
5
  id,
4
- text,
5
6
  ...props
6
- }: SGDS.Common.HintText) => {
7
+ }: HintTextProps) => {
7
8
  return (
8
9
  <p
9
10
  className="ds_hint-text"
10
- dangerouslySetInnerHTML={text ? { __html: text } : undefined}
11
11
  id={id}
12
12
  {...props}
13
13
  >
14
- {!text ? children : null}
14
+ {children}
15
15
  </p>
16
16
  );
17
17
  };
@@ -0,0 +1,4 @@
1
+ export interface HintTextProps extends React.AllHTMLAttributes<HTMLElement> {
2
+ id?: string;
3
+ text?: string;
4
+ }
@@ -1,5 +1,6 @@
1
1
  import React from 'react';
2
2
  import * as Icons from '../../images/icons';
3
+ import { IconProps } from './types';
3
4
 
4
5
  const Icon = ({
5
6
  ariaLabel,
@@ -7,7 +8,7 @@ const Icon = ({
7
8
  isFilled,
8
9
  icon,
9
10
  iconSize
10
- }: SGDS.Common.Icon) => {
11
+ }: IconProps) => {
11
12
  const IconComponent = Icons[icon];
12
13
 
13
14
  return (
@@ -0,0 +1,9 @@
1
+ import { IconName } from '../../shared-types';
2
+
3
+ export interface IconProps extends React.AllHTMLAttributes<SVGSVGElement> {
4
+ ariaLabel?: React.AriaAttributes['aria-label'];
5
+ className?: string;
6
+ isFilled?: boolean;
7
+ icon: IconName;
8
+ iconSize?: string;
9
+ }
@@ -1,7 +1,7 @@
1
1
  const ScreenReaderText = ({
2
2
  children,
3
3
  ...props
4
- }: SGDS.Common.ScreenReaderText) => {
4
+ }: React.AllHTMLAttributes<HTMLElement>) => {
5
5
  return (
6
6
  <span
7
7
  className="visually-hidden"
@@ -1,13 +1,15 @@
1
1
  /**
2
2
  * Wraps all children in a specified HTML tag.
3
3
  */
4
+ import React from 'react';
5
+ import { WrapperTagProps } from './types';
6
+
4
7
  const WrapperTag = ({
5
8
  children,
6
9
  tagName = 'div',
7
10
  ...props
8
- }: SGDS.Common.WrapperTag) => {
9
- const TagName = tagName;
10
- return <TagName {...props}>{children}</TagName>;
11
+ }: WrapperTagProps) => {
12
+ return React.createElement(tagName, props, children);
11
13
  };
12
14
 
13
15
  WrapperTag.displayName = 'WrapperTag';
@@ -0,0 +1,3 @@
1
+ export interface WrapperTagProps extends React.AllHTMLAttributes<HTMLElement> {
2
+ tagName?: string;
3
+ }
@@ -1,5 +1,4 @@
1
1
  import type { Meta, StoryObj } from '@storybook/react-vite';
2
- import argTypes from '../../../.storybook/sgdsArgTypes';
3
2
 
4
3
  import Accordion from './Accordion';
5
4
 
@@ -15,9 +14,6 @@ const meta = {
15
14
  required: true
16
15
  }
17
16
  },
18
- headingLevel: argTypes.headingLevel({
19
- description: 'Heading level for the component\'s heading. It is best to set this on the parent Accordion.'
20
- }),
21
17
  id: {
22
18
  description: 'ID to use for the accordion item if you want to override the automatically generated default',
23
19
  type: 'string'
@@ -37,7 +33,7 @@ const meta = {
37
33
  Veterans are entitled to the same healthcare as any citizen. And there are health care options and support available specifically for veterans.
38
34
  </p>
39
35
  <p>
40
- If you have a health condition that's related to your service, you're entitled to priority treatment based on clinical need.
36
+ If you have a health condition that&apos;s related to your service, you&apos;re entitled to priority treatment based on clinical need.
41
37
  </p>
42
38
  </>
43
39
  }
@@ -12,7 +12,7 @@ const meta = {
12
12
  }),
13
13
  hideOpenAll: {
14
14
  control: 'boolean',
15
- description: 'Do not show the open all button',
15
+ description: 'Do not show the \'open all\' button',
16
16
  type: 'boolean'
17
17
  },
18
18
  children: {
@@ -26,17 +26,17 @@ const meta = {
26
26
  Veterans are entitled to the same healthcare as any citizen. And there are health care options and support available specifically for veterans.
27
27
  </p>
28
28
  <p>
29
- If you have a health condition that's related to your service, you're entitled to priority treatment based on clinical need.
29
+ If you have a health condition that&apos;s related to your service, you&apos;re entitled to priority treatment based on clinical need.
30
30
  </p>
31
31
  </Accordion.Item>
32
32
  <Accordion.Item id='accordion-2' heading='Employability for veterans'>
33
33
  <p>
34
- If you're looking for a job, there are several organisations that can help you <a href="#accordion-link">find a job or develop new skills</a>.
34
+ If you&apos;re looking for a job, there are several organisations that can help you <a href="#accordion-link">find a job or develop new skills</a>.
35
35
  </p>
36
36
  </Accordion.Item>
37
37
  <Accordion.Item id='accordion-3' heading='Housing for veterans'>
38
38
  <p>
39
- If you need <a href="#accordion-link"> help finding a place to live</a> there's support specifically for veterans.
39
+ If you need <a href="#accordion-link"> help finding a place to live</a> there&apos;s support specifically for veterans.
40
40
  </p>
41
41
  </Accordion.Item>
42
42
  </>
@@ -53,7 +53,7 @@ export const Default: Story = {
53
53
  export const HideOpenAll: Story = {
54
54
  args: {
55
55
  hideOpenAll: true
56
- },
56
+ }
57
57
  }
58
58
 
59
59
  export const InvalidNoChildren: Story = {