@tpzdsp/next-toolkit 2.5.1 → 3.1.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 (357) hide show
  1. package/package.json +21 -12
  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 +34 -0
  62. package/src/components/ErrorModal/ErrorModal.stories.tsx +100 -0
  63. package/src/components/ErrorModal/ErrorModal.tsx +123 -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 +3 -2
  77. package/src/components/Footer/Footer.stories.tsx +27 -0
  78. package/src/components/Footer/Footer.tsx +46 -0
  79. package/src/components/Footer/Licence.tsx +18 -0
  80. package/src/components/Footer/MetaLinks.tsx +47 -0
  81. package/src/components/Footer/Small/SmallFooter.stories.tsx +3 -0
  82. package/src/components/Footer/Small/SmallFooter.tsx +53 -41
  83. package/src/components/Form/FormGroup.css +18 -0
  84. package/src/components/Form/FormGroup.stories.tsx +87 -0
  85. package/src/components/Form/FormGroup.tsx +16 -0
  86. package/src/components/{layout/header → Header}/Header.stories.tsx +26 -12
  87. package/src/components/Header/Header.test.tsx +87 -0
  88. package/src/components/Header/Header.tsx +304 -0
  89. package/src/components/Header/HeaderAppContent.tsx +120 -0
  90. package/src/components/Heading/Heading.css +40 -0
  91. package/src/components/Heading/Heading.stories.tsx +15 -5
  92. package/src/components/Heading/Heading.tsx +21 -44
  93. package/src/components/Heading/HeadingSkeleton.stories.tsx +30 -0
  94. package/src/components/Heading/HeadingSkeleton.tsx +14 -0
  95. package/src/components/Hero/Hero.css +19 -0
  96. package/src/components/Hero/Hero.stories.tsx +41 -0
  97. package/src/components/Hero/Hero.tsx +14 -0
  98. package/src/components/HintText/HintText.css +5 -0
  99. package/src/components/HintText/HintText.stories.tsx +29 -0
  100. package/src/components/HintText/HintText.tsx +13 -0
  101. package/src/components/InfoBox/InfoBox.css +38 -0
  102. package/src/components/InfoBox/InfoBox.stories.tsx +51 -403
  103. package/src/components/InfoBox/InfoBox.tsx +31 -158
  104. package/src/components/Input/Input.css +77 -0
  105. package/src/components/Input/Input.stories.tsx +123 -0
  106. package/src/components/Input/Input.tsx +74 -0
  107. package/src/components/InputGroup/InputGroup.css +140 -0
  108. package/src/components/InputGroup/InputGroup.stories.tsx +125 -0
  109. package/src/components/InputGroup/InputGroup.tsx +47 -0
  110. package/src/components/InsetText/InsetText.css +5 -0
  111. package/src/components/InsetText/InsetText.stories.tsx +30 -0
  112. package/src/components/InsetText/InsetText.tsx +9 -0
  113. package/src/components/Keyboard/Keyboard.css +9 -0
  114. package/src/components/Keyboard/Keyboard.stories.tsx +63 -0
  115. package/src/components/Keyboard/Keyboard.tsx +30 -0
  116. package/src/components/Label/Label.css +27 -0
  117. package/src/components/Label/Label.stories.tsx +40 -0
  118. package/src/components/Label/Label.tsx +17 -0
  119. package/src/components/LayerSwitcher/LayerSwitcher.css +59 -0
  120. package/src/components/LayerSwitcher/LayerSwitcher.stories.tsx +112 -0
  121. package/src/components/LayerSwitcher/LayerSwitcher.tsx +61 -0
  122. package/src/components/Layout/401/401.stories.tsx +23 -0
  123. package/src/components/Layout/401/401.tsx +1 -0
  124. package/src/components/Layout/403/403.stories.tsx +23 -0
  125. package/src/components/Layout/403/403.tsx +21 -0
  126. package/src/components/Layout/404/404.stories.tsx +23 -0
  127. package/src/components/Layout/404/404.tsx +28 -0
  128. package/src/components/Layout/500/500.stories.tsx +56 -0
  129. package/src/components/Layout/500/500.tsx +63 -0
  130. package/src/components/Layout/ButtonGroup/ButtonGroup.css +52 -0
  131. package/src/components/Layout/ButtonGroup/ButtonGroup.stories.tsx +156 -0
  132. package/src/components/Layout/ButtonGroup/ButtonGroup.tsx +50 -0
  133. package/src/components/Layout/HeadingGroup/HeadingGroup.css +21 -0
  134. package/src/components/Layout/HeadingGroup/HeadingGroup.stories.tsx +84 -0
  135. package/src/components/Layout/HeadingGroup/HeadingGroup.tsx +9 -0
  136. package/src/components/Layout/MainWrapper/MainWrapper.css +12 -0
  137. package/src/components/Layout/MainWrapper/MainWrapper.stories.tsx +36 -0
  138. package/src/components/Layout/MainWrapper/MainWrapper.tsx +14 -0
  139. package/src/components/Layout/PageShell/PageShell.css +42 -0
  140. package/src/components/Layout/PageShell/PageShell.stories.tsx +108 -0
  141. package/src/components/Layout/PageShell/PageShell.tsx +31 -0
  142. package/src/components/Layout/ParagraphGroup/ParagraphGroup.css +5 -0
  143. package/src/components/Layout/ParagraphGroup/ParagraphGroup.stories.tsx +34 -0
  144. package/src/components/Layout/ParagraphGroup/ParagraphGroup.tsx +9 -0
  145. package/src/components/Layout/Stack/Stack.css +29 -0
  146. package/src/components/Layout/Stack/Stack.stories.tsx +83 -0
  147. package/src/components/Layout/Stack/Stack.tsx +19 -0
  148. package/src/components/Layout/WidthContainer/WidthContainer.css +17 -0
  149. package/src/components/Layout/WidthContainer/WidthContainer.stories.tsx +59 -0
  150. package/src/components/Layout/WidthContainer/WidthContainer.tsx +13 -0
  151. package/src/components/Legend/Legend.css +95 -0
  152. package/src/components/Legend/Legend.stories.tsx +81 -0
  153. package/src/components/Legend/Legend.tsx +32 -0
  154. package/src/components/Legend/LegendDot.tsx +15 -0
  155. package/src/components/Legend/LegendPanel.stories.tsx +101 -0
  156. package/src/components/Legend/LegendPanel.tsx +68 -0
  157. package/src/components/Legend/LegendSkeleton.stories.tsx +87 -0
  158. package/src/components/Legend/LegendSkeleton.tsx +73 -0
  159. package/src/components/LegendSelect/LegendSelect.css +8 -0
  160. package/src/components/LegendSelect/LegendSelect.stories.tsx +80 -0
  161. package/src/components/LegendSelect/LegendSelect.tsx +26 -0
  162. package/src/components/Link/Link.css +98 -0
  163. package/src/components/Link/Link.stories.tsx +70 -0
  164. package/src/components/Link/Link.tsx +52 -0
  165. package/src/components/LinkButton/LinkButton.css +67 -0
  166. package/src/components/LinkButton/LinkButton.stories.tsx +90 -42
  167. package/src/components/LinkButton/LinkButton.tsx +50 -63
  168. package/src/components/LinkList/LinkList.css +28 -0
  169. package/src/components/LinkList/LinkList.stories.tsx +46 -0
  170. package/src/components/LinkList/LinkList.tsx +23 -0
  171. package/src/components/List/Li.tsx +9 -0
  172. package/src/components/List/List.css +9 -0
  173. package/src/components/List/OrderedList.stories.tsx +36 -0
  174. package/src/components/List/OrderedList.tsx +9 -0
  175. package/src/components/List/UnorderedList.stories.tsx +36 -0
  176. package/src/components/List/UnorderedList.tsx +9 -0
  177. package/src/components/LoadingBox/LoadingBox.css +27 -0
  178. package/src/components/LoadingBox/LoadingBox.stories.tsx +66 -0
  179. package/src/components/LoadingBox/LoadingBox.tsx +40 -0
  180. package/src/components/Modal/Modal.css +111 -0
  181. package/src/components/Modal/Modal.stories.tsx +94 -155
  182. package/src/components/Modal/Modal.tsx +141 -75
  183. package/src/components/NoScriptBanner/NoScriptBanner.css +17 -0
  184. package/src/components/NoScriptBanner/NoScriptBanner.stories.tsx +46 -0
  185. package/src/components/NoScriptBanner/NoScriptBanner.tsx +26 -0
  186. package/src/components/Paragraph/Paragraph.css +22 -0
  187. package/src/components/Paragraph/Paragraph.stories.tsx +1 -42
  188. package/src/components/Paragraph/Paragraph.tsx +4 -3
  189. package/src/components/Paragraph/ParagraphSkeleton.stories.tsx +44 -0
  190. package/src/components/Paragraph/ParagraphSkeleton.tsx +33 -0
  191. package/src/components/PasswordInput/PasswordInput.css +3 -0
  192. package/src/components/PasswordInput/PasswordInput.stories.tsx +47 -0
  193. package/src/components/PasswordInput/PasswordInput.tsx +45 -0
  194. package/src/components/PhaseBanner/PhaseBanner.css +12 -0
  195. package/src/components/PhaseBanner/PhaseBanner.stories.tsx +61 -0
  196. package/src/components/PhaseBanner/PhaseBanner.tsx +17 -0
  197. package/src/components/Popover/Popover.css +43 -0
  198. package/src/components/Popover/Popover.stories.tsx +102 -0
  199. package/src/components/Popover/Popover.tsx +40 -0
  200. package/src/components/Radio/Radio.css +69 -0
  201. package/src/components/Radio/Radio.stories.tsx +169 -0
  202. package/src/components/Radio/Radio.tsx +56 -0
  203. package/src/components/Resizable/Resizable.css +86 -0
  204. package/src/components/Resizable/Resizable.stories.tsx +123 -0
  205. package/src/components/Resizable/Resizable.tsx +86 -0
  206. package/src/components/ScrollArea/ScrollArea.css +9 -0
  207. package/src/components/ScrollArea/ScrollArea.stories.tsx +42 -0
  208. package/src/components/ScrollArea/ScrollArea.tsx +11 -0
  209. package/src/components/SearchBox/SearchBox.stories.tsx +88 -0
  210. package/src/components/SearchBox/SearchBox.tsx +36 -0
  211. package/src/components/Select/AsyncSelect.stories.tsx +84 -0
  212. package/src/components/Select/AsyncSelect.tsx +41 -0
  213. package/src/components/Select/Select.css +202 -0
  214. package/src/components/Select/Select.stories.tsx +162 -0
  215. package/src/components/Select/Select.test.tsx +36 -0
  216. package/src/components/Select/Select.tsx +296 -0
  217. package/src/components/Select/SelectSkeleton.stories.tsx +51 -0
  218. package/src/components/Select/SelectSkeleton.tsx +23 -0
  219. package/src/components/Separator/Separator.css +41 -0
  220. package/src/components/Separator/Separator.stories.tsx +63 -0
  221. package/src/components/Separator/Separator.tsx +42 -0
  222. package/src/components/Sidebar/ResizableSidebar.tsx +118 -0
  223. package/src/components/Sidebar/Sidebar.css +203 -0
  224. package/src/components/Sidebar/Sidebar.stories.tsx +438 -0
  225. package/src/components/Sidebar/Sidebar.tsx +225 -0
  226. package/src/components/Skeleton/Skeleton.css +16 -0
  227. package/src/components/Skeleton/Skeleton.stories.tsx +39 -0
  228. package/src/components/Skeleton/Skeleton.tsx +12 -0
  229. package/src/components/SkipLink/SkipLink.css +16 -0
  230. package/src/components/SkipLink/SkipLink.stories.tsx +40 -0
  231. package/src/components/SkipLink/SkipLink.tsx +15 -0
  232. package/src/components/Spinner/Spinner.css +30 -0
  233. package/src/components/Spinner/Spinner.stories.tsx +36 -0
  234. package/src/components/Spinner/Spinner.tsx +45 -0
  235. package/src/components/StartButton/StartButton.css +13 -0
  236. package/src/components/StartButton/StartButton.stories.tsx +68 -0
  237. package/src/components/StartButton/StartButton.tsx +50 -0
  238. package/src/components/SubmitButton/SubmitButton.stories.tsx +31 -0
  239. package/src/components/SubmitButton/SubmitButton.tsx +14 -0
  240. package/src/components/SummaryList/SummaryList.css +71 -0
  241. package/src/components/SummaryList/SummaryList.stories.tsx +211 -0
  242. package/src/components/SummaryList/SummaryList.tsx +41 -0
  243. package/src/components/SummaryList/SummaryListSkeleton.stories.tsx +67 -0
  244. package/src/components/SummaryList/SummaryListSkeleton.tsx +40 -0
  245. package/src/components/Tabs/Tabs.css +84 -0
  246. package/src/components/Tabs/Tabs.stories.tsx +133 -0
  247. package/src/components/Tabs/Tabs.tsx +66 -0
  248. package/src/components/Tag/Tag.css +8 -0
  249. package/src/components/Tag/Tag.stories.tsx +96 -0
  250. package/src/components/Tag/Tag.tsx +34 -0
  251. package/src/components/Textarea/Textarea.css +38 -0
  252. package/src/components/Textarea/Textarea.stories.tsx +131 -0
  253. package/src/components/Textarea/Textarea.tsx +50 -0
  254. package/src/components/TextareaCount/TextareaCount.css +17 -0
  255. package/src/components/TextareaCount/TextareaCount.stories.tsx +131 -0
  256. package/src/components/TextareaCount/TextareaCount.tsx +108 -0
  257. package/src/components/Tooltip/Tooltip.css +43 -0
  258. package/src/components/Tooltip/Tooltip.stories.tsx +110 -0
  259. package/src/components/Tooltip/Tooltip.tsx +53 -0
  260. package/src/components/WarningText/WarningText.css +20 -0
  261. package/src/components/WarningText/WarningText.stories.tsx +29 -0
  262. package/src/components/WarningText/WarningText.tsx +17 -0
  263. package/src/components/index.ts +343 -61
  264. package/src/errors/errorDisplay.ts +70 -0
  265. package/src/errors/index.ts +1 -0
  266. package/src/http/constants.ts +2 -0
  267. package/src/http/fetch.ts +7 -3
  268. package/src/map/LayerSwitcherPanel.tsx +2 -173
  269. package/src/map/LegendShim.tsx +2 -0
  270. package/src/map/MapComponent.tsx +7 -17
  271. package/src/map/MapControlsOverlay.tsx +68 -175
  272. package/src/map/Popup.tsx +71 -24
  273. package/src/map/geocoder/Geocoder.test.tsx +46 -3
  274. package/src/map/geocoder/Geocoder.tsx +155 -278
  275. package/src/map/index.ts +1 -1
  276. package/src/types/utils.ts +0 -10
  277. package/src/utils/components.ts +96 -0
  278. package/src/utils/index.ts +1 -0
  279. package/src/utils/utils.ts +0 -12
  280. package/src/assets/images/defra-logo.svg +0 -51
  281. package/src/assets/images/ea-logo.svg +0 -58
  282. package/src/assets/images/ogl.svg +0 -1
  283. package/src/components/Button/Button.test.tsx +0 -53
  284. package/src/components/ButtonLink/ButtonLink.test.tsx +0 -154
  285. package/src/components/Card/Card.test.tsx +0 -51
  286. package/src/components/ErrorBoundary/ErrorBoundary.test.tsx +0 -75
  287. package/src/components/ErrorBoundary/ErrorFallback.test.tsx +0 -107
  288. package/src/components/ErrorText/ErrorText.test.tsx +0 -33
  289. package/src/components/Heading/Heading.test.tsx +0 -22
  290. package/src/components/Hint/Hint.stories.tsx +0 -58
  291. package/src/components/Hint/Hint.test.tsx +0 -33
  292. package/src/components/Hint/Hint.tsx +0 -12
  293. package/src/components/InfoBox/InfoBox.test.tsx +0 -330
  294. package/src/components/InfoBox/types.ts +0 -6
  295. package/src/components/LinkButton/LinkButton.test.tsx +0 -177
  296. package/src/components/Modal/Modal.test.tsx +0 -246
  297. package/src/components/NotificationBanner/NotificationBanner.stories.tsx +0 -45
  298. package/src/components/NotificationBanner/NotificationBanner.test.tsx +0 -58
  299. package/src/components/NotificationBanner/NotificationBanner.tsx +0 -45
  300. package/src/components/Paragraph/Paragraph.test.tsx +0 -10
  301. package/src/components/SlidingPanel/SlidingPanel.stories.tsx +0 -129
  302. package/src/components/SlidingPanel/SlidingPanel.test.tsx +0 -83
  303. package/src/components/SlidingPanel/SlidingPanel.tsx +0 -258
  304. package/src/components/accordion/Accordion.stories.tsx +0 -234
  305. package/src/components/accordion/Accordion.test.tsx +0 -192
  306. package/src/components/accordion/Accordion.tsx +0 -73
  307. package/src/components/backToTop/BackToTop.stories.tsx +0 -407
  308. package/src/components/backToTop/BackToTop.test.tsx +0 -57
  309. package/src/components/backToTop/BackToTop.tsx +0 -134
  310. package/src/components/chip/Chip.stories.tsx +0 -61
  311. package/src/components/chip/Chip.test.tsx +0 -31
  312. package/src/components/chip/Chip.tsx +0 -23
  313. package/src/components/container/Container.tsx +0 -42
  314. package/src/components/cookieBanner/CookieBanner.stories.tsx +0 -257
  315. package/src/components/cookieBanner/CookieBanner.test.tsx +0 -68
  316. package/src/components/cookieBanner/CookieBanner.tsx +0 -73
  317. package/src/components/divider/RuleDivider.stories.tsx +0 -254
  318. package/src/components/divider/RuleDivider.test.tsx +0 -164
  319. package/src/components/divider/RuleDivider.tsx +0 -23
  320. package/src/components/dropdown/DropdownMenu.test.tsx +0 -211
  321. package/src/components/dropdown/DropdownMenu.tsx +0 -108
  322. package/src/components/dropdown/useDropdownMenu.ts +0 -249
  323. package/src/components/form/Input.stories.tsx +0 -435
  324. package/src/components/form/Input.test.tsx +0 -206
  325. package/src/components/form/Input.tsx +0 -23
  326. package/src/components/form/TextArea.stories.tsx +0 -464
  327. package/src/components/form/TextArea.test.tsx +0 -232
  328. package/src/components/form/TextArea.tsx +0 -23
  329. package/src/components/layout/footer/Footer.tsx +0 -26
  330. package/src/components/layout/footer/Licence.tsx +0 -19
  331. package/src/components/layout/footer/MetaLinks.tsx +0 -36
  332. package/src/components/layout/header/Header.test.tsx +0 -36
  333. package/src/components/layout/header/Header.tsx +0 -90
  334. package/src/components/layout/header/HeaderAuthClient.test.tsx +0 -45
  335. package/src/components/layout/header/HeaderAuthClient.tsx +0 -40
  336. package/src/components/layout/header/HeaderNavClient.test.tsx +0 -44
  337. package/src/components/layout/header/HeaderNavClient.tsx +0 -67
  338. package/src/components/link/ExternalLink.test.tsx +0 -102
  339. package/src/components/link/ExternalLink.tsx +0 -29
  340. package/src/components/link/Link.tsx +0 -26
  341. package/src/components/select/Select.stories.tsx +0 -336
  342. package/src/components/select/Select.test.tsx +0 -474
  343. package/src/components/select/Select.tsx +0 -125
  344. package/src/components/select/SelectSkeleton.stories.tsx +0 -194
  345. package/src/components/select/SelectSkeleton.test.tsx +0 -104
  346. package/src/components/select/SelectSkeleton.tsx +0 -23
  347. package/src/components/select/common.ts +0 -3
  348. package/src/components/select/index.ts +0 -18
  349. package/src/components/skipLink/SkipLink.stories.tsx +0 -346
  350. package/src/components/skipLink/SkipLink.test.tsx +0 -22
  351. package/src/components/skipLink/SkipLink.tsx +0 -49
  352. package/src/map/LegendPanel.tsx +0 -85
  353. /package/src/{components → assets}/images/DefraLogo.tsx +0 -0
  354. /package/src/{components → assets}/images/EaLogo.tsx +0 -0
  355. /package/src/{components → assets}/images/OglLogo.tsx +0 -0
  356. /package/src/components/{googleAnalytics → GoogleAnalytics}/GlobalVars.tsx +0 -0
  357. /package/src/components/{googleAnalytics → GoogleAnalytics}/GoogleAnalytics.tsx +0 -0
@@ -0,0 +1,46 @@
1
+ import { Copyright } from './Copyright';
2
+ import { Licence } from './Licence';
3
+ import { MetaLinks } from './MetaLinks';
4
+ import { DefraLogo } from '../../assets/images/DefraLogo';
5
+ import { WidthContainer } from '../Layout/WidthContainer/WidthContainer';
6
+
7
+ export type FooterProps = {
8
+ /** Passed straight through to MetaLinks, see its own accessibilityStatementHref doc. */
9
+ accessibilityStatementHref?: string;
10
+ };
11
+
12
+ export const Footer = ({ accessibilityStatementHref }: FooterProps) => (
13
+ <footer className="bg-wash">
14
+ <WidthContainer className="py-gds-3">
15
+ <div
16
+ className="grid gap-gds-2 grid-cols-1 sm:grid-cols-[1fr_min-content]
17
+ grid-rows-[min-content_min-content_min-content_min-content]
18
+ sm:grid-rows-[min-content_min-content_min-content] md:grid-rows-[min-content_min-content]"
19
+ >
20
+ <nav className="row-start-1 col-start-1 w-full pb-gds-2 self-end">
21
+ <h2 className="sr-only">Support Links</h2>
22
+
23
+ <MetaLinks accessibilityStatementHref={accessibilityStatementHref} />
24
+ </nav>
25
+
26
+ <div className="row-start-2 col-start-1 self-end pt-gds-1">
27
+ <Licence />
28
+ </div>
29
+
30
+ <DefraLogo
31
+ aria-hidden
32
+ className="row-start-3 sm:row-span-3 md:row-span-1 sm:row-start-1 col-start-1
33
+ sm:col-start-2 h-20 w-auto shrink-0 fill-body md:h-20 justify-self-start
34
+ sm:justify-self-end"
35
+ />
36
+
37
+ <div
38
+ className="row-start-4 sm:row-start-3 col-start-1 md:row-start-2 md:col-start-2 self-end
39
+ justify-self-start md:justify-self-end"
40
+ >
41
+ <Copyright />
42
+ </div>
43
+ </div>
44
+ </WidthContainer>
45
+ </footer>
46
+ );
@@ -0,0 +1,18 @@
1
+ import { OglLogo } from '../../assets/images/OglLogo';
2
+ import { ExternalLink } from '../ExternalLink/ExternalLink';
3
+
4
+ export const Licence = () => (
5
+ <span className="block w-full wrap-break-word text-body">
6
+ <OglLogo className="inline w-9 mr-gds-2 align-middle" aria-hidden />
7
+ All content is available under the{' '}
8
+ <ExternalLink
9
+ className="wrap-break-word"
10
+ appearance="contrast"
11
+ variant="plain"
12
+ href="https://www.nationalarchives.gov.uk/doc/open-government-licence/version/3/"
13
+ >
14
+ Open Government Licence v3.0
15
+ </ExternalLink>
16
+ , except where otherwise stated.
17
+ </span>
18
+ );
@@ -0,0 +1,47 @@
1
+ import { Link } from '../Link/Link';
2
+
3
+ const STATIC_LINKS = [
4
+ {
5
+ label: 'Cookie Policy',
6
+ url: '/help/cookies',
7
+ },
8
+ {
9
+ label: 'Terms and Conditions',
10
+ url: '/support/faqs/275811163/275811177',
11
+ },
12
+ {
13
+ label: 'Privacy',
14
+ url: '/support/faqs/275811163/275811229',
15
+ },
16
+ {
17
+ label: 'Contact Us',
18
+ url: '/support',
19
+ },
20
+ ];
21
+
22
+ export type MetaLinksProps = {
23
+ /** No single accessibility statement applies across every app this footer
24
+ * ships in, so unlike the other, shared support links above, this one has
25
+ * to be supplied by the consuming app rather than hardcoded here. Optional
26
+ * for now, apps that don't have one yet just don't get the link, rather
27
+ * than one pointing nowhere. */
28
+ accessibilityStatementHref?: string;
29
+ };
30
+
31
+ export const MetaLinks = ({ accessibilityStatementHref }: MetaLinksProps) => {
32
+ const links = accessibilityStatementHref
33
+ ? [{ label: 'Accessibility statement', url: accessibilityStatementHref }, ...STATIC_LINKS]
34
+ : STATIC_LINKS;
35
+
36
+ return (
37
+ <ul className="flex w-full flex-wrap gap-x-gds-4 gap-y-gds-2 md:gap-gds-5 md:justify-start">
38
+ {links.map((link) => (
39
+ <li className="flex" key={link.label}>
40
+ <Link className="md:text-left" appearance="contrast" href={link.url}>
41
+ {link.label}
42
+ </Link>
43
+ </li>
44
+ ))}
45
+ </ul>
46
+ );
47
+ };
@@ -15,6 +15,9 @@ const meta = {
15
15
  },
16
16
  },
17
17
  tags: ['autodocs'],
18
+ args: {
19
+ accessibilityStatementHref: '/accessibility-statement',
20
+ },
18
21
  } satisfies Meta<typeof SmallFooter>;
19
22
 
20
23
  export default meta;
@@ -1,6 +1,9 @@
1
- import { DefraLogo } from '../../images/DefraLogo';
2
- import { EaLogo } from '../../images/EaLogo';
3
- import { OglLogo } from '../../images/OglLogo';
1
+ import { DefraLogo } from '../../../assets/images/DefraLogo';
2
+ import { EaLogo } from '../../../assets/images/EaLogo';
3
+ import { OglLogo } from '../../../assets/images/OglLogo';
4
+ import { ExternalLink } from '../../ExternalLink/ExternalLink';
5
+ import { WidthContainer } from '../../Layout/WidthContainer/WidthContainer';
6
+ import { Link } from '../../Link/Link';
4
7
 
5
8
  const CROWN_COPYRIGHT_URL =
6
9
  'https://www.nationalarchives.gov.uk/information-management/re-using-public-sector-information/uk-government-licensing-framework/crown-copyright/';
@@ -11,51 +14,60 @@ const LICENSING_DETAILS_URL =
11
14
  export type SmallFooterProps = {
12
15
  eaLogoPrimaryFill?: string;
13
16
  eaLogoHighlightFill?: string;
17
+ /** Same as Footer's own accessibilityStatementHref: no universal default,
18
+ * omit it to hide the link entirely rather than pointing at nothing. */
19
+ accessibilityStatementHref?: string;
14
20
  };
15
21
 
16
22
  export const SmallFooter = ({
17
23
  eaLogoPrimaryFill = '#F3F2F1',
18
24
  eaLogoHighlightFill = '#79A12F',
25
+ accessibilityStatementHref,
19
26
  }: SmallFooterProps) => (
20
- <footer
21
- aria-label="Site footer"
22
- className="flex justify-center border-t border-gray-200 bg-[##F3F2F1] px-4 py-2"
23
- >
24
- <div className="flex w-full max-w-[1020px] items-center justify-between px-4 md:px-36">
25
- <div className="flex items-center gap-2">
26
- <EaLogo
27
- className="h-8 w-auto"
28
- aria-hidden="true"
29
- primaryFill={eaLogoPrimaryFill}
30
- highlightFill={eaLogoHighlightFill}
31
- />
32
- </div>
27
+ <footer aria-label="Site footer" className="flex justify-center">
28
+ <WidthContainer className="bg-wash py-gds-2">
29
+ <div className="flex items-center justify-between">
30
+ <div className="flex items-center gap-2">
31
+ <EaLogo
32
+ className="h-8 w-auto"
33
+ aria-hidden="true"
34
+ primaryFill={eaLogoPrimaryFill}
35
+ highlightFill={eaLogoHighlightFill}
36
+ />
37
+ </div>
38
+
39
+ <div className="flex items-center gap-gds-6 xs:gap-gds-2">
40
+ {accessibilityStatementHref ? (
41
+ <Link appearance="contrast" href={accessibilityStatementHref}>
42
+ Accessibility statement
43
+ </Link>
44
+ ) : null}
45
+
46
+ <ExternalLink
47
+ appearance="contrast"
48
+ variant="plain"
49
+ href={LICENSING_DETAILS_URL}
50
+ className="flex gap-gds-1 items-center"
51
+ >
52
+ <OglLogo className="size-10 shrink-0" aria-hidden="true" />
53
+
54
+ <span className="hidden xs:inline">Licencing details</span>
55
+ </ExternalLink>
56
+
57
+ <ExternalLink
58
+ appearance="contrast"
59
+ variant="plain"
60
+ href={CROWN_COPYRIGHT_URL}
61
+ className="flex gap-gds-1 items-center"
62
+ >
63
+ <DefraLogo className="size-10 shrink-0" aria-hidden="true" />
64
+
65
+ <span className="inline xs:hidden">©</span>
33
66
 
34
- <div className="flex items-center gap-2 text-sm">
35
- <OglLogo className="h-4 w-auto" aria-hidden="true" />
36
-
37
- <a
38
- href={LICENSING_DETAILS_URL}
39
- target="_blank"
40
- rel="noopener noreferrer"
41
- className="underline"
42
- >
43
- Licencing details
44
- </a>
45
-
46
- <span aria-hidden="true">|</span>
47
-
48
- <a
49
- href={CROWN_COPYRIGHT_URL}
50
- target="_blank"
51
- rel="noopener noreferrer"
52
- className="underline"
53
- >
54
- © Crown copyright
55
- </a>
56
-
57
- <DefraLogo className="h-8 w-auto" aria-hidden="true" />
67
+ <span className="hidden xs:inline">© Crown copyright</span>
68
+ </ExternalLink>
69
+ </div>
58
70
  </div>
59
- </div>
71
+ </WidthContainer>
60
72
  </footer>
61
73
  );
@@ -0,0 +1,18 @@
1
+ @layer components {
2
+ /* MARK: Form group */
3
+ .cn-form-group {
4
+ @apply flex flex-col gap-gds-1;
5
+ }
6
+
7
+ .cn-form-group[data-invalid] {
8
+ @apply pl-gds-2;
9
+
10
+ border-left: 5px solid var(--color-error);
11
+ }
12
+
13
+ /* Label.css handles disabled via sibling combinator (~ :disabled), which
14
+ doesn't pierce wrapper elements like InputGroup. This catches that case. */
15
+ .cn-form-group:has(:is(:disabled, [aria-disabled='true'])) .cn-label {
16
+ @apply cursor-not-allowed select-none text-body-secondary;
17
+ }
18
+ }
@@ -0,0 +1,87 @@
1
+ import type { Meta, StoryObj } from '@storybook/react-vite';
2
+
3
+ import { FormGroup } from './FormGroup';
4
+ import { Alert, AlertBody, AlertList, AlertListItem, AlertTitle } from '../Alert/Alert';
5
+ import { ErrorText } from '../ErrorText/ErrorText';
6
+ import { HintText } from '../HintText/HintText';
7
+ import { Input } from '../Input/Input';
8
+ import { Label } from '../Label/Label';
9
+ import { Link } from '../Link/Link';
10
+
11
+ const meta: Meta<typeof FormGroup> = {
12
+ title: 'Components/Form/FormGroup',
13
+ component: FormGroup,
14
+ tags: ['autodocs'],
15
+ parameters: {
16
+ docs: {
17
+ description: {
18
+ component:
19
+ 'A layout wrapper that groups a form field with its label, hint, and error text. When `invalid` is set, a red left border is applied to the whole group, matching the GDS error pattern. Accessibility attributes (`aria-describedby`, `aria-invalid`, `id`) must be wired manually on the input.',
20
+ },
21
+ },
22
+ },
23
+ };
24
+
25
+ export default meta;
26
+
27
+ type Story = StoryObj<typeof FormGroup>;
28
+
29
+ export const Default: Story = {
30
+ render: () => (
31
+ <FormGroup>
32
+ <Label htmlFor="name">Full name</Label>
33
+
34
+ <HintText>As it appears on your passport</HintText>
35
+
36
+ <Input id="name" aria-describedby="name-hint" />
37
+ </FormGroup>
38
+ ),
39
+ };
40
+
41
+ export const Invalid: Story = {
42
+ render: () => (
43
+ <FormGroup invalid>
44
+ <Label htmlFor="name-invalid">Full name</Label>
45
+
46
+ <HintText id="name-invalid-hint">As it appears on your passport</HintText>
47
+
48
+ <ErrorText id="name-invalid-error">Enter your full name</ErrorText>
49
+
50
+ <Input
51
+ id="name-invalid"
52
+ aria-invalid
53
+ aria-describedby="name-invalid-hint name-invalid-error"
54
+ />
55
+ </FormGroup>
56
+ ),
57
+ };
58
+
59
+ export const WithErrorSummary: Story = {
60
+ render: () => (
61
+ <div className="flex flex-col gap-gds-4">
62
+ <Alert appearance="error">
63
+ <AlertTitle>There is a problem</AlertTitle>
64
+
65
+ <AlertBody>
66
+ <AlertList>
67
+ <AlertListItem>
68
+ <Link appearance="error" href="#full-name">
69
+ Enter your full name
70
+ </Link>
71
+ </AlertListItem>
72
+ </AlertList>
73
+ </AlertBody>
74
+ </Alert>
75
+
76
+ <FormGroup invalid>
77
+ <Label htmlFor="full-name">Full name</Label>
78
+
79
+ <HintText id="full-name-hint">As it appears on your passport</HintText>
80
+
81
+ <ErrorText id="full-name-error">Enter your full name</ErrorText>
82
+
83
+ <Input id="full-name" aria-invalid aria-describedby="full-name-hint full-name-error" />
84
+ </FormGroup>
85
+ </div>
86
+ ),
87
+ };
@@ -0,0 +1,16 @@
1
+ import type { ComponentProps } from 'react';
2
+
3
+ import { cn } from '../../utils/components';
4
+
5
+ export type FormGroupProps = ComponentProps<'div'> & {
6
+ invalid?: boolean;
7
+ };
8
+
9
+ export const FormGroup = ({ invalid, className, ...props }: FormGroupProps) => (
10
+ <div
11
+ data-slot="form-group"
12
+ data-invalid={invalid ? true : undefined}
13
+ className={cn('cn-form-group', className)}
14
+ {...props}
15
+ />
16
+ );
@@ -1,14 +1,8 @@
1
1
  import type { Meta, StoryObj } from '@storybook/react-vite';
2
2
 
3
3
  import { Header } from './Header';
4
- import type { Credentials } from '../../../types/auth';
5
- import type { NavLink } from '../../../types/navigation';
6
-
7
- const navLinks: NavLink[] = [
8
- { label: 'Home', url: '/', openInNewTab: false },
9
- { label: 'API', url: '/api-docs', openInNewTab: false },
10
- { label: 'Support', url: 'https://example.com/support', openInNewTab: true },
11
- ];
4
+ import { HeaderAppContent } from './HeaderAppContent';
5
+ import type { Credentials } from '../../types/auth';
12
6
 
13
7
  const authenticatedCredentials: Credentials = {
14
8
  token: 'mock-token',
@@ -20,7 +14,7 @@ const authenticatedCredentials: Credentials = {
20
14
  };
21
15
 
22
16
  export default {
23
- title: 'Components/Layout/Header',
17
+ title: 'Components/Header',
24
18
  component: Header,
25
19
  parameters: {
26
20
  layout: 'fullscreen',
@@ -32,15 +26,35 @@ export default {
32
26
  },
33
27
  },
34
28
  args: {
35
- dspUrl: 'https://environment.data.gov.uk',
36
- appName: 'Wetlands Inventory',
37
- navLinks,
38
29
  credentials: null,
39
30
  },
40
31
  } as Meta<typeof Header>;
41
32
 
42
33
  export const Default: StoryObj<typeof Header> = {};
43
34
 
35
+ export const AppSpecificContent: StoryObj<typeof Header> = {
36
+ parameters: {
37
+ docs: {
38
+ description: {
39
+ story:
40
+ "Resize the viewport (or Storybook's own frame) narrower to see the app nav links collapse from an inline list into a dropdown menu once the row no longer comfortably fits both the title and the links.",
41
+ },
42
+ },
43
+ },
44
+ args: {
45
+ appContent: (
46
+ <HeaderAppContent
47
+ title="UK Wetland Inventory"
48
+ links={[
49
+ { url: '/apis', label: 'Wetlands APIs' },
50
+ { url: '/downloads', label: 'Downloads' },
51
+ { url: '/faqs', label: 'FAQs' },
52
+ ]}
53
+ />
54
+ ),
55
+ },
56
+ };
57
+
44
58
  export const Authenticated: StoryObj<typeof Header> = {
45
59
  args: {
46
60
  credentials: authenticatedCredentials,
@@ -0,0 +1,87 @@
1
+ import { Header } from './Header';
2
+ import { render, screen, userEvent } from '../../test/renderers';
3
+ import type { Credentials } from '../../types/auth';
4
+
5
+ const ARIA_EXPANDED = 'aria-expanded';
6
+
7
+ const CREDENTIALS: Credentials = {
8
+ token: 'mock-token',
9
+ user: {
10
+ name: 'Jamie Taylor',
11
+ email: 'jamie.taylor@example.com',
12
+ groupInfoIds: ['group-1', 'group-2'],
13
+ },
14
+ };
15
+
16
+ describe('Header', () => {
17
+ it('renders the DEFRA and Data Services Platform brand links', () => {
18
+ render(<Header />);
19
+
20
+ expect(screen.getByRole('link', { name: 'DEFRA' })).toBeInTheDocument();
21
+ expect(screen.getByRole('link', { name: /data services platform/i })).toBeInTheDocument();
22
+ });
23
+
24
+ it('shows a Sign-in link pointing at /login when signed out', async () => {
25
+ render(<Header />);
26
+
27
+ const signInLink = await screen.findByRole('link', { name: 'Sign-in' });
28
+
29
+ expect(signInLink).toHaveAttribute('href', expect.stringContaining('/login?redirect_uri='));
30
+ });
31
+
32
+ it('shows a Profile menu with a sign-out link when signed in', async () => {
33
+ const user = userEvent.setup();
34
+
35
+ render(<Header credentials={CREDENTIALS} />);
36
+
37
+ expect(screen.queryByRole('link', { name: 'Sign-in' })).not.toBeInTheDocument();
38
+
39
+ await user.click(await screen.findByRole('button', { name: 'Profile' }));
40
+
41
+ expect(await screen.findByText(CREDENTIALS.user.email)).toBeInTheDocument();
42
+
43
+ const signOutLink = screen.getByRole('link', { name: 'Sign-out' });
44
+
45
+ expect(signOutLink).toHaveAttribute('href', expect.stringContaining('/logout?redirect_uri='));
46
+ });
47
+
48
+ it('toggles the nav drawer open and closed', async () => {
49
+ const user = userEvent.setup();
50
+
51
+ render(<Header />);
52
+
53
+ const trigger = screen.getByRole('button', { name: 'Navigation drawer' });
54
+
55
+ expect(trigger).toHaveAttribute(ARIA_EXPANDED, 'false');
56
+
57
+ await user.click(trigger);
58
+
59
+ expect(trigger).toHaveAttribute(ARIA_EXPANDED, 'true');
60
+ expect(screen.getByRole('navigation', { name: 'More navigation' })).toBeInTheDocument();
61
+
62
+ await user.click(screen.getByRole('button', { name: 'Close' }));
63
+
64
+ expect(trigger).toHaveAttribute(ARIA_EXPANDED, 'false');
65
+ });
66
+
67
+ it('toggles the search drawer open and closed', async () => {
68
+ const user = userEvent.setup();
69
+
70
+ render(<Header />);
71
+
72
+ const trigger = screen.getByRole('button', { name: 'Search the Data Services Platform' });
73
+
74
+ expect(trigger).toHaveAttribute(ARIA_EXPANDED, 'false');
75
+
76
+ await user.click(trigger);
77
+
78
+ expect(trigger).toHaveAttribute(ARIA_EXPANDED, 'true');
79
+ expect(screen.getByRole('searchbox')).toBeInTheDocument();
80
+ });
81
+
82
+ it('renders appContent when provided', () => {
83
+ render(<Header appContent={<div>App-specific content</div>} />);
84
+
85
+ expect(screen.getByText('App-specific content')).toBeInTheDocument();
86
+ });
87
+ });