@tpzdsp/next-toolkit 2.5.0 → 3.0.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 (355) hide show
  1. package/package.json +22 -13
  2. package/src/assets/styles/globals.css +75 -95
  3. package/src/assets/styles/ol.css +57 -16
  4. package/src/assets/styles/utils.css +80 -0
  5. package/src/components/Accordion/Accordion.css +85 -0
  6. package/src/components/Accordion/Accordion.stories.tsx +264 -0
  7. package/src/components/Accordion/Accordion.tsx +98 -0
  8. package/src/components/Alert/Alert.css +129 -0
  9. package/src/components/Alert/Alert.stories.tsx +291 -0
  10. package/src/components/Alert/Alert.tsx +76 -0
  11. package/src/components/BackLink/BackLink.css +12 -0
  12. package/src/components/BackLink/BackLink.stories.tsx +52 -0
  13. package/src/components/BackLink/BackLink.tsx +44 -0
  14. package/src/components/BackToTop/BackToTop.css +23 -0
  15. package/src/components/BackToTop/BackToTop.stories.tsx +41 -0
  16. package/src/components/BackToTop/BackToTop.tsx +48 -0
  17. package/src/components/Breadcrumb/Breadcrumb.css +42 -0
  18. package/src/components/Breadcrumb/Breadcrumb.stories.tsx +94 -0
  19. package/src/components/Breadcrumb/Breadcrumb.tsx +135 -0
  20. package/src/components/Button/Button.css +229 -0
  21. package/src/components/Button/Button.stories.tsx +140 -20
  22. package/src/components/Button/Button.tsx +53 -28
  23. package/src/components/Button/ButtonSkeleton.stories.tsx +50 -0
  24. package/src/components/Button/ButtonSkeleton.tsx +14 -0
  25. package/src/components/ButtonGroup/ButtonGroup.css +52 -0
  26. package/src/components/ButtonGroup/ButtonGroup.stories.tsx +156 -0
  27. package/src/components/ButtonGroup/ButtonGroup.tsx +50 -0
  28. package/src/components/ButtonLink/ButtonLink.css +114 -0
  29. package/src/components/ButtonLink/ButtonLink.stories.tsx +38 -51
  30. package/src/components/ButtonLink/ButtonLink.tsx +54 -23
  31. package/src/components/Card/Card.css +13 -0
  32. package/src/components/Card/Card.stories.tsx +98 -57
  33. package/src/components/Card/Card.tsx +4 -13
  34. package/src/components/CardGroup/CardGroup.css +10 -0
  35. package/src/components/CardGroup/CardGroup.stories.tsx +81 -0
  36. package/src/components/CardGroup/CardGroup.tsx +9 -0
  37. package/src/components/Checkbox/Checkbox.css +49 -0
  38. package/src/components/Checkbox/Checkbox.stories.tsx +86 -0
  39. package/src/components/Checkbox/Checkbox.tsx +32 -0
  40. package/src/components/Chip/Chip.css +54 -0
  41. package/src/components/Chip/Chip.stories.tsx +94 -0
  42. package/src/components/Chip/Chip.tsx +34 -0
  43. package/src/components/CookieBanner/CookieBanner.css +19 -0
  44. package/src/components/CookieBanner/CookieBanner.stories.tsx +52 -0
  45. package/src/components/CookieBanner/CookieBanner.tsx +55 -0
  46. package/src/components/CopyButton/CopyButton.stories.tsx +28 -0
  47. package/src/components/CopyButton/CopyButton.tsx +65 -0
  48. package/src/components/DateInput/DateInput.css +13 -0
  49. package/src/components/DateInput/DateInput.stories.tsx +131 -0
  50. package/src/components/DateInput/DateInput.test.tsx +21 -0
  51. package/src/components/DateInput/DateInput.tsx +98 -0
  52. package/src/components/Details/Details.css +28 -0
  53. package/src/components/Details/Details.stories.tsx +48 -0
  54. package/src/components/Details/Details.tsx +41 -0
  55. package/src/components/Dropdown/Dropdown.css +81 -0
  56. package/src/components/Dropdown/Dropdown.stories.tsx +131 -0
  57. package/src/components/Dropdown/Dropdown.tsx +69 -0
  58. package/src/components/ErrorBoundary/ErrorBoundary.stories.tsx +4 -39
  59. package/src/components/ErrorBoundary/ErrorBoundary.tsx +7 -4
  60. package/src/components/ErrorBoundary/ErrorFallback.tsx +32 -66
  61. package/src/components/ErrorModal/ErrorModal.css +32 -0
  62. package/src/components/ErrorModal/ErrorModal.stories.tsx +101 -0
  63. package/src/components/ErrorModal/ErrorModal.tsx +120 -0
  64. package/src/components/ErrorText/ErrorText.css +22 -0
  65. package/src/components/ErrorText/ErrorText.stories.tsx +42 -27
  66. package/src/components/ErrorText/ErrorText.tsx +10 -8
  67. package/src/components/ExternalLink/ExternalLink.css +12 -0
  68. package/src/components/ExternalLink/ExternalLink.stories.tsx +43 -0
  69. package/src/components/ExternalLink/ExternalLink.tsx +43 -0
  70. package/src/components/Fieldset/Fieldset.css +103 -0
  71. package/src/components/Fieldset/Fieldset.stories.tsx +304 -0
  72. package/src/components/Fieldset/Fieldset.tsx +38 -0
  73. package/src/components/FileUpload/FileUpload.css +85 -0
  74. package/src/components/FileUpload/FileUpload.stories.tsx +106 -0
  75. package/src/components/FileUpload/FileUpload.tsx +99 -0
  76. package/src/components/{layout/footer → Footer}/Copyright.tsx +4 -2
  77. package/src/components/Footer/Footer.stories.tsx +24 -0
  78. package/src/components/Footer/Footer.tsx +41 -0
  79. package/src/components/Footer/Licence.tsx +18 -0
  80. package/src/components/{layout/footer → Footer}/MetaLinks.tsx +8 -3
  81. package/src/components/Footer/Small/SmallFooter.tsx +43 -42
  82. package/src/components/Form/FormGroup.css +18 -0
  83. package/src/components/Form/FormGroup.stories.tsx +87 -0
  84. package/src/components/Form/FormGroup.tsx +16 -0
  85. package/src/components/{layout/header → Header}/Header.stories.tsx +26 -12
  86. package/src/components/Header/Header.test.tsx +87 -0
  87. package/src/components/Header/Header.tsx +303 -0
  88. package/src/components/Header/HeaderAppContent.tsx +120 -0
  89. package/src/components/Heading/Heading.css +40 -0
  90. package/src/components/Heading/Heading.stories.tsx +15 -5
  91. package/src/components/Heading/Heading.tsx +21 -44
  92. package/src/components/Heading/HeadingSkeleton.stories.tsx +30 -0
  93. package/src/components/Heading/HeadingSkeleton.tsx +14 -0
  94. package/src/components/Hero/Hero.css +19 -0
  95. package/src/components/Hero/Hero.stories.tsx +41 -0
  96. package/src/components/Hero/Hero.tsx +14 -0
  97. package/src/components/HintText/HintText.css +5 -0
  98. package/src/components/HintText/HintText.stories.tsx +29 -0
  99. package/src/components/HintText/HintText.tsx +13 -0
  100. package/src/components/InfoBox/InfoBox.css +38 -0
  101. package/src/components/InfoBox/InfoBox.stories.tsx +51 -403
  102. package/src/components/InfoBox/InfoBox.tsx +31 -158
  103. package/src/components/Input/Input.css +77 -0
  104. package/src/components/Input/Input.stories.tsx +123 -0
  105. package/src/components/Input/Input.tsx +74 -0
  106. package/src/components/InputGroup/InputGroup.css +140 -0
  107. package/src/components/InputGroup/InputGroup.stories.tsx +125 -0
  108. package/src/components/InputGroup/InputGroup.tsx +47 -0
  109. package/src/components/InsetText/InsetText.css +5 -0
  110. package/src/components/InsetText/InsetText.stories.tsx +30 -0
  111. package/src/components/InsetText/InsetText.tsx +9 -0
  112. package/src/components/Keyboard/Keyboard.css +9 -0
  113. package/src/components/Keyboard/Keyboard.stories.tsx +63 -0
  114. package/src/components/Keyboard/Keyboard.tsx +30 -0
  115. package/src/components/Label/Label.css +27 -0
  116. package/src/components/Label/Label.stories.tsx +40 -0
  117. package/src/components/Label/Label.tsx +17 -0
  118. package/src/components/LayerSwitcher/LayerSwitcher.css +59 -0
  119. package/src/components/LayerSwitcher/LayerSwitcher.stories.tsx +112 -0
  120. package/src/components/LayerSwitcher/LayerSwitcher.tsx +61 -0
  121. package/src/components/Layout/401/401.stories.tsx +23 -0
  122. package/src/components/Layout/401/401.tsx +1 -0
  123. package/src/components/Layout/403/403.stories.tsx +23 -0
  124. package/src/components/Layout/403/403.tsx +21 -0
  125. package/src/components/Layout/404/404.stories.tsx +23 -0
  126. package/src/components/Layout/404/404.tsx +28 -0
  127. package/src/components/Layout/500/500.stories.tsx +56 -0
  128. package/src/components/Layout/500/500.tsx +63 -0
  129. package/src/components/Layout/ButtonGroup/ButtonGroup.css +52 -0
  130. package/src/components/Layout/ButtonGroup/ButtonGroup.stories.tsx +156 -0
  131. package/src/components/Layout/ButtonGroup/ButtonGroup.tsx +50 -0
  132. package/src/components/Layout/HeadingGroup/HeadingGroup.css +21 -0
  133. package/src/components/Layout/HeadingGroup/HeadingGroup.stories.tsx +84 -0
  134. package/src/components/Layout/HeadingGroup/HeadingGroup.tsx +9 -0
  135. package/src/components/Layout/MainWrapper/MainWrapper.css +12 -0
  136. package/src/components/Layout/MainWrapper/MainWrapper.stories.tsx +36 -0
  137. package/src/components/Layout/MainWrapper/MainWrapper.tsx +14 -0
  138. package/src/components/Layout/PageShell/PageShell.css +42 -0
  139. package/src/components/Layout/PageShell/PageShell.stories.tsx +108 -0
  140. package/src/components/Layout/PageShell/PageShell.tsx +31 -0
  141. package/src/components/Layout/ParagraphGroup/ParagraphGroup.css +5 -0
  142. package/src/components/Layout/ParagraphGroup/ParagraphGroup.stories.tsx +34 -0
  143. package/src/components/Layout/ParagraphGroup/ParagraphGroup.tsx +9 -0
  144. package/src/components/Layout/Stack/Stack.css +29 -0
  145. package/src/components/Layout/Stack/Stack.stories.tsx +83 -0
  146. package/src/components/Layout/Stack/Stack.tsx +19 -0
  147. package/src/components/Layout/WidthContainer/WidthContainer.css +17 -0
  148. package/src/components/Layout/WidthContainer/WidthContainer.stories.tsx +59 -0
  149. package/src/components/Layout/WidthContainer/WidthContainer.tsx +13 -0
  150. package/src/components/Legend/Legend.css +95 -0
  151. package/src/components/Legend/Legend.stories.tsx +81 -0
  152. package/src/components/Legend/Legend.tsx +32 -0
  153. package/src/components/Legend/LegendDot.tsx +15 -0
  154. package/src/components/Legend/LegendPanel.stories.tsx +101 -0
  155. package/src/components/Legend/LegendPanel.tsx +68 -0
  156. package/src/components/Legend/LegendSkeleton.stories.tsx +87 -0
  157. package/src/components/Legend/LegendSkeleton.tsx +73 -0
  158. package/src/components/LegendSelect/LegendSelect.css +8 -0
  159. package/src/components/LegendSelect/LegendSelect.stories.tsx +80 -0
  160. package/src/components/LegendSelect/LegendSelect.tsx +26 -0
  161. package/src/components/Link/Link.css +98 -0
  162. package/src/components/Link/Link.stories.tsx +70 -0
  163. package/src/components/Link/Link.tsx +52 -0
  164. package/src/components/LinkButton/LinkButton.css +67 -0
  165. package/src/components/LinkButton/LinkButton.stories.tsx +90 -42
  166. package/src/components/LinkButton/LinkButton.tsx +50 -63
  167. package/src/components/LinkList/LinkList.css +28 -0
  168. package/src/components/LinkList/LinkList.stories.tsx +46 -0
  169. package/src/components/LinkList/LinkList.tsx +23 -0
  170. package/src/components/List/Li.tsx +9 -0
  171. package/src/components/List/List.css +9 -0
  172. package/src/components/List/OrderedList.stories.tsx +36 -0
  173. package/src/components/List/OrderedList.tsx +9 -0
  174. package/src/components/List/UnorderedList.stories.tsx +36 -0
  175. package/src/components/List/UnorderedList.tsx +9 -0
  176. package/src/components/LoadingBox/LoadingBox.css +27 -0
  177. package/src/components/LoadingBox/LoadingBox.stories.tsx +66 -0
  178. package/src/components/LoadingBox/LoadingBox.tsx +40 -0
  179. package/src/components/Modal/Modal.css +114 -0
  180. package/src/components/Modal/Modal.stories.tsx +41 -160
  181. package/src/components/Modal/Modal.tsx +132 -75
  182. package/src/components/NoScriptBanner/NoScriptBanner.css +17 -0
  183. package/src/components/NoScriptBanner/NoScriptBanner.stories.tsx +46 -0
  184. package/src/components/NoScriptBanner/NoScriptBanner.tsx +26 -0
  185. package/src/components/Paragraph/Paragraph.css +22 -0
  186. package/src/components/Paragraph/Paragraph.stories.tsx +1 -42
  187. package/src/components/Paragraph/Paragraph.tsx +4 -3
  188. package/src/components/Paragraph/ParagraphSkeleton.stories.tsx +44 -0
  189. package/src/components/Paragraph/ParagraphSkeleton.tsx +33 -0
  190. package/src/components/PasswordInput/PasswordInput.css +3 -0
  191. package/src/components/PasswordInput/PasswordInput.stories.tsx +47 -0
  192. package/src/components/PasswordInput/PasswordInput.tsx +45 -0
  193. package/src/components/PhaseBanner/PhaseBanner.css +12 -0
  194. package/src/components/PhaseBanner/PhaseBanner.stories.tsx +61 -0
  195. package/src/components/PhaseBanner/PhaseBanner.tsx +17 -0
  196. package/src/components/Popover/Popover.css +43 -0
  197. package/src/components/Popover/Popover.stories.tsx +102 -0
  198. package/src/components/Popover/Popover.tsx +40 -0
  199. package/src/components/Radio/Radio.css +69 -0
  200. package/src/components/Radio/Radio.stories.tsx +169 -0
  201. package/src/components/Radio/Radio.tsx +56 -0
  202. package/src/components/Resizable/Resizable.css +86 -0
  203. package/src/components/Resizable/Resizable.stories.tsx +123 -0
  204. package/src/components/Resizable/Resizable.tsx +86 -0
  205. package/src/components/ScrollArea/ScrollArea.css +9 -0
  206. package/src/components/ScrollArea/ScrollArea.stories.tsx +42 -0
  207. package/src/components/ScrollArea/ScrollArea.tsx +11 -0
  208. package/src/components/SearchBox/SearchBox.stories.tsx +88 -0
  209. package/src/components/SearchBox/SearchBox.tsx +36 -0
  210. package/src/components/Select/AsyncSelect.stories.tsx +84 -0
  211. package/src/components/Select/AsyncSelect.tsx +41 -0
  212. package/src/components/Select/Select.css +194 -0
  213. package/src/components/Select/Select.stories.tsx +162 -0
  214. package/src/components/Select/Select.test.tsx +36 -0
  215. package/src/components/Select/Select.tsx +291 -0
  216. package/src/components/Select/SelectSkeleton.stories.tsx +51 -0
  217. package/src/components/Select/SelectSkeleton.tsx +23 -0
  218. package/src/components/Separator/Separator.css +41 -0
  219. package/src/components/Separator/Separator.stories.tsx +63 -0
  220. package/src/components/Separator/Separator.tsx +42 -0
  221. package/src/components/Sidebar/ResizableSidebar.tsx +118 -0
  222. package/src/components/Sidebar/Sidebar.css +203 -0
  223. package/src/components/Sidebar/Sidebar.stories.tsx +438 -0
  224. package/src/components/Sidebar/Sidebar.tsx +225 -0
  225. package/src/components/Skeleton/Skeleton.css +16 -0
  226. package/src/components/Skeleton/Skeleton.stories.tsx +39 -0
  227. package/src/components/Skeleton/Skeleton.tsx +12 -0
  228. package/src/components/SkipLink/SkipLink.css +16 -0
  229. package/src/components/SkipLink/SkipLink.stories.tsx +40 -0
  230. package/src/components/SkipLink/SkipLink.tsx +15 -0
  231. package/src/components/Spinner/Spinner.css +30 -0
  232. package/src/components/Spinner/Spinner.stories.tsx +36 -0
  233. package/src/components/Spinner/Spinner.tsx +45 -0
  234. package/src/components/StartButton/StartButton.css +13 -0
  235. package/src/components/StartButton/StartButton.stories.tsx +68 -0
  236. package/src/components/StartButton/StartButton.tsx +50 -0
  237. package/src/components/SubmitButton/SubmitButton.stories.tsx +31 -0
  238. package/src/components/SubmitButton/SubmitButton.tsx +14 -0
  239. package/src/components/SummaryList/SummaryList.css +71 -0
  240. package/src/components/SummaryList/SummaryList.stories.tsx +211 -0
  241. package/src/components/SummaryList/SummaryList.tsx +41 -0
  242. package/src/components/SummaryList/SummaryListSkeleton.stories.tsx +67 -0
  243. package/src/components/SummaryList/SummaryListSkeleton.tsx +40 -0
  244. package/src/components/Tabs/Tabs.css +84 -0
  245. package/src/components/Tabs/Tabs.stories.tsx +133 -0
  246. package/src/components/Tabs/Tabs.tsx +66 -0
  247. package/src/components/Tag/Tag.css +8 -0
  248. package/src/components/Tag/Tag.stories.tsx +96 -0
  249. package/src/components/Tag/Tag.tsx +34 -0
  250. package/src/components/Textarea/Textarea.css +38 -0
  251. package/src/components/Textarea/Textarea.stories.tsx +131 -0
  252. package/src/components/Textarea/Textarea.tsx +50 -0
  253. package/src/components/TextareaCount/TextareaCount.css +17 -0
  254. package/src/components/TextareaCount/TextareaCount.stories.tsx +131 -0
  255. package/src/components/TextareaCount/TextareaCount.tsx +108 -0
  256. package/src/components/Tooltip/Tooltip.css +43 -0
  257. package/src/components/Tooltip/Tooltip.stories.tsx +110 -0
  258. package/src/components/Tooltip/Tooltip.tsx +53 -0
  259. package/src/components/WarningText/WarningText.css +20 -0
  260. package/src/components/WarningText/WarningText.stories.tsx +29 -0
  261. package/src/components/WarningText/WarningText.tsx +17 -0
  262. package/src/components/index.ts +342 -61
  263. package/src/errors/errorDisplay.ts +70 -0
  264. package/src/errors/index.ts +1 -0
  265. package/src/http/constants.ts +1 -0
  266. package/src/http/fetch.ts +7 -3
  267. package/src/map/LayerSwitcherPanel.tsx +2 -173
  268. package/src/map/LegendShim.tsx +2 -0
  269. package/src/map/MapComponent.tsx +7 -17
  270. package/src/map/MapControlsOverlay.tsx +68 -175
  271. package/src/map/Popup.tsx +71 -24
  272. package/src/map/geocoder/Geocoder.test.tsx +46 -3
  273. package/src/map/geocoder/Geocoder.tsx +155 -278
  274. package/src/map/index.ts +1 -1
  275. package/src/types/utils.ts +0 -10
  276. package/src/utils/components.ts +96 -0
  277. package/src/utils/index.ts +1 -0
  278. package/src/utils/utils.ts +0 -12
  279. package/src/assets/images/defra-logo.svg +0 -51
  280. package/src/assets/images/ea-logo.svg +0 -58
  281. package/src/assets/images/ogl.svg +0 -1
  282. package/src/components/Button/Button.test.tsx +0 -53
  283. package/src/components/ButtonLink/ButtonLink.test.tsx +0 -154
  284. package/src/components/Card/Card.test.tsx +0 -51
  285. package/src/components/ErrorBoundary/ErrorBoundary.test.tsx +0 -75
  286. package/src/components/ErrorBoundary/ErrorFallback.test.tsx +0 -107
  287. package/src/components/ErrorText/ErrorText.test.tsx +0 -33
  288. package/src/components/Heading/Heading.test.tsx +0 -22
  289. package/src/components/Hint/Hint.stories.tsx +0 -58
  290. package/src/components/Hint/Hint.test.tsx +0 -33
  291. package/src/components/Hint/Hint.tsx +0 -12
  292. package/src/components/InfoBox/InfoBox.test.tsx +0 -330
  293. package/src/components/InfoBox/types.ts +0 -6
  294. package/src/components/LinkButton/LinkButton.test.tsx +0 -177
  295. package/src/components/Modal/Modal.test.tsx +0 -246
  296. package/src/components/NotificationBanner/NotificationBanner.stories.tsx +0 -45
  297. package/src/components/NotificationBanner/NotificationBanner.test.tsx +0 -58
  298. package/src/components/NotificationBanner/NotificationBanner.tsx +0 -45
  299. package/src/components/Paragraph/Paragraph.test.tsx +0 -10
  300. package/src/components/SlidingPanel/SlidingPanel.stories.tsx +0 -129
  301. package/src/components/SlidingPanel/SlidingPanel.test.tsx +0 -83
  302. package/src/components/SlidingPanel/SlidingPanel.tsx +0 -258
  303. package/src/components/accordion/Accordion.stories.tsx +0 -234
  304. package/src/components/accordion/Accordion.test.tsx +0 -192
  305. package/src/components/accordion/Accordion.tsx +0 -73
  306. package/src/components/backToTop/BackToTop.stories.tsx +0 -407
  307. package/src/components/backToTop/BackToTop.test.tsx +0 -57
  308. package/src/components/backToTop/BackToTop.tsx +0 -134
  309. package/src/components/chip/Chip.stories.tsx +0 -61
  310. package/src/components/chip/Chip.test.tsx +0 -31
  311. package/src/components/chip/Chip.tsx +0 -23
  312. package/src/components/container/Container.tsx +0 -42
  313. package/src/components/cookieBanner/CookieBanner.stories.tsx +0 -257
  314. package/src/components/cookieBanner/CookieBanner.test.tsx +0 -68
  315. package/src/components/cookieBanner/CookieBanner.tsx +0 -73
  316. package/src/components/divider/RuleDivider.stories.tsx +0 -254
  317. package/src/components/divider/RuleDivider.test.tsx +0 -164
  318. package/src/components/divider/RuleDivider.tsx +0 -23
  319. package/src/components/dropdown/DropdownMenu.test.tsx +0 -211
  320. package/src/components/dropdown/DropdownMenu.tsx +0 -108
  321. package/src/components/dropdown/useDropdownMenu.ts +0 -249
  322. package/src/components/form/Input.stories.tsx +0 -435
  323. package/src/components/form/Input.test.tsx +0 -206
  324. package/src/components/form/Input.tsx +0 -23
  325. package/src/components/form/TextArea.stories.tsx +0 -464
  326. package/src/components/form/TextArea.test.tsx +0 -232
  327. package/src/components/form/TextArea.tsx +0 -23
  328. package/src/components/layout/footer/Footer.tsx +0 -26
  329. package/src/components/layout/footer/Licence.tsx +0 -19
  330. package/src/components/layout/header/Header.test.tsx +0 -36
  331. package/src/components/layout/header/Header.tsx +0 -90
  332. package/src/components/layout/header/HeaderAuthClient.test.tsx +0 -45
  333. package/src/components/layout/header/HeaderAuthClient.tsx +0 -40
  334. package/src/components/layout/header/HeaderNavClient.test.tsx +0 -44
  335. package/src/components/layout/header/HeaderNavClient.tsx +0 -67
  336. package/src/components/link/ExternalLink.test.tsx +0 -102
  337. package/src/components/link/ExternalLink.tsx +0 -29
  338. package/src/components/link/Link.tsx +0 -26
  339. package/src/components/select/Select.stories.tsx +0 -336
  340. package/src/components/select/Select.test.tsx +0 -474
  341. package/src/components/select/Select.tsx +0 -125
  342. package/src/components/select/SelectSkeleton.stories.tsx +0 -194
  343. package/src/components/select/SelectSkeleton.test.tsx +0 -104
  344. package/src/components/select/SelectSkeleton.tsx +0 -23
  345. package/src/components/select/common.ts +0 -3
  346. package/src/components/select/index.ts +0 -18
  347. package/src/components/skipLink/SkipLink.stories.tsx +0 -346
  348. package/src/components/skipLink/SkipLink.test.tsx +0 -22
  349. package/src/components/skipLink/SkipLink.tsx +0 -49
  350. package/src/map/LegendPanel.tsx +0 -85
  351. /package/src/{components → assets}/images/DefraLogo.tsx +0 -0
  352. /package/src/{components → assets}/images/EaLogo.tsx +0 -0
  353. /package/src/{components → assets}/images/OglLogo.tsx +0 -0
  354. /package/src/components/{googleAnalytics → GoogleAnalytics}/GlobalVars.tsx +0 -0
  355. /package/src/components/{googleAnalytics → GoogleAnalytics}/GoogleAnalytics.tsx +0 -0
@@ -0,0 +1,304 @@
1
+ import type { Meta, StoryObj } from '@storybook/react-vite';
2
+
3
+ import { FieldDivider, FieldItem, FieldLegend, FieldSet } from './Fieldset';
4
+ import { Checkbox } from '../Checkbox/Checkbox';
5
+ import { ErrorText } from '../ErrorText/ErrorText';
6
+ import { FormGroup } from '../Form/FormGroup';
7
+ import { Heading } from '../Heading/Heading';
8
+ import { HintText } from '../HintText/HintText';
9
+ import { Label } from '../Label/Label';
10
+ import { Radio, RadioGroup } from '../Radio/Radio';
11
+
12
+ const meta: Meta<typeof FieldSet> = {
13
+ title: 'Components/Fieldset',
14
+ component: FieldSet,
15
+ tags: ['autodocs'],
16
+ parameters: {
17
+ docs: {
18
+ description: {
19
+ component:
20
+ "Semantic wrapper for groups of related controls such as checkboxes and radio buttons. `FieldLegend` acts as the group label, screen readers announce it alongside each control's own label. `<fieldset disabled>` propagates disabled to every descendant without individual `disabled` props. `FieldItem` wraps each control, its `Label`, and an optional `HintText`, mirroring GDS's own govuk-radios__item/govuk-checkboxes__item markup (a plain div with separately-associated control/label/hint, not a wrapping label, so a hint is announced as its own accessible description). Wire `id`/`htmlFor`/`aria-describedby` by hand, same as `FormGroup`. Use `FieldDivider` to separate groups within the same fieldset.",
21
+ },
22
+ },
23
+ },
24
+ };
25
+
26
+ export default meta;
27
+
28
+ type Story = StoryObj<typeof FieldSet>;
29
+
30
+ export const CheckboxGroup: Story = {
31
+ parameters: {
32
+ docs: {
33
+ description: {
34
+ story: '`FieldLegend` is plain body text by default, matching GDS.',
35
+ },
36
+ },
37
+ },
38
+ render: () => (
39
+ <FieldSet>
40
+ <FieldLegend>Which countries have you visited?</FieldLegend>
41
+
42
+ <div className="flex flex-col gap-gds-2">
43
+ <FieldItem>
44
+ <Checkbox id="country-france" defaultChecked />
45
+
46
+ <Label htmlFor="country-france">France</Label>
47
+ </FieldItem>
48
+
49
+ <FieldItem>
50
+ <Checkbox id="country-germany" />
51
+
52
+ <Label htmlFor="country-germany">Germany</Label>
53
+ </FieldItem>
54
+
55
+ <FieldItem>
56
+ <Checkbox id="country-spain" />
57
+
58
+ <Label htmlFor="country-spain">Spain</Label>
59
+ </FieldItem>
60
+ </div>
61
+ </FieldSet>
62
+ ),
63
+ };
64
+
65
+ export const WithRadios: Story = {
66
+ render: () => (
67
+ <FieldSet>
68
+ <FieldLegend>Have you changed your name?</FieldLegend>
69
+
70
+ <RadioGroup defaultValue="no">
71
+ <FieldItem>
72
+ <Radio id="name-changed-yes" value="yes" />
73
+
74
+ <Label htmlFor="name-changed-yes">Yes</Label>
75
+ </FieldItem>
76
+
77
+ <FieldItem>
78
+ <Radio id="name-changed-no" value="no" />
79
+
80
+ <Label htmlFor="name-changed-no">No</Label>
81
+ </FieldItem>
82
+ </RadioGroup>
83
+ </FieldSet>
84
+ ),
85
+ };
86
+
87
+ export const WithHints: Story = {
88
+ parameters: {
89
+ docs: {
90
+ description: {
91
+ story:
92
+ 'Add a HintText inside FieldItem for a per-option hint, matching GDS\'s "How do you want to sign in?" pattern. id/htmlFor/aria-describedby are wired by hand here, same as everywhere else in the library.',
93
+ },
94
+ },
95
+ },
96
+ render: () => (
97
+ <FormGroup>
98
+ <FieldSet aria-describedby="sign-in-hint">
99
+ <FieldLegend>
100
+ <Heading level="h1">How do you want to sign in?</Heading>
101
+ </FieldLegend>
102
+
103
+ <HintText id="sign-in-hint">
104
+ You&apos;ll need an account to prove your identity and complete your Self Assessment
105
+ </HintText>
106
+
107
+ <RadioGroup defaultValue="government-gateway">
108
+ <FieldItem>
109
+ <Radio id="sign-in" value="government-gateway" aria-describedby="sign-in-item-hint" />
110
+
111
+ <Label htmlFor="sign-in">Sign in with Government Gateway</Label>
112
+
113
+ <HintText id="sign-in-item-hint">
114
+ You&apos;ll have a user ID if you&apos;ve registered for Self Assessment or filed a
115
+ tax return online before
116
+ </HintText>
117
+ </FieldItem>
118
+
119
+ <FieldItem>
120
+ <Radio id="sign-in-2" value="one-login" aria-describedby="sign-in-2-item-hint" />
121
+
122
+ <Label htmlFor="sign-in-2">Sign in with GOV.UK One Login</Label>
123
+
124
+ <HintText id="sign-in-2-item-hint">
125
+ If you don&apos;t have a GOV.UK One Login, you can create one
126
+ </HintText>
127
+ </FieldItem>
128
+ </RadioGroup>
129
+ </FieldSet>
130
+ </FormGroup>
131
+ ),
132
+ };
133
+
134
+ export const WithDivider: Story = {
135
+ parameters: {
136
+ docs: {
137
+ description: {
138
+ story:
139
+ '`FieldDivider` separates two groups of options within the same fieldset. The default text is "or" but it can be overridden. Matches the GDS pattern for "select one of these, or this other option".',
140
+ },
141
+ },
142
+ },
143
+ render: () => (
144
+ <FieldSet>
145
+ <FieldLegend>What is your nationality?</FieldLegend>
146
+
147
+ <div className="flex flex-col gap-gds-2">
148
+ <FieldItem>
149
+ <Checkbox id="nationality-british" />
150
+
151
+ <Label htmlFor="nationality-british">British</Label>
152
+ </FieldItem>
153
+
154
+ <FieldItem>
155
+ <Checkbox id="nationality-irish" />
156
+
157
+ <Label htmlFor="nationality-irish">Irish</Label>
158
+ </FieldItem>
159
+
160
+ <FieldDivider />
161
+
162
+ <FieldItem>
163
+ <Checkbox id="nationality-other" />
164
+
165
+ <Label htmlFor="nationality-other">Citizen of another country</Label>
166
+ </FieldItem>
167
+ </div>
168
+ </FieldSet>
169
+ ),
170
+ };
171
+
172
+ export const WithDividerRadios: Story = {
173
+ render: () => (
174
+ <FieldSet>
175
+ <FieldLegend>Do you want to be contacted about this?</FieldLegend>
176
+
177
+ <RadioGroup>
178
+ <FieldItem>
179
+ <Radio id="contact-yes" value="yes" />
180
+
181
+ <Label htmlFor="contact-yes">Yes</Label>
182
+ </FieldItem>
183
+
184
+ <FieldItem>
185
+ <Radio id="contact-no" value="no" />
186
+
187
+ <Label htmlFor="contact-no">No</Label>
188
+ </FieldItem>
189
+
190
+ <FieldDivider />
191
+
192
+ <FieldItem>
193
+ <Radio id="contact-unsure" value="unsure" />
194
+
195
+ <Label htmlFor="contact-unsure">I&apos;m not sure</Label>
196
+ </FieldItem>
197
+ </RadioGroup>
198
+ </FieldSet>
199
+ ),
200
+ };
201
+
202
+ export const Invalid: Story = {
203
+ render: () => (
204
+ <FormGroup invalid>
205
+ <FieldSet>
206
+ <FieldLegend>Which countries have you visited?</FieldLegend>
207
+
208
+ <ErrorText id="countries-error">Select at least one country</ErrorText>
209
+
210
+ <div className="flex flex-col gap-gds-2">
211
+ <FieldItem>
212
+ <Checkbox id="invalid-country-france" aria-invalid aria-describedby="countries-error" />
213
+
214
+ <Label htmlFor="invalid-country-france">France</Label>
215
+ </FieldItem>
216
+
217
+ <FieldItem>
218
+ <Checkbox
219
+ id="invalid-country-germany"
220
+ aria-invalid
221
+ aria-describedby="countries-error"
222
+ />
223
+
224
+ <Label htmlFor="invalid-country-germany">Germany</Label>
225
+ </FieldItem>
226
+
227
+ <FieldItem>
228
+ <Checkbox id="invalid-country-spain" aria-invalid aria-describedby="countries-error" />
229
+
230
+ <Label htmlFor="invalid-country-spain">Spain</Label>
231
+ </FieldItem>
232
+ </div>
233
+ </FieldSet>
234
+ </FormGroup>
235
+ ),
236
+ };
237
+
238
+ export const Disabled: Story = {
239
+ parameters: {
240
+ docs: {
241
+ description: {
242
+ story:
243
+ '`<fieldset disabled>` disables every descendant form control at once. Labels are also dimmed via the `fieldset:disabled` CSS rule.',
244
+ },
245
+ },
246
+ },
247
+ render: () => (
248
+ <FieldSet disabled>
249
+ <FieldLegend>Which countries have you visited?</FieldLegend>
250
+
251
+ <div className="flex flex-col gap-gds-2">
252
+ <FieldItem>
253
+ <Checkbox id="disabled-country-france" defaultChecked />
254
+
255
+ <Label htmlFor="disabled-country-france">France</Label>
256
+ </FieldItem>
257
+
258
+ <FieldItem>
259
+ <Checkbox id="disabled-country-germany" />
260
+
261
+ <Label htmlFor="disabled-country-germany">Germany</Label>
262
+ </FieldItem>
263
+
264
+ <FieldItem>
265
+ <Checkbox id="disabled-country-spain" />
266
+
267
+ <Label htmlFor="disabled-country-spain">Spain</Label>
268
+ </FieldItem>
269
+ </div>
270
+ </FieldSet>
271
+ ),
272
+ };
273
+
274
+ export const WithHeading: Story = {
275
+ parameters: {
276
+ docs: {
277
+ description: {
278
+ story:
279
+ "FieldLegend has no size variants, it's plain body text, matching GDS. For a heading-like look (e.g. when the fieldset's question is the only content on the page), nest a real Heading inside it instead, the same pattern GDS itself documents: an <h1> inside <legend>.",
280
+ },
281
+ },
282
+ },
283
+ render: () => (
284
+ <FieldSet>
285
+ <FieldLegend>
286
+ <Heading level="h1">Consent preferences</Heading>
287
+ </FieldLegend>
288
+
289
+ <div className="flex flex-col gap-gds-2">
290
+ <FieldItem>
291
+ <Checkbox id="consent-name" defaultChecked />
292
+
293
+ <Label htmlFor="consent-name">Share my name</Label>
294
+ </FieldItem>
295
+
296
+ <FieldItem>
297
+ <Checkbox id="consent-email" />
298
+
299
+ <Label htmlFor="consent-email">Share my email address</Label>
300
+ </FieldItem>
301
+ </div>
302
+ </FieldSet>
303
+ ),
304
+ };
@@ -0,0 +1,38 @@
1
+ 'use client';
2
+
3
+ import type { ComponentProps } from 'react';
4
+
5
+ import { cn } from '../../utils/components';
6
+
7
+ export type FieldSetProps = ComponentProps<'fieldset'>;
8
+
9
+ export const FieldSet = ({ className, ...props }: FieldSetProps) => (
10
+ <fieldset data-slot="field-set" className={cn('cn-field-set', className)} {...props} />
11
+ );
12
+
13
+ export type FieldLegendProps = ComponentProps<'legend'>;
14
+
15
+ export const FieldLegend = ({ className, ...props }: FieldLegendProps) => (
16
+ <legend data-slot="field-legend" className={cn('cn-field-legend', className)} {...props} />
17
+ );
18
+
19
+ // MARK: FieldItem
20
+ // Mirrors GDS's own govuk-radios__item/govuk-checkboxes__item: a plain div
21
+ // around explicit, separately-associated Radio/Checkbox + Label + optional
22
+ // HintText siblings (real GDS, not a wrapping <label>), so a hint is
23
+ // announced as its own accessible description rather than folded into the
24
+ // control's name. Wire id/htmlFor/aria-describedby by hand, same as
25
+ // FormGroup, no context here, see the WithHints story for the pattern.
26
+ export type FieldItemProps = ComponentProps<'div'>;
27
+
28
+ export const FieldItem = ({ className, ...props }: FieldItemProps) => (
29
+ <div data-slot="field-item" className={cn('cn-field-item', className)} {...props} />
30
+ );
31
+
32
+ export type FieldDividerProps = ComponentProps<'div'>;
33
+
34
+ export const FieldDivider = ({ className, children = 'or', ...props }: FieldDividerProps) => (
35
+ <div data-slot="field-divider" className={cn('cn-field-divider', className)} {...props}>
36
+ {children}
37
+ </div>
38
+ );
@@ -0,0 +1,85 @@
1
+ @layer components {
2
+ /* MARK: File upload
3
+ Two-bordered-section layout: trigger has its own cn-form-border (right edge
4
+ acts as the internal divider), field wrapper has cn-form-border with no left
5
+ border so it merges flush. Error border and focus ring apply only to the
6
+ field section, matching the InputGroup prefix/swatch pattern. */
7
+ .cn-file-upload {
8
+ @apply flex w-full;
9
+
10
+ &:has(:disabled) {
11
+ @apply opacity-50;
12
+
13
+ .cn-file-upload-trigger {
14
+ @apply cursor-not-allowed;
15
+ }
16
+ }
17
+ }
18
+
19
+ /* MARK: Trigger
20
+ <label> styled as a secondary-button swatch. Its right border doubles as
21
+ the visual divider between the trigger and the filename area. */
22
+ .cn-file-upload-trigger {
23
+ @apply cn-form-swatch shrink-0 px-gds-2 text-body cursor-pointer select-none border-r-0;
24
+ }
25
+
26
+ .cn-file-upload:not(:has(:disabled)) .cn-file-upload-trigger {
27
+ &:hover {
28
+ @apply bg-muted;
29
+ }
30
+ }
31
+
32
+ /* MARK: Field
33
+ Wraps the hidden input and filename display. No left border, butts flush
34
+ against the trigger. Focus ring and error border are scoped here so the
35
+ trigger is unaffected when the field is invalid. bg-panel is explicit
36
+ since, unlike a real <input> (opaque by default via the browser's own
37
+ UA styles), the filename display is a plain <span> with no background
38
+ of its own, it would otherwise show through to whatever's behind the
39
+ component (e.g. blending into an Accordion's own background) instead of
40
+ reading as a distinct field. */
41
+ .cn-file-upload-field {
42
+ @apply cn-form-border relative flex items-center flex-1 min-w-0 h-10 bg-panel;
43
+
44
+ &:focus-within {
45
+ @apply outline-focus;
46
+ box-shadow: inset 0 0 0 var(--border-width-form) var(--color-divider-input);
47
+ }
48
+
49
+ &:has([aria-invalid='true']),
50
+ &:has(:user-invalid) {
51
+ @apply border-error;
52
+
53
+ &:focus-within {
54
+ box-shadow: inset 0 0 0 var(--border-width-form) var(--color-error);
55
+ }
56
+ }
57
+ }
58
+
59
+ /* MARK: Hidden input */
60
+ .cn-file-upload-input {
61
+ @apply sr-only;
62
+ }
63
+
64
+ /* MARK: Filename display
65
+ min-w-0 overrides the flex item default of min-width: auto, which
66
+ otherwise refuses to shrink below the filename's own unbroken width
67
+ (truncate implies white-space: nowrap) and overflows the container
68
+ instead of actually truncating. Same fix applied to the parent
69
+ cn-file-upload-field above, a flex item itself, for the same reason. */
70
+ .cn-file-upload-filename {
71
+ @apply flex-1 min-w-0 px-gds-2 text-base text-body truncate;
72
+ }
73
+
74
+ .cn-file-upload[data-state='empty'] .cn-file-upload-filename {
75
+ @apply text-body-secondary;
76
+ }
77
+
78
+ /* MARK: Clear button
79
+ Sits inside the same bordered field as the filename, not a separate
80
+ element outside it. mr-gds-1 keeps it off the field's own right border,
81
+ matching the breathing room the filename already gets on its own side. */
82
+ .cn-file-upload-clear {
83
+ @apply mr-gds-1;
84
+ }
85
+ }
@@ -0,0 +1,106 @@
1
+ import type { Meta, StoryObj } from '@storybook/react-vite';
2
+
3
+ import { FileUpload } from './FileUpload';
4
+ import { ErrorText } from '../ErrorText/ErrorText';
5
+ import { FormGroup } from '../Form/FormGroup';
6
+ import { HintText } from '../HintText/HintText';
7
+ import { Label } from '../Label/Label';
8
+
9
+ const meta: Meta<typeof FileUpload> = {
10
+ title: 'Components/FileUpload',
11
+ component: FileUpload,
12
+ tags: ['autodocs'],
13
+ parameters: {
14
+ docs: {
15
+ description: {
16
+ component:
17
+ 'A styled file picker that matches the height and border treatment of the Input component. The "Select file" trigger is a `<label>` element associated with a visually hidden but keyboard-accessible `<input type="file">`, so no JavaScript is needed to open the file dialog. It works with click, touch, and keyboard. Pair it with a `<Label>` above for the field name, the same as any other form field. Once a file is selected, a clear button appears to remove it, pick a real file in the Default story below to see it.',
18
+ },
19
+ },
20
+ },
21
+ };
22
+
23
+ export default meta;
24
+
25
+ type Story = StoryObj<typeof FileUpload>;
26
+
27
+ export const Default: Story = {
28
+ render: (args) => (
29
+ <FormGroup>
30
+ <Label htmlFor="id-a">Upload boundary file</Label>
31
+
32
+ <FileUpload {...args} id="id-a" />
33
+ </FormGroup>
34
+ ),
35
+ };
36
+
37
+ export const WithAcceptHint: Story = {
38
+ parameters: {
39
+ docs: {
40
+ description: {
41
+ story:
42
+ 'Pass `accept` to restrict the file picker to specific types. Hint text below the field describes the constraint to users, the component itself does not render hint text.',
43
+ },
44
+ },
45
+ },
46
+ render: (args) => (
47
+ <FormGroup>
48
+ <Label htmlFor="id-b">Upload boundary file</Label>
49
+
50
+ <HintText>Supports .geojson, .kml.</HintText>
51
+
52
+ <FileUpload {...args} id="id-b" accept=".geojson,.kml" />
53
+ </FormGroup>
54
+ ),
55
+ };
56
+
57
+ export const WithError: Story = {
58
+ parameters: {
59
+ docs: {
60
+ description: {
61
+ story: 'Set `aria-invalid="true"` to show the error border on the filename area.',
62
+ },
63
+ },
64
+ },
65
+ render: (args) => (
66
+ <FormGroup invalid>
67
+ <Label htmlFor="id-c">Upload boundary file</Label>
68
+
69
+ <ErrorText id="file-upload-error">Select a file to continue</ErrorText>
70
+
71
+ <FileUpload {...args} aria-invalid="true" aria-describedby="file-upload-error" id="id-c" />
72
+ </FormGroup>
73
+ ),
74
+ };
75
+
76
+ export const LongFilename: Story = {
77
+ parameters: {
78
+ docs: {
79
+ description: {
80
+ story:
81
+ 'A long filename truncates with an ellipsis rather than overflowing the field, the component stays no wider than its container. Uses `placeholder` here to demonstrate this without needing to actually pick a file, real selected filenames go through the same truncation.',
82
+ },
83
+ },
84
+ },
85
+ render: (args) => (
86
+ <FormGroup className="max-w-xs">
87
+ <Label htmlFor="id-e">Upload boundary file</Label>
88
+
89
+ <FileUpload
90
+ {...args}
91
+ id="id-e"
92
+ placeholder="environment-agency-flood-risk-boundary-data-2024-final-v3.geojson"
93
+ />
94
+ </FormGroup>
95
+ ),
96
+ };
97
+
98
+ export const Disabled: Story = {
99
+ render: (args) => (
100
+ <FormGroup>
101
+ <Label htmlFor="id-d">Upload boundary file</Label>
102
+
103
+ <FileUpload {...args} id="id-d" disabled />
104
+ </FormGroup>
105
+ ),
106
+ };
@@ -0,0 +1,99 @@
1
+ 'use client';
2
+
3
+ import { useRef, useState, type ChangeEvent, type ComponentProps, type ReactNode } from 'react';
4
+
5
+ import { LuX } from 'react-icons/lu';
6
+
7
+ import { cn } from '../../utils/components';
8
+ import { Button } from '../Button/Button';
9
+
10
+ export type FileUploadProps = Omit<ComponentProps<'input'>, 'type' | 'id'> & {
11
+ id: string;
12
+ triggerLabel?: ReactNode;
13
+ placeholder?: ReactNode;
14
+ };
15
+
16
+ export const FileUpload = ({
17
+ id,
18
+ triggerLabel = 'Select file',
19
+ placeholder = 'No file selected',
20
+ className,
21
+ onChange,
22
+ ...props
23
+ }: FileUploadProps) => {
24
+ const inputRef = useRef<HTMLInputElement>(null);
25
+ const [displayName, setDisplayName] = useState<string | null>(null);
26
+
27
+ const handleChange = (event: ChangeEvent<HTMLInputElement>) => {
28
+ const files = event.target.files;
29
+
30
+ if (!files || files.length === 0) {
31
+ setDisplayName(null);
32
+ } else if (files.length === 1 && files[0]) {
33
+ setDisplayName(files[0].name);
34
+ } else {
35
+ setDisplayName(`${files.length} files selected`);
36
+ }
37
+
38
+ onChange?.(event);
39
+ };
40
+
41
+ const handleClear = () => {
42
+ const input = inputRef.current;
43
+
44
+ if (!input) {
45
+ return;
46
+ }
47
+
48
+ // A file input's value can't be set programmatically, but clearing it
49
+ // back to empty is allowed. Dispatching a real change event (rather than
50
+ // calling setDisplayName directly) reuses handleChange as the single
51
+ // source of truth, so the consumer's own onChange fires too, exactly as
52
+ // if the file had been cleared through the picker itself.
53
+ input.value = '';
54
+ input.dispatchEvent(new Event('change', { bubbles: true }));
55
+
56
+ // The clear button disappears once displayName clears, move focus
57
+ // somewhere sensible rather than letting it fall back to <body>.
58
+ input.focus();
59
+ };
60
+
61
+ return (
62
+ <div
63
+ data-slot="file-upload"
64
+ data-state={displayName ? 'has-file' : 'empty'}
65
+ className={cn('cn-file-upload', className)}
66
+ >
67
+ <label htmlFor={id} className="cn-file-upload-trigger">
68
+ {triggerLabel}
69
+ </label>
70
+
71
+ <div className="cn-file-upload-field">
72
+ <input
73
+ ref={inputRef}
74
+ type="file"
75
+ id={id}
76
+ className="cn-file-upload-input"
77
+ onChange={handleChange}
78
+ {...props}
79
+ />
80
+
81
+ <span className="cn-file-upload-filename" aria-live="polite">
82
+ {displayName ?? placeholder}
83
+ </span>
84
+
85
+ {displayName ? (
86
+ <Button
87
+ variant="icon"
88
+ appearance="ghost"
89
+ aria-label="Remove selected file"
90
+ onClick={handleClear}
91
+ className="cn-file-upload-clear"
92
+ >
93
+ <LuX aria-hidden />
94
+ </Button>
95
+ ) : null}
96
+ </div>
97
+ </div>
98
+ );
99
+ };
@@ -1,11 +1,13 @@
1
- import { ExternalLink } from '../../link/ExternalLink';
1
+ import { ExternalLink } from '../ExternalLink/ExternalLink';
2
2
 
3
3
  export const Copyright = () => {
4
4
  const currentYear = new Date().getFullYear();
5
5
 
6
6
  return (
7
7
  <ExternalLink
8
- className="text-black text-balance sm:text-nowrap text-center sm:text-left justify-start"
8
+ className="text-balance sm:text-nowrap text-center sm:text-left justify-start"
9
+ appearance="contrast"
10
+ variant="plain"
9
11
  href="https://www.nationalarchives.gov.uk/information-management/re-using-public-sector-information/uk-government-licensing-framework/crown-copyright/"
10
12
  >
11
13
  &copy; Crown Copyright {currentYear}
@@ -0,0 +1,24 @@
1
+ import type { Meta, StoryObj } from '@storybook/react-vite';
2
+
3
+ import { Footer } from './Footer';
4
+
5
+ const meta = {
6
+ title: 'Components/Footer',
7
+ component: Footer,
8
+ parameters: {
9
+ layout: 'fullscreen',
10
+ docs: {
11
+ description: {
12
+ component:
13
+ 'Full site footer with support links, the Open Government Licence notice, and crown copyright.',
14
+ },
15
+ },
16
+ },
17
+ tags: ['autodocs'],
18
+ } satisfies Meta<typeof Footer>;
19
+
20
+ export default meta;
21
+
22
+ type Story = StoryObj<typeof meta>;
23
+
24
+ export const Default: Story = {};