@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,225 @@
1
+ 'use client';
2
+
3
+ import {
4
+ createContext,
5
+ useCallback,
6
+ useContext,
7
+ useEffect,
8
+ useMemo,
9
+ useState,
10
+ type CSSProperties,
11
+ type ComponentProps,
12
+ type MouseEvent,
13
+ } from 'react';
14
+
15
+ import { LuX } from 'react-icons/lu';
16
+
17
+ import { cn } from '../../utils/components';
18
+ import { Button } from '../Button/Button';
19
+
20
+ // MARK: Types
21
+
22
+ type SidebarSide = 'left' | 'right' | 'top' | 'bottom';
23
+ type SidebarOrientation = 'horizontal' | 'vertical';
24
+
25
+ type SidebarContextValue = {
26
+ open: boolean;
27
+ setOpen: (open: boolean) => void;
28
+ toggleSidebar: () => void;
29
+ isMobile: boolean;
30
+ };
31
+
32
+ type SidebarProviderProps = ComponentProps<'div'> & {
33
+ open?: boolean;
34
+ onOpenChange?: (open: boolean) => void;
35
+ defaultOpen?: boolean;
36
+ /** Width of the sidebar panel for left/right sidebars. */
37
+ width?: string;
38
+ /** Height of the sidebar panel for top/bottom sidebars. */
39
+ height?: string;
40
+ /** Must be 'vertical' when using side="top" or side="bottom". */
41
+ orientation?: SidebarOrientation;
42
+ };
43
+
44
+ type SidebarProps = ComponentProps<'aside'> & {
45
+ side?: SidebarSide;
46
+ variant?: 'push' | 'overlay';
47
+ };
48
+
49
+ // MARK: Context
50
+
51
+ const SidebarContext = createContext<SidebarContextValue | null>(null);
52
+
53
+ export const useSidebar = (): SidebarContextValue => {
54
+ const context = useContext(SidebarContext);
55
+
56
+ if (!context) {
57
+ throw new Error('useSidebar must be used inside SidebarProvider');
58
+ }
59
+
60
+ return context;
61
+ };
62
+
63
+ const useIsMobile = (breakpoint = 640) => {
64
+ const [isMobile, setIsMobile] = useState(false);
65
+
66
+ useEffect(() => {
67
+ const mq = window.matchMedia(`(max-width: ${breakpoint - 1}px)`);
68
+
69
+ setIsMobile(mq.matches);
70
+ const handler = (event: MediaQueryListEvent) => setIsMobile(event.matches);
71
+
72
+ mq.addEventListener('change', handler);
73
+
74
+ return () => mq.removeEventListener('change', handler);
75
+ }, [breakpoint]);
76
+
77
+ return isMobile;
78
+ };
79
+
80
+ // MARK: SidebarProvider
81
+
82
+ export const SidebarProvider = ({
83
+ open: controlledOpen,
84
+ onOpenChange,
85
+ defaultOpen = true,
86
+ width = '16rem',
87
+ height = '12rem',
88
+ orientation = 'horizontal',
89
+ children,
90
+ className,
91
+ style,
92
+ ...props
93
+ }: SidebarProviderProps) => {
94
+ const [_open, _setOpen] = useState(defaultOpen);
95
+ const open = controlledOpen ?? _open;
96
+ const isMobile = useIsMobile();
97
+
98
+ const setOpen = useCallback(
99
+ (value: boolean) => {
100
+ _setOpen(value);
101
+ onOpenChange?.(value);
102
+ },
103
+ [onOpenChange],
104
+ );
105
+
106
+ const toggleSidebar = useCallback(() => setOpen(!open), [open, setOpen]);
107
+
108
+ const contextValue = useMemo(
109
+ () => ({ open, setOpen, toggleSidebar, isMobile }),
110
+ [open, setOpen, toggleSidebar, isMobile],
111
+ );
112
+
113
+ return (
114
+ <SidebarContext.Provider value={contextValue}>
115
+ <div
116
+ data-slot="sidebar-provider"
117
+ data-orientation={orientation}
118
+ className={cn('cn-sidebar-provider', className)}
119
+ style={
120
+ {
121
+ '--cn-sidebar-width': width,
122
+ '--cn-sidebar-height': height,
123
+ ...style,
124
+ } as CSSProperties
125
+ }
126
+ {...props}
127
+ >
128
+ {children}
129
+ </div>
130
+ </SidebarContext.Provider>
131
+ );
132
+ };
133
+
134
+ // MARK: Sidebar
135
+
136
+ export const Sidebar = ({
137
+ side = 'left',
138
+ variant = 'push',
139
+ children,
140
+ className,
141
+ 'aria-label': ariaLabel = 'Sidebar',
142
+ ...props
143
+ }: SidebarProps) => {
144
+ const { open, isMobile, setOpen } = useSidebar();
145
+ const state = open ? 'expanded' : 'collapsed';
146
+
147
+ return (
148
+ <div
149
+ data-state={state}
150
+ data-side={side}
151
+ data-variant={variant}
152
+ data-mobile={isMobile || undefined}
153
+ className="cn-sidebar-root"
154
+ >
155
+ <div aria-hidden="true" className="cn-sidebar-gap" />
156
+
157
+ {isMobile && open && (
158
+ <div aria-hidden="true" className="cn-sidebar-backdrop" onClick={() => setOpen(false)} />
159
+ )}
160
+
161
+ <aside
162
+ data-slot="sidebar"
163
+ data-state={state}
164
+ aria-label={ariaLabel}
165
+ inert={open ? undefined : true}
166
+ className={cn('cn-sidebar', className)}
167
+ {...props}
168
+ >
169
+ {children}
170
+ </aside>
171
+ </div>
172
+ );
173
+ };
174
+
175
+ // MARK: SidebarClose
176
+
177
+ export const SidebarClose = ({
178
+ className,
179
+ 'aria-label': ariaLabel = 'Close sidebar',
180
+ onClick,
181
+ ...props
182
+ }: Omit<ComponentProps<'button'>, 'children'>) => {
183
+ const { setOpen } = useSidebar();
184
+
185
+ const handleClick = (event: MouseEvent<HTMLButtonElement>) => {
186
+ setOpen(false);
187
+ onClick?.(event);
188
+ };
189
+
190
+ return (
191
+ <Button
192
+ variant="icon"
193
+ appearance="ghost"
194
+ data-slot="sidebar-close"
195
+ className={cn(className)}
196
+ aria-label={ariaLabel}
197
+ onClick={handleClick}
198
+ {...props}
199
+ >
200
+ <LuX aria-hidden />
201
+ </Button>
202
+ );
203
+ };
204
+
205
+ // MARK: SidebarInset
206
+
207
+ export const SidebarInset = ({ className, ...props }: ComponentProps<'div'>) => (
208
+ <div data-slot="sidebar-inset" className={cn('cn-sidebar-inset', className)} {...props} />
209
+ );
210
+
211
+ // MARK: Structure
212
+
213
+ export const SidebarHeader = ({ className, ...props }: ComponentProps<'div'>) => (
214
+ <div data-slot="sidebar-header" className={cn('cn-sidebar-header', className)} {...props} />
215
+ );
216
+
217
+ export const SidebarContent = ({ className, ...props }: ComponentProps<'div'>) => (
218
+ <div data-slot="sidebar-content" className={cn('cn-sidebar-content', className)} {...props} />
219
+ );
220
+
221
+ export const SidebarFooter = ({ className, ...props }: ComponentProps<'div'>) => (
222
+ <div data-slot="sidebar-footer" className={cn('cn-sidebar-footer', className)} {...props} />
223
+ );
224
+
225
+ export type { SidebarSide, SidebarOrientation, SidebarProviderProps, SidebarProps };
@@ -0,0 +1,16 @@
1
+ @layer components {
2
+ /* MARK: Skeleton
3
+ Base placeholder shape shared by every per-component skeleton.
4
+ inline-block so it drops into text flow (heading/paragraph/button label
5
+ bars) without a forced line break, size it via className. Purely
6
+ decorative (aria-hidden), if you're assembling several of these into a
7
+ loading page, wrap the whole group in one role="status" region rather
8
+ than announcing loading per shape. */
9
+ .cn-skeleton {
10
+ /* bg-wash (5% black) is too faint to read clearly against a white page,
11
+ it's tuned for subtle hover backgrounds, not something that needs to
12
+ stand out. bg-muted (20% black, the same token dividers/disabled
13
+ states use) has enough contrast to actually read as "loading". */
14
+ @apply inline-block bg-muted animate-pulse;
15
+ }
16
+ }
@@ -0,0 +1,39 @@
1
+ import type { Meta, StoryObj } from '@storybook/react-vite';
2
+
3
+ import { Skeleton } from './Skeleton';
4
+
5
+ const meta: Meta<typeof Skeleton> = {
6
+ title: 'Components/Skeleton',
7
+ component: Skeleton,
8
+ tags: ['autodocs'],
9
+ parameters: {
10
+ docs: {
11
+ description: {
12
+ component:
13
+ "Base placeholder shape shared by every per-component skeleton (HeadingSkeleton, ParagraphSkeleton, ButtonSkeleton, ...). Size it via `className`. Prefer reusing a real component's own classes over building a shape from scratch, so the skeleton always matches that component's real dimensions and never causes a layout shift when the real content loads in.",
14
+ },
15
+ },
16
+ },
17
+ };
18
+
19
+ export default meta;
20
+
21
+ type Story = StoryObj<typeof Skeleton>;
22
+
23
+ export const Default: Story = {
24
+ render: () => <Skeleton className="h-4 w-48" />,
25
+ };
26
+
27
+ export const Shapes: Story = {
28
+ render: () => (
29
+ <div className="flex flex-col gap-gds-2">
30
+ <Skeleton className="h-4 w-64" />
31
+
32
+ <Skeleton className="h-4 w-48" />
33
+
34
+ <Skeleton className="h-10 w-32" />
35
+
36
+ <Skeleton className="size-10" />
37
+ </div>
38
+ ),
39
+ };
@@ -0,0 +1,12 @@
1
+ import type { ComponentProps } from 'react';
2
+
3
+ import { cn } from '../../utils/components';
4
+
5
+ export type SkeletonProps = ComponentProps<'div'> & {
6
+ /** Explicitly disallow children, a skeleton is a placeholder shape, not a content wrapper. */
7
+ children?: never;
8
+ };
9
+
10
+ export const Skeleton = ({ className, ...props }: SkeletonProps) => (
11
+ <div data-slot="skeleton" aria-hidden className={cn('cn-skeleton', className)} {...props} />
12
+ );
@@ -0,0 +1,16 @@
1
+ @layer components {
2
+ .cn-skip-link {
3
+ @apply w-full block underline text-on-focus;
4
+
5
+ text-decoration-thickness: max(1px, 0.0625rem);
6
+ text-underline-offset: 0.1578em;
7
+
8
+ &:not(:focus) {
9
+ @apply sr-only;
10
+ }
11
+
12
+ &:focus {
13
+ @apply bg-focus outline-focus p-gds-3;
14
+ }
15
+ }
16
+ }
@@ -0,0 +1,40 @@
1
+ import type { Meta, StoryObj } from '@storybook/react-vite';
2
+
3
+ import { SkipLink } from './SkipLink';
4
+ import { Paragraph } from '../Paragraph/Paragraph';
5
+
6
+ const meta: Meta<typeof SkipLink> = {
7
+ title: 'Components/SkipLink',
8
+ component: SkipLink,
9
+ parameters: {
10
+ docs: {
11
+ description: {
12
+ component: 'Use a SkipLink to associate text with form controls and improve accessibility.',
13
+ },
14
+ },
15
+ },
16
+ argTypes: {
17
+ contentId: { control: 'text' },
18
+ },
19
+ args: {
20
+ contentId: 'main-content',
21
+ },
22
+ };
23
+
24
+ export default meta;
25
+
26
+ type Story = StoryObj<typeof SkipLink>;
27
+
28
+ export const Example: Story = {
29
+ render: (args) => (
30
+ <div>
31
+ <SkipLink contentId={args.contentId} />
32
+
33
+ <main id="main-content">
34
+ <Paragraph>
35
+ This is the main content. Click inside this example and press tab to see the skip link.
36
+ </Paragraph>
37
+ </main>
38
+ </div>
39
+ ),
40
+ };
@@ -0,0 +1,15 @@
1
+ import type { ComponentProps } from 'react';
2
+
3
+ import { cn } from '../../utils/components';
4
+
5
+ export type SkipLinkProps = Omit<ComponentProps<'a'>, 'href' | 'children' | 'target' | 'ref'> & {
6
+ contentId: string;
7
+ };
8
+
9
+ export const SkipLink = ({ className, contentId, ...props }: SkipLinkProps) => {
10
+ return (
11
+ <a href={`#${contentId}`} className={cn('cn-skip-link', className)} {...props}>
12
+ Skip to main content
13
+ </a>
14
+ );
15
+ };
@@ -0,0 +1,30 @@
1
+ @layer components {
2
+ /* MARK: Spinner
3
+ h-10 w-10 is a reasonable general-purpose default, override via
4
+ className for a specific context (e.g. LoadingBox sizes it larger). */
5
+ .cn-spinner {
6
+ @apply h-10 w-10;
7
+ }
8
+
9
+ /* animation-duration is forced to 0.01ms under prefers-reduced-motion by
10
+ the shared base rule (see @tpzdsp/eslint-config-dsp's utilities.css),
11
+ no extra handling needed here. */
12
+ .cn-spinner-rect {
13
+ animation: cn-spinner-fade 1s linear infinite;
14
+ }
15
+
16
+ @keyframes cn-spinner-fade {
17
+ 0% {
18
+ opacity: 0.250075;
19
+ }
20
+ 0.01% {
21
+ opacity: 0.25;
22
+ }
23
+ 0.03% {
24
+ opacity: 1;
25
+ }
26
+ 100% {
27
+ opacity: 0.250075;
28
+ }
29
+ }
30
+ }
@@ -0,0 +1,36 @@
1
+ import type { Meta, StoryObj } from '@storybook/react-vite';
2
+
3
+ import { Spinner } from './Spinner';
4
+
5
+ const meta: Meta<typeof Spinner> = {
6
+ title: 'Components/Spinner',
7
+ component: Spinner,
8
+ tags: ['autodocs'],
9
+ parameters: {
10
+ docs: {
11
+ description: {
12
+ component:
13
+ "GOV.UK-style loading spinner: 12 rects in a circle, each flashing then fading, staggered to sweep round like a clock. Sizes and colours via className, it's currentColor-based. Usually used via LoadingBox rather than directly.",
14
+ },
15
+ },
16
+ },
17
+ };
18
+
19
+ export default meta;
20
+
21
+ type Story = StoryObj<typeof Spinner>;
22
+
23
+ export const Default: Story = {};
24
+
25
+ export const CustomSize: Story = {
26
+ render: () => <Spinner className="h-20 w-20" />,
27
+ };
28
+
29
+ export const CustomColor: Story = {
30
+ parameters: {
31
+ docs: {
32
+ description: { story: 'fill is currentColor, so it follows the text colour utility.' },
33
+ },
34
+ },
35
+ render: () => <Spinner className="text-accent" />,
36
+ };
@@ -0,0 +1,45 @@
1
+ import type { ComponentProps } from 'react';
2
+
3
+ import { cn } from '../../utils/components';
4
+
5
+ // 12 rects arranged in a circle, each fading in then slowly back out (see
6
+ // Spinner.css), staggered by delay so the flashes appear to sweep round like
7
+ // a clock. Matches GOV.UK's own loading spinner. Fixed, stable keys (not
8
+ // array index) even though these never reorder, same convention as this
9
+ // library's skeleton components.
10
+ const SPINNER_RECTS = Array.from({ length: 12 }, (_, index) => ({
11
+ key: `rect-${index}`,
12
+ angle: index * 30,
13
+ delayMs: index * 83,
14
+ }));
15
+
16
+ export type SpinnerProps = Omit<ComponentProps<'svg'>, 'title'> & {
17
+ title?: string;
18
+ };
19
+
20
+ export const Spinner = ({ className, title = 'Loading', ...props }: SpinnerProps) => (
21
+ <svg
22
+ data-slot="spinner"
23
+ viewBox="-25 -25 50 50"
24
+ preserveAspectRatio="xMidYMid meet"
25
+ fill="currentColor"
26
+ className={cn('cn-spinner', className)}
27
+ {...props}
28
+ >
29
+ {title ? <title>{title}</title> : null}
30
+
31
+ {SPINNER_RECTS.map(({ key, angle, delayMs }) => (
32
+ <rect
33
+ key={key}
34
+ className="cn-spinner-rect"
35
+ width="12"
36
+ height="5"
37
+ rx="2.5"
38
+ ry="2.5"
39
+ opacity="0"
40
+ transform={`rotate(${angle}, 0, 2) translate(10 0)`}
41
+ style={{ animationDelay: `${delayMs}ms` }}
42
+ />
43
+ ))}
44
+ </svg>
45
+ );
@@ -0,0 +1,13 @@
1
+ @layer components {
2
+ .cn-start-button {
3
+ @apply text-base sm:text-xl;
4
+ }
5
+
6
+ .cn-start-button-content {
7
+ @apply flex items-center gap-2;
8
+ }
9
+
10
+ .cn-start-button-icon {
11
+ @apply size-6 sm:size-7 stroke-3 sm:stroke-4;
12
+ }
13
+ }
@@ -0,0 +1,68 @@
1
+ import type { Meta, StoryObj } from '@storybook/react-vite';
2
+
3
+ import { StartButton, StartButtonContent } from './StartButton';
4
+
5
+ const meta: Meta<typeof StartButton> = {
6
+ title: 'Components/StartButton',
7
+ component: StartButton,
8
+ tags: ['autodocs'],
9
+ parameters: {
10
+ docs: {
11
+ description: {
12
+ component:
13
+ "Use a start button for the main call to action on your service’s Start page. It renders as a link (an `<a>`), not a `<button>`, matching the GDS start button: it navigates to the first page of a service rather than submitting data or triggering a JS action, so it needs a real `href`. Pass `asChild` to render your own element instead (e.g. Next.js's `Link`, for prefetching and base-path handling), nesting `StartButtonContent` inside it so both modes render identically.",
14
+ },
15
+ },
16
+ },
17
+ argTypes: {
18
+ appearance: {
19
+ control: { type: 'radio' },
20
+ options: ['primary', 'secondary'],
21
+ },
22
+ },
23
+ };
24
+
25
+ export default meta;
26
+
27
+ type Story = StoryObj<typeof StartButton>;
28
+
29
+ export const Primary: Story = {
30
+ args: {
31
+ appearance: 'primary',
32
+ href: '#',
33
+ },
34
+ };
35
+
36
+ export const Secondary: Story = {
37
+ args: {
38
+ appearance: 'secondary',
39
+ href: '#',
40
+ },
41
+ };
42
+
43
+ export const CustomText: Story = {
44
+ args: {
45
+ appearance: 'primary',
46
+ href: '#',
47
+ children: 'Explore data',
48
+ },
49
+ };
50
+
51
+ export const AsChild: Story = {
52
+ parameters: {
53
+ docs: {
54
+ description: {
55
+ story:
56
+ 'Use `asChild` to render your own element as the actual link, e.g. Next.js\'s `Link`, so it handles prefetching and the app\'s base path rather than a plain `<a>`. The child stands in for a framework link component here; nest `StartButtonContent` inside it to get the same "Start now" text and chevron.',
57
+ },
58
+ },
59
+ },
60
+ render: () => (
61
+ <StartButton asChild appearance="primary">
62
+ {/* eslint-disable-next-line jsx-a11y/anchor-is-valid */}
63
+ <a href="#">
64
+ <StartButtonContent />
65
+ </a>
66
+ </StartButton>
67
+ ),
68
+ };
@@ -0,0 +1,50 @@
1
+ import type { ComponentProps, ReactNode } from 'react';
2
+
3
+ import { LuChevronRight } from 'react-icons/lu';
4
+
5
+ import { cn } from '../../utils/components';
6
+ import { LinkButton } from '../LinkButton/LinkButton';
7
+ import type { LinkButtonAppearance } from '../LinkButton/LinkButton';
8
+
9
+ export type StartButtonProps = ComponentProps<'a'> & {
10
+ asChild?: boolean;
11
+ appearance: Extract<LinkButtonAppearance, 'primary' | 'secondary'>;
12
+ };
13
+
14
+ export type StartButtonContentProps = {
15
+ children?: ReactNode;
16
+ };
17
+
18
+ export const StartButton = ({
19
+ appearance,
20
+ asChild = false,
21
+ children,
22
+ className,
23
+ ...props
24
+ }: StartButtonProps) => {
25
+ return (
26
+ <LinkButton
27
+ asChild={asChild}
28
+ className={cn('cn-start-button', className)}
29
+ appearance={appearance}
30
+ variant="cta"
31
+ {...props}
32
+ >
33
+ {asChild ? children : <StartButtonContent>{children}</StartButtonContent>}
34
+ </LinkButton>
35
+ );
36
+ };
37
+
38
+ // The "Start now" text + chevron markup StartButton renders internally. Reuse
39
+ // this inside your own link element when composing StartButton with
40
+ // `asChild` (e.g. wrapping Next.js's `Link`), so both modes render identically:
41
+ // <StartButton asChild appearance="primary"><NextLink href="/start"><StartButtonContent /></NextLink></StartButton>
42
+ export const StartButtonContent = ({ children }: StartButtonContentProps) => {
43
+ return (
44
+ <span className="cn-start-button-content">
45
+ <span className="cn-start-button-text">{children ?? 'Start now'}</span>
46
+
47
+ <LuChevronRight className="cn-start-button-icon" />
48
+ </span>
49
+ );
50
+ };
@@ -0,0 +1,31 @@
1
+ import type { Meta, StoryObj } from '@storybook/react-vite';
2
+
3
+ import { SubmitButton } from './SubmitButton';
4
+
5
+ const meta: Meta<typeof SubmitButton> = {
6
+ title: 'Components/SubmitButton',
7
+ component: SubmitButton,
8
+ tags: ['autodocs'],
9
+ parameters: {
10
+ docs: {
11
+ description: {
12
+ component: 'Use SubmitButton for an action that submits a form.',
13
+ },
14
+ },
15
+ },
16
+ argTypes: {
17
+ children: { control: 'text' },
18
+ },
19
+ };
20
+
21
+ export default meta;
22
+
23
+ type Story = StoryObj<typeof SubmitButton>;
24
+
25
+ export const Default: Story = {};
26
+
27
+ export const CustomText: Story = {
28
+ args: {
29
+ children: 'Click to submit',
30
+ },
31
+ };
@@ -0,0 +1,14 @@
1
+ import type { ComponentProps } from 'react';
2
+
3
+ import { cn } from '../../utils/components';
4
+ import { Button } from '../Button/Button';
5
+
6
+ export type SubmitButtonProps = Omit<ComponentProps<typeof Button>, 'type'>;
7
+
8
+ export const SubmitButton = ({ className, children, ...props }: SubmitButtonProps) => {
9
+ return (
10
+ <Button {...props} type="submit" className={cn(className, 'cn-submit-button')}>
11
+ {children ?? 'Submit'}
12
+ </Button>
13
+ );
14
+ };