@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
@@ -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
+ }