@scottish-government/designsystem-react 0.8.0 → 0.10.0-beta.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 (169) hide show
  1. package/.storybook/main.ts +20 -0
  2. package/.storybook/manager.ts +13 -0
  3. package/.storybook/preview-head.html +1 -0
  4. package/.storybook/preview.tsx +56 -0
  5. package/.storybook/sgdsArgTypes.ts +123 -0
  6. package/.storybook/sgdsTheme.ts +9 -0
  7. package/.storybook/vitest.setup.ts +7 -0
  8. package/@types/common/AbstractNotificationBanner.d.ts +2 -2
  9. package/@types/common/ActionLink.d.ts +1 -1
  10. package/@types/common/Icon.d.ts +1 -1
  11. package/@types/components/Accordion.d.ts +2 -3
  12. package/@types/components/Button.d.ts +5 -5
  13. package/@types/components/CategoryItem.d.ts +10 -0
  14. package/@types/components/CategoryList.d.ts +7 -0
  15. package/@types/components/Checkbox.d.ts +2 -2
  16. package/@types/components/ContentsNav.d.ts +1 -1
  17. package/@types/components/DatePicker.d.ts +1 -1
  18. package/@types/components/ErrorMessage.d.ts +1 -2
  19. package/@types/components/ErrorSummary.d.ts +1 -1
  20. package/@types/components/FileDownload.d.ts +2 -2
  21. package/@types/components/Metadata.d.ts +1 -1
  22. package/@types/components/Pagination.d.ts +1 -1
  23. package/@types/components/RadioButton.d.ts +2 -2
  24. package/@types/components/SideNavigation.d.ts +1 -1
  25. package/@types/components/SiteNavigation.d.ts +1 -1
  26. package/@types/components/SummaryList.d.ts +1 -1
  27. package/@types/components/Tabs.d.ts +3 -3
  28. package/@types/components/TextInput.d.ts +1 -1
  29. package/@types/sgds.d.ts +2 -1
  30. package/CHANGELOG.md +29 -0
  31. package/dist/common/AbstractNotificationBanner.jsx +4 -4
  32. package/dist/common/Icon.jsx +2 -2
  33. package/dist/components/Accordion/Accordion.jsx +8 -7
  34. package/dist/components/Button/Button.jsx +6 -6
  35. package/dist/components/CategoryItem/CategoryItem.jsx +35 -0
  36. package/dist/components/CategoryList/CategoryList.jsx +55 -0
  37. package/dist/components/Checkbox/Checkbox.jsx +7 -4
  38. package/dist/components/Checkbox/CheckboxGroup.jsx +5 -11
  39. package/dist/components/ContentsNav/ContentsNav.jsx +2 -2
  40. package/dist/components/DatePicker/DatePicker.jsx +1 -1
  41. package/dist/components/ErrorMessage/ErrorMessage.jsx +3 -3
  42. package/dist/components/FileDownload/FileDownload.jsx +2 -2
  43. package/dist/components/NotificationBanner/NotificationBanner.jsx +2 -2
  44. package/dist/components/PageMetadata/PageMetadata.jsx +4 -4
  45. package/dist/components/Pagination/Pagination.jsx +4 -4
  46. package/dist/components/Question/Question.jsx +1 -1
  47. package/dist/components/RadioButton/RadioButton.jsx +6 -2
  48. package/dist/components/RadioButton/RadioGroup.jsx +7 -47
  49. package/dist/components/Select/Select.jsx +1 -1
  50. package/dist/components/SideNavigation/SideNavigation.jsx +2 -2
  51. package/dist/components/SiteHeader/SiteHeader.jsx +3 -3
  52. package/dist/components/SiteNavigation/SiteNavigation.jsx +2 -2
  53. package/dist/components/SiteSearch/SiteSearch.jsx +1 -1
  54. package/dist/components/SkipLinks/SkipLinks.jsx +1 -1
  55. package/dist/components/SummaryList/SummaryList.jsx +3 -3
  56. package/dist/components/Tabs/Tabs.jsx +6 -7
  57. package/dist/components/TextInput/TextInput.jsx +5 -5
  58. package/dist/components/Textarea/Textarea.jsx +1 -1
  59. package/dist/hooks/useTracking.js +21 -0
  60. package/dist/tsconfig.tsbuildinfo +1 -1
  61. package/dist/utils/context.js +5 -0
  62. package/package.json +15 -4
  63. package/src/common/AbstractNotificationBanner.test.tsx +1 -1
  64. package/src/common/AbstractNotificationBanner.tsx +4 -4
  65. package/src/common/Icon.test.tsx +1 -1
  66. package/src/common/Icon.tsx +2 -2
  67. package/src/components/Accordion/Accordion.stories.tsx +111 -0
  68. package/src/components/Accordion/Accordion.test.tsx +5 -17
  69. package/src/components/Accordion/Accordion.tsx +11 -10
  70. package/src/components/AspectBox/AspectBox.stories.tsx +64 -0
  71. package/src/components/BackToTop/BackToTop.stories.tsx +36 -0
  72. package/src/components/Breadcrumbs/Breadcrumbs.stories.tsx +49 -0
  73. package/src/components/Breadcrumbs/Breadcrumbs.test.tsx +0 -1
  74. package/src/components/Breadcrumbs/Breadcrumbs.tsx +1 -1
  75. package/src/components/Button/Button.stories.tsx +194 -0
  76. package/src/components/Button/Button.test.tsx +4 -4
  77. package/src/components/Button/Button.tsx +9 -9
  78. package/src/components/CategoryItem/CategoryItem.stories.tsx +55 -0
  79. package/src/components/CategoryItem/CategoryItem.test.tsx +93 -0
  80. package/src/components/CategoryItem/CategoryItem.tsx +56 -0
  81. package/src/components/CategoryList/CategoryList.stories.tsx +65 -0
  82. package/src/components/CategoryList/CategoryList.test.tsx +59 -0
  83. package/src/components/CategoryList/CategoryList.tsx +33 -0
  84. package/src/components/Checkbox/Checkbox.stories.tsx +85 -0
  85. package/src/components/Checkbox/Checkbox.test.tsx +2 -2
  86. package/src/components/Checkbox/Checkbox.tsx +11 -6
  87. package/src/components/Checkbox/CheckboxGroup.stories.tsx +68 -0
  88. package/src/components/Checkbox/CheckboxGroup.tsx +7 -12
  89. package/src/components/ConfirmationMessage/ConfirmationMessage.stories.tsx +38 -0
  90. package/src/components/ContentsNav/ContentsNav.stories.tsx +43 -0
  91. package/src/components/ContentsNav/ContentsNav.test.tsx +2 -2
  92. package/src/components/ContentsNav/ContentsNav.tsx +2 -2
  93. package/src/components/CookieBanner/CookieBanner.stories.tsx +33 -0
  94. package/src/components/DatePicker/DatePicker.stories.tsx +113 -0
  95. package/src/components/DatePicker/DatePicker.tsx +1 -1
  96. package/src/components/Details/Details.stories.tsx +36 -0
  97. package/src/components/ErrorMessage/ErrorMessage.stories.tsx +19 -0
  98. package/src/components/ErrorMessage/ErrorMessage.test.tsx +3 -15
  99. package/src/components/ErrorMessage/ErrorMessage.tsx +1 -3
  100. package/src/components/ErrorSummary/ErrorSummary.stories.tsx +38 -0
  101. package/src/components/FileDownload/FileDownload.stories.tsx +75 -0
  102. package/src/components/FileDownload/FileDownload.test.tsx +1 -1
  103. package/src/components/FileDownload/FileDownload.tsx +2 -2
  104. package/src/components/HideThisPage/HideThisPage.stories.tsx +20 -0
  105. package/src/components/InsetText/InsetText.stories.tsx +21 -0
  106. package/src/components/NotificationBanner/NotificationBanner.stories.tsx +57 -0
  107. package/src/components/NotificationBanner/NotificationBanner.test.tsx +1 -1
  108. package/src/components/NotificationBanner/NotificationBanner.tsx +4 -4
  109. package/src/components/NotificationPanel/NotificationPanel.stories.tsx +32 -0
  110. package/src/components/PageHeader/PageHeader.stories.tsx +60 -0
  111. package/src/components/PageMetadata/PageMetadata.stories.tsx +58 -0
  112. package/src/components/PageMetadata/PageMetadata.test.tsx +2 -2
  113. package/src/components/PageMetadata/PageMetadata.tsx +4 -4
  114. package/src/components/Pagination/Pagination.stories.tsx +69 -0
  115. package/src/components/Pagination/Pagination.test.tsx +1 -1
  116. package/src/components/Pagination/Pagination.tsx +4 -4
  117. package/src/components/PhaseBanner/PhaseBanner.stories.tsx +38 -0
  118. package/src/components/Question/Question.stories.tsx +78 -0
  119. package/src/components/Question/Question.tsx +1 -1
  120. package/src/components/RadioButton/RadioButton.stories.tsx +67 -0
  121. package/src/components/RadioButton/RadioButton.test.tsx +2 -1
  122. package/src/components/RadioButton/RadioButton.tsx +9 -3
  123. package/src/components/RadioButton/RadioGroup.stories.tsx +77 -0
  124. package/src/components/RadioButton/RadioGroup.test.tsx +2 -2
  125. package/src/components/RadioButton/RadioGroup.tsx +8 -15
  126. package/src/components/Select/Select.stories.tsx +76 -0
  127. package/src/components/Select/Select.tsx +1 -1
  128. package/src/components/SequentialNavigation/SequentialNavigation.stories.tsx +31 -0
  129. package/src/components/SideNavigation/SideNavigation.stories.tsx +92 -0
  130. package/src/components/SideNavigation/SideNavigation.test.tsx +2 -2
  131. package/src/components/SideNavigation/SideNavigation.tsx +2 -2
  132. package/src/components/SiteFooter/SiteFooter.stories.tsx +65 -0
  133. package/src/components/SiteHeader/SiteHeader.stories.tsx +92 -0
  134. package/src/components/SiteHeader/SiteHeader.tsx +2 -7
  135. package/src/components/SiteNavigation/SiteNavigation.stories.tsx +45 -0
  136. package/src/components/SiteNavigation/SiteNavigation.test.tsx +1 -1
  137. package/src/components/SiteNavigation/SiteNavigation.tsx +2 -2
  138. package/src/components/SiteSearch/SiteSearch.stories.tsx +81 -0
  139. package/src/components/SiteSearch/SiteSearch.tsx +1 -1
  140. package/src/components/SkipLinks/SkipLinks.stories.tsx +57 -0
  141. package/src/components/SkipLinks/SkipLinks.tsx +1 -1
  142. package/src/components/SummaryCard/SummaryCard.stories.tsx +46 -0
  143. package/src/components/SummaryList/SummaryList.stories.tsx +75 -0
  144. package/src/components/SummaryList/SummaryList.test.tsx +1 -1
  145. package/src/components/SummaryList/SummaryList.tsx +3 -3
  146. package/src/components/Table/Table.stories.tsx +96 -0
  147. package/src/components/Tabs/Tabs.stories.tsx +90 -0
  148. package/src/components/Tabs/Tabs.test.tsx +6 -8
  149. package/src/components/Tabs/Tabs.tsx +8 -9
  150. package/src/components/Tag/Tag.stories.tsx +25 -0
  151. package/src/components/TaskList/TaskList.stories.tsx +129 -0
  152. package/src/components/TextInput/TextInput.stories.tsx +123 -0
  153. package/src/components/TextInput/TextInput.test.tsx +2 -2
  154. package/src/components/TextInput/TextInput.tsx +5 -5
  155. package/src/components/Textarea/Textarea.stories.tsx +71 -0
  156. package/src/components/Textarea/Textarea.tsx +1 -1
  157. package/src/components/WarningText/WarningText.stories.tsx +21 -0
  158. package/src/hooks/useTracking.test.tsx +64 -0
  159. package/src/hooks/useTracking.ts +19 -0
  160. package/src/utils/context.ts +3 -0
  161. package/static/data/autocomplete-dummy-data.json +2361 -0
  162. package/static/images/highland-cow.jpg +0 -0
  163. package/static/images/scottish-government--min.svg +11 -0
  164. package/static/images/scottish-government.svg +6 -0
  165. package/tsconfig.json +3 -2
  166. package/vite.config.ts +45 -11
  167. package/vitest-setup.ts +1 -0
  168. package/vitest.shims.d.ts +1 -0
  169. package/src/utils/slugify.ts +0 -13
@@ -64,7 +64,7 @@ const DatePicker = ({
64
64
  {(multiple ? (
65
65
  <fieldset className="ds_datepicker__input-wrapper">
66
66
  <legend>{label}</legend>
67
- {errorMessage && <ErrorMessage text={errorMessage}/>}
67
+ {errorMessage && <ErrorMessage>{errorMessage}</ErrorMessage>}
68
68
  <div>
69
69
  <TextInput
70
70
  className="js-datepicker-date"
@@ -0,0 +1,36 @@
1
+ import type { Meta, StoryObj } from '@storybook/react-vite';
2
+ import argTypes from '../../../.storybook/sgdsArgTypes';
3
+
4
+ import Details from './Details';
5
+
6
+ const meta = {
7
+ title: 'Components/Details',
8
+ component: Details,
9
+ argTypes: {
10
+ children: argTypes.children(),
11
+ summary: {
12
+ description: 'Text to use for the details component\'s ‘summary’ element',
13
+ type: {
14
+ name: 'string',
15
+ required: true
16
+ }
17
+ }
18
+ },
19
+ args: {
20
+ summary: 'I cannot sign in'
21
+ }
22
+ } satisfies Meta<typeof Details>;
23
+
24
+ export default meta;
25
+ type Story = StoryObj<typeof meta>;
26
+
27
+ export const Default: Story = {
28
+ args: {
29
+ children: <>
30
+ <p>Contact the design system team if you cannot sign in.</p>,
31
+ <p>Email <a href="mailto:designsystem@gov.scot">designsystem@gov.scot</a>.</p>,
32
+ <p>Or phone 0000 123 4567<br/>
33
+ Monday to Friday, 9am to 5pm</p>
34
+ </>
35
+ }
36
+ };
@@ -0,0 +1,19 @@
1
+ import type { Meta, StoryObj } from '@storybook/react-vite';
2
+ import argTypes from '../../../.storybook/sgdsArgTypes';
3
+
4
+ import ErrorMessage from './ErrorMessage';
5
+
6
+ const meta = {
7
+ title: 'Components/Error message',
8
+ component: ErrorMessage,
9
+ argTypes: {
10
+ children: argTypes.children()
11
+ }
12
+ } satisfies Meta<typeof ErrorMessage>;
13
+
14
+ export default meta;
15
+ type Story = StoryObj<typeof meta>;
16
+
17
+ export const Default: Story = {
18
+ args: { children: <>This field is required</> }
19
+ };
@@ -8,7 +8,7 @@ const ERROR_ID = 'errormessage';
8
8
  test('error message renders correctly', () => {
9
9
 
10
10
  render(
11
- <ErrorMessage text={ERROR_TEXT} id={ERROR_ID}/>
11
+ <ErrorMessage id={ERROR_ID}>{ERROR_TEXT}</ErrorMessage>
12
12
  );
13
13
 
14
14
  const errorMessageElement = screen.getByRole('paragraph');
@@ -18,21 +18,9 @@ test('error message renders correctly', () => {
18
18
  expect(errorMessageElement.textContent).toEqual(ERROR_TEXT);
19
19
  });
20
20
 
21
- test('error message with HTML content', () => {
22
- const ERROR_ID = 'errormessage';
23
-
24
- render(
25
- <ErrorMessage id={ERROR_ID}>hello <a href="#foo">world</a></ErrorMessage>
26
- );
27
-
28
- const errorMessageElement = screen.getByRole('paragraph');
29
-
30
- expect(errorMessageElement.innerHTML).toEqual('hello <a href="#foo">world</a>');
31
- });
32
-
33
21
  test('passing additional props', () => {
34
22
  render(
35
- <ErrorMessage data-test="foo" text={ERROR_TEXT} id={ERROR_ID}/>
23
+ <ErrorMessage data-test="foo" id={ERROR_ID}>{ERROR_TEXT}</ErrorMessage>
36
24
  )
37
25
 
38
26
  const errorMessageElement = screen.getByRole('paragraph');
@@ -41,7 +29,7 @@ test('passing additional props', () => {
41
29
 
42
30
  test('passing additional CSS classes', () => {
43
31
  render(
44
- <ErrorMessage className="foo" text={ERROR_TEXT} id={ERROR_ID}/>
32
+ <ErrorMessage className="foo" id={ERROR_ID}>{ERROR_TEXT}</ErrorMessage>
45
33
  )
46
34
 
47
35
  const errorMessageElement = screen.getByRole('paragraph');
@@ -2,7 +2,6 @@ const ErrorMessage = ({
2
2
  children,
3
3
  className,
4
4
  id,
5
- text,
6
5
  ...props
7
6
  }: SGDS.Component.ErrorMessage) => {
8
7
  return (
@@ -11,11 +10,10 @@ const ErrorMessage = ({
11
10
  'ds_question__error-message',
12
11
  className
13
12
  ].join(' ')}
14
- dangerouslySetInnerHTML={text ? { __html: text } : undefined}
15
13
  id={id}
16
14
  {...props}
17
15
  >
18
- {!text ? children : null}
16
+ {children}
19
17
  </p>
20
18
  );
21
19
  };
@@ -0,0 +1,38 @@
1
+ import type { Meta, StoryObj } from '@storybook/react-vite';
2
+ import argTypes from '../../../.storybook/sgdsArgTypes';
3
+
4
+ import ErrorSummary from './ErrorSummary';
5
+
6
+ const meta = {
7
+ title: 'Components/Error summary',
8
+ component: ErrorSummary,
9
+ argTypes: {
10
+ linkComponent: argTypes.linkComponent(),
11
+ title: {
12
+ description: 'The title of the error summary',
13
+ type: 'string'
14
+ },
15
+ children: argTypes.children()
16
+ },
17
+ args: {
18
+ children: <>
19
+ <ErrorSummary.Item fragmentId="did-resolve">
20
+ Did this resolve your issue?
21
+ </ErrorSummary.Item>
22
+ <ErrorSummary.Item fragmentId="what-topics">
23
+ What topics are you interested in?
24
+ </ErrorSummary.Item>
25
+ <ErrorSummary.Item fragmentId="more-detail">
26
+ Please provide more detail
27
+ </ErrorSummary.Item>
28
+ </>,
29
+ title: 'There is a problem'
30
+ }
31
+ } satisfies Meta<typeof ErrorSummary>;
32
+
33
+ export default meta;
34
+ type Story = StoryObj<typeof meta>;
35
+
36
+ export const Default: Story = {
37
+
38
+ };
@@ -0,0 +1,75 @@
1
+ import type { Meta, StoryObj } from '@storybook/react-vite';
2
+
3
+ import FileDownload from './FileDownload';
4
+
5
+ const meta = {
6
+ title: 'Components/File download',
7
+ component: FileDownload,
8
+ argTypes: {
9
+ cover: {
10
+ description: 'URL of a custom cover image',
11
+ type: 'string'
12
+ },
13
+ fileSize: {
14
+ description: 'Description of the file size',
15
+ type: 'string'
16
+ },
17
+ fileType: {
18
+ description: 'A description of the file type',
19
+ type: 'string'
20
+ },
21
+ fileUrl: {
22
+ description: 'The URL of the file to download',
23
+ type: 'string'
24
+ },
25
+ icon: {
26
+ options: ['Audio','Csv','Excel','File','Generic','Geodata','Ical','Ico','Image','Odf','Odg','Odp','Ods','Odt','Pdf','Ppt','Rtf','Text','Video','Word','Xml','Zip'],
27
+ control: { type: 'select' },
28
+ type: 'string'
29
+ },
30
+ isHighlighted: {
31
+ control: 'boolean',
32
+ description: 'Add a highlight to the file download'
33
+ },
34
+ title: {
35
+ description: 'The document title, used in the link text',
36
+ type: {
37
+ name: 'string',
38
+ required: true
39
+ }
40
+ }
41
+ },
42
+ args: {
43
+ fileUrl: '#',
44
+ title: 'My file',
45
+ icon: 'Pdf',
46
+ fileSize: '1.2MB',
47
+ fileType: '6 page PDF'
48
+ }
49
+ } satisfies Meta<typeof FileDownload>;
50
+
51
+ export default meta;
52
+ type Story = StoryObj<typeof meta>;
53
+
54
+ export const Default: Story = {
55
+
56
+ };
57
+
58
+ export const Highlighted: Story = {
59
+ args: {
60
+ isHighlighted: true
61
+ }
62
+ };
63
+
64
+ export const CoverImage: Story = {
65
+ args: {
66
+ cover: 'static/images/highland-cow.jpg'
67
+ }
68
+ };
69
+
70
+ export const NoMetadata: Story = {
71
+ args: {
72
+ fileSize: undefined,
73
+ fileType: undefined
74
+ }
75
+ };
@@ -45,7 +45,7 @@ test('inset text renders correctly', () => {
45
45
 
46
46
  test('highlighted file download', () => {
47
47
  render(
48
- <FileDownload highlighted fileUrl={FILE_URL} title={FILE_TITLE} data-testid="file-download" />
48
+ <FileDownload isHighlighted fileUrl={FILE_URL} title={FILE_TITLE} data-testid="file-download" />
49
49
  );
50
50
 
51
51
  const fileDownload = screen.getByTestId('file-download');
@@ -4,8 +4,8 @@ import FileIcon from '../../common/FileIcon';
4
4
  const FileDownload = ({
5
5
  className,
6
6
  cover,
7
- highlighted,
8
7
  icon = 'Generic',
8
+ isHighlighted,
9
9
  fileSize,
10
10
  fileType,
11
11
  fileUrl,
@@ -18,7 +18,7 @@ const FileDownload = ({
18
18
  return (
19
19
  <div className={[
20
20
  'ds_file-download',
21
- highlighted && 'ds_file-download--highlighted',
21
+ isHighlighted && 'ds_file-download--highlighted',
22
22
  className
23
23
  ].join(' ')}
24
24
  {...props}
@@ -0,0 +1,20 @@
1
+ import type { Meta, StoryObj } from '@storybook/react-vite';
2
+ import HideThisPage from './HideThisPage';
3
+
4
+ const meta = {
5
+ title: 'Components/Hide this page',
6
+ component: HideThisPage,
7
+ argTypes: {
8
+ escapeUrl: {
9
+ description: 'The URL to take the user to',
10
+ type: 'string'
11
+ }
12
+ }
13
+ } satisfies Meta<typeof HideThisPage>;
14
+
15
+ export default meta;
16
+ type Story = StoryObj<typeof meta>;
17
+
18
+ export const Default: Story = {
19
+
20
+ };
@@ -0,0 +1,21 @@
1
+ import type { Meta, StoryObj } from '@storybook/react-vite';
2
+ import argTypes from '../../../.storybook/sgdsArgTypes';
3
+
4
+ import InsetText from './InsetText';
5
+
6
+ const meta = {
7
+ title: 'Components/Inset text',
8
+ component: InsetText,
9
+ argTypes: {
10
+ children: argTypes.children()
11
+ }
12
+ } satisfies Meta<typeof InsetText>;
13
+
14
+ export default meta;
15
+ type Story = StoryObj<typeof meta>;
16
+
17
+ export const Default: Story = {
18
+ args: {
19
+ children: <p>You may be able to <a href="#inset">apply for free school meals</a> at the same time as you apply for the clothing grant.</p>
20
+ }
21
+ };
@@ -0,0 +1,57 @@
1
+ import type { Meta, StoryObj } from '@storybook/react-vite';
2
+ import argTypes from '../../../.storybook/sgdsArgTypes';
3
+
4
+ import NotificationBanner from './NotificationBanner';
5
+
6
+ const meta = {
7
+ title: 'Components/Notification banner',
8
+ component: NotificationBanner,
9
+ argTypes: {
10
+ children: argTypes.children(),
11
+ hasColourIcon: {
12
+ control: 'boolean',
13
+ description: 'Makes the icon display in the alternative colour scheme'
14
+ },
15
+ hasIcon: {
16
+ description: 'Shows the ‘high priority’ icon on the notification banner',
17
+ control: 'boolean'
18
+ },
19
+ hasInverseIcon: {
20
+ control: 'boolean',
21
+ description: 'Makes the icon be inverted against a circle background'
22
+ },
23
+ isDismissable: {
24
+ control: 'boolean',
25
+ description: 'Shows a ‘close’ button on the notification banner'
26
+ },
27
+ title: {
28
+ description: 'A hidden title for the notification banner, useful for screen reader users',
29
+ type: 'string'
30
+ }
31
+ },
32
+ args: {
33
+ children: <p>We need to tell you about <a href="#notification">something</a></p>,
34
+ title: 'Information'
35
+ }
36
+ } satisfies Meta<typeof NotificationBanner>;
37
+
38
+ export default meta;
39
+ type Story = StoryObj<typeof meta>;
40
+
41
+ export const Default: Story = {
42
+
43
+ };
44
+
45
+ export const Dismissable: Story = {
46
+ args: {
47
+ isDismissable: true
48
+ }
49
+ };
50
+
51
+ export const WithIcon: Story = {
52
+ args: {
53
+ hasColourIcon: true,
54
+ hasInverseIcon: true,
55
+ hasIcon: true
56
+ }
57
+ };
@@ -29,7 +29,7 @@ test('notification banner renders correctly', () => {
29
29
  */
30
30
  test('notification banner with icon', () => {
31
31
  render(
32
- <NotificationBanner icon>
32
+ <NotificationBanner hasIcon>
33
33
  {BANNER_TEXT}
34
34
  </NotificationBanner>
35
35
  );
@@ -6,10 +6,10 @@ import DSNotificationBanner from '@scottish-government/design-system/src/compone
6
6
  const NotificationBanner = ({
7
7
  children,
8
8
  className,
9
- close,
10
9
  hasColourIcon,
10
+ hasIcon,
11
11
  hasInverseIcon,
12
- icon,
12
+ isDismissable,
13
13
  title,
14
14
  ...props
15
15
  }: SGDS.Common.AbstractNotificationBanner) => {
@@ -27,8 +27,8 @@ const NotificationBanner = ({
27
27
  'ds_reversed',
28
28
  className
29
29
  ].join(' ')}
30
- close={close}
31
- icon={icon ? "PriorityHigh" : undefined}
30
+ isDismissable={isDismissable}
31
+ icon={hasIcon ? "PriorityHigh" : undefined}
32
32
  hasColourIcon={hasColourIcon}
33
33
  hasInverseIcon={hasInverseIcon}
34
34
  ref={ref}
@@ -0,0 +1,32 @@
1
+ import type { Meta, StoryObj } from '@storybook/react-vite';
2
+ import argTypes from '../../../.storybook/sgdsArgTypes';
3
+
4
+ import NotificationPanel from './NotificationPanel';
5
+
6
+ const meta = {
7
+ title: 'Components/Notification panel',
8
+ component: NotificationPanel,
9
+ argTypes: {
10
+ ariaLive: argTypes.ariaLive(),
11
+ headingLevel: argTypes.headingLevel(),
12
+ title: {
13
+ description: 'Title of the notification panel',
14
+ type: {
15
+ name: 'string',
16
+ required: true
17
+ }
18
+ },
19
+ children: argTypes.children()
20
+ },
21
+ args: {
22
+ children: <p>Your Saltire Scholarship Application form has been successfully submitted.</p>,
23
+ title: 'Thank you'
24
+ }
25
+ } satisfies Meta<typeof NotificationPanel>;
26
+
27
+ export default meta;
28
+ type Story = StoryObj<typeof meta>;
29
+
30
+ export const Default: Story = {
31
+
32
+ };
@@ -0,0 +1,60 @@
1
+ import type { Meta, StoryObj } from '@storybook/react-vite';
2
+ import argTypes from '../../../.storybook/sgdsArgTypes';
3
+
4
+ import PageHeader from './PageHeader';
5
+ import Metadata from '../PageMetadata/PageMetadata';
6
+
7
+ const meta = {
8
+ title: 'Components/Page header',
9
+ component: PageHeader,
10
+ argTypes: {
11
+ children: argTypes.children(),
12
+ label: {
13
+ description: 'Text to use for a label shown above the H1 element',
14
+ type: 'string'
15
+ },
16
+ title: {
17
+ description: 'Text to use for the H1 element',
18
+ type: {
19
+ name: 'string',
20
+ required: true
21
+ }
22
+ }
23
+ },
24
+ args: {
25
+ label: 'Publication - Research and analysis',
26
+ title: 'Cancer prehabilitation in Scotland: 2025 survey findings report'
27
+ }
28
+ } satisfies Meta<typeof PageHeader>;
29
+
30
+ export default meta;
31
+ type Story = StoryObj<typeof meta>;
32
+
33
+ export const Default: Story = {
34
+
35
+ };
36
+
37
+ export const WithMetadata: Story = {
38
+ args: {
39
+ children: <>
40
+ <Metadata>
41
+ <Metadata.Item name="Published">
42
+ 3 September 2025
43
+ </Metadata.Item>
44
+ <Metadata.Item name="From">
45
+ <a href="#two">
46
+ Director-General Health and Social Care
47
+ </a>
48
+ </Metadata.Item>
49
+ <Metadata.Item name="Directorate">
50
+ <a href="#one">
51
+ Population Health Directorate
52
+ </a>
53
+ </Metadata.Item>
54
+ <Metadata.Item name="ISBN">
55
+ 9781806431007
56
+ </Metadata.Item>
57
+ </Metadata>
58
+ </>
59
+ }
60
+ };
@@ -0,0 +1,58 @@
1
+ import type { Meta, StoryObj } from '@storybook/react-vite';
2
+ import argTypes from '../../../.storybook/sgdsArgTypes';
3
+
4
+ import Metadata from './PageMetadata';
5
+
6
+ const meta = {
7
+ title: 'Components/Page metadata',
8
+ component: Metadata,
9
+ argTypes: {
10
+ children: argTypes.children(),
11
+ isInline: {
12
+ control: 'boolean',
13
+ description: 'Makes the page metadata use the truncated ‘inline’ display'
14
+ },
15
+ },
16
+ args: {
17
+ children: <Metadata.Item name="Last updated">
18
+ 21/04/2020
19
+ </Metadata.Item>
20
+ }
21
+ } satisfies Meta<typeof Metadata>;
22
+
23
+ export default meta;
24
+ type Story = StoryObj<typeof meta>;
25
+
26
+ export const Default: Story = {
27
+
28
+ };
29
+
30
+ export const WithLinks: Story = {
31
+ args: {
32
+ children: <>
33
+ <Metadata.Item name="Part of">
34
+ <a href="#two">
35
+ Equality and rights
36
+ </a>
37
+ ,{' '}
38
+ <a href="#three">
39
+ Law and order
40
+ </a>
41
+ </Metadata.Item>
42
+ </>
43
+ }
44
+ }
45
+
46
+ export const Inline: Story = {
47
+ args: {
48
+ children: <>
49
+ <Metadata.Item name="Content type">
50
+ Publication
51
+ </Metadata.Item>
52
+ <Metadata.Item name="Last updated">
53
+ 21/04/2020
54
+ </Metadata.Item>
55
+ </>,
56
+ isInline: true
57
+ }
58
+ }
@@ -24,12 +24,12 @@ test('metadata renders correctly', () => {
24
24
  expect(metadataItemKey).toHaveClass('ds_metadata__key');
25
25
  expect(metadataItemKey.textContent).toEqual(NAME);
26
26
  expect(metadataItemValue).toHaveClass('ds_metadata__value');
27
- expect(metadataItemValue.textContent).toEqual(VALUE);
27
+ expect(metadataItemValue.textContent.trim()).toEqual(VALUE);
28
28
  });
29
29
 
30
30
  test('inline metadata', () => {
31
31
  render(
32
- <Metadata inline>
32
+ <Metadata isInline>
33
33
  <Metadata.Item name={NAME}>
34
34
  {VALUE}
35
35
  </Metadata.Item>
@@ -11,9 +11,9 @@ const MetadataItem= ({
11
11
  ].join(' ')}
12
12
  {...props}
13
13
  >
14
- <dt className="ds_metadata__key">{name}</dt>{' '}
14
+ <dt className="ds_metadata__key">{name}</dt>
15
15
  <dd className="ds_metadata__value">
16
- {children}
16
+ {children}{' '}
17
17
  </dd>
18
18
  </div>
19
19
  );
@@ -22,14 +22,14 @@ const MetadataItem= ({
22
22
  const Metadata = ({
23
23
  children,
24
24
  className,
25
- inline,
25
+ isInline,
26
26
  ...props
27
27
  }: SGDS.Component.Metadata) => {
28
28
  return (
29
29
  <dl
30
30
  className={[
31
31
  'ds_metadata',
32
- inline && 'ds_metadata--inline',
32
+ isInline && 'ds_metadata--inline',
33
33
  className
34
34
  ].join(' ')}
35
35
  {...props}
@@ -0,0 +1,69 @@
1
+ import type { Meta, StoryObj } from '@storybook/react-vite';
2
+ import argTypes from '../../../.storybook/sgdsArgTypes';
3
+
4
+ import Pagination from './Pagination';
5
+
6
+ const meta = {
7
+ title: 'Components/Pagination',
8
+ component: Pagination,
9
+ argTypes: {
10
+ ariaLabel: argTypes.ariaLabel(),
11
+ onClick: argTypes.onClick(),
12
+ linkComponent: argTypes.linkComponent({
13
+ description: 'Function that returns an element, to customise the output. Used on all links in the pagination.'
14
+ }),
15
+ padding: {
16
+ description: 'Number of other pages to show on either side of the current page',
17
+ type: 'number'
18
+ },
19
+ page: {
20
+ description: 'Current page number',
21
+ type: {
22
+ name: 'number',
23
+ required: true
24
+ }
25
+ },
26
+ pattern: {
27
+ description: 'Pattern to use for the pagination links',
28
+ type: 'string'
29
+ },
30
+ totalPages: {
31
+ description: 'Total number of pages',
32
+ type: {
33
+ name: 'number',
34
+ required: true
35
+ }
36
+ }
37
+ },
38
+ args: {
39
+ ariaLabel: 'Pages',
40
+ page: 1,
41
+ padding: 1,
42
+ pattern: '/search?page=$1',
43
+ totalPages: 21
44
+ }
45
+ } satisfies Meta<typeof Pagination>;
46
+
47
+ export default meta;
48
+ type Story = StoryObj<typeof meta>;
49
+
50
+ export const Default: Story = {
51
+
52
+ };
53
+
54
+ export const MiddlePage: Story = {
55
+ args: {page: 10}
56
+ }
57
+
58
+ export const MorePadding: Story = {
59
+ args: {page: 10, padding: 3}
60
+ }
61
+
62
+ export const Click: Story = {
63
+ args: {
64
+ onClick: (event) => { event.preventDefault(); console.log('pagination click'); }
65
+ },
66
+ play: async ({ canvas, userEvent }) => {
67
+ await userEvent.click(canvas.getAllByRole('link')[0]);
68
+ }
69
+ }