@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,88 @@
1
+ import type { Meta, StoryObj } from '@storybook/react-vite';
2
+
3
+ import { SearchBox } from './SearchBox';
4
+ import { ErrorText } from '../ErrorText/ErrorText';
5
+ import { FormGroup } from '../Form/FormGroup';
6
+ import { HintText } from '../HintText/HintText';
7
+ import { Label } from '../Label/Label';
8
+
9
+ const meta: Meta<typeof SearchBox> = {
10
+ title: 'Components/SearchBox',
11
+ component: SearchBox,
12
+ tags: ['autodocs'],
13
+ parameters: {
14
+ docs: {
15
+ description: {
16
+ component:
17
+ 'A search input with a primary submit button. Wrap in a `<form role="search">` to wire up submission. The button is `type="submit"` so it works with standard form behaviour. Accepts all `Input` props except `type`.',
18
+ },
19
+ },
20
+ },
21
+ };
22
+
23
+ export default meta;
24
+
25
+ type Story = StoryObj<typeof SearchBox>;
26
+
27
+ export const Default: Story = {
28
+ render: (args) => (
29
+ <form role="search" onSubmit={(event) => event.preventDefault()}>
30
+ <SearchBox placeholder="Search" {...args} />
31
+ </form>
32
+ ),
33
+ };
34
+
35
+ export const WithLabel: Story = {
36
+ render: (args) => (
37
+ <form role="search" onSubmit={(event) => event.preventDefault()}>
38
+ <div className="flex flex-col gap-gds-1">
39
+ <Label htmlFor="site-search">Search this site</Label>
40
+
41
+ <HintText id="site-search-hint">Enter a keyword or phrase.</HintText>
42
+
43
+ <SearchBox
44
+ id="site-search"
45
+ placeholder="Search"
46
+ aria-describedby="site-search-hint"
47
+ {...args}
48
+ />
49
+ </div>
50
+ </form>
51
+ ),
52
+ };
53
+
54
+ export const Invalid: Story = {
55
+ render: (args) => (
56
+ <form role="search" onSubmit={(event) => event.preventDefault()}>
57
+ <FormGroup invalid>
58
+ <Label htmlFor="search-invalid">Search this site</Label>
59
+
60
+ <ErrorText id="search-invalid-error">Enter a search term</ErrorText>
61
+
62
+ <SearchBox
63
+ id="search-invalid"
64
+ placeholder="Search"
65
+ aria-invalid
66
+ aria-describedby="search-invalid-error"
67
+ {...args}
68
+ />
69
+ </FormGroup>
70
+ </form>
71
+ ),
72
+ };
73
+
74
+ export const Disabled: Story = {
75
+ render: (args) => (
76
+ <form role="search">
77
+ <SearchBox placeholder="Search" disabled {...args} />
78
+ </form>
79
+ ),
80
+ };
81
+
82
+ export const CustomLabel: Story = {
83
+ render: (args) => (
84
+ <form role="search" onSubmit={(event) => event.preventDefault()}>
85
+ <SearchBox placeholder="Enter location" buttonLabel="Find" {...args} />
86
+ </form>
87
+ ),
88
+ };
@@ -0,0 +1,36 @@
1
+ 'use client';
2
+
3
+ import { useId, type ComponentProps } from 'react';
4
+
5
+ import { LuSearch } from 'react-icons/lu';
6
+
7
+ import { Button } from '../Button/Button';
8
+ import { Input } from '../Input/Input';
9
+ import { InputGroup, InputSuffix } from '../InputGroup/InputGroup';
10
+
11
+ export type SearchBoxProps = Omit<ComponentProps<typeof Input>, 'type'> & {
12
+ buttonLabel?: string;
13
+ };
14
+
15
+ export const SearchBox = ({ id, buttonLabel = 'Search', disabled, ...props }: SearchBoxProps) => {
16
+ const generatedId = useId();
17
+ const inputId = id ?? generatedId;
18
+
19
+ return (
20
+ <InputGroup aria-disabled={disabled}>
21
+ <Input id={inputId} type="search" disabled={disabled} {...props} />
22
+
23
+ <InputSuffix>
24
+ <Button
25
+ type="submit"
26
+ appearance="primary"
27
+ variant="icon"
28
+ aria-label={buttonLabel}
29
+ disabled={disabled}
30
+ >
31
+ <LuSearch aria-hidden />
32
+ </Button>
33
+ </InputSuffix>
34
+ </InputGroup>
35
+ );
36
+ };
@@ -0,0 +1,84 @@
1
+ import { useCallback, useRef } from 'react';
2
+
3
+ import type { OptionsOrGroups } from 'react-select';
4
+
5
+ import type { Meta, StoryObj } from '@storybook/react-vite';
6
+
7
+ import { AsyncSelect } from './AsyncSelect';
8
+ import { Label } from '../Label/Label';
9
+
10
+ const meta: Meta<typeof AsyncSelect> = {
11
+ title: 'Components/Select/AsyncSelect',
12
+ component: AsyncSelect,
13
+ tags: ['autodocs'],
14
+ parameters: {
15
+ docs: {
16
+ description: {
17
+ component:
18
+ "Select with remote, `loadOptions`-driven options instead of a fixed local list, for search-as-you-type against an API. Composes react-select's own `useAsync` and `useStateManager` directly onto this project's Select, so it shares the exact same styling and indicator overrides (including the loading spinner). `loadOptions` isn't debounced by react-select itself, it fires on every keystroke, wrap it in your own debounce as shown here.",
19
+ },
20
+ },
21
+ },
22
+ };
23
+
24
+ export default meta;
25
+
26
+ type Story = StoryObj<typeof AsyncSelect>;
27
+
28
+ type Country = { id: string; label: string };
29
+
30
+ const COUNTRIES: Country[] = [
31
+ { id: 'eng', label: 'England' },
32
+ { id: 'sco', label: 'Scotland' },
33
+ { id: 'wal', label: 'Wales' },
34
+ { id: 'nir', label: 'Northern Ireland' },
35
+ ];
36
+
37
+ // Stands in for a real API call, filters the local list after a short delay
38
+ // so the loading indicator is visible.
39
+ const fakeSearch = (query: string): Promise<Country[]> =>
40
+ new Promise((resolve) => {
41
+ setTimeout(() => {
42
+ resolve(
43
+ COUNTRIES.filter((country) => country.label.toLowerCase().includes(query.toLowerCase())),
44
+ );
45
+ }, 600);
46
+ });
47
+
48
+ const DebouncedExample = () => {
49
+ const debounceRef = useRef<ReturnType<typeof setTimeout> | null>(null);
50
+
51
+ const loadOptions = useCallback(
52
+ (inputValue: string, callback: (options: OptionsOrGroups<Country, never>) => void) => {
53
+ if (debounceRef.current) {
54
+ clearTimeout(debounceRef.current);
55
+ }
56
+
57
+ debounceRef.current = setTimeout(async () => {
58
+ callback(await fakeSearch(inputValue));
59
+ }, 300);
60
+ },
61
+ [],
62
+ );
63
+
64
+ return (
65
+ <div>
66
+ <Label htmlFor="async-country">Country</Label>
67
+
68
+ <AsyncSelect<Country>
69
+ inputId="async-country"
70
+ loadOptions={loadOptions}
71
+ getOptionLabel={(option) => option.label}
72
+ getOptionValue={(option) => option.id}
73
+ placeholder="Search for a country"
74
+ noOptionsMessage={({ inputValue }) =>
75
+ inputValue ? 'No countries found' : 'Start typing to search'
76
+ }
77
+ />
78
+ </div>
79
+ );
80
+ };
81
+
82
+ export const Default: Story = {
83
+ render: () => <DebouncedExample />,
84
+ };
@@ -0,0 +1,41 @@
1
+ 'use client';
2
+
3
+ import type { GroupBase } from 'react-select';
4
+ import { useStateManager } from 'react-select';
5
+ import { useAsync } from 'react-select/async';
6
+ import type { AsyncProps } from 'react-select/async';
7
+
8
+ import { Select } from './Select';
9
+ import type { SelectProps } from './Select';
10
+
11
+ export type AsyncSelectProps<
12
+ Option = unknown,
13
+ IsMulti extends boolean = false,
14
+ Group extends GroupBase<Option> = GroupBase<Option>,
15
+ > = Omit<SelectProps<Option, IsMulti, Group>, keyof AsyncProps<Option, IsMulti, Group>> &
16
+ AsyncProps<Option, IsMulti, Group>;
17
+
18
+ /**
19
+ * Select with remote, `loadOptions`-driven options instead of a fixed local
20
+ * list. Composes react-select's own `useAsync` (manages the loading state
21
+ * and current options) and `useStateManager` (controlled/uncontrolled
22
+ * value/inputValue bridging) directly onto our own styled Select, the same
23
+ * way react-select's own AsyncSelect composes them onto its unstyled one, so
24
+ * this gets identical behaviour with our styling and indicator overrides.
25
+ *
26
+ * `loadOptions` is not debounced by react-select itself, it fires on every
27
+ * keystroke, wrap it in your own debounce (e.g. a timeout cleared on each
28
+ * call) if that's not the desired behaviour.
29
+ */
30
+ export const AsyncSelect = <
31
+ Option = unknown,
32
+ IsMulti extends boolean = false,
33
+ Group extends GroupBase<Option> = GroupBase<Option>,
34
+ >(
35
+ props: AsyncSelectProps<Option, IsMulti, Group>,
36
+ ) => {
37
+ const asyncProps = useAsync(props);
38
+ const statefulProps = useStateManager(asyncProps);
39
+
40
+ return <Select {...statefulProps} />;
41
+ };
@@ -0,0 +1,202 @@
1
+ @layer components {
2
+ /* MARK: Select
3
+ Styled to match the GDS text input: same height, border, padding, and
4
+ focus ring. The dropdown menu uses panel (white bg, form-weight border)
5
+ with no border-radius, matching GDS panel conventions. */
6
+
7
+ /* MARK: Container
8
+ w-full mirrors .cn-input: harmless in normal block flow (already full
9
+ width there), but needed as a flex item (e.g. the main field in an
10
+ InputGroup row alongside InputPrefix/InputSuffix), where it would
11
+ otherwise shrink to the width of its content instead of filling the
12
+ remaining row space. InputGroup.css overrides this back to w-auto when
13
+ a Select is used as a narrow addon nested inside a prefix/suffix. */
14
+ .cn-select-container {
15
+ @apply relative w-full;
16
+ }
17
+
18
+ /* MARK: Control
19
+ Mirrors .cn-input: 40px height, 2px border, 5px horizontal padding. */
20
+ .cn-select-control {
21
+ @apply cn-form-border h-10 px-gds-1 bg-white flex items-center cursor-default text-base
22
+ box-border;
23
+ }
24
+
25
+ .cn-select-control-focused {
26
+ @apply outline-focus outline-offset-0;
27
+ box-shadow: inset 0 0 0 var(--border-width-form) var(--color-divider-input);
28
+ }
29
+
30
+ .cn-select-control-invalid {
31
+ @apply border-error;
32
+ }
33
+
34
+ .cn-select-control-disabled {
35
+ @apply opacity-50 cursor-not-allowed;
36
+ }
37
+
38
+ /* MARK: Value area */
39
+
40
+ .cn-select-value-container {
41
+ @apply flex flex-1 items-center flex-wrap h-full overflow-hidden;
42
+ }
43
+
44
+ .cn-select-value-container-multi {
45
+ /* The visible gap between chips equals the gap property value: the 3px white
46
+ borders on each side of each chip are part of the perceived separation, not
47
+ subtracted from it (border-to-border = gap - 6, but visible = gap - 6 + 3 + 3 = gap).
48
+ Edge gap = px-gds-1 (5px) + chip border (3px) = 8px, so gap-2 (8px) matches. */
49
+ @apply gap-2;
50
+
51
+ &:has(.cn-select-multi-value) {
52
+ /* Horizontal padding only, vertical padding reduces the centering area
53
+ from 40px to 34px and shifts chips off-centre. The chip's focus border
54
+ (3px) sits 5.5px from the top/bottom container edges, so no vertical
55
+ padding is needed to protect it from overflow: hidden. */
56
+ padding-right: var(--focus-ring-width);
57
+ padding-left: var(--focus-ring-width);
58
+ }
59
+ }
60
+
61
+ .cn-select-single-value {
62
+ @apply text-body truncate;
63
+ }
64
+
65
+ .cn-select-placeholder {
66
+ @apply text-body-secondary;
67
+ }
68
+
69
+ /* The hidden search input react-select renders inside the control */
70
+ .cn-select-input {
71
+ @apply text-base text-body;
72
+ }
73
+
74
+ /* MARK: Indicators */
75
+
76
+ .cn-select-indicators {
77
+ @apply flex items-center gap-1 flex-none;
78
+ }
79
+
80
+ .cn-select-dropdown-indicator {
81
+ @apply w-5 h-5 flex items-center justify-center text-body;
82
+ }
83
+
84
+ .cn-select-dropdown-indicator-open {
85
+ @apply rotate-180;
86
+ }
87
+
88
+ .cn-select-clear-indicator {
89
+ @apply w-5 h-5 flex items-center justify-center cursor-pointer text-body-secondary
90
+ hover:text-body;
91
+ }
92
+
93
+ .cn-select-loading-indicator {
94
+ @apply w-5 h-5 flex items-center justify-center text-body-secondary;
95
+ }
96
+
97
+ /* MARK: Menu */
98
+
99
+ .cn-select-menu {
100
+ @apply panel absolute w-full mt-1 overflow-hidden cn-z-overlay;
101
+ }
102
+
103
+ /* react-select flips the menu above the control when there isn't room
104
+ below. mt-1 pushes it further down rather than opening a gap in that
105
+ direction, mirror it as mb-1 so there's still a visible gap between
106
+ control and menu regardless of which side it opens on. */
107
+ .cn-select-menu-top {
108
+ @apply mt-0 mb-1;
109
+ }
110
+
111
+ .cn-select-menu-list {
112
+ @apply flex flex-col overflow-y-auto max-h-60;
113
+ }
114
+
115
+ /* MARK: Options */
116
+
117
+ .cn-select-option {
118
+ @apply px-gds-1 py-1 text-base text-body cursor-pointer;
119
+ }
120
+
121
+ .cn-select-option-focused {
122
+ @apply bg-wash;
123
+ }
124
+
125
+ .cn-select-option-selected {
126
+ @apply bg-accent text-on-accent;
127
+ }
128
+
129
+ .cn-select-option-disabled {
130
+ @apply opacity-50 cursor-not-allowed;
131
+ }
132
+
133
+ .cn-select-no-options {
134
+ @apply px-gds-1 py-gds-1 text-base text-body select-none;
135
+ }
136
+
137
+ /* MARK: Groups */
138
+
139
+ .cn-select-group:first-child {
140
+ @apply pt-2;
141
+ }
142
+
143
+ /* MARK: Multi-value chips
144
+ The entire chip is a <button> that removes the value on click, giving a
145
+ larger, GDS-compliant touch target rather than a tiny X icon alone. */
146
+
147
+ .cn-select-multi-value {
148
+ /* The margin cancels the space the 3px border takes up in the flex layout so
149
+ chips look the same size as they would without a border. */
150
+ @apply cn-chip-size-sm cn-chip-appearance-neutral flex items-center gap-1 cursor-pointer
151
+ border-solid border-panel outline-none;
152
+ border-width: var(--focus-ring-width);
153
+ margin: 0 calc(var(--focus-ring-width) * -1) 0 calc(var(--focus-ring-width) * -1);
154
+
155
+ &:focus {
156
+ @apply border-focus;
157
+ }
158
+ }
159
+
160
+ .cn-select-multi-value-remove {
161
+ @apply w-3.5 h-3.5 flex-none;
162
+ }
163
+
164
+ /* MARK: Tags below
165
+ Used when `tagsPlacement="below"`: selected values render in a row under
166
+ the control instead of as inline chips, so the control keeps a fixed
167
+ 40px height regardless of how many values are selected. */
168
+
169
+ .cn-select-tags {
170
+ @apply flex flex-wrap gap-2 mt-2;
171
+ }
172
+
173
+ .cn-select-tag {
174
+ /* Same margin-cancels-border trick as .cn-select-multi-value, so the gap
175
+ between tags matches the gap between inline chips exactly. */
176
+ @apply cn-chip-size-sm cn-chip-appearance-neutral flex items-center gap-1 cursor-pointer
177
+ border-solid border-panel outline-none;
178
+ border-width: var(--focus-ring-width);
179
+ margin: 0 calc(var(--focus-ring-width) * -1) 0 calc(var(--focus-ring-width) * -1);
180
+
181
+ &:focus {
182
+ @apply border-focus;
183
+ }
184
+
185
+ &:disabled {
186
+ @apply opacity-50 cursor-not-allowed;
187
+ }
188
+ }
189
+
190
+ /* MARK: Skeleton
191
+ SelectSkeleton reuses cn-select-container/control/value-container/
192
+ indicators directly, so its dimensions (40px height, border, padding,
193
+ the flex-1 vs flex-none split) always match the real control, these
194
+ two are just the decorative placeholder shapes inside it. */
195
+ .cn-select-skeleton-value {
196
+ @apply h-4 w-24;
197
+ }
198
+
199
+ .cn-select-skeleton-indicator {
200
+ @apply size-4;
201
+ }
202
+ }
@@ -0,0 +1,162 @@
1
+ import type { Meta, StoryObj } from '@storybook/react-vite';
2
+
3
+ import { Select } from './Select';
4
+ import { ErrorText } from '../ErrorText/ErrorText';
5
+ import { FormGroup } from '../Form/FormGroup';
6
+ import { Label } from '../Label/Label';
7
+
8
+ const meta: Meta<typeof Select> = {
9
+ title: 'Components/Select/Select',
10
+ component: Select,
11
+ tags: ['autodocs'],
12
+ parameters: {
13
+ docs: {
14
+ description: {
15
+ component:
16
+ 'Searchable select built on react-select. Styled to match the GDS text input, same height, border, and focus ring. The dropdown uses the standard GDS panel (white background, black border, no border-radius). Supports single and multi-select, option groups, async loading, and creatable options via react-select props.',
17
+ },
18
+ },
19
+ },
20
+ };
21
+
22
+ export default meta;
23
+
24
+ type Story = StoryObj<typeof Select>;
25
+
26
+ const SELECT_A_COUNTRY = 'Select a country';
27
+
28
+ const COUNTRIES = [
29
+ { value: 'eng', label: 'England' },
30
+ { value: 'sco', label: 'Scotland' },
31
+ { value: 'wal', label: 'Wales' },
32
+ { value: 'nir', label: 'Northern Ireland' },
33
+ ];
34
+
35
+ const SPECIES = [
36
+ {
37
+ label: 'Birds',
38
+ options: [
39
+ { value: 'lapwing', label: 'Lapwing' },
40
+ { value: 'curlew', label: 'Curlew' },
41
+ { value: 'redshank', label: 'Redshank' },
42
+ ],
43
+ },
44
+ {
45
+ label: 'Mammals',
46
+ options: [
47
+ { value: 'otter', label: 'Otter' },
48
+ { value: 'water-vole', label: 'Water vole' },
49
+ { value: 'hedgehog', label: 'Hedgehog' },
50
+ ],
51
+ },
52
+ {
53
+ label: 'Plants',
54
+ options: [
55
+ { value: 'bluebell', label: 'Bluebell' },
56
+ { value: 'meadow-buttercup', label: 'Meadow buttercup' },
57
+ ],
58
+ },
59
+ ];
60
+
61
+ export const Default: Story = {
62
+ args: {
63
+ options: COUNTRIES,
64
+ placeholder: SELECT_A_COUNTRY,
65
+ },
66
+ };
67
+
68
+ export const Clearable: Story = {
69
+ args: {
70
+ options: COUNTRIES,
71
+ placeholder: SELECT_A_COUNTRY,
72
+ isClearable: true,
73
+ defaultValue: COUNTRIES[0],
74
+ },
75
+ };
76
+
77
+ export const MultiSelect: Story = {
78
+ args: {
79
+ options: COUNTRIES,
80
+ placeholder: 'Select countries',
81
+ isMulti: true,
82
+ isClearable: true,
83
+ defaultValue: [COUNTRIES[0], COUNTRIES[2]],
84
+ },
85
+ };
86
+
87
+ export const MultiSelectTagsBelow: Story = {
88
+ parameters: {
89
+ docs: {
90
+ description: {
91
+ story:
92
+ 'Set `tagsPlacement="below"` to list selected values under the control instead of as inline chips. The control keeps a fixed height regardless of how many values are selected.',
93
+ },
94
+ },
95
+ },
96
+ args: {
97
+ options: COUNTRIES,
98
+ placeholder: 'Select countries',
99
+ isMulti: true,
100
+ isClearable: true,
101
+ tagsPlacement: 'below',
102
+ defaultValue: [COUNTRIES[0], COUNTRIES[2]],
103
+ },
104
+ };
105
+
106
+ export const WithGroups: Story = {
107
+ args: {
108
+ options: SPECIES,
109
+ placeholder: 'Select a species',
110
+ isClearable: true,
111
+ },
112
+ };
113
+
114
+ export const Disabled: Story = {
115
+ args: {
116
+ options: COUNTRIES,
117
+ placeholder: SELECT_A_COUNTRY,
118
+ isDisabled: true,
119
+ defaultValue: COUNTRIES[1],
120
+ },
121
+ };
122
+
123
+ export const Invalid: Story = {
124
+ parameters: {
125
+ docs: {
126
+ description: {
127
+ story: 'Pass `invalid` to show the error border. Clears when the control receives focus.',
128
+ },
129
+ },
130
+ },
131
+ render: () => (
132
+ <FormGroup invalid>
133
+ <Label htmlFor="select-invalid">Country</Label>
134
+
135
+ <ErrorText id="select-invalid-error">Select a country</ErrorText>
136
+
137
+ <Select
138
+ inputId="select-invalid"
139
+ aria-describedby="select-invalid-error"
140
+ options={COUNTRIES}
141
+ placeholder={SELECT_A_COUNTRY}
142
+ invalid
143
+ />
144
+ </FormGroup>
145
+ ),
146
+ };
147
+
148
+ export const NonSearchable: Story = {
149
+ parameters: {
150
+ docs: {
151
+ description: {
152
+ story:
153
+ 'Set `isSearchable={false}` for short lists where filtering adds no value. The cursor becomes a pointer to reinforce non-editable behaviour.',
154
+ },
155
+ },
156
+ },
157
+ args: {
158
+ options: COUNTRIES,
159
+ placeholder: 'Select a country',
160
+ isSearchable: false,
161
+ },
162
+ };
@@ -0,0 +1,36 @@
1
+ import { Select } from './Select';
2
+ import { render, screen } from '../../test/renderers';
3
+
4
+ const COUNTRIES = [
5
+ { value: 'eng', label: 'England' },
6
+ { value: 'sco', label: 'Scotland' },
7
+ ];
8
+
9
+ const ERROR_ID = 'country-error';
10
+
11
+ describe('Select', () => {
12
+ it('merges aria-describedby alongside react-select’s own value, rather than replacing it', () => {
13
+ render(
14
+ <Select
15
+ inputId="country"
16
+ options={COUNTRIES}
17
+ aria-describedby={ERROR_ID}
18
+ aria-label="Country"
19
+ />,
20
+ );
21
+
22
+ const describedBy = screen.getByRole('combobox').getAttribute('aria-describedby');
23
+
24
+ expect(describedBy).toContain(ERROR_ID);
25
+ // react-select's own placeholder/live-region id is still present, not replaced.
26
+ expect(describedBy?.split(' ').length).toBeGreaterThan(1);
27
+ });
28
+
29
+ it('omits the extra id when aria-describedby is not provided', () => {
30
+ render(<Select inputId="country" options={COUNTRIES} aria-label="Country" />);
31
+
32
+ const describedBy = screen.getByRole('combobox').getAttribute('aria-describedby');
33
+
34
+ expect(describedBy).not.toContain(ERROR_ID);
35
+ });
36
+ });