@tpzdsp/next-toolkit 2.5.1 → 3.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (357) hide show
  1. package/package.json +21 -12
  2. package/src/assets/styles/globals.css +75 -95
  3. package/src/assets/styles/ol.css +57 -16
  4. package/src/assets/styles/utils.css +80 -0
  5. package/src/components/Accordion/Accordion.css +85 -0
  6. package/src/components/Accordion/Accordion.stories.tsx +264 -0
  7. package/src/components/Accordion/Accordion.tsx +98 -0
  8. package/src/components/Alert/Alert.css +129 -0
  9. package/src/components/Alert/Alert.stories.tsx +291 -0
  10. package/src/components/Alert/Alert.tsx +76 -0
  11. package/src/components/BackLink/BackLink.css +12 -0
  12. package/src/components/BackLink/BackLink.stories.tsx +52 -0
  13. package/src/components/BackLink/BackLink.tsx +44 -0
  14. package/src/components/BackToTop/BackToTop.css +23 -0
  15. package/src/components/BackToTop/BackToTop.stories.tsx +41 -0
  16. package/src/components/BackToTop/BackToTop.tsx +48 -0
  17. package/src/components/Breadcrumb/Breadcrumb.css +42 -0
  18. package/src/components/Breadcrumb/Breadcrumb.stories.tsx +94 -0
  19. package/src/components/Breadcrumb/Breadcrumb.tsx +135 -0
  20. package/src/components/Button/Button.css +229 -0
  21. package/src/components/Button/Button.stories.tsx +140 -20
  22. package/src/components/Button/Button.tsx +53 -28
  23. package/src/components/Button/ButtonSkeleton.stories.tsx +50 -0
  24. package/src/components/Button/ButtonSkeleton.tsx +14 -0
  25. package/src/components/ButtonGroup/ButtonGroup.css +52 -0
  26. package/src/components/ButtonGroup/ButtonGroup.stories.tsx +156 -0
  27. package/src/components/ButtonGroup/ButtonGroup.tsx +50 -0
  28. package/src/components/ButtonLink/ButtonLink.css +114 -0
  29. package/src/components/ButtonLink/ButtonLink.stories.tsx +38 -51
  30. package/src/components/ButtonLink/ButtonLink.tsx +54 -23
  31. package/src/components/Card/Card.css +13 -0
  32. package/src/components/Card/Card.stories.tsx +98 -57
  33. package/src/components/Card/Card.tsx +4 -13
  34. package/src/components/CardGroup/CardGroup.css +10 -0
  35. package/src/components/CardGroup/CardGroup.stories.tsx +81 -0
  36. package/src/components/CardGroup/CardGroup.tsx +9 -0
  37. package/src/components/Checkbox/Checkbox.css +49 -0
  38. package/src/components/Checkbox/Checkbox.stories.tsx +86 -0
  39. package/src/components/Checkbox/Checkbox.tsx +32 -0
  40. package/src/components/Chip/Chip.css +54 -0
  41. package/src/components/Chip/Chip.stories.tsx +94 -0
  42. package/src/components/Chip/Chip.tsx +34 -0
  43. package/src/components/CookieBanner/CookieBanner.css +19 -0
  44. package/src/components/CookieBanner/CookieBanner.stories.tsx +52 -0
  45. package/src/components/CookieBanner/CookieBanner.tsx +55 -0
  46. package/src/components/CopyButton/CopyButton.stories.tsx +28 -0
  47. package/src/components/CopyButton/CopyButton.tsx +65 -0
  48. package/src/components/DateInput/DateInput.css +13 -0
  49. package/src/components/DateInput/DateInput.stories.tsx +131 -0
  50. package/src/components/DateInput/DateInput.test.tsx +21 -0
  51. package/src/components/DateInput/DateInput.tsx +98 -0
  52. package/src/components/Details/Details.css +28 -0
  53. package/src/components/Details/Details.stories.tsx +48 -0
  54. package/src/components/Details/Details.tsx +41 -0
  55. package/src/components/Dropdown/Dropdown.css +81 -0
  56. package/src/components/Dropdown/Dropdown.stories.tsx +131 -0
  57. package/src/components/Dropdown/Dropdown.tsx +69 -0
  58. package/src/components/ErrorBoundary/ErrorBoundary.stories.tsx +4 -39
  59. package/src/components/ErrorBoundary/ErrorBoundary.tsx +7 -4
  60. package/src/components/ErrorBoundary/ErrorFallback.tsx +32 -66
  61. package/src/components/ErrorModal/ErrorModal.css +34 -0
  62. package/src/components/ErrorModal/ErrorModal.stories.tsx +100 -0
  63. package/src/components/ErrorModal/ErrorModal.tsx +123 -0
  64. package/src/components/ErrorText/ErrorText.css +22 -0
  65. package/src/components/ErrorText/ErrorText.stories.tsx +42 -27
  66. package/src/components/ErrorText/ErrorText.tsx +10 -8
  67. package/src/components/ExternalLink/ExternalLink.css +12 -0
  68. package/src/components/ExternalLink/ExternalLink.stories.tsx +43 -0
  69. package/src/components/ExternalLink/ExternalLink.tsx +43 -0
  70. package/src/components/Fieldset/Fieldset.css +103 -0
  71. package/src/components/Fieldset/Fieldset.stories.tsx +304 -0
  72. package/src/components/Fieldset/Fieldset.tsx +38 -0
  73. package/src/components/FileUpload/FileUpload.css +85 -0
  74. package/src/components/FileUpload/FileUpload.stories.tsx +106 -0
  75. package/src/components/FileUpload/FileUpload.tsx +99 -0
  76. package/src/components/{layout/footer → Footer}/Copyright.tsx +3 -2
  77. package/src/components/Footer/Footer.stories.tsx +27 -0
  78. package/src/components/Footer/Footer.tsx +46 -0
  79. package/src/components/Footer/Licence.tsx +18 -0
  80. package/src/components/Footer/MetaLinks.tsx +47 -0
  81. package/src/components/Footer/Small/SmallFooter.stories.tsx +3 -0
  82. package/src/components/Footer/Small/SmallFooter.tsx +53 -41
  83. package/src/components/Form/FormGroup.css +18 -0
  84. package/src/components/Form/FormGroup.stories.tsx +87 -0
  85. package/src/components/Form/FormGroup.tsx +16 -0
  86. package/src/components/{layout/header → Header}/Header.stories.tsx +26 -12
  87. package/src/components/Header/Header.test.tsx +87 -0
  88. package/src/components/Header/Header.tsx +304 -0
  89. package/src/components/Header/HeaderAppContent.tsx +120 -0
  90. package/src/components/Heading/Heading.css +40 -0
  91. package/src/components/Heading/Heading.stories.tsx +15 -5
  92. package/src/components/Heading/Heading.tsx +21 -44
  93. package/src/components/Heading/HeadingSkeleton.stories.tsx +30 -0
  94. package/src/components/Heading/HeadingSkeleton.tsx +14 -0
  95. package/src/components/Hero/Hero.css +19 -0
  96. package/src/components/Hero/Hero.stories.tsx +41 -0
  97. package/src/components/Hero/Hero.tsx +14 -0
  98. package/src/components/HintText/HintText.css +5 -0
  99. package/src/components/HintText/HintText.stories.tsx +29 -0
  100. package/src/components/HintText/HintText.tsx +13 -0
  101. package/src/components/InfoBox/InfoBox.css +38 -0
  102. package/src/components/InfoBox/InfoBox.stories.tsx +51 -403
  103. package/src/components/InfoBox/InfoBox.tsx +31 -158
  104. package/src/components/Input/Input.css +77 -0
  105. package/src/components/Input/Input.stories.tsx +123 -0
  106. package/src/components/Input/Input.tsx +74 -0
  107. package/src/components/InputGroup/InputGroup.css +140 -0
  108. package/src/components/InputGroup/InputGroup.stories.tsx +125 -0
  109. package/src/components/InputGroup/InputGroup.tsx +47 -0
  110. package/src/components/InsetText/InsetText.css +5 -0
  111. package/src/components/InsetText/InsetText.stories.tsx +30 -0
  112. package/src/components/InsetText/InsetText.tsx +9 -0
  113. package/src/components/Keyboard/Keyboard.css +9 -0
  114. package/src/components/Keyboard/Keyboard.stories.tsx +63 -0
  115. package/src/components/Keyboard/Keyboard.tsx +30 -0
  116. package/src/components/Label/Label.css +27 -0
  117. package/src/components/Label/Label.stories.tsx +40 -0
  118. package/src/components/Label/Label.tsx +17 -0
  119. package/src/components/LayerSwitcher/LayerSwitcher.css +59 -0
  120. package/src/components/LayerSwitcher/LayerSwitcher.stories.tsx +112 -0
  121. package/src/components/LayerSwitcher/LayerSwitcher.tsx +61 -0
  122. package/src/components/Layout/401/401.stories.tsx +23 -0
  123. package/src/components/Layout/401/401.tsx +1 -0
  124. package/src/components/Layout/403/403.stories.tsx +23 -0
  125. package/src/components/Layout/403/403.tsx +21 -0
  126. package/src/components/Layout/404/404.stories.tsx +23 -0
  127. package/src/components/Layout/404/404.tsx +28 -0
  128. package/src/components/Layout/500/500.stories.tsx +56 -0
  129. package/src/components/Layout/500/500.tsx +63 -0
  130. package/src/components/Layout/ButtonGroup/ButtonGroup.css +52 -0
  131. package/src/components/Layout/ButtonGroup/ButtonGroup.stories.tsx +156 -0
  132. package/src/components/Layout/ButtonGroup/ButtonGroup.tsx +50 -0
  133. package/src/components/Layout/HeadingGroup/HeadingGroup.css +21 -0
  134. package/src/components/Layout/HeadingGroup/HeadingGroup.stories.tsx +84 -0
  135. package/src/components/Layout/HeadingGroup/HeadingGroup.tsx +9 -0
  136. package/src/components/Layout/MainWrapper/MainWrapper.css +12 -0
  137. package/src/components/Layout/MainWrapper/MainWrapper.stories.tsx +36 -0
  138. package/src/components/Layout/MainWrapper/MainWrapper.tsx +14 -0
  139. package/src/components/Layout/PageShell/PageShell.css +42 -0
  140. package/src/components/Layout/PageShell/PageShell.stories.tsx +108 -0
  141. package/src/components/Layout/PageShell/PageShell.tsx +31 -0
  142. package/src/components/Layout/ParagraphGroup/ParagraphGroup.css +5 -0
  143. package/src/components/Layout/ParagraphGroup/ParagraphGroup.stories.tsx +34 -0
  144. package/src/components/Layout/ParagraphGroup/ParagraphGroup.tsx +9 -0
  145. package/src/components/Layout/Stack/Stack.css +29 -0
  146. package/src/components/Layout/Stack/Stack.stories.tsx +83 -0
  147. package/src/components/Layout/Stack/Stack.tsx +19 -0
  148. package/src/components/Layout/WidthContainer/WidthContainer.css +17 -0
  149. package/src/components/Layout/WidthContainer/WidthContainer.stories.tsx +59 -0
  150. package/src/components/Layout/WidthContainer/WidthContainer.tsx +13 -0
  151. package/src/components/Legend/Legend.css +95 -0
  152. package/src/components/Legend/Legend.stories.tsx +81 -0
  153. package/src/components/Legend/Legend.tsx +32 -0
  154. package/src/components/Legend/LegendDot.tsx +15 -0
  155. package/src/components/Legend/LegendPanel.stories.tsx +101 -0
  156. package/src/components/Legend/LegendPanel.tsx +68 -0
  157. package/src/components/Legend/LegendSkeleton.stories.tsx +87 -0
  158. package/src/components/Legend/LegendSkeleton.tsx +73 -0
  159. package/src/components/LegendSelect/LegendSelect.css +8 -0
  160. package/src/components/LegendSelect/LegendSelect.stories.tsx +80 -0
  161. package/src/components/LegendSelect/LegendSelect.tsx +26 -0
  162. package/src/components/Link/Link.css +98 -0
  163. package/src/components/Link/Link.stories.tsx +70 -0
  164. package/src/components/Link/Link.tsx +52 -0
  165. package/src/components/LinkButton/LinkButton.css +67 -0
  166. package/src/components/LinkButton/LinkButton.stories.tsx +90 -42
  167. package/src/components/LinkButton/LinkButton.tsx +50 -63
  168. package/src/components/LinkList/LinkList.css +28 -0
  169. package/src/components/LinkList/LinkList.stories.tsx +46 -0
  170. package/src/components/LinkList/LinkList.tsx +23 -0
  171. package/src/components/List/Li.tsx +9 -0
  172. package/src/components/List/List.css +9 -0
  173. package/src/components/List/OrderedList.stories.tsx +36 -0
  174. package/src/components/List/OrderedList.tsx +9 -0
  175. package/src/components/List/UnorderedList.stories.tsx +36 -0
  176. package/src/components/List/UnorderedList.tsx +9 -0
  177. package/src/components/LoadingBox/LoadingBox.css +27 -0
  178. package/src/components/LoadingBox/LoadingBox.stories.tsx +66 -0
  179. package/src/components/LoadingBox/LoadingBox.tsx +40 -0
  180. package/src/components/Modal/Modal.css +111 -0
  181. package/src/components/Modal/Modal.stories.tsx +94 -155
  182. package/src/components/Modal/Modal.tsx +141 -75
  183. package/src/components/NoScriptBanner/NoScriptBanner.css +17 -0
  184. package/src/components/NoScriptBanner/NoScriptBanner.stories.tsx +46 -0
  185. package/src/components/NoScriptBanner/NoScriptBanner.tsx +26 -0
  186. package/src/components/Paragraph/Paragraph.css +22 -0
  187. package/src/components/Paragraph/Paragraph.stories.tsx +1 -42
  188. package/src/components/Paragraph/Paragraph.tsx +4 -3
  189. package/src/components/Paragraph/ParagraphSkeleton.stories.tsx +44 -0
  190. package/src/components/Paragraph/ParagraphSkeleton.tsx +33 -0
  191. package/src/components/PasswordInput/PasswordInput.css +3 -0
  192. package/src/components/PasswordInput/PasswordInput.stories.tsx +47 -0
  193. package/src/components/PasswordInput/PasswordInput.tsx +45 -0
  194. package/src/components/PhaseBanner/PhaseBanner.css +12 -0
  195. package/src/components/PhaseBanner/PhaseBanner.stories.tsx +61 -0
  196. package/src/components/PhaseBanner/PhaseBanner.tsx +17 -0
  197. package/src/components/Popover/Popover.css +43 -0
  198. package/src/components/Popover/Popover.stories.tsx +102 -0
  199. package/src/components/Popover/Popover.tsx +40 -0
  200. package/src/components/Radio/Radio.css +69 -0
  201. package/src/components/Radio/Radio.stories.tsx +169 -0
  202. package/src/components/Radio/Radio.tsx +56 -0
  203. package/src/components/Resizable/Resizable.css +86 -0
  204. package/src/components/Resizable/Resizable.stories.tsx +123 -0
  205. package/src/components/Resizable/Resizable.tsx +86 -0
  206. package/src/components/ScrollArea/ScrollArea.css +9 -0
  207. package/src/components/ScrollArea/ScrollArea.stories.tsx +42 -0
  208. package/src/components/ScrollArea/ScrollArea.tsx +11 -0
  209. package/src/components/SearchBox/SearchBox.stories.tsx +88 -0
  210. package/src/components/SearchBox/SearchBox.tsx +36 -0
  211. package/src/components/Select/AsyncSelect.stories.tsx +84 -0
  212. package/src/components/Select/AsyncSelect.tsx +41 -0
  213. package/src/components/Select/Select.css +202 -0
  214. package/src/components/Select/Select.stories.tsx +162 -0
  215. package/src/components/Select/Select.test.tsx +36 -0
  216. package/src/components/Select/Select.tsx +296 -0
  217. package/src/components/Select/SelectSkeleton.stories.tsx +51 -0
  218. package/src/components/Select/SelectSkeleton.tsx +23 -0
  219. package/src/components/Separator/Separator.css +41 -0
  220. package/src/components/Separator/Separator.stories.tsx +63 -0
  221. package/src/components/Separator/Separator.tsx +42 -0
  222. package/src/components/Sidebar/ResizableSidebar.tsx +118 -0
  223. package/src/components/Sidebar/Sidebar.css +203 -0
  224. package/src/components/Sidebar/Sidebar.stories.tsx +438 -0
  225. package/src/components/Sidebar/Sidebar.tsx +225 -0
  226. package/src/components/Skeleton/Skeleton.css +16 -0
  227. package/src/components/Skeleton/Skeleton.stories.tsx +39 -0
  228. package/src/components/Skeleton/Skeleton.tsx +12 -0
  229. package/src/components/SkipLink/SkipLink.css +16 -0
  230. package/src/components/SkipLink/SkipLink.stories.tsx +40 -0
  231. package/src/components/SkipLink/SkipLink.tsx +15 -0
  232. package/src/components/Spinner/Spinner.css +30 -0
  233. package/src/components/Spinner/Spinner.stories.tsx +36 -0
  234. package/src/components/Spinner/Spinner.tsx +45 -0
  235. package/src/components/StartButton/StartButton.css +13 -0
  236. package/src/components/StartButton/StartButton.stories.tsx +68 -0
  237. package/src/components/StartButton/StartButton.tsx +50 -0
  238. package/src/components/SubmitButton/SubmitButton.stories.tsx +31 -0
  239. package/src/components/SubmitButton/SubmitButton.tsx +14 -0
  240. package/src/components/SummaryList/SummaryList.css +71 -0
  241. package/src/components/SummaryList/SummaryList.stories.tsx +211 -0
  242. package/src/components/SummaryList/SummaryList.tsx +41 -0
  243. package/src/components/SummaryList/SummaryListSkeleton.stories.tsx +67 -0
  244. package/src/components/SummaryList/SummaryListSkeleton.tsx +40 -0
  245. package/src/components/Tabs/Tabs.css +84 -0
  246. package/src/components/Tabs/Tabs.stories.tsx +133 -0
  247. package/src/components/Tabs/Tabs.tsx +66 -0
  248. package/src/components/Tag/Tag.css +8 -0
  249. package/src/components/Tag/Tag.stories.tsx +96 -0
  250. package/src/components/Tag/Tag.tsx +34 -0
  251. package/src/components/Textarea/Textarea.css +38 -0
  252. package/src/components/Textarea/Textarea.stories.tsx +131 -0
  253. package/src/components/Textarea/Textarea.tsx +50 -0
  254. package/src/components/TextareaCount/TextareaCount.css +17 -0
  255. package/src/components/TextareaCount/TextareaCount.stories.tsx +131 -0
  256. package/src/components/TextareaCount/TextareaCount.tsx +108 -0
  257. package/src/components/Tooltip/Tooltip.css +43 -0
  258. package/src/components/Tooltip/Tooltip.stories.tsx +110 -0
  259. package/src/components/Tooltip/Tooltip.tsx +53 -0
  260. package/src/components/WarningText/WarningText.css +20 -0
  261. package/src/components/WarningText/WarningText.stories.tsx +29 -0
  262. package/src/components/WarningText/WarningText.tsx +17 -0
  263. package/src/components/index.ts +343 -61
  264. package/src/errors/errorDisplay.ts +70 -0
  265. package/src/errors/index.ts +1 -0
  266. package/src/http/constants.ts +2 -0
  267. package/src/http/fetch.ts +7 -3
  268. package/src/map/LayerSwitcherPanel.tsx +2 -173
  269. package/src/map/LegendShim.tsx +2 -0
  270. package/src/map/MapComponent.tsx +7 -17
  271. package/src/map/MapControlsOverlay.tsx +68 -175
  272. package/src/map/Popup.tsx +71 -24
  273. package/src/map/geocoder/Geocoder.test.tsx +46 -3
  274. package/src/map/geocoder/Geocoder.tsx +155 -278
  275. package/src/map/index.ts +1 -1
  276. package/src/types/utils.ts +0 -10
  277. package/src/utils/components.ts +96 -0
  278. package/src/utils/index.ts +1 -0
  279. package/src/utils/utils.ts +0 -12
  280. package/src/assets/images/defra-logo.svg +0 -51
  281. package/src/assets/images/ea-logo.svg +0 -58
  282. package/src/assets/images/ogl.svg +0 -1
  283. package/src/components/Button/Button.test.tsx +0 -53
  284. package/src/components/ButtonLink/ButtonLink.test.tsx +0 -154
  285. package/src/components/Card/Card.test.tsx +0 -51
  286. package/src/components/ErrorBoundary/ErrorBoundary.test.tsx +0 -75
  287. package/src/components/ErrorBoundary/ErrorFallback.test.tsx +0 -107
  288. package/src/components/ErrorText/ErrorText.test.tsx +0 -33
  289. package/src/components/Heading/Heading.test.tsx +0 -22
  290. package/src/components/Hint/Hint.stories.tsx +0 -58
  291. package/src/components/Hint/Hint.test.tsx +0 -33
  292. package/src/components/Hint/Hint.tsx +0 -12
  293. package/src/components/InfoBox/InfoBox.test.tsx +0 -330
  294. package/src/components/InfoBox/types.ts +0 -6
  295. package/src/components/LinkButton/LinkButton.test.tsx +0 -177
  296. package/src/components/Modal/Modal.test.tsx +0 -246
  297. package/src/components/NotificationBanner/NotificationBanner.stories.tsx +0 -45
  298. package/src/components/NotificationBanner/NotificationBanner.test.tsx +0 -58
  299. package/src/components/NotificationBanner/NotificationBanner.tsx +0 -45
  300. package/src/components/Paragraph/Paragraph.test.tsx +0 -10
  301. package/src/components/SlidingPanel/SlidingPanel.stories.tsx +0 -129
  302. package/src/components/SlidingPanel/SlidingPanel.test.tsx +0 -83
  303. package/src/components/SlidingPanel/SlidingPanel.tsx +0 -258
  304. package/src/components/accordion/Accordion.stories.tsx +0 -234
  305. package/src/components/accordion/Accordion.test.tsx +0 -192
  306. package/src/components/accordion/Accordion.tsx +0 -73
  307. package/src/components/backToTop/BackToTop.stories.tsx +0 -407
  308. package/src/components/backToTop/BackToTop.test.tsx +0 -57
  309. package/src/components/backToTop/BackToTop.tsx +0 -134
  310. package/src/components/chip/Chip.stories.tsx +0 -61
  311. package/src/components/chip/Chip.test.tsx +0 -31
  312. package/src/components/chip/Chip.tsx +0 -23
  313. package/src/components/container/Container.tsx +0 -42
  314. package/src/components/cookieBanner/CookieBanner.stories.tsx +0 -257
  315. package/src/components/cookieBanner/CookieBanner.test.tsx +0 -68
  316. package/src/components/cookieBanner/CookieBanner.tsx +0 -73
  317. package/src/components/divider/RuleDivider.stories.tsx +0 -254
  318. package/src/components/divider/RuleDivider.test.tsx +0 -164
  319. package/src/components/divider/RuleDivider.tsx +0 -23
  320. package/src/components/dropdown/DropdownMenu.test.tsx +0 -211
  321. package/src/components/dropdown/DropdownMenu.tsx +0 -108
  322. package/src/components/dropdown/useDropdownMenu.ts +0 -249
  323. package/src/components/form/Input.stories.tsx +0 -435
  324. package/src/components/form/Input.test.tsx +0 -206
  325. package/src/components/form/Input.tsx +0 -23
  326. package/src/components/form/TextArea.stories.tsx +0 -464
  327. package/src/components/form/TextArea.test.tsx +0 -232
  328. package/src/components/form/TextArea.tsx +0 -23
  329. package/src/components/layout/footer/Footer.tsx +0 -26
  330. package/src/components/layout/footer/Licence.tsx +0 -19
  331. package/src/components/layout/footer/MetaLinks.tsx +0 -36
  332. package/src/components/layout/header/Header.test.tsx +0 -36
  333. package/src/components/layout/header/Header.tsx +0 -90
  334. package/src/components/layout/header/HeaderAuthClient.test.tsx +0 -45
  335. package/src/components/layout/header/HeaderAuthClient.tsx +0 -40
  336. package/src/components/layout/header/HeaderNavClient.test.tsx +0 -44
  337. package/src/components/layout/header/HeaderNavClient.tsx +0 -67
  338. package/src/components/link/ExternalLink.test.tsx +0 -102
  339. package/src/components/link/ExternalLink.tsx +0 -29
  340. package/src/components/link/Link.tsx +0 -26
  341. package/src/components/select/Select.stories.tsx +0 -336
  342. package/src/components/select/Select.test.tsx +0 -474
  343. package/src/components/select/Select.tsx +0 -125
  344. package/src/components/select/SelectSkeleton.stories.tsx +0 -194
  345. package/src/components/select/SelectSkeleton.test.tsx +0 -104
  346. package/src/components/select/SelectSkeleton.tsx +0 -23
  347. package/src/components/select/common.ts +0 -3
  348. package/src/components/select/index.ts +0 -18
  349. package/src/components/skipLink/SkipLink.stories.tsx +0 -346
  350. package/src/components/skipLink/SkipLink.test.tsx +0 -22
  351. package/src/components/skipLink/SkipLink.tsx +0 -49
  352. package/src/map/LegendPanel.tsx +0 -85
  353. /package/src/{components → assets}/images/DefraLogo.tsx +0 -0
  354. /package/src/{components → assets}/images/EaLogo.tsx +0 -0
  355. /package/src/{components → assets}/images/OglLogo.tsx +0 -0
  356. /package/src/components/{googleAnalytics → GoogleAnalytics}/GlobalVars.tsx +0 -0
  357. /package/src/components/{googleAnalytics → GoogleAnalytics}/GoogleAnalytics.tsx +0 -0
@@ -0,0 +1,304 @@
1
+ 'use client';
2
+
3
+ import { type ReactNode, useEffect, useId, useRef, useState } from 'react';
4
+
5
+ import { LuEllipsis, LuSearch, LuX } from 'react-icons/lu';
6
+
7
+ import {
8
+ ButtonLink,
9
+ DefraLogo,
10
+ ExternalLink,
11
+ FormGroup,
12
+ Label,
13
+ Link,
14
+ PopoverContent,
15
+ PopoverTrigger,
16
+ SearchBox,
17
+ Separator,
18
+ WidthContainer,
19
+ Popover,
20
+ ParagraphGroup,
21
+ } from '@tpzdsp/next-toolkit/components';
22
+ import { cn } from '@tpzdsp/next-toolkit/utils';
23
+
24
+ import type { Credentials } from '../../types/auth';
25
+
26
+ export type HeaderProps = {
27
+ appContent?: ReactNode;
28
+ credentials?: Credentials | null;
29
+ };
30
+
31
+ const DSP_NAV_LINKS = [
32
+ {
33
+ href: '/appgallery',
34
+ label: 'Apps',
35
+ mainNav: '@max-[520px]/main:hidden',
36
+ drawerNav: 'hidden @max-[520px]/drawer:block',
37
+ },
38
+ {
39
+ href: '/apiportal',
40
+ label: 'APIs',
41
+ mainNav: '@max-[620px]/main:hidden',
42
+ drawerNav: 'hidden @max-[620px]/drawer:block',
43
+ },
44
+ {
45
+ href: '/survey',
46
+ label: 'Survey',
47
+ mainNav: '@max-[720px]/main:hidden',
48
+ drawerNav: 'hidden @max-[720px]/drawer:block',
49
+ },
50
+ {
51
+ href: '/support',
52
+ label: 'Support',
53
+ mainNav: '@max-[820px]/main:hidden',
54
+ drawerNav: 'hidden @max-[820px]/drawer:block',
55
+ },
56
+ {
57
+ href: '/register',
58
+ label: 'Create an account',
59
+ mainNav: '@max-[970px]/main:hidden',
60
+ drawerNav: 'hidden @max-[970px]/drawer:block',
61
+ },
62
+ ] as const;
63
+
64
+ const HOME_URL = '/';
65
+ const LOGIN_URL = '/login';
66
+ const LOGOUT_URL = '/logout';
67
+ const DEFRA_URL =
68
+ 'https://www.gov.uk/government/organisations/department-for-environment-food-rural-affairs';
69
+ const GLOBAL_SEARCH_URL = '/globalSearch';
70
+ const GLOBAL_SEARCH_QUERY_PARAM = 'query';
71
+
72
+ export const Header = ({ appContent, credentials }: HeaderProps) => {
73
+ const navDrawerId = useId();
74
+ const searchDrawerId = useId();
75
+ const searchInputId = useId();
76
+
77
+ const [isDrawerOpen, setIsDrawerOpen] = useState(false);
78
+ const [isSearchOpen, setIsSearchOpen] = useState(false);
79
+ const [redirectUri, setRedirectUri] = useState('');
80
+
81
+ const triggerRef = useRef<HTMLLIElement>(null);
82
+ const drawerRef = useRef<HTMLDivElement>(null);
83
+ const hasOpenedRef = useRef(false);
84
+
85
+ // window isn't available during SSR, and the raw value needs encoding
86
+ // anyway (an unescaped ?/&/# in the current URL would otherwise corrupt
87
+ // this query string), so this is deferred to a client-only effect rather
88
+ // than read directly during render. Full absolute URL (not just path +
89
+ // search), sign-in/sign-out live on a separate origin, so it needs the
90
+ // hostname to know where to send the user back to.
91
+ useEffect(() => {
92
+ setRedirectUri(encodeURIComponent(window.location.href));
93
+ }, []);
94
+
95
+ // Move focus into the drawer when it opens; return it to the trigger when it closes.
96
+ // hasOpenedRef prevents a focus jump on initial render.
97
+ useEffect(() => {
98
+ if (isDrawerOpen) {
99
+ hasOpenedRef.current = true;
100
+
101
+ const firstFocusable = drawerRef.current?.querySelector<HTMLElement>(
102
+ 'a[href], button:not([disabled])',
103
+ );
104
+
105
+ firstFocusable?.focus();
106
+ } else if (hasOpenedRef.current) {
107
+ triggerRef.current?.querySelector<HTMLElement>('button')?.focus();
108
+ }
109
+ }, [isDrawerOpen]);
110
+
111
+ useEffect(() => {
112
+ if (!isDrawerOpen) {
113
+ return;
114
+ }
115
+
116
+ const handleKeyDown = (e: KeyboardEvent) => {
117
+ if (e.key === 'Escape') {
118
+ setIsDrawerOpen(false);
119
+ }
120
+ };
121
+
122
+ document.addEventListener('keydown', handleKeyDown);
123
+
124
+ return () => document.removeEventListener('keydown', handleKeyDown);
125
+ }, [isDrawerOpen]);
126
+
127
+ return (
128
+ <header className="w-full text-white border-b border-neutral-mid">
129
+ <WidthContainer className="flex items-center justify-center bg-accent z-10 relative">
130
+ <div
131
+ className="w-full h-14 flex p-gds-2 justify-between items-center gap-gds-4
132
+ @container/main"
133
+ >
134
+ <div className="flex h-full min-w-0 items-center gap-gds-4">
135
+ <div className="flex shrink-0 gap-gds-2 h-full items-center">
136
+ <ExternalLink
137
+ href={DEFRA_URL}
138
+ appearance="inverse"
139
+ variant="plain"
140
+ className="flex gap-gds-1 h-full items-center"
141
+ >
142
+ <DefraLogo aria-hidden className="h-full w-auto shrink-0 block" />
143
+
144
+ <abbr
145
+ title="Department for Environment, Food, and Rural Affairs"
146
+ className="sr-only xs:not-sr-only no-underline"
147
+ >
148
+ DEFRA
149
+ </abbr>
150
+ </ExternalLink>
151
+
152
+ <Separator orientation="vertical" className="bg-white" />
153
+
154
+ <Link href={HOME_URL} appearance="inverse" className="text-nowrap">
155
+ <span className="hidden xs:inline">Data Services Platform</span>
156
+
157
+ <span className="inline xs:hidden">
158
+ <abbr title="Data Services Platform" className="no-underline">
159
+ DSP
160
+ </abbr>
161
+ </span>
162
+ </Link>
163
+ </div>
164
+
165
+ <nav aria-label="Primary navigation" className="min-w-0">
166
+ <ul className="flex items-center gap-gds-4">
167
+ {DSP_NAV_LINKS.map((item) => (
168
+ <li className={cn('flex items-center nav-item', item.mainNav)} key={item.href}>
169
+ <Link href={item.href} appearance="inverse">
170
+ {item.label}
171
+ </Link>
172
+ </li>
173
+ ))}
174
+ <li ref={triggerRef} className="flex items-center more-btn shrink-0">
175
+ <ButtonLink
176
+ aria-label="Navigation drawer"
177
+ aria-expanded={isDrawerOpen}
178
+ aria-controls={navDrawerId}
179
+ appearance="inverse"
180
+ variant="icon"
181
+ onClick={() => setIsDrawerOpen(!isDrawerOpen)}
182
+ >
183
+ <LuEllipsis aria-hidden />
184
+ </ButtonLink>
185
+ </li>
186
+ </ul>
187
+ </nav>
188
+ </div>
189
+
190
+ <div className="flex shrink-0 gap-gds-2 h-full items-center">
191
+ {credentials ? (
192
+ <Popover>
193
+ <PopoverTrigger asChild>
194
+ <ButtonLink appearance="inverse">Profile</ButtonLink>
195
+ </PopoverTrigger>
196
+
197
+ <PopoverContent sideOffset={0}>
198
+ <ParagraphGroup>
199
+ <div>
200
+ <div className="font-bold">Signed in as:</div>
201
+
202
+ <div>{credentials.user.email}</div>
203
+ </div>
204
+
205
+ <Link href={`${LOGOUT_URL}?redirect_uri=${redirectUri}`}>Sign-out</Link>
206
+ </ParagraphGroup>
207
+ </PopoverContent>
208
+ </Popover>
209
+ ) : (
210
+ <Link
211
+ href={`${LOGIN_URL}?redirect_uri=${redirectUri}`}
212
+ appearance="inverse"
213
+ className="text-nowrap"
214
+ >
215
+ Sign-in
216
+ </Link>
217
+ )}
218
+
219
+ <Separator orientation="vertical" className="bg-white" />
220
+
221
+ <ButtonLink
222
+ appearance="inverse"
223
+ variant="icon"
224
+ aria-label="Search the Data Services Platform"
225
+ aria-controls={searchDrawerId}
226
+ aria-expanded={isSearchOpen}
227
+ onClick={() => setIsSearchOpen(!isSearchOpen)}
228
+ >
229
+ <LuSearch aria-hidden />
230
+ </ButtonLink>
231
+ </div>
232
+ </div>
233
+ </WidthContainer>
234
+
235
+ <div
236
+ id={searchDrawerId}
237
+ inert={!isSearchOpen}
238
+ className={cn(
239
+ 'w-full bg-wash grid transition-[grid-template-rows] duration-200',
240
+ isSearchOpen ? 'grid-rows-[1fr]' : 'grid-rows-[0fr]',
241
+ )}
242
+ >
243
+ <WidthContainer className="min-h-0 overflow-hidden">
244
+ <div className="w-full h-40 p-gds-6 flex items-center">
245
+ <form action={GLOBAL_SEARCH_URL} className="w-full">
246
+ <FormGroup>
247
+ <Label htmlFor={searchInputId} className="font-bold text-2xl">
248
+ Search DSP
249
+ </Label>
250
+
251
+ <SearchBox id={searchInputId} name={GLOBAL_SEARCH_QUERY_PARAM} />
252
+ </FormGroup>
253
+ </form>
254
+ </div>
255
+ </WidthContainer>
256
+ </div>
257
+
258
+ <div
259
+ id={navDrawerId}
260
+ ref={drawerRef}
261
+ inert={!isDrawerOpen}
262
+ className={cn(
263
+ `w-full bg-accent grid transition-[grid-template-rows] duration-200 border-b
264
+ border-neutral-mid`,
265
+ isDrawerOpen ? 'grid-rows-[1fr]' : 'grid-rows-[0fr]',
266
+ )}
267
+ >
268
+ <WidthContainer className="bg-accent min-h-0 overflow-hidden">
269
+ <div
270
+ className="w-full min-h-14 flex p-gds-2 justify-between items-center gap-gds-4
271
+ @container/drawer"
272
+ >
273
+ <nav aria-label="More navigation">
274
+ <ul className="flex flex-wrap w-full gap-x-gds-2 gap-y-gds-2">
275
+ {DSP_NAV_LINKS.map((item) => (
276
+ <li className={cn('flex items-center nav-item', item.drawerNav)} key={item.href}>
277
+ <Link href={item.href} appearance="inverse">
278
+ {item.label}
279
+ </Link>
280
+ </li>
281
+ ))}
282
+ </ul>
283
+ </nav>
284
+
285
+ <ButtonLink
286
+ aria-label="Close"
287
+ appearance="inverse"
288
+ variant="icon"
289
+ onClick={() => setIsDrawerOpen(false)}
290
+ >
291
+ <LuX aria-hidden />
292
+ </ButtonLink>
293
+ </div>
294
+ </WidthContainer>
295
+ </div>
296
+
297
+ {appContent ? (
298
+ <WidthContainer className="bg-body-secondary">
299
+ <div className="w-full h-14 flex p-gds-2 items-center">{appContent}</div>
300
+ </WidthContainer>
301
+ ) : null}
302
+ </header>
303
+ );
304
+ };
@@ -0,0 +1,120 @@
1
+ import type { ComponentType } from 'react';
2
+
3
+ import { LuEllipsis } from 'react-icons/lu';
4
+
5
+ import {
6
+ ButtonLink,
7
+ DropdownMenu,
8
+ DropdownMenuContent,
9
+ DropdownMenuItem,
10
+ DropdownMenuTrigger,
11
+ Link,
12
+ } from '@tpzdsp/next-toolkit/components';
13
+ import type { LinkProps } from '@tpzdsp/next-toolkit/components';
14
+
15
+ import type { NavLink } from '../../types';
16
+
17
+ export type HeaderAppContentProps = {
18
+ /** App name, shown on the left. Plain text, or a NavLink if it should link
19
+ * somewhere (e.g. back to the app's home page). */
20
+ title: string | NavLink;
21
+ links?: NavLink[];
22
+ /** Defaults to this library's own Link (a plain <a>). Pass your app's own Link
23
+ * wrapper instead if it needs Next.js client-side routing, e.g. one that uses
24
+ * asChild internally with next/link, it just needs to accept the same props. */
25
+ linkComponent?: ComponentType<LinkProps>;
26
+ };
27
+
28
+ // Omit<LinkProps, ...> (not a fixed prop list): when this sits inside
29
+ // DropdownMenuItem asChild, Radix clones this component and merges its own
30
+ // props onto it (role="menuitem", tabIndex, the keyboard/selection
31
+ // handlers roving-tabindex needs, className). Without a rest spread here to
32
+ // forward all of that through to LinkComponent, Radix's merge dead-ends at
33
+ // this component and every one of those props is silently dropped, not
34
+ // just a styling gap, menuitem role and keyboard handling would be missing
35
+ // too.
36
+ type HeaderAppContentNavLinkProps = Omit<LinkProps, 'href' | 'children'> & {
37
+ link: NavLink;
38
+ linkComponent: ComponentType<LinkProps>;
39
+ };
40
+
41
+ const HeaderAppContentNavLink = ({
42
+ link,
43
+ linkComponent: LinkComponent,
44
+ appearance = 'inverse',
45
+ ...props
46
+ }: HeaderAppContentNavLinkProps) => (
47
+ <LinkComponent
48
+ href={link.url}
49
+ appearance={appearance}
50
+ target={link.openInNewTab ? '_blank' : undefined}
51
+ rel={link.openInNewTab ? 'noopener noreferrer' : undefined}
52
+ {...props}
53
+ >
54
+ {link.label}
55
+ </LinkComponent>
56
+ );
57
+
58
+ export const HeaderAppContent = ({
59
+ title,
60
+ links = [],
61
+ linkComponent: LinkComponent = Link,
62
+ }: HeaderAppContentProps) => (
63
+ <div className="@container/app-nav flex w-full items-center justify-between gap-gds-4">
64
+ <div className="flex shrink-0 items-center gap-gds-2 text-lg font-bold">
65
+ {typeof title === 'string' ? (
66
+ title
67
+ ) : (
68
+ <HeaderAppContentNavLink link={title} linkComponent={LinkComponent} />
69
+ )}
70
+ </div>
71
+
72
+ {links.length > 0 ? (
73
+ <>
74
+ {/* 650px: below this the inline list and the title no longer
75
+ comfortably fit side by side. A single width rather than
76
+ per-link breakpoints (contrast Header.tsx's own DSP_NAV_LINKS,
77
+ which hides one specific, known link at a time): links here are
78
+ an arbitrary, app-supplied list, there's no fixed set to
79
+ hand-tune individual cutoffs for, so this collapses the whole
80
+ list to a menu at once instead. A reasonable default, not a
81
+ computed value, nudge it if a specific app's title/link lengths
82
+ need something else. */}
83
+ <nav aria-label="App" className="hidden min-w-0 @min-[650px]/app-nav:block">
84
+ <ul className="flex items-center gap-gds-4">
85
+ {links.map((link) => (
86
+ <li key={link.url}>
87
+ <HeaderAppContentNavLink link={link} linkComponent={LinkComponent} />
88
+ </li>
89
+ ))}
90
+ </ul>
91
+ </nav>
92
+
93
+ <DropdownMenu>
94
+ <DropdownMenuTrigger asChild>
95
+ <ButtonLink
96
+ appearance="inverse"
97
+ variant="icon"
98
+ aria-label="App navigation"
99
+ className="@min-[650px]/app-nav:hidden"
100
+ >
101
+ <LuEllipsis aria-hidden />
102
+ </ButtonLink>
103
+ </DropdownMenuTrigger>
104
+
105
+ <DropdownMenuContent align="end">
106
+ {links.map((link) => (
107
+ <DropdownMenuItem key={link.url} asChild>
108
+ <HeaderAppContentNavLink
109
+ link={link}
110
+ linkComponent={LinkComponent}
111
+ appearance="contrast"
112
+ />
113
+ </DropdownMenuItem>
114
+ ))}
115
+ </DropdownMenuContent>
116
+ </DropdownMenu>
117
+ </>
118
+ ) : null}
119
+ </div>
120
+ );
@@ -0,0 +1,40 @@
1
+ @layer components {
2
+ /* MARK: Heading */
3
+ .cn-heading {
4
+ @apply font-bold;
5
+ }
6
+
7
+ .cn-heading-1 {
8
+ @apply text-[2rem] sm:text-5xl;
9
+ }
10
+
11
+ .cn-heading-2 {
12
+ @apply text-2xl sm:text-4xl;
13
+ }
14
+
15
+ .cn-heading-3 {
16
+ @apply text-xl sm:text-3xl;
17
+ }
18
+
19
+ .cn-heading-4 {
20
+ @apply text-lg sm:text-2xl;
21
+ }
22
+
23
+ .cn-heading-5 {
24
+ @apply text-base sm:text-xl;
25
+ }
26
+
27
+ .cn-heading-6 {
28
+ @apply text-sm sm:text-lg;
29
+ }
30
+
31
+ /* MARK: Skeleton
32
+ Sized in em so it scales with whichever cn-heading-N font-size applies,
33
+ one rule covers every level. Shorter than the line-height (~1.2-1.5x
34
+ font-size for every text-* utility here) so it sits inside the line box
35
+ rather than stretching it, the heading ends up exactly as tall as it
36
+ would be with real text. */
37
+ .cn-heading-skeleton-bar {
38
+ @apply h-[0.7em] w-3/4;
39
+ }
40
+ }
@@ -2,16 +2,26 @@ import type { Meta, StoryObj } from '@storybook/react-vite';
2
2
 
3
3
  import { Heading, type HeadingProps } from './Heading';
4
4
 
5
- export default {
6
- children: 'Heading',
5
+ const meta: Meta<typeof Heading> = {
6
+ title: 'Components/Heading/Heading',
7
7
  component: Heading,
8
- } as Meta;
8
+ tags: ['autodocs'],
9
+ parameters: {
10
+ docs: {
11
+ description: {
12
+ component: 'Responsive heading text.',
13
+ },
14
+ },
15
+ },
16
+ };
17
+
18
+ export default meta;
9
19
 
10
20
  export const AllHeadings: StoryObj<typeof Heading> = {
11
21
  render: () => (
12
22
  <div>
13
- {(['h1', 'h2', 'h3', 'h4', 'h5', 'h6'] as HeadingProps['type'][]).map((type) => (
14
- <Heading key={type} type={type}>
23
+ {(['h1', 'h2', 'h3', 'h4', 'h5', 'h6'] as HeadingProps['level'][]).map((type) => (
24
+ <Heading key={type} level={type}>
15
25
  {type.toUpperCase()} Example
16
26
  </Heading>
17
27
  ))}
@@ -1,50 +1,27 @@
1
- import type { ExtendProps } from '../../types';
1
+ import type { ComponentProps } from 'react';
2
+
2
3
  import { cn } from '../../utils';
3
4
 
4
- type Props = {
5
- type: 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6';
5
+ // h1 through h6 have identical props
6
+ export type HeadingProps = ComponentProps<'h1'> & {
7
+ level: 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6';
6
8
  };
7
9
 
8
- // h1 through h6 have identical props
9
- export type HeadingProps = ExtendProps<'h1', Props>;
10
+ const HEADING_LEVELS = {
11
+ h1: 'cn-heading-1',
12
+ h2: 'cn-heading-2',
13
+ h3: 'cn-heading-3',
14
+ h4: 'cn-heading-4',
15
+ h5: 'cn-heading-5',
16
+ h6: 'cn-heading-6',
17
+ } as const;
18
+
19
+ export const Heading = ({ level, className, children, ...props }: HeadingProps) => {
20
+ const Comp = level;
10
21
 
11
- export const Heading = ({ type, className, children, ...props }: HeadingProps) => {
12
- switch (type) {
13
- case 'h1':
14
- return (
15
- <h1 className={cn('py-4 text-4xl font-bold text-text-primary', className)} {...props}>
16
- {children}
17
- </h1>
18
- );
19
- case 'h2':
20
- return (
21
- <h2 className={cn('py-3 text-3xl font-bold text-text-primary', className)} {...props}>
22
- {children}
23
- </h2>
24
- );
25
- case 'h3':
26
- return (
27
- <h3 className={cn('py-3 text-xl font-bold text-text-primary', className)} {...props}>
28
- {children}
29
- </h3>
30
- );
31
- case 'h4':
32
- return (
33
- <h4 className={cn('py-3 text-lg font-bold text-text-primary', className)} {...props}>
34
- {children}
35
- </h4>
36
- );
37
- case 'h5':
38
- return (
39
- <h5 className={cn('py-2 text-base font-bold text-text-primary', className)} {...props}>
40
- {children}
41
- </h5>
42
- );
43
- case 'h6':
44
- return (
45
- <h6 className={cn('py-2 text-sm font-bold text-text-primary', className)} {...props}>
46
- {children}
47
- </h6>
48
- );
49
- }
22
+ return (
23
+ <Comp className={cn('cn-heading', HEADING_LEVELS[level], className)} {...props}>
24
+ {children}
25
+ </Comp>
26
+ );
50
27
  };
@@ -0,0 +1,30 @@
1
+ import type { Meta, StoryObj } from '@storybook/react-vite';
2
+
3
+ import type { HeadingProps } from './Heading';
4
+ import { HeadingSkeleton } from './HeadingSkeleton';
5
+
6
+ const meta: Meta<typeof HeadingSkeleton> = {
7
+ title: 'Components/Heading/Skeleton',
8
+ component: HeadingSkeleton,
9
+ tags: ['autodocs'],
10
+ parameters: {
11
+ docs: {
12
+ description: {
13
+ component:
14
+ 'Placeholder for a Heading while its real text is loading. Renders a real Heading at the given level, so the font-size and line-height (and therefore the rendered height) always match what real text at that level would produce, no layout shift when it swaps in.',
15
+ },
16
+ },
17
+ },
18
+ };
19
+
20
+ export default meta;
21
+
22
+ export const AllLevels: StoryObj<typeof HeadingSkeleton> = {
23
+ render: () => (
24
+ <div className="flex flex-col gap-gds-2">
25
+ {(['h1', 'h2', 'h3', 'h4', 'h5', 'h6'] as HeadingProps['level'][]).map((level) => (
26
+ <HeadingSkeleton key={level} level={level} />
27
+ ))}
28
+ </div>
29
+ ),
30
+ };
@@ -0,0 +1,14 @@
1
+ import type { ComponentProps } from 'react';
2
+
3
+ import { Heading } from './Heading';
4
+ import { Skeleton } from '../Skeleton/Skeleton';
5
+
6
+ export type HeadingSkeletonProps = Omit<ComponentProps<typeof Heading>, 'children'> & {
7
+ children?: never;
8
+ };
9
+
10
+ export const HeadingSkeleton = ({ className, ...props }: HeadingSkeletonProps) => (
11
+ <Heading aria-hidden className={className} {...props}>
12
+ <Skeleton className="cn-heading-skeleton-bar" />
13
+ </Heading>
14
+ );
@@ -0,0 +1,19 @@
1
+ @layer components {
2
+ /* Full-bleed breakout: Hero is meant to span the viewport regardless of
3
+ where it's mounted, but it's built on WidthContainer, so if it's ever
4
+ nested inside another WidthContainer/MainWrapper (e.g. rendered as page
5
+ content under a shared layout's <main>), it would otherwise inherit that
6
+ ancestor's max-w-page cap. left: 50% shifts it to the viewport's
7
+ horizontal center regardless of the containing block's width, as long as
8
+ that containing block is itself symmetrically centered, true here since
9
+ every ancestor up to the viewport is either full-width or mx-auto; width:
10
+ 100vw + the negative margins then pull its edges out to the true viewport
11
+ edges. Pair with overflow-x-clip on PageShell (or another page-level
12
+ ancestor), 100vw includes the scrollbar gutter in browsers that reserve
13
+ space for it, which can otherwise introduce a few pixels of unwanted
14
+ horizontal scroll. */
15
+ .cn-hero {
16
+ @apply bg-accent text-on-accent py-gds-4 sm:py-gds-6;
17
+ position: relative;
18
+ }
19
+ }
@@ -0,0 +1,41 @@
1
+ import type { Meta, StoryObj } from '@storybook/react-vite';
2
+
3
+ import { Hero } from './Hero';
4
+ import { Heading } from '../Heading/Heading';
5
+ import { ButtonGroup } from '../Layout/ButtonGroup/ButtonGroup';
6
+ import { HeadingGroup } from '../Layout/HeadingGroup/HeadingGroup';
7
+ import { Paragraph } from '../Paragraph/Paragraph';
8
+ import { StartButton } from '../StartButton/StartButton';
9
+
10
+ const meta: Meta<typeof Hero> = {
11
+ title: 'Components/Hero',
12
+ component: Hero,
13
+ tags: ['autodocs'],
14
+ parameters: {
15
+ docs: {
16
+ description: {
17
+ component: 'Use a Hero to associate text with form controls and improve accessibility.',
18
+ },
19
+ },
20
+ },
21
+ };
22
+
23
+ export default meta;
24
+
25
+ type Story = StoryObj<typeof Hero>;
26
+
27
+ export const Default: Story = {
28
+ render: () => (
29
+ <Hero>
30
+ <ButtonGroup orientation="vertical">
31
+ <HeadingGroup>
32
+ <Heading level="h1">UK Wetland Inventory</Heading>
33
+
34
+ <Paragraph>Explore the UK&apos;s vital wetland habits</Paragraph>
35
+ </HeadingGroup>
36
+
37
+ <StartButton appearance="secondary" href="#" />
38
+ </ButtonGroup>
39
+ </Hero>
40
+ ),
41
+ };