@scottish-government/designsystem-react 0.5.1 → 0.7.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 (242) hide show
  1. package/.svgrrc +2 -1
  2. package/.svgrrc_documents +15 -0
  3. package/@types/common/FileIcon.d.ts +7 -0
  4. package/@types/components/Accordion.d.ts +2 -2
  5. package/@types/components/ConfirmationMessage.d.ts +1 -1
  6. package/@types/components/FileDownload.d.ts +11 -0
  7. package/@types/components/NotificationPanel.d.ts +1 -1
  8. package/@types/components/SummaryCard.d.ts +1 -1
  9. package/@types/components/Tabs.d.ts +1 -1
  10. package/@types/sgds.d.ts +2 -1
  11. package/CHANGELOG.md +81 -0
  12. package/README.md +4 -0
  13. package/dist/common/AbstractNotificationBanner.jsx +63 -0
  14. package/dist/common/ConditionalWrapper.jsx +8 -0
  15. package/dist/common/FileIcon.jsx +51 -0
  16. package/dist/common/HintText.jsx +9 -0
  17. package/dist/common/Icon.jsx +57 -0
  18. package/dist/common/ScreenReaderText.jsx +9 -0
  19. package/dist/common/WrapperTag.jsx +11 -0
  20. package/dist/common/file-icon.jsx +51 -0
  21. package/dist/common/icon.jsx +1 -1
  22. package/dist/components/Accordion/Accordion.jsx +102 -0
  23. package/dist/components/AspectBox/AspectBox.jsx +79 -0
  24. package/dist/components/BackToTop/BackToTop.jsx +27 -0
  25. package/dist/components/Breadcrumbs/Breadcrumbs.jsx +28 -0
  26. package/dist/components/Button/Button.jsx +30 -0
  27. package/dist/components/Checkbox/Checkbox.jsx +62 -0
  28. package/dist/components/ConfirmationMessage/ConfirmationMessage.jsx +24 -0
  29. package/dist/components/ContentsNav/ContentsNav.jsx +33 -0
  30. package/dist/components/CookieBanner/CookieBanner.jsx +21 -0
  31. package/dist/components/DatePicker/DatePicker.jsx +54 -0
  32. package/dist/components/Details/Details.jsx +17 -0
  33. package/dist/components/ErrorMessage/ErrorMessage.jsx +12 -0
  34. package/dist/components/ErrorSummary/ErrorSummary.jsx +27 -0
  35. package/dist/components/FileDownload/FileDownload.jsx +50 -0
  36. package/dist/components/HideThisPage/HideThisPage.jsx +71 -0
  37. package/dist/components/InsetText/InsetText.jsx +14 -0
  38. package/dist/components/NotificationBanner/NotificationBanner.jsx +26 -0
  39. package/dist/components/NotificationPanel/NotificationPanel.jsx +21 -0
  40. package/dist/components/PageHeader/PageHeader.jsx +15 -0
  41. package/dist/components/PageMetadata/PageMetadata.jsx +26 -0
  42. package/dist/components/Pagination/Pagination.jsx +97 -0
  43. package/dist/components/PhaseBanner/PhaseBanner.jsx +23 -0
  44. package/dist/components/Question/Question.jsx +22 -0
  45. package/dist/components/RadioButton/RadioButton.jsx +43 -0
  46. package/dist/components/Select/Select.jsx +52 -0
  47. package/dist/components/SequentialNavigation/SequentialNavigation.jsx +31 -0
  48. package/dist/components/SideNavigation/SideNavigation.jsx +52 -0
  49. package/dist/components/SiteHeader/SiteHeader.jsx +68 -0
  50. package/dist/components/SiteNavigation/SiteNavigation.jsx +22 -0
  51. package/dist/components/SiteSearch/SiteSearch.jsx +55 -0
  52. package/dist/components/SkipLinks/SkipLinks.jsx +21 -0
  53. package/dist/components/SummaryCard/SummaryCard.jsx +67 -0
  54. package/dist/components/SummaryList/SummaryList.jsx +75 -0
  55. package/dist/components/Table/Table.jsx +24 -0
  56. package/dist/components/Tabs/Tabs.jsx +99 -0
  57. package/dist/components/Tag/Tag.jsx +13 -0
  58. package/dist/components/TaskList/TaskList.jsx +95 -0
  59. package/dist/components/TextInput/TextInput.jsx +58 -0
  60. package/dist/components/Textarea/Textarea.jsx +54 -0
  61. package/dist/components/WarningText/WarningText.jsx +16 -0
  62. package/dist/components/file-download/file-download.jsx +50 -0
  63. package/dist/images/documents/audio.jsx +47 -0
  64. package/dist/images/documents/csv.jsx +57 -0
  65. package/dist/images/documents/excel.jsx +57 -0
  66. package/dist/images/documents/file.jsx +48 -0
  67. package/dist/images/documents/generic.jsx +47 -0
  68. package/dist/images/documents/geodata.jsx +44 -0
  69. package/dist/images/documents/ical.jsx +48 -0
  70. package/dist/images/documents/ico.jsx +48 -0
  71. package/dist/images/documents/image.jsx +43 -0
  72. package/dist/images/documents/index.js +50 -0
  73. package/dist/images/documents/odf.jsx +46 -0
  74. package/dist/images/documents/odg.jsx +46 -0
  75. package/dist/images/documents/odp.jsx +45 -0
  76. package/dist/images/documents/ods.jsx +55 -0
  77. package/dist/images/documents/odt.jsx +46 -0
  78. package/dist/images/documents/pdf.jsx +48 -0
  79. package/dist/images/documents/ppt.jsx +47 -0
  80. package/dist/images/documents/rtf.jsx +48 -0
  81. package/dist/images/documents/text.jsx +48 -0
  82. package/dist/images/documents/video.jsx +47 -0
  83. package/dist/images/documents/word.jsx +48 -0
  84. package/dist/images/documents/xml.jsx +48 -0
  85. package/dist/images/documents/zip.jsx +48 -0
  86. package/dist/images/icons/arrow_upward.jsx +41 -0
  87. package/dist/images/icons/calendar_today.jsx +41 -0
  88. package/dist/images/icons/cancel.jsx +40 -0
  89. package/dist/images/icons/check_circle.jsx +41 -0
  90. package/dist/images/icons/chevron_left.jsx +41 -0
  91. package/dist/images/icons/chevron_right.jsx +41 -0
  92. package/dist/images/icons/close.jsx +41 -0
  93. package/dist/images/icons/description.jsx +41 -0
  94. package/dist/images/icons/double_chevron_left.jsx +40 -0
  95. package/dist/images/icons/double_chevron_right.jsx +40 -0
  96. package/dist/images/icons/error.jsx +41 -0
  97. package/dist/images/icons/expand_less.jsx +41 -0
  98. package/dist/images/icons/expand_more.jsx +41 -0
  99. package/dist/images/icons/index.js +40 -0
  100. package/dist/images/icons/list.jsx +44 -0
  101. package/dist/images/icons/menu.jsx +41 -0
  102. package/dist/images/icons/priority_high.jsx +42 -0
  103. package/dist/images/icons/search.jsx +41 -0
  104. package/dist/tsconfig.tsbuildinfo +1 -1
  105. package/package.json +2 -1
  106. package/src/common/{abstract-notification-banner.test.tsx → AbstractNotificationBanner.test.tsx} +11 -11
  107. package/src/common/{abstract-notification-banner.tsx → AbstractNotificationBanner.tsx} +2 -2
  108. package/src/common/{conditional-wrapper.test.tsx → ConditionalWrapper.test.tsx} +1 -1
  109. package/src/common/FileIcon.test.tsx +50 -0
  110. package/src/common/FileIcon.tsx +25 -0
  111. package/src/common/{hint-text.test.tsx → HintText.test.tsx} +12 -12
  112. package/src/common/{icon.test.tsx → Icon.test.tsx} +16 -16
  113. package/src/common/{icon.tsx → Icon.tsx} +1 -1
  114. package/src/common/{screen-reader-text.test.tsx → ScreenReaderText.test.tsx} +5 -5
  115. package/src/common/{wrapper-tag.test.tsx → WrapperTag.test.tsx} +5 -5
  116. package/src/components/{accordion/accordion.test.tsx → Accordion/Accordion.test.tsx} +35 -35
  117. package/src/components/{accordion/accordion.tsx → Accordion/Accordion.tsx} +5 -5
  118. package/src/components/{aspect-box/aspect-box.test.tsx → AspectBox/AspectBox.test.tsx} +2 -2
  119. package/src/components/{back-to-top/back-to-top.test.tsx → BackToTop/BackToTop.test.tsx} +1 -1
  120. package/src/components/{back-to-top/back-to-top.tsx → BackToTop/BackToTop.tsx} +1 -1
  121. package/src/components/{breadcrumbs/breadcrumbs.test.tsx → Breadcrumbs/Breadcrumbs.test.tsx} +7 -7
  122. package/src/components/{button/button.test.tsx → Button/Button.test.tsx} +1 -1
  123. package/src/components/{button/button.tsx → Button/Button.tsx} +3 -3
  124. package/src/components/{checkbox/checkbox.test.tsx → Checkbox/Checkbox.test.tsx} +16 -16
  125. package/src/components/{checkbox/checkbox.tsx → Checkbox/Checkbox.tsx} +1 -1
  126. package/src/components/{confirmation-message/confirmation-message.test.tsx → ConfirmationMessage/ConfirmationMessage.test.tsx} +12 -14
  127. package/src/components/{confirmation-message/confirmation-message.tsx → ConfirmationMessage/ConfirmationMessage.tsx} +4 -4
  128. package/src/components/{contents-nav/contents-nav.test.tsx → ContentsNav/ContentsNav.test.tsx} +21 -28
  129. package/src/components/{contents-nav/contents-nav.tsx → ContentsNav/ContentsNav.tsx} +1 -1
  130. package/src/components/{cookie-banner/cookie-banner.test.tsx → CookieBanner/CookieBanner.test.tsx} +3 -3
  131. package/src/components/{cookie-banner/cookie-banner.tsx → CookieBanner/CookieBanner.tsx} +1 -1
  132. package/src/components/{date-picker/date-picker.test.tsx → DatePicker/DatePicker.test.tsx} +76 -66
  133. package/src/components/{date-picker/date-picker.tsx → DatePicker/DatePicker.tsx} +2 -2
  134. package/src/components/{details/details.test.tsx → Details/Details.test.tsx} +10 -10
  135. package/src/components/{error-message/error-message.test.tsx → ErrorMessage/ErrorMessage.test.tsx} +10 -10
  136. package/src/components/{error-summary/error-summary.test.tsx → ErrorSummary/ErrorSummary.test.tsx} +13 -14
  137. package/src/components/{error-summary/error-summary.tsx → ErrorSummary/ErrorSummary.tsx} +1 -1
  138. package/src/components/FileDownload/FileDownload.test.tsx +167 -0
  139. package/src/components/FileDownload/FileDownload.tsx +67 -0
  140. package/src/components/{hide-this-page/hide-this-page.test.tsx → HideThisPage/HideThisPage.test.tsx} +4 -4
  141. package/src/components/{hide-this-page/hide-this-page.tsx → HideThisPage/HideThisPage.tsx} +3 -3
  142. package/src/components/{inset-text/inset-text.test.tsx → InsetText/InsetText.test.tsx} +1 -1
  143. package/src/components/{notification-banner/notification-banner.test.tsx → NotificationBanner/NotificationBanner.test.tsx} +4 -4
  144. package/src/components/{notification-banner/notification-banner.tsx → NotificationBanner/NotificationBanner.tsx} +1 -1
  145. package/src/components/{notification-panel/notification-panel.test.tsx → NotificationPanel/NotificationPanel.test.tsx} +24 -23
  146. package/src/components/{notification-panel/notification-panel.tsx → NotificationPanel/NotificationPanel.tsx} +3 -3
  147. package/src/components/{page-header/page-header.test.tsx → PageHeader/PageHeader.test.tsx} +9 -9
  148. package/src/components/{page-metadata/page-metadata.test.tsx → PageMetadata/PageMetadata.test.tsx} +9 -9
  149. package/src/components/{pagination/pagination.test.tsx → Pagination/Pagination.test.tsx} +56 -56
  150. package/src/components/{pagination/pagination.tsx → Pagination/Pagination.tsx} +1 -1
  151. package/src/components/{phase-banner/phase-banner.test.tsx → PhaseBanner/PhaseBanner.test.tsx} +9 -9
  152. package/src/components/{phase-banner/phase-banner.tsx → PhaseBanner/PhaseBanner.tsx} +1 -1
  153. package/src/components/{question/question.test.tsx → Question/Question.test.tsx} +10 -10
  154. package/src/components/{question/question.tsx → Question/Question.tsx} +3 -3
  155. package/src/components/{radio-button/radio-button.test.tsx → RadioButton/RadioButton.test.tsx} +23 -23
  156. package/src/components/{radio-button/radio-button.tsx → RadioButton/RadioButton.tsx} +1 -1
  157. package/src/components/{select/select.test.tsx → Select/Select.test.tsx} +67 -64
  158. package/src/components/{select/select.tsx → Select/Select.tsx} +2 -2
  159. package/src/components/{sequential-navigation/sequential-navigation.test.tsx → SequentialNavigation/SequentialNavigation.test.tsx} +18 -18
  160. package/src/components/{side-navigation/side-navigation.test.tsx → SideNavigation/SideNavigation.test.tsx} +8 -8
  161. package/src/components/{site-header/site-header.test.tsx → SiteHeader/SiteHeader.test.tsx} +25 -25
  162. package/src/components/{site-header/site-header.tsx → SiteHeader/SiteHeader.tsx} +4 -4
  163. package/src/components/{site-navigation/site-navigation.test.tsx → SiteNavigation/SiteNavigation.test.tsx} +8 -8
  164. package/src/components/{site-search/site-search.test.tsx → SiteSearch/SiteSearch.test.tsx} +16 -16
  165. package/src/components/{site-search/site-search.tsx → SiteSearch/SiteSearch.tsx} +1 -1
  166. package/src/components/{skip-links/skip-links.test.tsx → SkipLinks/SkipLinks.test.tsx} +15 -15
  167. package/src/components/{summary-card/summary-card.test.tsx → SummaryCard/SummaryCard.test.tsx} +28 -28
  168. package/src/components/{summary-card/summary-card.tsx → SummaryCard/SummaryCard.tsx} +4 -4
  169. package/src/components/{summary-list/summary-list.test.tsx → SummaryList/SummaryList.test.tsx} +55 -56
  170. package/src/components/{summary-list/summary-list.tsx → SummaryList/SummaryList.tsx} +2 -2
  171. package/src/components/{table/table.test.tsx → Table/Table.test.tsx} +4 -4
  172. package/src/components/{tabs/tabs.test.tsx → Tabs/Tabs.test.tsx} +22 -42
  173. package/src/components/{tabs/tabs.tsx → Tabs/Tabs.tsx} +3 -3
  174. package/src/components/{tag/tag.test.tsx → Tag/Tag.test.tsx} +10 -10
  175. package/src/components/{task-list/task-list.test.tsx → TaskList/TaskList.test.tsx} +109 -108
  176. package/src/components/{task-list/task-list.tsx → TaskList/TaskList.tsx} +4 -4
  177. package/src/components/{text-input/text-input.test.tsx → TextInput/TextInput.test.tsx} +92 -87
  178. package/src/components/{text-input/text-input.tsx → TextInput/TextInput.tsx} +4 -4
  179. package/src/components/{textarea/textarea.test.tsx → Textarea/Textarea.test.tsx} +71 -67
  180. package/src/components/{textarea/textarea.tsx → Textarea/Textarea.tsx} +3 -3
  181. package/src/components/{warning-text/warning-text.test.tsx → WarningText/WarningText.test.tsx} +1 -1
  182. package/src/images/documents/audio.tsx +34 -0
  183. package/src/images/documents/csv.tsx +39 -0
  184. package/src/images/documents/excel.tsx +39 -0
  185. package/src/images/documents/file.tsx +30 -0
  186. package/src/images/documents/generic.tsx +26 -0
  187. package/src/images/documents/geodata.tsx +29 -0
  188. package/src/images/documents/ical.tsx +30 -0
  189. package/src/images/documents/ico.tsx +30 -0
  190. package/src/images/documents/image.tsx +25 -0
  191. package/src/images/documents/index.ts +22 -0
  192. package/src/images/documents/odf.tsx +28 -0
  193. package/src/images/documents/odg.tsx +28 -0
  194. package/src/images/documents/odp.tsx +33 -0
  195. package/src/images/documents/ods.tsx +37 -0
  196. package/src/images/documents/odt.tsx +28 -0
  197. package/src/images/documents/pdf.tsx +30 -0
  198. package/src/images/documents/ppt.tsx +28 -0
  199. package/src/images/documents/rtf.tsx +30 -0
  200. package/src/images/documents/text.tsx +30 -0
  201. package/src/images/documents/video.tsx +34 -0
  202. package/src/images/documents/word.tsx +30 -0
  203. package/src/images/documents/xml.tsx +30 -0
  204. package/src/images/documents/zip.tsx +30 -0
  205. package/src/images/icons/index.ts +17 -0
  206. package/vite.config.ts +1 -1
  207. package/src/icons/index.ts +0 -17
  208. /package/src/common/{conditional-wrapper.tsx → ConditionalWrapper.tsx} +0 -0
  209. /package/src/common/{hint-text.tsx → HintText.tsx} +0 -0
  210. /package/src/common/{screen-reader-text.tsx → ScreenReaderText.tsx} +0 -0
  211. /package/src/common/{wrapper-tag.tsx → WrapperTag.tsx} +0 -0
  212. /package/src/components/{aspect-box/aspect-box.tsx → AspectBox/AspectBox.tsx} +0 -0
  213. /package/src/components/{breadcrumbs/breadcrumbs.tsx → Breadcrumbs/Breadcrumbs.tsx} +0 -0
  214. /package/src/components/{details/details.tsx → Details/Details.tsx} +0 -0
  215. /package/src/components/{error-message/error-message.tsx → ErrorMessage/ErrorMessage.tsx} +0 -0
  216. /package/src/components/{inset-text/inset-text.tsx → InsetText/InsetText.tsx} +0 -0
  217. /package/src/components/{page-header/page-header.tsx → PageHeader/PageHeader.tsx} +0 -0
  218. /package/src/components/{page-metadata/page-metadata.tsx → PageMetadata/PageMetadata.tsx} +0 -0
  219. /package/src/components/{sequential-navigation/sequential-navigation.tsx → SequentialNavigation/SequentialNavigation.tsx} +0 -0
  220. /package/src/components/{side-navigation/side-navigation.tsx → SideNavigation/SideNavigation.tsx} +0 -0
  221. /package/src/components/{site-navigation/site-navigation.tsx → SiteNavigation/SiteNavigation.tsx} +0 -0
  222. /package/src/components/{skip-links/skip-links.tsx → SkipLinks/SkipLinks.tsx} +0 -0
  223. /package/src/components/{table/table.tsx → Table/Table.tsx} +0 -0
  224. /package/src/components/{tag/tag.tsx → Tag/Tag.tsx} +0 -0
  225. /package/src/components/{warning-text/warning-text.tsx → WarningText/WarningText.tsx} +0 -0
  226. /package/src/{icons/ArrowUpward.tsx → images/icons/arrow_upward.tsx} +0 -0
  227. /package/src/{icons/CalendarToday.tsx → images/icons/calendar_today.tsx} +0 -0
  228. /package/src/{icons/Cancel.tsx → images/icons/cancel.tsx} +0 -0
  229. /package/src/{icons/CheckCircle.tsx → images/icons/check_circle.tsx} +0 -0
  230. /package/src/{icons/ChevronLeft.tsx → images/icons/chevron_left.tsx} +0 -0
  231. /package/src/{icons/ChevronRight.tsx → images/icons/chevron_right.tsx} +0 -0
  232. /package/src/{icons/Close.tsx → images/icons/close.tsx} +0 -0
  233. /package/src/{icons/Description.tsx → images/icons/description.tsx} +0 -0
  234. /package/src/{icons/DoubleChevronLeft.tsx → images/icons/double_chevron_left.tsx} +0 -0
  235. /package/src/{icons/DoubleChevronRight.tsx → images/icons/double_chevron_right.tsx} +0 -0
  236. /package/src/{icons/Error.tsx → images/icons/error.tsx} +0 -0
  237. /package/src/{icons/ExpandLess.tsx → images/icons/expand_less.tsx} +0 -0
  238. /package/src/{icons/ExpandMore.tsx → images/icons/expand_more.tsx} +0 -0
  239. /package/src/{icons/List.tsx → images/icons/list.tsx} +0 -0
  240. /package/src/{icons/Menu.tsx → images/icons/menu.tsx} +0 -0
  241. /package/src/{icons/PriorityHigh.tsx → images/icons/priority_high.tsx} +0 -0
  242. /package/src/{icons/Search.tsx → images/icons/search.tsx} +0 -0
@@ -0,0 +1,167 @@
1
+ import { test, expect } from 'vitest';
2
+ import { screen, render } from '@testing-library/react';
3
+ import FileDownload from './FileDownload';
4
+
5
+ const FILE_TITLE = 'Scotland\'s Artificial Intelligence Strategy - Trustworthy, Ethical and Inclusive';
6
+ const FILE_URL = 'my-file.file';
7
+
8
+ test('inset text renders correctly', () => {
9
+ render(
10
+ <FileDownload fileUrl={FILE_URL} title={FILE_TITLE} data-testid="file-download" />
11
+ );
12
+
13
+ const fileDownload = screen.getByTestId('file-download');
14
+
15
+ const thumbnailImage = screen.getByRole('img', {hidden: true});
16
+ const thumbnailLink = thumbnailImage.parentElement;
17
+ const thumbnailContainer = thumbnailLink?.parentElement;
18
+
19
+ const fileLink = screen.getByRole('link');
20
+ const contentContainer = fileLink.parentElement;
21
+
22
+ expect(thumbnailImage).toHaveClass('ds_file-download__thumbnail-image');
23
+ expect(thumbnailImage).toHaveAttribute('aria-label', '');
24
+ expect(thumbnailImage.tagName).toEqual('svg');
25
+
26
+ expect(thumbnailLink).toHaveClass('ds_file-download__thumbnail-link');
27
+ expect(thumbnailLink).toHaveAttribute('aria-hidden', 'true');
28
+ expect(thumbnailLink).toHaveAttribute('tabindex', '-1');
29
+ expect(thumbnailLink).toHaveAttribute('href', FILE_URL);
30
+ expect(thumbnailLink?.tagName).toEqual('A');
31
+
32
+ expect(thumbnailContainer).toHaveClass('ds_file-download__thumbnail');
33
+ expect(thumbnailContainer?.tagName).toEqual('DIV');
34
+ expect(thumbnailContainer?.parentElement).toEqual(fileDownload);
35
+
36
+ expect(contentContainer).toHaveClass('ds_file-download__content');
37
+ expect(contentContainer?.tagName).toEqual('DIV');
38
+ expect(contentContainer?.parentElement).toEqual(fileDownload);
39
+
40
+ expect(fileLink).toHaveClass('ds_file-download__title');
41
+ expect(fileLink).toHaveAttribute('href', FILE_URL);
42
+ expect(fileLink?.tagName).toEqual('A');
43
+ expect(fileLink?.textContent).toEqual(FILE_TITLE);
44
+ });
45
+
46
+ test('highlighted file download', () => {
47
+ render(
48
+ <FileDownload highlighted fileUrl={FILE_URL} title={FILE_TITLE} data-testid="file-download" />
49
+ );
50
+
51
+ const fileDownload = screen.getByTestId('file-download');
52
+
53
+ expect(fileDownload).toHaveClass('ds_file-download--highlighted');
54
+ });
55
+
56
+ // test('file download with specific icon', () => {
57
+
58
+ // });
59
+
60
+ test('file download with cover image', () => {
61
+ const COVER_URL = 'my-image.png';
62
+
63
+ render(
64
+ <FileDownload cover={COVER_URL} fileUrl={FILE_URL} title={FILE_TITLE} data-testid="file-download" />
65
+ );
66
+
67
+ const thumbnailImage = screen.getByRole('presentation', {hidden: true});
68
+
69
+ expect(thumbnailImage).toHaveClass('ds_file-download__thumbnail-image');
70
+ expect(thumbnailImage).toHaveAttribute('alt', '');
71
+ expect(thumbnailImage).toHaveAttribute('src', COVER_URL);
72
+ expect(thumbnailImage.tagName).toEqual('IMG');
73
+ });
74
+
75
+ test('file download with file size', () => {
76
+ const FILE_SIZE = '1.2 MB';
77
+
78
+ render(
79
+ <FileDownload fileSize={FILE_SIZE} fileUrl={FILE_URL} title={FILE_TITLE} data-testid="file-download" />
80
+ );
81
+
82
+ const metadataKey = screen.getByRole('term');
83
+ const metadataValue = screen.getByRole('definition');
84
+ const metadataItem = metadataKey.parentElement;
85
+ const metadataList = metadataItem?.parentElement;
86
+ const downloadDetails = metadataList?.parentElement;
87
+
88
+ expect(downloadDetails).toHaveClass('ds_file-download__details');
89
+ expect(downloadDetails?.tagName).toEqual('DIV');
90
+
91
+ expect(metadataList).toHaveClass('ds_metadata', 'ds_metadata--inline');
92
+ expect(metadataList?.tagName).toEqual('DL');
93
+
94
+ expect(metadataItem).toHaveClass('ds_metadata__item');
95
+ expect(metadataItem?.tagName).toEqual('DIV');
96
+
97
+ expect(metadataKey).toHaveClass('ds_metadata__key', 'visually-hidden');
98
+ expect(metadataKey.textContent).toEqual('File size');
99
+
100
+ expect(metadataValue).toHaveClass('ds_metadata__value');
101
+ expect(metadataValue.textContent).toEqual(FILE_SIZE);
102
+ expect(metadataValue.previousElementSibling).toEqual(metadataKey);
103
+ });
104
+
105
+ test('file download with file type', () => {
106
+ const FILE_TYPE = '5 page PDF';
107
+
108
+ render(
109
+ <FileDownload fileType={FILE_TYPE} fileUrl={FILE_URL} title={FILE_TITLE} data-testid="file-download" />
110
+ );
111
+
112
+ const metadataKey = screen.getByRole('term');
113
+ const metadataValue = screen.getByRole('definition');
114
+ const metadataItem = metadataKey.parentElement;
115
+ const metadataList = metadataItem?.parentElement;
116
+ const downloadDetails = metadataList?.parentElement;
117
+
118
+ expect(downloadDetails).toHaveClass('ds_file-download__details');
119
+ expect(downloadDetails?.tagName).toEqual('DIV');
120
+
121
+ expect(metadataList).toHaveClass('ds_metadata', 'ds_metadata--inline');
122
+ expect(metadataList?.tagName).toEqual('DL');
123
+
124
+ expect(metadataItem).toHaveClass('ds_metadata__item');
125
+ expect(metadataItem?.tagName).toEqual('DIV');
126
+
127
+ expect(metadataKey).toHaveClass('ds_metadata__key', 'visually-hidden');
128
+ expect(metadataKey.textContent).toEqual('File type');
129
+
130
+ expect(metadataValue).toHaveClass('ds_metadata__value');
131
+ expect(metadataValue.textContent).toEqual(FILE_TYPE + ',');
132
+ expect(metadataValue.previousElementSibling).toEqual(metadataKey);
133
+ });
134
+
135
+ test('association of metadata with file link', () => {
136
+ const FILE_SIZE = '1.2 MB';
137
+
138
+ render(
139
+ <FileDownload fileSize={FILE_SIZE} fileUrl={FILE_URL} title={FILE_TITLE} data-testid="file-download" />
140
+ );
141
+
142
+ const fileLink = screen.getByRole('link');
143
+ const metadataKey = screen.getByRole('term');
144
+ const metadataItem = metadataKey.parentElement;
145
+ const metadataList = metadataItem?.parentElement;
146
+ const downloadDetails = metadataList?.parentElement;
147
+
148
+ expect(fileLink).toHaveAttribute('aria-describedby', downloadDetails?.id);
149
+ });
150
+
151
+ test('passing additional props', () => {
152
+ render(
153
+ <FileDownload fileUrl={FILE_URL} title={FILE_TITLE} data-testid="file-download" data-test="foo" />
154
+ );
155
+
156
+ const fileDownload = screen.getByTestId('file-download');
157
+ expect(fileDownload?.dataset.test).toEqual('foo');
158
+ });
159
+
160
+ test('passing additional CSS classes', () => {
161
+ render(
162
+ <FileDownload fileUrl={FILE_URL} title={FILE_TITLE} data-testid="file-download" className="foo" />
163
+ );
164
+
165
+ const fileDownload = screen.getByTestId('file-download');
166
+ expect(fileDownload).toHaveClass('foo');
167
+ });
@@ -0,0 +1,67 @@
1
+ import { useId } from 'react';
2
+ import FileIcon from '../../common/FileIcon';
3
+
4
+ const FileDownload: React.FC<SGDS.Component.FileDownload> = ({
5
+ className,
6
+ cover,
7
+ highlighted,
8
+ icon = 'Generic',
9
+ fileSize,
10
+ fileType,
11
+ fileUrl,
12
+ title,
13
+ ...props
14
+ }) => {
15
+ const hasMetadata = !!fileType || !!fileSize;
16
+ const metaContainerId = `file-download-${useId()}`;
17
+
18
+ return (
19
+ <div className={[
20
+ 'ds_file-download',
21
+ highlighted && 'ds_file-download--highlighted',
22
+ className
23
+ ].join(' ')}
24
+ {...props}
25
+ >
26
+ <div className="ds_file-download__thumbnail">
27
+ <a className="ds_file-download__thumbnail-link" aria-hidden="true" tabIndex={-1} href={fileUrl}>
28
+ {cover ?
29
+ <img alt="" className="ds_file-download__thumbnail-image" src={cover}/>
30
+ :
31
+ <FileIcon ariaLabel="" className="ds_file-download__thumbnail-image" icon={icon} />
32
+ }
33
+ </a>
34
+ </div>
35
+
36
+ <div className="ds_file-download__content">
37
+ <a href={fileUrl} className="ds_file-download__title" aria-describedby={hasMetadata ? metaContainerId : undefined}>
38
+ {title}
39
+ </a>
40
+
41
+ {hasMetadata &&
42
+ <div id={metaContainerId} className="ds_file-download__details">
43
+ <dl className="ds_metadata ds_metadata--inline">
44
+ {fileType &&
45
+ <div className="ds_metadata__item">
46
+ <dt className="ds_metadata__key visually-hidden">File type</dt>
47
+ <dd className="ds_metadata__value">{fileType}<span className="visually-hidden">,</span></dd>
48
+ </div>
49
+ }
50
+
51
+ {fileSize &&
52
+ <div className="ds_metadata__item">
53
+ <dt className="ds_metadata__key visually-hidden">File size</dt>
54
+ <dd className="ds_metadata__value">{fileSize}</dd>
55
+ </div>
56
+ }
57
+ </dl>
58
+ </div>
59
+ }
60
+ </div>
61
+ </div>
62
+ );
63
+ };
64
+
65
+ FileDownload.displayName = 'FileDownload';
66
+
67
+ export default FileDownload;
@@ -1,6 +1,6 @@
1
1
  import { test, expect } from 'vitest';
2
2
  import { render, screen, within } from '@testing-library/react';
3
- import HideThisPage from './hide-this-page';
3
+ import HideThisPage from './HideThisPage';
4
4
 
5
5
  test('hide this page renders correctly', () => {
6
6
  render(
@@ -39,16 +39,16 @@ test('hide this page renders correctly', () => {
39
39
  });
40
40
 
41
41
  test('custom escape URL', () => {
42
- const escapeUrl = 'https://www.mygov.scot';
42
+ const ESCAPE_URL = 'https://www.mygov.scot';
43
43
 
44
44
  render(
45
- <HideThisPage data-testid="htp" escapeUrl={escapeUrl} />
45
+ <HideThisPage data-testid="htp" escapeUrl={ESCAPE_URL} />
46
46
  );
47
47
 
48
48
  const hideThisPageElement = screen.getByTestId('htp');
49
49
  const link = within(hideThisPageElement).getByRole('link');
50
50
 
51
- expect(link).toHaveAttribute('href', escapeUrl);
51
+ expect(link).toHaveAttribute('href', ESCAPE_URL);
52
52
  })
53
53
 
54
54
  test('passing additional props', () => {
@@ -13,10 +13,10 @@ const HideThisPage: React.FC<SGDS.Component.HideThisPage> = ({
13
13
  if (ref.current) {
14
14
  new DSHideThisPage().init();
15
15
 
16
- const htpDivId = 'hide-this-page-instruction';
17
- if (!document.getElementById(htpDivId)) {
16
+ const HIDE_THIS_PAGE_DIV_ID = 'hide-this-page-instruction';
17
+ if (!document.getElementById(HIDE_THIS_PAGE_DIV_ID)) {
18
18
  const htpDiv = document.createElement('div');
19
- htpDiv.id = htpDivId;
19
+ htpDiv.id = HIDE_THIS_PAGE_DIV_ID;
20
20
  htpDiv.classList.add('visually-hidden');
21
21
  htpDiv.classList.add('ds_hide-page');
22
22
  htpDiv.innerHTML = '<p>To leave the page quickly, press the escape key.</p>';
@@ -1,6 +1,6 @@
1
1
  import { test, expect } from 'vitest';
2
2
  import { render } from '@testing-library/react';
3
- import InsetText from './inset-text';
3
+ import InsetText from './InsetText';
4
4
 
5
5
  const text = `You may be able to apply for free school meals at the same
6
6
  time as you apply for the clothing grant.`;
@@ -5,9 +5,9 @@
5
5
 
6
6
  import { test, expect } from 'vitest';
7
7
  import { render, screen, within } from '@testing-library/react';
8
- import NotificationBanner from './notification-banner';
8
+ import NotificationBanner from './NotificationBanner';
9
9
 
10
- const text = 'We need to tell you about something';
10
+ const BANNER_TEXT = 'We need to tell you about something';
11
11
 
12
12
  /**
13
13
  * NotificationBanner has the ds_reversed class
@@ -15,7 +15,7 @@ const text = 'We need to tell you about something';
15
15
  test('notification banner renders correctly', () => {
16
16
  render(
17
17
  <NotificationBanner>
18
- {text}
18
+ {BANNER_TEXT}
19
19
  </NotificationBanner>
20
20
  );
21
21
 
@@ -30,7 +30,7 @@ test('notification banner renders correctly', () => {
30
30
  test('notification banner with icon', () => {
31
31
  render(
32
32
  <NotificationBanner icon>
33
- {text}
33
+ {BANNER_TEXT}
34
34
  </NotificationBanner>
35
35
  );
36
36
 
@@ -1,5 +1,5 @@
1
1
  import { useEffect, useRef } from 'react';
2
- import AbstractNotificationBanner from '../../common/abstract-notification-banner';
2
+ import AbstractNotificationBanner from '../../common/AbstractNotificationBanner';
3
3
  // @ts-ignore
4
4
  import DSNotificationBanner from '@scottish-government/design-system/src/components/notification-banner/notification-banner';
5
5
 
@@ -1,14 +1,14 @@
1
1
  import { test, expect } from 'vitest';
2
2
  import { render, screen } from '@testing-library/react';
3
- import NotificationPanel from './notification-panel';
3
+ import NotificationPanel from './NotificationPanel';
4
4
 
5
- const headingText = 'Thank you';
6
- const text = 'Your Saltire Scholarship Application form has been successfully submitted.';
5
+ const HEADING_TEXT = 'Thank you';
6
+ const TEXT = 'Your Saltire Scholarship Application form has been successfully submitted.';
7
7
 
8
8
  test('notification banner renders correctly', () => {
9
9
  render(
10
- <NotificationPanel title={headingText}>
11
- {text}
10
+ <NotificationPanel title={HEADING_TEXT}>
11
+ {TEXT}
12
12
  </NotificationPanel>
13
13
  );
14
14
 
@@ -18,56 +18,57 @@ test('notification banner renders correctly', () => {
18
18
 
19
19
  expect(notificationPanel).toHaveClass('ds_notification-panel');
20
20
  expect(notificationPanelHeading).toHaveClass('ds_notification-panel__title');
21
- expect(notificationPanelHeading.textContent).toEqual(headingText);
21
+ expect(notificationPanelHeading.textContent).toEqual(HEADING_TEXT);
22
22
  expect(notificationPanelHeading.tagName).toEqual('H1');
23
23
  expect(notificationPanelContent).toHaveClass('ds_notification-panel__content');
24
- expect(notificationPanelContent?.textContent).toEqual(text);
24
+ expect(notificationPanelContent?.textContent).toEqual(TEXT);
25
25
  });
26
26
 
27
27
  test('notification banner with custom heading level', () => {
28
- const headerLevel = 'h2';
28
+ const HEADING_LEVEL = 'h2';
29
29
 
30
30
  render(
31
- <NotificationPanel headerLevel={headerLevel} title={headingText}>
32
- {text}
31
+ <NotificationPanel headingLevel={HEADING_LEVEL} title={HEADING_TEXT}>
32
+ {TEXT}
33
33
  </NotificationPanel>
34
34
  );
35
35
 
36
36
  const notificationPanelHeading = screen.getByRole('heading');
37
- expect(notificationPanelHeading.tagName).toEqual(headerLevel.toUpperCase());
37
+ expect(notificationPanelHeading.tagName).toEqual(HEADING_LEVEL.toUpperCase());
38
38
  });
39
39
 
40
40
  test('notification banner with aria-live', () => {
41
- const ariaLive = 'polite';
41
+ const ARIA_LIVE = 'polite';
42
42
 
43
43
  render(
44
- <NotificationPanel ariaLive={ariaLive} title={headingText}>
45
- {text}
44
+ <NotificationPanel ariaLive={ARIA_LIVE} title={HEADING_TEXT}>
45
+ {TEXT}
46
46
  </NotificationPanel>
47
47
  );
48
48
 
49
49
  const notificationPanelHeading = screen.getByRole('heading');
50
50
  const notificationPanel = notificationPanelHeading.parentElement;
51
51
 
52
- expect(notificationPanel).toHaveAttribute('aria-live', ariaLive);
52
+ expect(notificationPanel).toHaveAttribute('aria-live', ARIA_LIVE);
53
53
  });
54
54
 
55
55
  test('notification banner with nonsense heading level reverts to H1', () => {
56
- const headerLevel = 'h2';
56
+ const HEADING_LEVEL = 'h2';
57
+
57
58
  render(
58
- <NotificationPanel headerLevel={headerLevel} title={headingText}>
59
- {text}
59
+ <NotificationPanel headingLevel={HEADING_LEVEL} title={HEADING_TEXT}>
60
+ {TEXT}
60
61
  </NotificationPanel>
61
62
  );
62
63
 
63
64
  const notificationPanelHeading = screen.getByRole('heading');
64
- expect(notificationPanelHeading.tagName).toEqual(headerLevel.toUpperCase());
65
+ expect(notificationPanelHeading.tagName).toEqual(HEADING_LEVEL.toUpperCase());
65
66
  });
66
67
 
67
68
  test('passing additional props', () => {
68
69
  render(
69
- <NotificationPanel title={headingText} data-test="foo">
70
- {text}
70
+ <NotificationPanel title={HEADING_TEXT} data-test="foo">
71
+ {TEXT}
71
72
  </NotificationPanel>
72
73
  )
73
74
 
@@ -78,8 +79,8 @@ test('passing additional props', () => {
78
79
 
79
80
  test('passing additional CSS classes', () => {
80
81
  render(
81
- <NotificationPanel title={headingText} className="foo">
82
- {text}
82
+ <NotificationPanel title={HEADING_TEXT} className="foo">
83
+ {TEXT}
83
84
  </NotificationPanel>
84
85
  )
85
86
 
@@ -1,10 +1,10 @@
1
- import WrapperTag from '../../common/wrapper-tag';
1
+ import WrapperTag from '../../common/WrapperTag';
2
2
 
3
3
  const NotificationPanel: React.FC<SGDS.Component.NotificationPanel> = function ({
4
4
  ariaLive,
5
5
  children,
6
6
  className,
7
- headerLevel = 'h1',
7
+ headingLevel = 'h1',
8
8
  title,
9
9
  ...props
10
10
  }) {
@@ -19,7 +19,7 @@ const NotificationPanel: React.FC<SGDS.Component.NotificationPanel> = function (
19
19
  >
20
20
  <WrapperTag
21
21
  className="ds_notification-panel__title"
22
- tagName={headerLevel}
22
+ tagName={headingLevel}
23
23
  >
24
24
  {title}
25
25
  </WrapperTag>
@@ -1,13 +1,13 @@
1
1
  import { test, expect } from 'vitest';
2
2
  import { render, screen, within } from '@testing-library/react';
3
- import PageHeader from './page-header';
3
+ import PageHeader from './PageHeader';
4
4
 
5
- const labelText = 'Guide';
6
- const titleText = 'Apply for or renew a disabled parking permit';
5
+ const LABEL_TEXT = 'Guide';
6
+ const TITLE_TEXT = 'Apply for or renew a disabled parking permit';
7
7
 
8
8
  test('notification banner renders correctly', () => {
9
9
  render(
10
- <PageHeader label={labelText} title={titleText}/>
10
+ <PageHeader label={LABEL_TEXT} title={TITLE_TEXT}/>
11
11
  );
12
12
 
13
13
  const header = screen.getByRole('banner');
@@ -18,17 +18,17 @@ test('notification banner renders correctly', () => {
18
18
  expect(header.tagName).toEqual('HEADER');
19
19
 
20
20
  expect(label).toHaveClass('ds_page-header__label', 'ds_content-label');
21
- expect(label?.textContent).toEqual(labelText);
21
+ expect(label?.textContent).toEqual(LABEL_TEXT);
22
22
  expect(label?.tagName).toEqual('SPAN');
23
23
 
24
24
  expect(title).toHaveClass('ds_page-header__title');
25
- expect(title.textContent).toEqual(titleText);
25
+ expect(title.textContent).toEqual(TITLE_TEXT);
26
26
  expect(title.tagName).toEqual('H1');
27
27
  });
28
28
 
29
29
  test('header with no label', () => {
30
30
  render(
31
- <PageHeader title={titleText}/>
31
+ <PageHeader title={TITLE_TEXT}/>
32
32
  );
33
33
 
34
34
  const header = screen.getByRole('banner');
@@ -40,7 +40,7 @@ test('header with no label', () => {
40
40
 
41
41
  test('passing additional props', () => {
42
42
  render(
43
- <PageHeader data-test="foo" label={labelText} title={titleText}/>
43
+ <PageHeader data-test="foo" label={LABEL_TEXT} title={TITLE_TEXT}/>
44
44
  )
45
45
 
46
46
  const header = screen.getByRole('banner');
@@ -49,7 +49,7 @@ test('passing additional props', () => {
49
49
 
50
50
  test('passing additional CSS classes', () => {
51
51
  render(
52
- <PageHeader className="foo" label={labelText} title={titleText}/>
52
+ <PageHeader className="foo" label={LABEL_TEXT} title={TITLE_TEXT}/>
53
53
  )
54
54
 
55
55
  const header = screen.getByRole('banner');
@@ -1,15 +1,15 @@
1
1
  import { test, expect } from 'vitest';
2
2
  import { render, screen } from '@testing-library/react';
3
- import Metadata from './page-metadata';
3
+ import Metadata from './PageMetadata';
4
4
 
5
- const name = 'Directorate';
6
- const value = 'Equality, Inclusion and Human Rights Directorate';
5
+ const NAME = 'Directorate';
6
+ const VALUE = 'Equality, Inclusion and Human Rights Directorate';
7
7
 
8
8
  test('metadata renders correctly', () => {
9
9
  render(
10
10
  <Metadata>
11
- <Metadata.Item name={name}>
12
- {value}
11
+ <Metadata.Item name={NAME}>
12
+ {VALUE}
13
13
  </Metadata.Item>
14
14
  </Metadata>
15
15
  );
@@ -22,16 +22,16 @@ test('metadata renders correctly', () => {
22
22
  expect(metadata).toBeInTheDocument();
23
23
  expect(metadataItem).toBeInTheDocument();
24
24
  expect(metadataItemKey).toHaveClass('ds_metadata__key');
25
- expect(metadataItemKey.textContent).toEqual(name);
25
+ expect(metadataItemKey.textContent).toEqual(NAME);
26
26
  expect(metadataItemValue).toHaveClass('ds_metadata__value');
27
- expect(metadataItemValue.textContent).toEqual(value);
27
+ expect(metadataItemValue.textContent).toEqual(VALUE);
28
28
  });
29
29
 
30
30
  test('inline metadata', () => {
31
31
  render(
32
32
  <Metadata inline>
33
- <Metadata.Item name={name}>
34
- {value}
33
+ <Metadata.Item name={NAME}>
34
+ {VALUE}
35
35
  </Metadata.Item>
36
36
  </Metadata>
37
37
  );