@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
@@ -1,171 +1,44 @@
1
- 'use client';
1
+ import type { ComponentProps, ReactNode } from 'react';
2
2
 
3
- import { type ReactNode, type ComponentType, useRef, useId, useState } from 'react';
3
+ import { LuInfo } from 'react-icons/lu';
4
4
 
5
- import { FaInfoCircle } from 'react-icons/fa';
5
+ import { cn } from '../../utils/components';
6
+ import { Popover, PopoverContent, PopoverTrigger } from '../Popover/Popover';
6
7
 
7
- import {
8
- useFloating,
9
- autoUpdate,
10
- offset,
11
- flip,
12
- shift,
13
- arrow,
14
- useClick,
15
- useDismiss,
16
- useRole,
17
- useInteractions,
18
- FloatingArrow,
19
- FloatingFocusManager,
20
- FloatingPortal,
21
- type Placement,
22
- } from '@floating-ui/react';
23
-
24
- import type { ExtendProps } from '../../types';
25
- import { cn } from '../../utils';
26
-
27
- type Props = {
28
- /** Optional title displayed at the top of the info box content */
29
- title?: string;
30
- /** Content to display inside the info box */
8
+ export type InfoBoxProps = Pick<
9
+ ComponentProps<typeof PopoverContent>,
10
+ 'side' | 'align' | 'sideOffset' | 'className'
11
+ > & {
31
12
  children: ReactNode;
32
- /** Whether the info box starts open (default: false) */
33
- defaultOpen?: boolean;
34
- /** Callback when the info box opens or closes */
35
- onOpenChange?: (isOpen: boolean) => void;
36
- /** Maximum width of the info box (default: '320px') */
37
- maxWidth?: string;
38
- /** Custom aria-label for the trigger button (default: 'Show information') */
39
- triggerLabel?: string;
40
- /** Preferred placement (Floating UI will auto-adjust if needed) */
41
- placement?: Placement;
42
- /** Custom icon component to replace the default FaInfoCircle */
43
- icon?: ComponentType<{ className?: string }>;
13
+ label?: string;
44
14
  };
45
15
 
46
- export type InfoBoxProps = ExtendProps<'div', Props>;
47
-
48
16
  export const InfoBox = ({
49
- title,
50
17
  children,
51
- defaultOpen = false,
52
- onOpenChange,
53
- maxWidth = '320px',
54
- triggerLabel = 'Show information',
55
- placement = 'bottom-start',
56
- icon: Icon = FaInfoCircle,
18
+ label = 'More information',
19
+ side,
20
+ align,
21
+ sideOffset,
57
22
  className,
58
- ...props
59
- }: InfoBoxProps) => {
60
- const [isOpen, setIsOpen] = useState(defaultOpen);
61
- const arrowRef = useRef(null);
62
-
63
- const { refs, floatingStyles, context } = useFloating({
64
- open: isOpen,
65
- onOpenChange: (open) => {
66
- setIsOpen(open);
67
- onOpenChange?.(open);
68
- },
69
- placement,
70
- middleware: [
71
- offset(12), // Distance from trigger
72
- flip(), // Flip to opposite side if not enough space
73
- shift({ padding: 8 }), // Shift along the axis to stay in viewport
74
- arrow({ element: arrowRef }), // Arrow pointing to trigger
75
- ],
76
- whileElementsMounted: autoUpdate, // Update position on scroll/resize
77
- });
78
-
79
- const click = useClick(context);
80
- const dismiss = useDismiss(context);
81
- const role = useRole(context);
82
-
83
- const { getReferenceProps, getFloatingProps } = useInteractions([click, dismiss, role]);
84
-
85
- const triggerId = useId();
86
- const contentId = useId();
87
- const titleId = useId();
88
-
89
- const triggerClasses = cn(
90
- // Base styles - button structure only
91
- 'inline-flex items-center justify-center',
92
- 'w-6 h-6 rounded-full',
93
- 'bg-transparent border-none',
94
- // Focus outline only
95
- 'focus:outline focus:outline-[3px] focus:outline-focus',
96
- );
97
-
98
- const iconClasses = cn(
99
- // Icon size
100
- 'w-5 h-5',
101
- // Icon color - yellow when open, auto when closed
102
- isOpen ? 'text-focus' : '',
103
- // Hover state - yellow
104
- 'hover:text-focus',
105
- // Focus state - yellow
106
- 'focus:text-focus',
107
- // Transition
108
- 'transition-colors duration-150',
109
- );
110
-
111
- const contentClasses = cn(
112
- // Base styles
113
- 'bg-white rounded-lg shadow-lg border border-gray-200',
114
- 'p-4',
115
- // Width constraints
116
- 'min-w-[280px]',
117
- // Z-index
118
- 'z-50',
119
- );
120
-
121
- return (
122
- <div className={cn('relative inline-flex', className)} {...props}>
23
+ }: InfoBoxProps) => (
24
+ <Popover>
25
+ <PopoverTrigger asChild>
123
26
  <button
124
- ref={refs.setReference}
125
- id={triggerId}
126
27
  type="button"
127
- aria-expanded={isOpen}
128
- aria-controls={contentId}
129
- aria-haspopup="dialog"
130
- aria-label={triggerLabel}
131
- className={triggerClasses}
132
- {...getReferenceProps()}
28
+ aria-label={label}
29
+ className="cn-button cn-button-appearance-ghost cn-info-box-trigger"
133
30
  >
134
- <Icon className={iconClasses} aria-hidden="true" />
31
+ <LuInfo aria-hidden className="cn-info-box-icon" />
135
32
  </button>
136
-
137
- {isOpen ? (
138
- <FloatingPortal>
139
- <FloatingFocusManager context={context} modal={false}>
140
- <div
141
- ref={refs.setFloating}
142
- id={contentId}
143
- aria-labelledby={title ? titleId : undefined}
144
- aria-label={title ? undefined : 'Information'}
145
- style={{
146
- ...floatingStyles,
147
- maxWidth: `min(${maxWidth}, calc(100vw - 32px))`,
148
- }}
149
- className={contentClasses}
150
- {...getFloatingProps()}
151
- >
152
- <FloatingArrow ref={arrowRef} context={context} className="fill-white" />
153
-
154
- {title ? (
155
- <h2 id={titleId} className="text-sm font-semibold text-gray-900 mb-2">
156
- {title}
157
- </h2>
158
- ) : null}
159
- <div
160
- className="text-sm text-gray-700 max-h-[min(24rem,calc(100vh-200px))]
161
- overflow-y-auto"
162
- >
163
- {children}
164
- </div>
165
- </div>
166
- </FloatingFocusManager>
167
- </FloatingPortal>
168
- ) : null}
169
- </div>
170
- );
171
- };
33
+ </PopoverTrigger>
34
+
35
+ <PopoverContent
36
+ side={side}
37
+ align={align}
38
+ sideOffset={sideOffset}
39
+ className={cn('max-w-xs', className)}
40
+ >
41
+ {children}
42
+ </PopoverContent>
43
+ </Popover>
44
+ );
@@ -0,0 +1,77 @@
1
+ @layer components {
2
+ /* MARK: Input
3
+ GDS text input: 40px fixed height, 5px padding, 2px border via cn-form-border.
4
+ Focus uses the GDS focused-form-input pattern: yellow outline + inset black shadow. */
5
+ .cn-input {
6
+ @apply cn-form-border w-full h-10 p-gds-1 text-base box-border appearance-none bg-panel
7
+ text-body;
8
+
9
+ &:focus {
10
+ @apply outline-focus;
11
+ box-shadow: inset 0 0 0 var(--border-width-form) var(--color-divider-input);
12
+ }
13
+
14
+ &[aria-invalid='true'],
15
+ &:user-invalid {
16
+ @apply border-error;
17
+
18
+ &:focus {
19
+ @apply border-divider-input;
20
+ }
21
+ }
22
+
23
+ &:disabled,
24
+ &[aria-disabled='true'] {
25
+ @apply opacity-50 cursor-not-allowed;
26
+ color: inherit;
27
+ -webkit-user-select: none;
28
+ user-select: none;
29
+
30
+ &::placeholder {
31
+ -webkit-user-select: none;
32
+ user-select: none;
33
+ }
34
+ }
35
+ }
36
+
37
+ /* Remove browser-native number spinners */
38
+ .cn-input[type='number'] {
39
+ -moz-appearance: textfield;
40
+ appearance: textfield;
41
+
42
+ &::-webkit-outer-spin-button,
43
+ &::-webkit-inner-spin-button {
44
+ -webkit-appearance: none;
45
+ margin: 0;
46
+ }
47
+ }
48
+
49
+ /* MARK: Sizes
50
+ em-based max-widths constrain the input to its expected content length.
51
+ Based on GDS character-width classes. */
52
+ .cn-input-size-date-part {
53
+ max-width: 2.75em;
54
+ }
55
+ .cn-input-size-year {
56
+ max-width: 4.5em;
57
+ }
58
+ .cn-input-size-postcode {
59
+ max-width: 5.5em;
60
+ }
61
+ .cn-input-size-short {
62
+ max-width: 11.5em;
63
+ }
64
+ .cn-input-size-medium {
65
+ max-width: 20.5em;
66
+ }
67
+ .cn-input-size-long {
68
+ max-width: 29.5em;
69
+ }
70
+
71
+ /* MARK: Appearances */
72
+
73
+ .cn-input-appearance-code {
74
+ font-variant-numeric: tabular-nums;
75
+ letter-spacing: 0.05em;
76
+ }
77
+ }
@@ -0,0 +1,123 @@
1
+ import type { Meta, StoryObj } from '@storybook/react-vite';
2
+
3
+ import { Input } from './Input';
4
+ import { ErrorText } from '../ErrorText/ErrorText';
5
+ import { FormGroup } from '../Form/FormGroup';
6
+ import { Label } from '../Label/Label';
7
+
8
+ const meta: Meta<typeof Input> = {
9
+ title: 'Components/Input',
10
+ component: Input,
11
+ tags: ['autodocs'],
12
+ parameters: {
13
+ docs: {
14
+ description: {
15
+ component:
16
+ 'GDS-style text input. Use `size` to constrain the field to its expected content length. Compose with `InputGroup`, `InputPrefix`, `InputSuffix`, and `InputSwatch` for addon labels.',
17
+ },
18
+ },
19
+ },
20
+ argTypes: {
21
+ size: {
22
+ control: { type: 'select' },
23
+ options: ['base', 'date-part', 'year', 'postcode', 'short', 'medium', 'long'],
24
+ },
25
+ appearance: {
26
+ control: { type: 'radio' },
27
+ options: ['default', 'code'],
28
+ },
29
+ disabled: { control: 'boolean' },
30
+ placeholder: { control: 'text' },
31
+ },
32
+ args: {
33
+ size: 'base',
34
+ appearance: 'default',
35
+ },
36
+ };
37
+
38
+ export default meta;
39
+
40
+ type Story = StoryObj<typeof Input>;
41
+
42
+ export const Default: Story = {};
43
+
44
+ export const Sizes: Story = {
45
+ parameters: {
46
+ docs: {
47
+ description: {
48
+ story: 'Character-width constraints based on expected content length.',
49
+ },
50
+ },
51
+ },
52
+ render: () => (
53
+ <div className="flex flex-col gap-gds-3">
54
+ <div>
55
+ <Label htmlFor="size-date-part">date-part</Label>
56
+
57
+ <Input id="size-date-part" size="date-part" placeholder="DD" />
58
+ </div>
59
+
60
+ <div>
61
+ <Label htmlFor="size-year">year</Label>
62
+
63
+ <Input id="size-year" size="year" placeholder="YYYY" />
64
+ </div>
65
+
66
+ <div>
67
+ <Label htmlFor="size-postcode">postcode</Label>
68
+
69
+ <Input id="size-postcode" size="postcode" placeholder="SW1A 1AA" />
70
+ </div>
71
+
72
+ <div>
73
+ <Label htmlFor="size-short">short</Label>
74
+
75
+ <Input id="size-short" size="short" placeholder="07700 900000" />
76
+ </div>
77
+
78
+ <div>
79
+ <Label htmlFor="size-medium">medium</Label>
80
+
81
+ <Input id="size-medium" size="medium" />
82
+ </div>
83
+
84
+ <div>
85
+ <Label htmlFor="size-long">long</Label>
86
+
87
+ <Input id="size-long" size="long" />
88
+ </div>
89
+ </div>
90
+ ),
91
+ };
92
+
93
+ export const Code: Story = {
94
+ parameters: {
95
+ docs: {
96
+ description: {
97
+ story:
98
+ 'Tabular monospaced characters. Use for MFA codes, reference numbers, or any fixed-format string where character alignment matters.',
99
+ },
100
+ },
101
+ },
102
+ args: {
103
+ appearance: 'code',
104
+ size: 'short',
105
+ placeholder: 'ABCD 1234',
106
+ },
107
+ };
108
+
109
+ export const Invalid: Story = {
110
+ render: (args) => (
111
+ <FormGroup invalid>
112
+ <Label htmlFor="invalid-input">National Insurance number</Label>
113
+
114
+ <ErrorText id="ni-error">Enter a National Insurance number in the correct format</ErrorText>
115
+
116
+ <Input id="invalid-input" size="short" aria-invalid aria-describedby="ni-error" {...args} />
117
+ </FormGroup>
118
+ ),
119
+ };
120
+
121
+ export const Disabled: Story = {
122
+ args: { disabled: true, value: 'Cannot be changed' },
123
+ };
@@ -0,0 +1,74 @@
1
+ import type { ComponentProps } from 'react';
2
+
3
+ import { cn } from '../../utils/components';
4
+
5
+ const INPUT_APPEARANCES = {
6
+ default: 'cn-input-appearance-default',
7
+ code: 'cn-input-appearance-code',
8
+ } as const;
9
+
10
+ const INPUT_SIZES = {
11
+ base: 'cn-input-size-base',
12
+ 'date-part': 'cn-input-size-date-part',
13
+ year: 'cn-input-size-year',
14
+ postcode: 'cn-input-size-postcode',
15
+ short: 'cn-input-size-short',
16
+ medium: 'cn-input-size-medium',
17
+ long: 'cn-input-size-long',
18
+ } as const;
19
+
20
+ export type InputSize = keyof typeof INPUT_SIZES;
21
+ export type InputAppearance = keyof typeof INPUT_APPEARANCES;
22
+
23
+ // React's own HTMLInputTypeAttribute ends in `| (string & {})`, an
24
+ // autocomplete-with-escape-hatch trick that also defeats Exclude<>, any
25
+ // string (including "number") is still assignable to it. Listed by hand
26
+ // instead, dropping "number" for real: GDS advises against it, it silently
27
+ // strips non-numeric characters instead of validating them, adds browser
28
+ // spinner UI GDS doesn't want, and behaves inconsistently across
29
+ // locales/screen readers. Use the default type="text" with
30
+ // inputMode="numeric" instead.
31
+ export type InputType =
32
+ | 'button'
33
+ | 'checkbox'
34
+ | 'color'
35
+ | 'date'
36
+ | 'datetime-local'
37
+ | 'email'
38
+ | 'file'
39
+ | 'hidden'
40
+ | 'image'
41
+ | 'month'
42
+ | 'password'
43
+ | 'radio'
44
+ | 'range'
45
+ | 'reset'
46
+ | 'search'
47
+ | 'submit'
48
+ | 'tel'
49
+ | 'text'
50
+ | 'time'
51
+ | 'url'
52
+ | 'week';
53
+
54
+ export type InputProps = Omit<ComponentProps<'input'>, 'size' | 'type'> & {
55
+ size?: InputSize;
56
+ appearance?: InputAppearance;
57
+ type?: InputType;
58
+ };
59
+
60
+ export const Input = ({
61
+ className,
62
+ size = 'base',
63
+ appearance = 'default',
64
+ type = 'text',
65
+ ...props
66
+ }: InputProps) => (
67
+ <input
68
+ type={type}
69
+ data-slot="input"
70
+ className={cn('cn-input', INPUT_SIZES[size], INPUT_APPEARANCES[appearance], className)}
71
+ draggable="false"
72
+ {...props}
73
+ />
74
+ );
@@ -0,0 +1,140 @@
1
+ @layer components {
2
+ /* MARK: Group
3
+ Pure flex wrapper. Stacks vertically on mobile, horizontal on sm+.
4
+ direction="vertical" forces flex-col at all breakpoints, used to stack a
5
+ toolbar or count message above/below an input or textarea. */
6
+ .cn-input-group {
7
+ @apply flex flex-col sm:flex-row w-full;
8
+ }
9
+
10
+ .cn-input-group[data-direction='vertical'] {
11
+ @apply flex-col;
12
+
13
+ > * + * {
14
+ margin-top: var(--spacing-gds-1);
15
+ }
16
+
17
+ /* Toolbar border-bottom acts as the divider, no gap needed after it */
18
+ > .cn-input-toolbar + * {
19
+ margin-top: 0;
20
+ }
21
+ }
22
+
23
+ /* An icon-only Button addon (PasswordInput's show/hide toggle, SearchBox's
24
+ submit) is small enough to always fit next to the input, unlike a
25
+ toolbar or other arbitrary content, so a group containing one never
26
+ needs to drop it onto its own row on mobile. */
27
+ .cn-input-group:has(> .cn-input-prefix > .cn-button),
28
+ .cn-input-group:has(> .cn-input-suffix > .cn-button) {
29
+ @apply flex-row;
30
+ }
31
+
32
+ /* MARK: Toolbar
33
+ Sits above (or below) an input/textarea inside a vertical InputGroup.
34
+ Full cn-form-border except bottom, the adjacent field's top border
35
+ acts as the visual separator, creating one unified bordered region. */
36
+ .cn-input-toolbar {
37
+ @apply cn-form-border flex items-center gap-gds-1 px-gds-1 py-1 bg-wash justify-end;
38
+ border-bottom: none;
39
+ }
40
+
41
+ /* MARK: Prefix and Suffix
42
+ Pure positioning containers with no visual styling of their own.
43
+ Gap from the input is the default, swatch and select content remove it
44
+ via :has() and merge borders instead. items-center matters for content
45
+ that isn't already full-height and self-centering (InputSwatch and a
46
+ Select's control both are), e.g. a bare icon used as a decorative
47
+ addon, which would otherwise sit at the cross-start edge. self-start
48
+ stops this element itself stretching to fill cn-input-group's cross
49
+ axis, which is width once the group stacks to a column on mobile, that
50
+ stretch is otherwise invisible (this element has no background/border
51
+ of its own) but pushes a below-input row of content wide regardless of
52
+ what it actually contains. */
53
+ .cn-input-prefix,
54
+ .cn-input-suffix {
55
+ @apply flex flex-none items-center self-start;
56
+ }
57
+
58
+ .cn-input-suffix {
59
+ @apply mt-gds-1 sm:mt-0 sm:ml-gds-1;
60
+ }
61
+ .cn-input-prefix {
62
+ @apply mb-gds-1 sm:mb-0 sm:mr-gds-1;
63
+ }
64
+
65
+ /* Connected: swatch or select removes gap and merges borders. */
66
+ .cn-input-suffix:has(.cn-input-swatch),
67
+ .cn-input-suffix:has(.cn-select-container) {
68
+ @apply mt-0 ml-0;
69
+ }
70
+
71
+ .cn-input-prefix:has(.cn-input-swatch),
72
+ .cn-input-prefix:has(.cn-select-container) {
73
+ @apply mb-0 mr-0;
74
+ }
75
+
76
+ /* A Button addon keeps the group in a row at every size (see above), so
77
+ its own margin needs to be the row gap unconditionally too, rather than
78
+ mt-gds-1's mobile stacking gap (which would otherwise both add an
79
+ unwanted top offset and leave no horizontal gap from the input, below
80
+ sm where sm:ml-gds-1 isn't active yet). */
81
+ .cn-input-suffix:has(> .cn-button) {
82
+ @apply mt-0 ml-gds-1;
83
+ }
84
+
85
+ .cn-input-prefix:has(> .cn-button) {
86
+ @apply mb-0 mr-gds-1;
87
+ }
88
+
89
+ /* Select: auto width since select defaults to w-full. */
90
+ .cn-input-prefix > .cn-select-container,
91
+ .cn-input-suffix > .cn-select-container {
92
+ @apply w-auto;
93
+ }
94
+
95
+ .cn-input-prefix > .cn-select-container .cn-select-control {
96
+ @apply border-b-0 sm:border-b-form sm:border-r-0;
97
+ }
98
+
99
+ .cn-input-suffix > .cn-select-container .cn-select-control {
100
+ @apply border-t-0 sm:border-t-form sm:border-l-0;
101
+ }
102
+
103
+ /* MARK: Swatch
104
+ Decorative GDS-style addon (currency symbol, unit label).
105
+ Always aria-hidden, use a Button or Select for interactive addons. */
106
+ .cn-input-swatch {
107
+ @apply cn-form-swatch flex-none justify-center min-w-10 p-gds-1 text-body-secondary
108
+ whitespace-nowrap cursor-default;
109
+ }
110
+
111
+ /* An icon inside a swatch fills its padded box the same way cn-button's
112
+ icon variant does (see Button.css's cn-button-variant-icon), rather than
113
+ an arbitrary fixed size, so an icon swatch (e.g. Geocoder's search icon)
114
+ reads at the same proportions as an icon button instead of looking
115
+ smaller/inconsistent next to one. */
116
+ .cn-input-swatch svg {
117
+ @apply w-full h-full;
118
+ }
119
+
120
+ .cn-input-prefix > .cn-input-swatch {
121
+ @apply border-b-0 sm:border-b-form sm:border-r-0;
122
+ }
123
+
124
+ .cn-input-suffix > .cn-input-swatch {
125
+ @apply border-t-0 sm:border-t-form sm:border-l-0;
126
+ }
127
+
128
+ /* MARK: Button
129
+ A Button (e.g. PasswordInput's show/hide toggle, SearchBox's submit)
130
+ manages its own vertical footprint via height + box-shadow compensation
131
+ (see Button.css's --cn-button-shadow-size comments), sized specifically
132
+ assuming flex-start alignment: items-center above would otherwise leave
133
+ it sitting a pixel or two lower than the adjacent input, the shadow
134
+ compensating for the wrong gap. width: auto is the same safeguard
135
+ against stretch-to-fill as the Select rule above. */
136
+ .cn-input-prefix > .cn-button,
137
+ .cn-input-suffix > .cn-button {
138
+ @apply w-auto self-start;
139
+ }
140
+ }