@tpzdsp/next-toolkit 2.5.1 → 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 +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 +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,66 @@
1
+ 'use client';
2
+
3
+ import type { ComponentProps } from 'react';
4
+
5
+ import { Tabs as TabsPrimitive } from 'radix-ui';
6
+
7
+ import { cn } from '../../utils/components';
8
+
9
+ export type TabsProps<T extends string> = Omit<
10
+ ComponentProps<typeof TabsPrimitive.Root>,
11
+ 'defaultValue' | 'value' | 'onValueChange'
12
+ > & {
13
+ defaultValue?: T;
14
+ value?: T;
15
+ onValueChange?: (value: T) => void;
16
+ };
17
+
18
+ export const Tabs = <T extends string = string>({
19
+ className,
20
+ defaultValue,
21
+ value,
22
+ onValueChange,
23
+ ...props
24
+ }: TabsProps<T>) => (
25
+ <TabsPrimitive.Root
26
+ data-slot="tabs"
27
+ className={cn('cn-tabs', className)}
28
+ defaultValue={defaultValue as string}
29
+ value={value as string}
30
+ onValueChange={(value) => onValueChange?.(value as T)}
31
+ {...props}
32
+ />
33
+ );
34
+
35
+ export type TabsListProps = ComponentProps<typeof TabsPrimitive.List>;
36
+
37
+ export const TabsList = ({ className, ...props }: TabsListProps) => (
38
+ <TabsPrimitive.List data-slot="tabs-list" className={cn('cn-tabs-list', className)} {...props} />
39
+ );
40
+
41
+ export type TabsTriggerProps = ComponentProps<typeof TabsPrimitive.Trigger>;
42
+
43
+ export const TabsTrigger = ({ className, children, ...props }: TabsTriggerProps) => (
44
+ <TabsPrimitive.Trigger
45
+ data-slot="tabs-trigger"
46
+ className={cn('cn-tabs-trigger', className)}
47
+ {...props}
48
+ >
49
+ {/* Bold copy reserves the active-state width so siblings never shift. */}
50
+ <span aria-hidden className="cn-tabs-trigger-sizer">
51
+ {children}
52
+ </span>
53
+
54
+ <span className="cn-tabs-trigger-text">{children}</span>
55
+ </TabsPrimitive.Trigger>
56
+ );
57
+
58
+ export type TabsContentProps = ComponentProps<typeof TabsPrimitive.Content>;
59
+
60
+ export const TabsContent = ({ className, ...props }: TabsContentProps) => (
61
+ <TabsPrimitive.Content
62
+ data-slot="tabs-content"
63
+ className={cn('cn-tabs-content', className)}
64
+ {...props}
65
+ />
66
+ );
@@ -0,0 +1,8 @@
1
+ @layer components {
2
+ /* MARK: Tag
3
+ GDS-style status label rendered as <strong> for semantic importance.
4
+ Composes Chip utilities for sizing and colour, adds font-bold on top. */
5
+ .cn-tag {
6
+ @apply cn-chip font-bold;
7
+ }
8
+ }
@@ -0,0 +1,96 @@
1
+ import type { Meta, StoryObj } from '@storybook/react-vite';
2
+
3
+ import { Tag } from './Tag';
4
+
5
+ const meta: Meta<typeof Tag> = {
6
+ title: 'Components/Tag',
7
+ component: Tag,
8
+ tags: ['autodocs'],
9
+ parameters: {
10
+ docs: {
11
+ description: {
12
+ component:
13
+ 'GDS-style status label for communicating phase, status, or category. Rendered as `<strong>` for semantic importance. Uses the same colour palette as Chip but always bold.',
14
+ },
15
+ },
16
+ },
17
+ argTypes: {
18
+ appearance: {
19
+ control: { type: 'radio' },
20
+ options: ['neutral', 'success', 'warning', 'error', 'info'],
21
+ },
22
+ size: {
23
+ control: { type: 'radio' },
24
+ options: ['sm', 'base', 'lg'],
25
+ },
26
+ children: { control: 'text' },
27
+ },
28
+ args: {
29
+ appearance: 'info',
30
+ children: 'Alpha',
31
+ size: 'base',
32
+ },
33
+ };
34
+
35
+ export default meta;
36
+
37
+ type Story = StoryObj<typeof Tag>;
38
+
39
+ export const Default: Story = {};
40
+
41
+ export const Appearances: Story = {
42
+ parameters: {
43
+ docs: {
44
+ description: {
45
+ story: 'All appearances share the same subtle tinted palette as Chip.',
46
+ },
47
+ },
48
+ },
49
+ render: (args) => (
50
+ <div className="flex flex-wrap gap-gds-2">
51
+ <Tag {...args} appearance="neutral">
52
+ Inactive
53
+ </Tag>
54
+
55
+ <Tag {...args} appearance="success">
56
+ Active
57
+ </Tag>
58
+
59
+ <Tag {...args} appearance="warning">
60
+ Pending
61
+ </Tag>
62
+
63
+ <Tag {...args} appearance="error">
64
+ Rejected
65
+ </Tag>
66
+
67
+ <Tag {...args} appearance="info">
68
+ Alpha
69
+ </Tag>
70
+ </div>
71
+ ),
72
+ };
73
+
74
+ export const Small: Story = {
75
+ args: { size: 'sm', children: 'Beta' },
76
+ };
77
+
78
+ export const Large: Story = {
79
+ args: { size: 'lg', children: 'New' },
80
+ };
81
+
82
+ export const Inline: Story = {
83
+ parameters: {
84
+ docs: {
85
+ description: {
86
+ story:
87
+ 'Tags use negative margins so they sit inline within body text without inflating line height.',
88
+ },
89
+ },
90
+ },
91
+ render: (args) => (
92
+ <p>
93
+ This service is <Tag {...args} /> and actively being developed.
94
+ </p>
95
+ ),
96
+ };
@@ -0,0 +1,34 @@
1
+ import type { ComponentProps } from 'react';
2
+
3
+ import { cn } from '../../utils/components';
4
+
5
+ const TAG_APPEARANCES = {
6
+ neutral: 'cn-chip-appearance-neutral',
7
+ success: 'cn-chip-appearance-success',
8
+ warning: 'cn-chip-appearance-warning',
9
+ error: 'cn-chip-appearance-error',
10
+ info: 'cn-chip-appearance-info',
11
+ } as const;
12
+
13
+ const TAG_SIZES = {
14
+ sm: 'cn-chip-size-sm',
15
+ base: 'cn-chip-size-base',
16
+ lg: 'cn-chip-size-lg',
17
+ } as const;
18
+
19
+ export type TagAppearance = keyof typeof TAG_APPEARANCES;
20
+ export type TagSize = keyof typeof TAG_SIZES;
21
+
22
+ export type TagProps = ComponentProps<'strong'> & {
23
+ appearance: TagAppearance;
24
+ size?: TagSize;
25
+ };
26
+
27
+ export const Tag = ({ className, appearance, size = 'base', ...props }: TagProps) => (
28
+ <strong
29
+ data-slot="tag"
30
+ data-size={size}
31
+ className={cn('cn-tag', TAG_APPEARANCES[appearance], TAG_SIZES[size], className)}
32
+ {...props}
33
+ />
34
+ );
@@ -0,0 +1,38 @@
1
+ @layer components {
2
+ /* MARK: Textarea
3
+ GDS textarea: same border and focus as Input, vertical resize only.
4
+ Height is content-driven via rows, min-height matches the input baseline. */
5
+ .cn-textarea {
6
+ @apply cn-form-border w-full p-gds-1 text-base box-border appearance-none resize-y min-h-32;
7
+
8
+ &:focus {
9
+ @apply outline-focus;
10
+ box-shadow: inset 0 0 0 var(--border-width-form) var(--color-divider-input);
11
+ }
12
+
13
+ &[aria-invalid='true'],
14
+ &:user-invalid {
15
+ @apply border-error;
16
+
17
+ &:focus {
18
+ box-shadow: inset 0 0 0 var(--border-width-form) var(--color-error);
19
+ }
20
+ }
21
+
22
+ &[readonly] {
23
+ @apply bg-wash resize-none;
24
+ }
25
+
26
+ &:disabled,
27
+ &[aria-disabled='true'] {
28
+ @apply opacity-50 cursor-not-allowed select-none;
29
+ color: inherit;
30
+ }
31
+ }
32
+
33
+ /* MARK: Appearances */
34
+ .cn-textarea-appearance-code {
35
+ font-variant-numeric: tabular-nums;
36
+ letter-spacing: 0.05em;
37
+ }
38
+ }
@@ -0,0 +1,131 @@
1
+ 'use client';
2
+
3
+ import type { Meta, StoryObj } from '@storybook/react-vite';
4
+
5
+ import { Textarea } from './Textarea';
6
+ import { CopyButton } from '../CopyButton/CopyButton';
7
+ import { ErrorText } from '../ErrorText/ErrorText';
8
+ import { FormGroup } from '../Form/FormGroup';
9
+ import { HintText } from '../HintText/HintText';
10
+ import { InputGroup, InputToolbar } from '../InputGroup/InputGroup';
11
+ import { Label } from '../Label/Label';
12
+ import { TextareaCount, TextareaCountMessage } from '../TextareaCount/TextareaCount';
13
+
14
+ const meta: Meta<typeof Textarea> = {
15
+ title: 'Components/Textarea',
16
+ component: Textarea,
17
+ tags: ['autodocs'],
18
+ parameters: {
19
+ docs: {
20
+ description: {
21
+ component:
22
+ 'GDS-style multi-line text input. Resizes vertically. Compose with `TextareaCount` and `TextareaCountMessage` to add character or word count feedback. Use a vertical `InputGroup` with `InputToolbar` to add action buttons above the field.',
23
+ },
24
+ },
25
+ },
26
+ argTypes: {
27
+ appearance: {
28
+ control: { type: 'radio' },
29
+ options: ['default', 'code'],
30
+ },
31
+ rows: { control: { type: 'number', min: 1, max: 20 } },
32
+ disabled: { control: 'boolean' },
33
+ },
34
+ args: {
35
+ rows: 5,
36
+ appearance: 'default',
37
+ },
38
+ };
39
+
40
+ export default meta;
41
+
42
+ type Story = StoryObj<typeof Textarea>;
43
+
44
+ const SHARE_URL = 'https://environment.data.gov.uk/share/flood-risk-assessment/abc123xyz';
45
+
46
+ export const Default: Story = {};
47
+
48
+ export const Invalid: Story = {
49
+ render: (args) => (
50
+ <FormGroup invalid>
51
+ <Label htmlFor="textarea-invalid">Description</Label>
52
+
53
+ <ErrorText id="textarea-invalid-error">Enter a description</ErrorText>
54
+
55
+ <Textarea
56
+ id="textarea-invalid"
57
+ aria-invalid
58
+ aria-describedby="textarea-invalid-error"
59
+ {...args}
60
+ />
61
+ </FormGroup>
62
+ ),
63
+ };
64
+
65
+ export const ReadOnly: Story = {
66
+ args: {
67
+ readOnly: true,
68
+ defaultValue: 'This text can be selected and copied but not edited.',
69
+ rows: 3,
70
+ },
71
+ };
72
+
73
+ export const Disabled: Story = {
74
+ args: { disabled: true, value: 'This content cannot be edited' },
75
+ };
76
+
77
+ export const Code: Story = {
78
+ args: {
79
+ appearance: 'code',
80
+ rows: 8,
81
+ defaultValue: 'SELECT *\nFROM users\nWHERE active = true;',
82
+ },
83
+ };
84
+
85
+ export const WithToolbar: Story = {
86
+ render: () => {
87
+ return (
88
+ <div className="flex flex-col gap-gds-1">
89
+ <Label htmlFor="share-url">Share link</Label>
90
+
91
+ <HintText id="share-url-hint">Copy this link to share your flood risk assessment.</HintText>
92
+
93
+ <InputGroup direction="vertical">
94
+ <InputToolbar>
95
+ <CopyButton appearance="ghost" size="sm" content={SHARE_URL} />
96
+ </InputToolbar>
97
+
98
+ <Textarea
99
+ id="share-url"
100
+ readOnly
101
+ rows={3}
102
+ value={SHARE_URL}
103
+ aria-describedby="share-url-hint"
104
+ />
105
+ </InputGroup>
106
+ </div>
107
+ );
108
+ },
109
+ };
110
+
111
+ export const WithToolbarAndCount: Story = {
112
+ render: () => (
113
+ <div className="flex flex-col gap-gds-1">
114
+ <Label htmlFor="notes-count">Notes</Label>
115
+
116
+ <HintText id="notes-count-hint">Do not enter more than 200 characters.</HintText>
117
+
118
+ <TextareaCount maxLength={200}>
119
+ <InputGroup direction="vertical">
120
+ <InputToolbar>
121
+ <CopyButton appearance="ghost" size="sm" content="Some content" />
122
+ </InputToolbar>
123
+
124
+ <Textarea id="notes-count" rows={5} aria-describedby="notes-count-hint" />
125
+ </InputGroup>
126
+
127
+ <TextareaCountMessage />
128
+ </TextareaCount>
129
+ </div>
130
+ ),
131
+ };
@@ -0,0 +1,50 @@
1
+ 'use client';
2
+
3
+ import { useContext, type ChangeEvent, type ComponentProps } from 'react';
4
+
5
+ import { cn } from '../../utils/components';
6
+ import { TextareaCountContext } from '../TextareaCount/TextareaCount';
7
+
8
+ const TEXTAREA_APPEARANCES = {
9
+ default: '',
10
+ code: 'cn-textarea-appearance-code',
11
+ } as const;
12
+
13
+ export type TextareaAppearance = keyof typeof TEXTAREA_APPEARANCES;
14
+
15
+ export type TextareaProps = ComponentProps<'textarea'> & {
16
+ appearance?: TextareaAppearance;
17
+ };
18
+
19
+ export const Textarea = ({
20
+ className,
21
+ appearance = 'default',
22
+ rows = 5,
23
+ onChange,
24
+ 'aria-describedby': ariaDescribedby,
25
+ 'aria-invalid': ariaInvalid,
26
+ ...props
27
+ }: TextareaProps) => {
28
+ const countContext = useContext(TextareaCountContext);
29
+ const isCountOver = countContext !== null && countContext.currentCount > countContext.maxCount;
30
+
31
+ const handleChange = (event: ChangeEvent<HTMLTextAreaElement>) => {
32
+ countContext?.reportValue(event.target.value);
33
+ onChange?.(event);
34
+ };
35
+
36
+ const describedBy =
37
+ [ariaDescribedby, countContext?.messageId].filter(Boolean).join(' ') || undefined;
38
+
39
+ return (
40
+ <textarea
41
+ rows={rows}
42
+ data-slot="textarea"
43
+ aria-describedby={describedBy}
44
+ aria-invalid={ariaInvalid ?? (isCountOver ? 'true' : undefined)}
45
+ className={cn('cn-textarea', TEXTAREA_APPEARANCES[appearance], className)}
46
+ onChange={handleChange}
47
+ {...props}
48
+ />
49
+ );
50
+ };
@@ -0,0 +1,17 @@
1
+ @layer components {
2
+ /* MARK: Count message
3
+ Mirrors hint text styling in the normal state.
4
+ Hidden (but still in DOM for live region) when below threshold.
5
+ Over-limit state uses error styling. */
6
+ .cn-textarea-count-message {
7
+ @apply text-sm text-body-secondary mt-gds-1;
8
+ }
9
+
10
+ .cn-textarea-count-message[data-hidden] {
11
+ visibility: hidden;
12
+ }
13
+
14
+ .cn-textarea-count-message[data-over] {
15
+ @apply text-error font-bold;
16
+ }
17
+ }
@@ -0,0 +1,131 @@
1
+ 'use client';
2
+
3
+ import { useState } from 'react';
4
+
5
+ import type { Meta, StoryObj } from '@storybook/react-vite';
6
+
7
+ import { TextareaCount, TextareaCountMessage } from './TextareaCount';
8
+ import { FormGroup } from '../Form/FormGroup';
9
+ import { Label } from '../Label/Label';
10
+ import { Textarea } from '../Textarea/Textarea';
11
+
12
+ const meta: Meta<typeof TextareaCount> = {
13
+ title: 'Components/TextareaCount',
14
+ component: TextareaCount,
15
+ tags: ['autodocs'],
16
+ parameters: {
17
+ docs: {
18
+ description: {
19
+ component:
20
+ 'Wrapper that adds live character or word count feedback to a `Textarea`. Renders into context. Place `TextareaCountMessage` anywhere below the textarea to show the count hint.',
21
+ },
22
+ },
23
+ },
24
+ };
25
+
26
+ export default meta;
27
+
28
+ type Story = StoryObj<typeof TextareaCount>;
29
+
30
+ export const CharacterCount: Story = {
31
+ render: () => (
32
+ <div>
33
+ <Label htmlFor="char-count-textarea">Description</Label>
34
+
35
+ <TextareaCount maxLength={200}>
36
+ <Textarea id="char-count-textarea" />
37
+
38
+ <TextareaCountMessage />
39
+ </TextareaCount>
40
+ </div>
41
+ ),
42
+ };
43
+
44
+ export const WordCount: Story = {
45
+ render: () => (
46
+ <div>
47
+ <Label htmlFor="word-count-textarea">Summary</Label>
48
+
49
+ <TextareaCount maxWords={50}>
50
+ <Textarea id="word-count-textarea" />
51
+
52
+ <TextareaCountMessage />
53
+ </TextareaCount>
54
+ </div>
55
+ ),
56
+ };
57
+
58
+ export const WithThreshold: Story = {
59
+ parameters: {
60
+ docs: {
61
+ description: {
62
+ story:
63
+ 'The count message is hidden until the user reaches 75% of the limit, then appears. Type more than 150 characters to see it.',
64
+ },
65
+ },
66
+ },
67
+ render: () => (
68
+ <div>
69
+ <Label htmlFor="threshold-textarea">Description</Label>
70
+
71
+ <TextareaCount maxLength={200} threshold={0.75}>
72
+ <Textarea id="threshold-textarea" />
73
+
74
+ <TextareaCountMessage />
75
+ </TextareaCount>
76
+ </div>
77
+ ),
78
+ };
79
+
80
+ export const PreFilled: Story = {
81
+ parameters: {
82
+ docs: {
83
+ description: {
84
+ story:
85
+ 'Pass `initialValue` to `TextareaCount` to seed the count when the textarea has a pre-filled value.',
86
+ },
87
+ },
88
+ },
89
+ render: () => {
90
+ const value = 'This textarea already has some content in it.';
91
+
92
+ return (
93
+ <div>
94
+ <Label htmlFor="prefilled-textarea">Description</Label>
95
+
96
+ <TextareaCount maxLength={200} initialValue={value}>
97
+ <Textarea id="prefilled-textarea" defaultValue={value} />
98
+
99
+ <TextareaCountMessage />
100
+ </TextareaCount>
101
+ </div>
102
+ );
103
+ },
104
+ };
105
+
106
+ export const OverLimit: Story = {
107
+ parameters: {
108
+ docs: {
109
+ description: {
110
+ story:
111
+ 'The count message switches to error styling when the user exceeds the limit. `onValidityChange` fires whenever the over-limit boundary is crossed, letting a parent `FormGroup` react to the state.',
112
+ },
113
+ },
114
+ },
115
+ render: () => {
116
+ const value = 'a'.repeat(220);
117
+ const [isOver, setIsOver] = useState(false);
118
+
119
+ return (
120
+ <FormGroup invalid={isOver}>
121
+ <Label htmlFor="over-limit-textarea">Description</Label>
122
+
123
+ <TextareaCount maxLength={200} initialValue={value} onValidityChange={setIsOver}>
124
+ <Textarea id="over-limit-textarea" defaultValue={value} />
125
+
126
+ <TextareaCountMessage />
127
+ </TextareaCount>
128
+ </FormGroup>
129
+ );
130
+ },
131
+ };
@@ -0,0 +1,108 @@
1
+ 'use client';
2
+
3
+ import {
4
+ createContext,
5
+ useCallback,
6
+ useContext,
7
+ useEffect,
8
+ useId,
9
+ useMemo,
10
+ useState,
11
+ type ComponentProps,
12
+ type ReactNode,
13
+ } from 'react';
14
+
15
+ import { cn } from '../../utils/components';
16
+
17
+ type TextareaCountMode = 'characters' | 'words';
18
+
19
+ export type TextareaCountContextValue = {
20
+ mode: TextareaCountMode;
21
+ maxCount: number;
22
+ threshold: number;
23
+ currentCount: number;
24
+ messageId: string;
25
+ reportValue: (value: string) => void;
26
+ };
27
+
28
+ export const TextareaCountContext = createContext<TextareaCountContextValue | null>(null);
29
+
30
+ export type TextareaCountProps = {
31
+ children: ReactNode;
32
+ threshold?: number;
33
+ initialValue?: string;
34
+ onValidityChange?: (isOver: boolean) => void;
35
+ } & ({ maxLength: number; maxWords?: never } | { maxWords: number; maxLength?: never });
36
+
37
+ const countWords = (value: string) => (value.trim() === '' ? 0 : value.trim().split(/\s+/).length);
38
+
39
+ export const TextareaCount = ({
40
+ children,
41
+ maxLength,
42
+ maxWords,
43
+ threshold = 0,
44
+ initialValue = '',
45
+ onValidityChange,
46
+ }: TextareaCountProps) => {
47
+ const mode: TextareaCountMode = maxWords !== undefined ? 'words' : 'characters';
48
+ const maxCount = (mode === 'words' ? maxWords : maxLength) ?? 0;
49
+ const messageId = useId();
50
+
51
+ const [currentCount, setCurrentCount] = useState(() =>
52
+ mode === 'words' ? countWords(initialValue) : initialValue.length,
53
+ );
54
+
55
+ const isCountOver = currentCount > maxCount;
56
+
57
+ useEffect(() => {
58
+ onValidityChange?.(isCountOver);
59
+ }, [isCountOver, onValidityChange]);
60
+
61
+ const reportValue = useCallback(
62
+ (value: string) => {
63
+ setCurrentCount(mode === 'words' ? countWords(value) : value.length);
64
+ },
65
+ [mode],
66
+ );
67
+
68
+ const contextValue = useMemo(
69
+ () => ({ mode, maxCount, threshold, currentCount, messageId, reportValue }),
70
+ [mode, maxCount, threshold, currentCount, messageId, reportValue],
71
+ );
72
+
73
+ return (
74
+ <TextareaCountContext.Provider value={contextValue}>{children}</TextareaCountContext.Provider>
75
+ );
76
+ };
77
+
78
+ export type TextareaCountMessageProps = ComponentProps<'p'>;
79
+
80
+ export const TextareaCountMessage = ({ className, ...props }: TextareaCountMessageProps) => {
81
+ const context = useContext(TextareaCountContext);
82
+
83
+ if (!context) {
84
+ return null;
85
+ }
86
+
87
+ const { mode, maxCount, threshold, currentCount, messageId } = context;
88
+ const remaining = maxCount - currentCount;
89
+ const isOver = remaining < 0;
90
+ const isHidden = threshold > 0 && currentCount < maxCount * threshold;
91
+ const count = Math.abs(remaining);
92
+ const unit = mode === 'words' ? 'word' : 'character';
93
+ const label = count === 1 ? unit : `${unit}s`;
94
+
95
+ return (
96
+ <p
97
+ id={messageId}
98
+ aria-live="polite"
99
+ data-slot="textarea-count-message"
100
+ data-over={isOver ? true : undefined}
101
+ data-hidden={isHidden ? true : undefined}
102
+ className={cn('cn-textarea-count-message', className)}
103
+ {...props}
104
+ >
105
+ {isOver ? `You have ${count} ${label} too many` : `You have ${count} ${label} remaining`}
106
+ </p>
107
+ );
108
+ };