uikit-react-public 0.11.24 → 0.17.4

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 (301) hide show
  1. package/README.md +4 -2
  2. package/dist/components/Accordion/Accordion.Heading.d.ts +4 -4
  3. package/dist/components/Accordion/Accordion.Panel.d.ts +2 -2
  4. package/dist/components/Accordion/Accordion.d.ts +1 -1
  5. package/dist/components/Accordion/Accordion.stories.d.ts +57 -0
  6. package/dist/components/Accordion/index.d.ts +2 -0
  7. package/dist/components/Avatar/Avatar.stories.d.ts +107 -1
  8. package/dist/components/Badge/Badge.d.ts +6 -0
  9. package/dist/components/Badge/Badge.stories.d.ts +15 -0
  10. package/dist/components/Badge/index.d.ts +2 -0
  11. package/dist/components/Button/Button.d.ts +3 -1
  12. package/dist/components/Calendar/index.d.ts +1 -1
  13. package/dist/components/CookieNotice/CookieNotice.d.ts +16 -0
  14. package/dist/components/CookieNotice/index.d.ts +2 -0
  15. package/dist/components/Datepicker/Datepicker.d.ts +1 -1
  16. package/dist/components/Datepicker/Datepicker.stories.d.ts +4 -3
  17. package/dist/components/Datepicker/Datepicker.types.d.ts +4 -5
  18. package/dist/components/Datepicker/subcomponents/CustomDatepicker.d.ts +4 -1
  19. package/dist/components/Datepicker/subcomponents/DatepickerInput.d.ts +15 -2
  20. package/dist/components/Datepicker/subcomponents/Panel.d.ts +1 -1
  21. package/dist/components/Datepicker/subcomponents/VisibleField.d.ts +6 -1
  22. package/dist/components/Datepicker/subcomponents/index.d.ts +0 -1
  23. package/dist/components/Datepicker/utils/index.d.ts +0 -1
  24. package/dist/components/Dialog/BaseDialog.d.ts +8 -2
  25. package/dist/components/Dialog/Dialog.d.ts +2 -0
  26. package/dist/components/FileInput/FileInput.d.ts +8 -0
  27. package/dist/components/FileInput/FileInput.stories.d.ts +16 -0
  28. package/dist/components/FileInput/index.d.ts +2 -0
  29. package/dist/components/Header/Header.d.ts +7 -1
  30. package/dist/components/Header/Header.stories.d.ts +40 -0
  31. package/dist/components/Heading/Heading.d.ts +1 -1
  32. package/dist/components/Link/BaseLink.d.ts +10 -0
  33. package/dist/components/Link/Link.d.ts +5 -10
  34. package/dist/components/Link/Link.stories.d.ts +1 -1
  35. package/dist/components/Link/index.d.ts +1 -1
  36. package/dist/components/Main/Main.d.ts +21 -0
  37. package/dist/components/Main/Main.stories.d.ts +15 -0
  38. package/dist/components/Main/__tests__/Main.test.d.ts +1 -0
  39. package/dist/components/Main/index.d.ts +2 -0
  40. package/dist/components/Menu/MenuContent.d.ts +1 -1
  41. package/dist/components/Menu/MenuItem.d.ts +2 -0
  42. package/dist/components/Menu/MenuSection.d.ts +1 -1
  43. package/dist/components/NativeDatepicker/NativeDatepicker.d.ts +3 -0
  44. package/dist/components/NativeDatepicker/NativeDatepicker.stories.d.ts +36 -0
  45. package/dist/components/NativeDatepicker/NativeDatepicker.types.d.ts +10 -0
  46. package/dist/components/NativeDatepicker/index.d.ts +2 -0
  47. package/dist/components/{Datepicker → NativeDatepicker}/utils/dateToLocaleISOString/dateToLocaleISOString.d.ts +1 -1
  48. package/dist/components/NativeDatepicker/utils/dateToLocaleISOString/dateToLocaleISOString.test.d.ts +1 -0
  49. package/dist/components/NativeDatepicker/utils/index.d.ts +1 -0
  50. package/dist/components/Search/Search.d.ts +16 -0
  51. package/dist/components/Search/Search.stories.d.ts +34 -0
  52. package/dist/components/Search/__tests__/Search.test.d.ts +1 -0
  53. package/dist/components/Search/index.d.ts +2 -0
  54. package/dist/components/Select/Select.d.ts +1 -1
  55. package/dist/components/Select/Select.stories.d.ts +157 -9
  56. package/dist/components/Select/Select.types.d.ts +66 -32
  57. package/dist/components/Select/subcomponents/CustomOption.d.ts +1 -1
  58. package/dist/components/Select/subcomponents/CustomSelect.d.ts +3 -3
  59. package/dist/components/Select/subcomponents/FilterInput.d.ts +14 -0
  60. package/dist/components/Select/subcomponents/NativeSelect.d.ts +5 -1
  61. package/dist/components/Select/subcomponents/Panel.d.ts +1 -1
  62. package/dist/components/Select/subcomponents/VisibleField.d.ts +6 -4
  63. package/dist/components/Select/subcomponents/index.d.ts +1 -0
  64. package/dist/components/StandaloneLink/StandaloneLink.d.ts +12 -0
  65. package/dist/components/StandaloneLink/StandaloneLink.stories.d.ts +13 -0
  66. package/dist/components/StandaloneLink/__tests__/StandaloneLink.test.d.ts +1 -0
  67. package/dist/components/StandaloneLink/index.d.ts +2 -0
  68. package/dist/components/Table/Table.d.ts +10 -8
  69. package/dist/components/Table/Table.stories.d.ts +21 -0
  70. package/dist/components/Table/Table.types.d.ts +11 -0
  71. package/dist/components/Table/__tests__/Table.test.d.ts +1 -0
  72. package/dist/components/Table/index.d.ts +2 -1
  73. package/dist/components/Table/subcomponents/Body.d.ts +4 -0
  74. package/dist/components/Table/subcomponents/Cell/Cell.d.ts +12 -0
  75. package/dist/components/Table/subcomponents/Cell/Cell.stories.d.ts +313 -0
  76. package/dist/components/Table/subcomponents/Cell/CellContent.d.ts +10 -0
  77. package/dist/components/Table/subcomponents/Cell/__tests__/Cell.test.d.ts +1 -0
  78. package/dist/components/Table/subcomponents/Head.d.ts +4 -0
  79. package/dist/components/Table/subcomponents/HeadCell/HeadCell.d.ts +13 -0
  80. package/dist/components/Table/subcomponents/HeadCell/HeadCell.stories.d.ts +312 -0
  81. package/dist/components/Table/subcomponents/HeadCell/HeadCellContent.d.ts +10 -0
  82. package/dist/components/Table/subcomponents/HeadCell/__tests__/HeadCell.test.d.ts +1 -0
  83. package/dist/components/Table/subcomponents/Row.d.ts +5 -0
  84. package/dist/components/Table/subcomponents/SortIcon.d.ts +7 -0
  85. package/dist/components/Table/subcomponents/index.d.ts +10 -0
  86. package/dist/components/Tabs/Tab.d.ts +1 -1
  87. package/dist/components/Tabs/TabContext.d.ts +1 -0
  88. package/dist/components/Tabs/Tabs.d.ts +3 -1
  89. package/dist/components/Tabs/Tabs.stories.d.ts +3 -0
  90. package/dist/components/Timepicker/Timepicker.d.ts +10 -0
  91. package/dist/components/Timepicker/Timepicker.stories.d.ts +7 -0
  92. package/dist/components/Timepicker/__tests__/Timepicker.test.d.ts +1 -0
  93. package/dist/components/Timepicker/index.d.ts +2 -0
  94. package/dist/components/Timepicker/utils/convertDateToTimeString.d.ts +2 -0
  95. package/dist/components/Timepicker/utils/convertDateToTimeString.test.d.ts +1 -0
  96. package/dist/components/Timepicker/utils/index.d.ts +1 -0
  97. package/dist/components/WeekPicker/WeekPicker.d.ts +3 -0
  98. package/dist/components/WeekPicker/WeekPicker.stories.d.ts +41 -0
  99. package/dist/components/WeekPicker/WeekPicker.types.d.ts +16 -0
  100. package/dist/components/WeekPicker/index.d.ts +2 -0
  101. package/dist/components/WeekPicker/subcomponents/CustomDatepicker.d.ts +17 -0
  102. package/dist/components/WeekPicker/subcomponents/DatepickerInput.d.ts +13 -0
  103. package/dist/components/WeekPicker/subcomponents/VisibleField.d.ts +15 -0
  104. package/dist/components/WeekPicker/subcomponents/index.d.ts +3 -0
  105. package/dist/components/index.d.ts +19 -0
  106. package/dist/hooks/index.d.ts +2 -0
  107. package/dist/hooks/useFocusTrap.d.ts +10 -0
  108. package/dist/index.d.ts +2 -0
  109. package/dist/index.js +6460 -4607
  110. package/dist/theme/defaultTheme.d.ts +7 -0
  111. package/dist/theme/useTheme.d.ts +14 -0
  112. package/dist/utils/__tests__/announce.test.d.ts +1 -0
  113. package/dist/utils/__tests__/capitalise.test.d.ts +1 -0
  114. package/dist/utils/announce.d.ts +6 -0
  115. package/dist/utils/capitalise.d.ts +2 -0
  116. package/dist/utils/index.d.ts +1 -0
  117. package/lib/components/Accordion/Accordion.Heading.tsx +27 -8
  118. package/lib/components/Accordion/Accordion.Panel.tsx +11 -3
  119. package/lib/components/Accordion/Accordion.stories.tsx +139 -0
  120. package/lib/components/Accordion/Accordion.tsx +10 -8
  121. package/lib/components/Accordion/__tests__/__snapshots__/Accordion.test.tsx.snap +7 -7
  122. package/lib/components/Accordion/index.ts +2 -0
  123. package/lib/components/Alert/Alert.stories.tsx +1 -1
  124. package/lib/components/Alert/Alert.tsx +7 -1
  125. package/lib/components/Alert/__tests__/__snapshots__/Alert.test.tsx.snap +4 -0
  126. package/lib/components/Avatar/Avatar.mdx +117 -0
  127. package/lib/components/Avatar/Avatar.stories.tsx +110 -2
  128. package/lib/components/Badge/Badge.stories.tsx +19 -0
  129. package/lib/components/Badge/Badge.tsx +48 -0
  130. package/lib/components/Badge/index.ts +2 -0
  131. package/lib/components/Blanket/Blanket.stories.tsx +1 -1
  132. package/lib/components/Breadcrumbs/__tests__/__snapshots__/Breadcrumbs.test.tsx.snap +4 -4
  133. package/lib/components/Button/Button.stories.tsx +1 -1
  134. package/lib/components/Button/Button.tsx +6 -2
  135. package/lib/components/Calendar/Calendar.stories.tsx +12 -32
  136. package/lib/components/Calendar/__tests__/Calendar.test.tsx +23 -15
  137. package/lib/components/Calendar/index.ts +1 -5
  138. package/lib/components/Calendar/subcomponents/AcademicWeeks.tsx +2 -1
  139. package/lib/components/Calendar/subcomponents/ColumnHeading.tsx +5 -1
  140. package/lib/components/Calendar/subcomponents/EventDot.tsx +2 -1
  141. package/lib/components/Calendar/subcomponents/Grid.tsx +0 -1
  142. package/lib/components/Calendar/subcomponents/index.ts +1 -1
  143. package/lib/components/Calendar/utils/getDatesForCalendarGrid/getDatesForCalendarGrid.ts +43 -11
  144. package/lib/components/Calendar/utils/normaliseMonth/normaliseMonth.test.ts +5 -5
  145. package/lib/components/CookieNotice/CookieNotice.tsx +114 -0
  146. package/lib/components/CookieNotice/index.ts +2 -0
  147. package/lib/components/Datepicker/Datepicker.lld.md +108 -0
  148. package/lib/components/Datepicker/Datepicker.stories.tsx +44 -5
  149. package/lib/components/Datepicker/Datepicker.tsx +14 -36
  150. package/lib/components/Datepicker/Datepicker.types.ts +5 -14
  151. package/lib/components/Datepicker/__tests__/Datepicker.test.tsx +150 -8
  152. package/lib/components/Datepicker/__tests__/__snapshots__/Datepicker.test.tsx.snap +10 -4
  153. package/lib/components/Datepicker/subcomponents/CustomDatepicker.tsx +39 -5
  154. package/lib/components/Datepicker/subcomponents/DatepickerInput.tsx +30 -17
  155. package/lib/components/Datepicker/subcomponents/Panel.tsx +6 -2
  156. package/lib/components/Datepicker/subcomponents/VisibleField.tsx +40 -3
  157. package/lib/components/Datepicker/subcomponents/index.ts +0 -1
  158. package/lib/components/Datepicker/utils/index.ts +0 -1
  159. package/lib/components/Dialog/BaseDialog.tsx +55 -4
  160. package/lib/components/Dialog/Dialog.tsx +8 -1
  161. package/lib/components/Dialog/DialogBody.tsx +5 -1
  162. package/lib/components/Dialog/DialogHeader.tsx +2 -1
  163. package/lib/components/Divider/Divider.stories.tsx +1 -1
  164. package/lib/components/Field/ErrorText.tsx +1 -0
  165. package/lib/components/Field/Field.stories.tsx +1 -1
  166. package/lib/components/Field/__tests__/Field.test.tsx +161 -148
  167. package/lib/components/FileInput/FileInput.stories.tsx +70 -0
  168. package/lib/components/FileInput/FileInput.tsx +68 -0
  169. package/lib/components/FileInput/__tests__/FileInput.test.tsx +99 -0
  170. package/lib/components/FileInput/__tests__/__snapshots__/FileInput.test.tsx.snap +91 -0
  171. package/lib/components/FileInput/index.ts +2 -0
  172. package/lib/components/Footer/Footer.stories.tsx +1 -1
  173. package/lib/components/Footer/__tests__/__snapshots__/Footer.test.tsx.snap +28 -28
  174. package/lib/components/Header/Header.mdx +52 -0
  175. package/lib/components/Header/Header.stories.tsx +98 -0
  176. package/lib/components/Header/Header.tsx +65 -3
  177. package/lib/components/Header/__tests__/Header.test.tsx +17 -1
  178. package/lib/components/Header/__tests__/__snapshots__/Header.test.tsx.snap +4 -4
  179. package/lib/components/Heading/Documentation.mdx +1 -1
  180. package/lib/components/Heading/Heading.stories.tsx +1 -1
  181. package/lib/components/Heading/Heading.tsx +1 -1
  182. package/lib/components/Heading/__tests__/Heading.test.tsx +7 -19
  183. package/lib/components/Heading/__tests__/__snapshots__/Heading.test.tsx.snap +7 -7
  184. package/lib/components/Icon/Icon.stories.tsx +1 -1
  185. package/lib/components/IconButton/IconButton.stories.tsx +1 -1
  186. package/lib/components/Input/Input.stories.tsx +1 -1
  187. package/lib/components/Label/Label.stories.tsx +1 -1
  188. package/lib/components/Label/Label.tsx +0 -2
  189. package/lib/components/Label/__tests__/__snapshots__/Label.test.tsx.snap +7 -7
  190. package/lib/components/Link/BaseLink.tsx +84 -0
  191. package/lib/components/Link/Link.tsx +72 -32
  192. package/lib/components/Link/__tests__/__snapshots__/link.test.tsx.snap +3 -3
  193. package/lib/components/Link/__tests__/link.test.tsx +6 -13
  194. package/lib/components/Link/index.ts +1 -1
  195. package/lib/components/Main/Main.stories.tsx +36 -0
  196. package/lib/components/Main/Main.tsx +46 -0
  197. package/lib/components/Main/__tests__/Main.test.tsx +80 -0
  198. package/lib/components/Main/__tests__/__snapshots__/Main.test.tsx.snap +33 -0
  199. package/lib/components/Main/index.ts +2 -0
  200. package/lib/components/Menu/Menu.context.tsx +3 -1
  201. package/lib/components/Menu/Menu.tsx +2 -2
  202. package/lib/components/Menu/MenuContent.tsx +5 -5
  203. package/lib/components/Menu/MenuItem.tsx +20 -3
  204. package/lib/components/Menu/MenuSection.tsx +4 -3
  205. package/lib/components/NativeDatepicker/NativeDatepicker.stories.tsx +100 -0
  206. package/lib/components/{Datepicker/subcomponents → NativeDatepicker}/NativeDatepicker.tsx +14 -15
  207. package/lib/components/NativeDatepicker/NativeDatepicker.types.ts +19 -0
  208. package/lib/components/NativeDatepicker/index.ts +2 -0
  209. package/lib/components/{Datepicker → NativeDatepicker}/utils/dateToLocaleISOString/dateToLocaleISOString.ts +1 -1
  210. package/lib/components/NativeDatepicker/utils/index.ts +1 -0
  211. package/lib/components/Pagination/PaginationControls.tsx +56 -15
  212. package/lib/components/Pagination/PaginationInfo.tsx +5 -1
  213. package/lib/components/Paragraph/Paragraph.stories.tsx +1 -1
  214. package/lib/components/Search/Search.stories.tsx +41 -0
  215. package/lib/components/Search/Search.tsx +170 -0
  216. package/lib/components/Search/__tests__/Search.test.tsx +112 -0
  217. package/lib/components/Search/__tests__/__snapshots__/Search.test.tsx.snap +179 -0
  218. package/lib/components/Search/index.ts +2 -0
  219. package/lib/components/Select/Select.mdx +169 -0
  220. package/lib/components/Select/Select.stories.tsx +198 -77
  221. package/lib/components/Select/Select.tsx +37 -13
  222. package/lib/components/Select/Select.types.ts +77 -54
  223. package/lib/components/Select/__tests__/Select.test.tsx +448 -7
  224. package/lib/components/Select/__tests__/__snapshots__/Select.test.tsx.snap +3 -3
  225. package/lib/components/Select/subcomponents/CustomOption.tsx +24 -10
  226. package/lib/components/Select/subcomponents/CustomSelect.tsx +333 -52
  227. package/lib/components/Select/subcomponents/FilterInput.tsx +80 -0
  228. package/lib/components/Select/subcomponents/NativeSelect.tsx +13 -1
  229. package/lib/components/Select/subcomponents/Panel.tsx +4 -5
  230. package/lib/components/Select/subcomponents/VisibleField.tsx +36 -24
  231. package/lib/components/Select/subcomponents/index.tsx +1 -0
  232. package/lib/components/Snackbar/Snackbar.stories.tsx +1 -1
  233. package/lib/components/Spinner/Spinner.stories.tsx +1 -1
  234. package/lib/components/StandaloneLink/StandaloneLink.stories.tsx +32 -0
  235. package/lib/components/StandaloneLink/StandaloneLink.tsx +183 -0
  236. package/lib/components/StandaloneLink/__tests__/StandaloneLink.test.tsx +57 -0
  237. package/lib/components/StandaloneLink/__tests__/__snapshots__/StandaloneLink.test.tsx.snap +19 -0
  238. package/lib/components/StandaloneLink/index.ts +2 -0
  239. package/lib/components/Table/Table.stories.tsx +337 -0
  240. package/lib/components/Table/Table.tsx +42 -67
  241. package/lib/components/Table/Table.types.ts +14 -0
  242. package/lib/components/Table/__tests__/Table.test.tsx +121 -0
  243. package/lib/components/Table/__tests__/__snapshots__/Table.test.tsx.snap +210 -0
  244. package/lib/components/Table/index.ts +8 -1
  245. package/lib/components/Table/subcomponents/Body.tsx +18 -0
  246. package/lib/components/Table/subcomponents/Cell/Cell.stories.tsx +151 -0
  247. package/lib/components/Table/subcomponents/Cell/Cell.tsx +72 -0
  248. package/lib/components/Table/subcomponents/Cell/CellContent.tsx +91 -0
  249. package/lib/components/Table/subcomponents/Cell/__tests__/Cell.test.tsx +115 -0
  250. package/lib/components/Table/subcomponents/Cell/__tests__/__snapshots__/Cell.test.tsx.snap +107 -0
  251. package/lib/components/Table/subcomponents/Head.tsx +34 -0
  252. package/lib/components/Table/subcomponents/HeadCell/HeadCell.stories.tsx +85 -0
  253. package/lib/components/Table/subcomponents/HeadCell/HeadCell.tsx +99 -0
  254. package/lib/components/Table/subcomponents/HeadCell/HeadCellContent.tsx +61 -0
  255. package/lib/components/Table/subcomponents/HeadCell/__tests__/HeadCell.test.tsx +137 -0
  256. package/lib/components/Table/subcomponents/HeadCell/__tests__/__snapshots__/HeadCell.test.tsx.snap +110 -0
  257. package/lib/components/Table/subcomponents/Row.tsx +49 -0
  258. package/lib/components/Table/subcomponents/SortIcon.tsx +63 -0
  259. package/lib/components/Table/subcomponents/index.ts +14 -0
  260. package/lib/components/Tabs/Tab.tsx +3 -3
  261. package/lib/components/Tabs/TabContext.tsx +1 -0
  262. package/lib/components/Tabs/Tabs.stories.tsx +9 -3
  263. package/lib/components/Tabs/Tabs.tsx +10 -32
  264. package/lib/components/Tabs/__tests__/Tabs.test.tsx +10 -4
  265. package/lib/components/Tabs/__tests__/__snapshots__/Tabs.test.tsx.snap +32 -32
  266. package/lib/components/Textarea/Textarea.stories.tsx +1 -1
  267. package/lib/components/Timepicker/Timepicker.stories.tsx +43 -0
  268. package/lib/components/Timepicker/Timepicker.tsx +100 -0
  269. package/lib/components/Timepicker/__tests__/Timepicker.test.tsx +55 -0
  270. package/lib/components/Timepicker/__tests__/__snapshots__/Timepicker.test.tsx.snap +19 -0
  271. package/lib/components/Timepicker/index.tsx +2 -0
  272. package/lib/components/Timepicker/utils/convertDateToTimeString.test.ts +54 -0
  273. package/lib/components/Timepicker/utils/convertDateToTimeString.ts +10 -0
  274. package/lib/components/Timepicker/utils/index.ts +1 -0
  275. package/lib/components/Toggle/Toggle.stories.tsx +1 -1
  276. package/lib/components/Tooltip/Tooltip.stories.tsx +1 -1
  277. package/lib/components/WeekPicker/WeekPicker.stories.tsx +147 -0
  278. package/lib/components/WeekPicker/WeekPicker.tsx +26 -0
  279. package/lib/components/WeekPicker/WeekPicker.types.ts +21 -0
  280. package/lib/components/WeekPicker/index.ts +2 -0
  281. package/lib/components/WeekPicker/subcomponents/CustomDatepicker.tsx +298 -0
  282. package/lib/components/WeekPicker/subcomponents/DatepickerInput.tsx +111 -0
  283. package/lib/components/WeekPicker/subcomponents/VisibleField.tsx +126 -0
  284. package/lib/components/WeekPicker/subcomponents/index.ts +3 -0
  285. package/lib/components/common/Common.mdx +1 -1
  286. package/lib/components/index.ts +28 -2
  287. package/lib/hooks/index.ts +2 -0
  288. package/lib/hooks/useFocusTrap.ts +159 -0
  289. package/lib/index.ts +2 -0
  290. package/lib/theme/defaultTheme.ts +7 -0
  291. package/lib/utils/__tests__/announce.test.ts +121 -0
  292. package/lib/utils/__tests__/capitalise.test.ts +40 -0
  293. package/lib/utils/announce.ts +134 -0
  294. package/lib/utils/capitalise.ts +4 -0
  295. package/lib/utils/index.ts +1 -0
  296. package/package.json +3 -6
  297. package/dist/components/Datepicker/subcomponents/NativeDatepicker.d.ts +0 -6
  298. package/lib/components/Accordion/Accordion.stories.tsx.NOT_READY +0 -93
  299. package/lib/components/Field/__tests__/__snapshots__/Field.test.tsx.snap +0 -300
  300. /package/dist/components/{Datepicker/utils/dateToLocaleISOString/dateToLocaleISOString.test.d.ts → FileInput/__tests__/FileInput.test.d.ts} +0 -0
  301. /package/lib/components/{Datepicker → NativeDatepicker}/utils/dateToLocaleISOString/dateToLocaleISOString.test.ts +0 -0
@@ -0,0 +1,46 @@
1
+ import { cx } from '@emotion/css';
2
+ import Layout from '../Layout/Layout';
3
+
4
+ export interface MainProps extends React.HTMLAttributes<HTMLElement> {
5
+ /**
6
+ * Determines whether to wrap children in a `<Layout>` component,
7
+ * to apply the grid layout from the UCL Design System.
8
+ */
9
+ layout?: boolean;
10
+ /**
11
+ * ID for testing purposes.
12
+ * Added to the `data-testid` attribute of top-level `<main>` element.
13
+ * Default is `'ucl-uikit-main'`.
14
+ */
15
+ testId?: string;
16
+ }
17
+
18
+ export const NAME = 'ucl-uikit-main';
19
+
20
+ /**
21
+ * Semantic wrapper around HTML `<main>` element
22
+ *
23
+ * Optionally wraps children in the UCL Design System `Layout` grid when `layout` is true
24
+ */
25
+ const Main = ({
26
+ layout = false,
27
+ testId = NAME,
28
+ className,
29
+ children,
30
+ ...props
31
+ }: MainProps) => {
32
+ // No need for any additional styling -- just a semantic wrapper
33
+ const style = cx(NAME, className);
34
+
35
+ return (
36
+ <main
37
+ className={style}
38
+ data-testid={testId}
39
+ {...props}
40
+ >
41
+ {layout ? <Layout>{children}</Layout> : children}
42
+ </main>
43
+ );
44
+ };
45
+
46
+ export default Main;
@@ -0,0 +1,80 @@
1
+ import { describe, expect, test } from 'vitest';
2
+ import { render, screen } from '@testing-library/react';
3
+ import Main from '../Main';
4
+ import { ThemeContextProvider } from '../../../theme/useTheme';
5
+
6
+ describe('Main', () => {
7
+ // Snapshot tests
8
+
9
+ test('snapshot: no props', () => {
10
+ const renderResult = render(
11
+ <ThemeContextProvider>
12
+ <Main>Content</Main>
13
+ </ThemeContextProvider>
14
+ );
15
+ expect(renderResult.container.firstChild).toMatchSnapshot();
16
+ });
17
+
18
+ test('snapshot: layout prop true', () => {
19
+ const renderResult = render(
20
+ <ThemeContextProvider>
21
+ <Main layout>Content</Main>
22
+ </ThemeContextProvider>
23
+ );
24
+ expect(renderResult.container.firstChild).toMatchSnapshot();
25
+ });
26
+
27
+ test('snapshot: testId prop', () => {
28
+ const renderResult = render(
29
+ <ThemeContextProvider>
30
+ <Main testId='test123'>Content</Main>
31
+ </ThemeContextProvider>
32
+ );
33
+ expect(renderResult.container.firstChild).toMatchSnapshot();
34
+ });
35
+
36
+ // Interaction tests
37
+
38
+ test('Can find by default testId', () => {
39
+ render(
40
+ <ThemeContextProvider>
41
+ <Main>Content</Main>
42
+ </ThemeContextProvider>
43
+ );
44
+ const main = screen.getByTestId('ucl-uikit-main');
45
+ expect(main).toBeInTheDocument();
46
+ });
47
+
48
+ test('Can find by custom testId', () => {
49
+ render(
50
+ <ThemeContextProvider>
51
+ <Main testId='custom-test-id'>Content</Main>
52
+ </ThemeContextProvider>
53
+ );
54
+ const main = screen.getByTestId('custom-test-id');
55
+ expect(main).toBeInTheDocument();
56
+ });
57
+
58
+ test('Renders children correctly', () => {
59
+ render(
60
+ <ThemeContextProvider>
61
+ <Main>
62
+ <div data-testid='child-element'>Child Content</div>
63
+ </Main>
64
+ </ThemeContextProvider>
65
+ );
66
+ const child = screen.getByTestId('child-element');
67
+ expect(child).toBeInTheDocument();
68
+ expect(child).toHaveTextContent('Child Content');
69
+ });
70
+
71
+ test('Applies layout when layout prop is true', () => {
72
+ render(
73
+ <ThemeContextProvider>
74
+ <Main layout>Content</Main>
75
+ </ThemeContextProvider>
76
+ );
77
+ const layoutComponent = screen.getByTestId('ucl-uikit-layout');
78
+ expect(layoutComponent).toBeInTheDocument();
79
+ });
80
+ });
@@ -0,0 +1,33 @@
1
+ // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2
+
3
+ exports[`Main > snapshot: layout prop true 1`] = `
4
+ <main
5
+ class="ucl-uikit-main"
6
+ data-testid="ucl-uikit-main"
7
+ >
8
+ <div
9
+ class="css-3reham"
10
+ data-testid="ucl-uikit-layout"
11
+ >
12
+ Content
13
+ </div>
14
+ </main>
15
+ `;
16
+
17
+ exports[`Main > snapshot: no props 1`] = `
18
+ <main
19
+ class="ucl-uikit-main"
20
+ data-testid="ucl-uikit-main"
21
+ >
22
+ Content
23
+ </main>
24
+ `;
25
+
26
+ exports[`Main > snapshot: testId prop 1`] = `
27
+ <main
28
+ class="ucl-uikit-main"
29
+ data-testid="test123"
30
+ >
31
+ Content
32
+ </main>
33
+ `;
@@ -0,0 +1,2 @@
1
+ export { default } from './Main';
2
+ export type { MainProps } from './Main';
@@ -68,7 +68,9 @@ const MenuProvider = ({
68
68
  if (!isOpen || !contentRef.current) return;
69
69
 
70
70
  const focusableElements = Array.from(
71
- contentRef.current.querySelectorAll('[role="menuitem"]')
71
+ contentRef.current.querySelectorAll(
72
+ '[role="menuitem"], [aria-label="Close menu"]'
73
+ )
72
74
  ).filter((el) => {
73
75
  const element = el as HTMLElement;
74
76
  return (
@@ -37,7 +37,7 @@ const Menu = ({
37
37
  const style = cx(NAME, baseStyle, className);
38
38
 
39
39
  return (
40
- <div
40
+ <nav
41
41
  className={style}
42
42
  data-testid={testId}
43
43
  {...props}
@@ -52,7 +52,7 @@ const Menu = ({
52
52
  {children}
53
53
  </MenuContent>
54
54
  </MenuProvider>
55
- </div>
55
+ </nav>
56
56
  );
57
57
  };
58
58
 
@@ -9,7 +9,7 @@ import { useAppMenu } from './Menu.context';
9
9
 
10
10
  export const NAME = 'ucl-uikit-menu__content';
11
11
 
12
- export interface MenuContentProps extends HTMLAttributes<HTMLDivElement> {
12
+ export interface MenuContentProps extends HTMLAttributes<HTMLUListElement> {
13
13
  title?: string;
14
14
  testId?: string;
15
15
  position?: 'left' | 'right';
@@ -91,7 +91,8 @@ const MenuContent: React.FC<MenuContentProps> = ({
91
91
  list-style: none;
92
92
 
93
93
  @media (min-width: ${theme.breakpoints.desktop}px) {
94
- margin: 0 ${padding.p64} 0 ${padding.p72};
94
+ margin: 0 ${padding.p64};
95
+ padding: 0;
95
96
  }
96
97
  `;
97
98
 
@@ -114,14 +115,13 @@ const MenuContent: React.FC<MenuContentProps> = ({
114
115
  <header className={headerStyle}>
115
116
  <h3 className={titleStyle}>{title}</h3>
116
117
  <IconButton
117
- role='menuitem'
118
118
  onClick={toggleMenu}
119
119
  aria-label='Close menu'
120
120
  >
121
121
  <Icon.X size={40} />
122
122
  </IconButton>
123
123
  </header>
124
- <div
124
+ <ul
125
125
  role='menu'
126
126
  aria-labelledby='app-menu-button'
127
127
  className={bodyStyle}
@@ -130,7 +130,7 @@ const MenuContent: React.FC<MenuContentProps> = ({
130
130
  {...props}
131
131
  >
132
132
  {children}
133
- </div>
133
+ </ul>
134
134
  </div>
135
135
  );
136
136
 
@@ -1,12 +1,15 @@
1
1
  import React, { LiHTMLAttributes, memo } from 'react';
2
2
  import { css, cx } from '@emotion/css';
3
3
  import useTheme from '../../theme/useTheme';
4
+ import Icon from '../Icon/Icon';
4
5
 
5
6
  export const NAME = 'ucl-uikit-menu__item';
6
7
 
7
8
  export interface MenuItemProps extends LiHTMLAttributes<HTMLLIElement> {
8
9
  testId?: string;
9
10
  icon?: React.ReactNode;
11
+ secondary?: boolean;
12
+ externalLink?: boolean;
10
13
  }
11
14
 
12
15
  const MenuItem: React.FC<MenuItemProps> = ({
@@ -15,6 +18,8 @@ const MenuItem: React.FC<MenuItemProps> = ({
15
18
  children,
16
19
  className,
17
20
  onClick,
21
+ secondary,
22
+ externalLink,
18
23
  ...props
19
24
  }) => {
20
25
  const isClickable = !!onClick;
@@ -22,17 +27,21 @@ const MenuItem: React.FC<MenuItemProps> = ({
22
27
 
23
28
  const baseStyle = css`
24
29
  height: 40px;
25
- margin-bottom: ${theme.margin.m32};
30
+ margin-bottom: ${theme.margin.m16};
26
31
  display: flex;
27
32
  align-items: center;
28
33
  font-family: ${theme.font.family.primary};
29
34
  font-size: ${theme.font.size.f16};
30
- font-weight: ${theme.font.weight.bold};
35
+ font-weight: ${secondary
36
+ ? `${theme.font.weight.medium}`
37
+ : `${theme.font.weight.bold}`};
31
38
  color: ${theme.color.text.secondary};
32
39
  `;
33
40
 
34
41
  const clickableMenuItemStyle = css`
35
- color: ${theme.color.text.primary};
42
+ color: ${secondary
43
+ ? `${theme.color.text.secondary}`
44
+ : `${theme.color.text.primary}`};
36
45
  cursor: pointer;
37
46
  &:hover {
38
47
  background-color: ${theme.color.interaction.blue5};
@@ -77,6 +86,14 @@ const MenuItem: React.FC<MenuItemProps> = ({
77
86
  {...props}
78
87
  >
79
88
  {content}
89
+ {externalLink && (
90
+ <Icon.ExternalLink
91
+ size={16}
92
+ className={css`
93
+ margin-left: 8px;
94
+ `}
95
+ />
96
+ )}
80
97
  </li>
81
98
  );
82
99
  };
@@ -4,7 +4,7 @@ import { useTheme } from '../../theme';
4
4
 
5
5
  export const NAME = 'ucl-uikit-menu__section';
6
6
 
7
- export interface MenuSectionProps extends HTMLAttributes<HTMLElement> {
7
+ export interface MenuSectionProps extends HTMLAttributes<HTMLLIElement> {
8
8
  testId?: string;
9
9
  }
10
10
 
@@ -34,12 +34,13 @@ const MenuSection: React.FC<MenuSectionProps> = ({
34
34
  `;
35
35
 
36
36
  return (
37
- <section
37
+ <li
38
+ role='presentation'
38
39
  className={style}
39
40
  {...props}
40
41
  >
41
42
  <ul className={listStyle}>{children}</ul>
42
- </section>
43
+ </li>
43
44
  );
44
45
  };
45
46
 
@@ -0,0 +1,100 @@
1
+ import type { Meta, StoryObj } from '@storybook/react';
2
+ import { useArgs } from '@storybook/preview-api';
3
+ import NativeDatepicker from './NativeDatepicker';
4
+
5
+ const meta = {
6
+ title: 'Components/NativeDatepicker',
7
+ component: NativeDatepicker,
8
+ parameters: { layout: 'padded' },
9
+ argTypes: {
10
+ value: { control: { type: 'date' } },
11
+ minDate: { control: { type: 'date' } },
12
+ maxDate: { control: { type: 'date' } },
13
+ disabled: { control: { type: 'boolean' } },
14
+ },
15
+ tags: ['autodocs'],
16
+ } satisfies Meta<typeof NativeDatepicker>;
17
+
18
+ export default meta;
19
+ type Story = StoryObj<typeof meta>;
20
+
21
+ export const Default: Story = {
22
+ render: () => {
23
+ const [args, updateArgs] = useArgs();
24
+
25
+ // Storybook controls provide UNIX timestamps for dates, need to convert
26
+ // https://storybook.js.org/docs/essentials/controls#annotation
27
+ args.value = args.value ? new Date(args.value) : null;
28
+ args.minDate = args.minDate
29
+ ? new Date(args.minDate).toLocaleDateString('sv-SE')
30
+ : null;
31
+ args.maxDate = args.maxDate
32
+ ? new Date(args.maxDate).toLocaleDateString('sv-SE')
33
+ : null;
34
+
35
+ const onValueChange = (value: Date | null) => updateArgs({ value: value });
36
+ return (
37
+ <NativeDatepicker
38
+ {...args}
39
+ onValueChange={onValueChange}
40
+ />
41
+ );
42
+ },
43
+ };
44
+
45
+ export const Disabled: Story = {
46
+ name: 'Disabled',
47
+ args: {
48
+ disabled: true,
49
+ value: new Date(2025, 2, 10),
50
+ },
51
+ render: (args) => <NativeDatepicker {...args} />,
52
+ };
53
+
54
+ export const WithMinMaxDates: Story = {
55
+ name: 'With min and max dates',
56
+ args: {
57
+ // Initialise min date as 5 days into the current month
58
+ minDate: (() => {
59
+ const now = new Date();
60
+ return new Date(now.getFullYear(), now.getMonth(), 5).toLocaleDateString(
61
+ 'sv-SE'
62
+ );
63
+ })(),
64
+ // Initialise max date as 5 days before the last day of the current month
65
+ maxDate: (() => {
66
+ const now = new Date();
67
+ const lastDay = new Date(
68
+ now.getFullYear(),
69
+ now.getMonth() + 1,
70
+ 0
71
+ ).getDate();
72
+ return new Date(
73
+ now.getFullYear(),
74
+ now.getMonth(),
75
+ lastDay - 5
76
+ ).toLocaleDateString('sv-SE');
77
+ })(),
78
+ },
79
+ render: () => {
80
+ const [args, updateArgs] = useArgs();
81
+
82
+ // Storybook controls provide UNIX timestamps for dates, need to convert
83
+ // https://storybook.js.org/docs/essentials/controls#annotation
84
+ args.value = args.value ? new Date(args.value) : null;
85
+ args.minDate = args.minDate
86
+ ? new Date(args.minDate).toLocaleDateString('sv-SE')
87
+ : null;
88
+ args.maxDate = args.maxDate
89
+ ? new Date(args.maxDate).toLocaleDateString('sv-SE')
90
+ : null;
91
+
92
+ const onValueChange = (value: Date | null) => updateArgs({ value: value });
93
+ return (
94
+ <NativeDatepicker
95
+ {...args}
96
+ onValueChange={onValueChange}
97
+ />
98
+ );
99
+ },
100
+ };
@@ -1,19 +1,15 @@
1
1
  import { css, cx } from '@emotion/css';
2
- import { theme } from '../../../theme';
2
+ import { theme } from '../../theme';
3
+ import { dateToLocaleISOString } from './utils';
4
+ import type { NativeDatepickerProps } from './NativeDatepicker.types';
3
5
 
4
- interface NativeDatepickerProps
5
- extends React.InputHTMLAttributes<HTMLInputElement> {
6
- testId?: string;
7
- ref?: React.RefObject<HTMLInputElement>;
8
- }
9
-
10
- const NAME = 'ucl-uikit-datepicker--native';
6
+ const NAME = 'ucl-uikit-native-datepicker';
11
7
 
12
8
  const NativeDatepicker = ({
13
9
  value,
14
- onChange,
15
- min,
16
- max,
10
+ onValueChange,
11
+ minDate,
12
+ maxDate,
17
13
  className,
18
14
  disabled,
19
15
  testId = NAME,
@@ -54,10 +50,13 @@ const NativeDatepicker = ({
54
50
  return (
55
51
  <input
56
52
  type='date'
57
- value={value}
58
- onChange={onChange}
59
- min={min}
60
- max={max}
53
+ value={dateToLocaleISOString(value) ?? ''}
54
+ onChange={(event) => {
55
+ const dateString = event.target.value;
56
+ onValueChange?.(dateString ? new Date(dateString) : null, event);
57
+ }}
58
+ min={minDate || undefined}
59
+ max={maxDate || undefined}
61
60
  disabled={disabled}
62
61
  className={style}
63
62
  data-testid={testId}
@@ -0,0 +1,19 @@
1
+ import type { InputHTMLAttributes, RefObject } from 'react';
2
+
3
+ export type DatepickerValue = Date | null;
4
+
5
+ export interface NativeDatepickerProps
6
+ extends Omit<
7
+ InputHTMLAttributes<HTMLInputElement>,
8
+ 'value' | 'onChange' | 'min' | 'max'
9
+ > {
10
+ value?: DatepickerValue;
11
+ onValueChange?: (
12
+ value: DatepickerValue,
13
+ event?: React.SyntheticEvent
14
+ ) => void;
15
+ minDate?: string | null;
16
+ maxDate?: string | null;
17
+ testId?: string;
18
+ ref?: RefObject<HTMLInputElement>;
19
+ }
@@ -0,0 +1,2 @@
1
+ export { default } from './NativeDatepicker';
2
+ export type { NativeDatepickerProps } from './NativeDatepicker.types';
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Converts a Date object to a `YYYY-MM-DD` string based on the user's local timezone.
3
3
  *
4
- * Used for passing dates to <NativeDatepicker> in `Datepicker.tsx`
4
+ * Used for passing dates to <NativeDatepicker>
5
5
  *
6
6
  * This function uses the Swedish (`sv-SE`) locale with `toLocaleDateString`
7
7
  * as it conveniently defaults to the ISO 8601 `YYYY-MM-DD` format, while respecting
@@ -0,0 +1 @@
1
+ export { default as dateToLocaleISOString } from './dateToLocaleISOString/dateToLocaleISOString';
@@ -4,6 +4,7 @@ import useTheme from '../../theme/useTheme';
4
4
  import { PaginationContext } from './Pagination';
5
5
  import Button from '../Button';
6
6
  import getPaginationButtons from './getPaginationButtons';
7
+ import { useMediaQuery } from '../../hooks';
7
8
 
8
9
  export const NAME = 'ucl-ukit-pagination__controls';
9
10
  export const DEFAULT_MAX_BUTTONS = 9;
@@ -21,6 +22,10 @@ const PaginationControls = ({
21
22
  }: PaginationControlsProps) => {
22
23
  const [theme] = useTheme();
23
24
 
25
+ const isTabletPlus = useMediaQuery(
26
+ `(min-width: ${theme.breakpoints.tablet}px)`
27
+ );
28
+
24
29
  const contextValue = useContext(PaginationContext);
25
30
 
26
31
  const handlePageChange = useCallback(
@@ -48,7 +53,7 @@ const PaginationControls = ({
48
53
  const paginationButtons = getPaginationButtons(
49
54
  currentPage,
50
55
  totalPages,
51
- maxNumberButtons
56
+ isTabletPlus ? maxNumberButtons : 5
52
57
  );
53
58
 
54
59
  const baseStyle = css``;
@@ -61,23 +66,58 @@ const PaginationControls = ({
61
66
  display: flex;
62
67
  justify-content: center;
63
68
  align-items: center;
64
- gap: ${theme.margin.m8};
65
69
  list-style: none;
66
- `;
70
+ gap: ${theme.margin.m4};
71
+ flex-wrap: nowrap;
67
72
 
68
- const previousButtonStyle = css`
69
- margin-right: ${theme.margin.m16};
73
+ @media (min-width: ${theme.breakpoints.tablet}px) {
74
+ gap: ${theme.margin.m8};
75
+ }
70
76
  `;
71
77
 
72
- const nextButtonStyle = css`
73
- margin-left: ${theme.margin.m16};
78
+ const buttonBaseStyle = css`
79
+ @media (max-width: ${theme.breakpoints.tablet}px) {
80
+ gap: ${theme.margin.m4};
81
+ }
74
82
  `;
75
83
 
76
- const pageNumberButtonBaseStyle = css`
77
- height: 48px;
78
- min-width: 48px;
79
- padding: 0;
80
- `;
84
+ const previousButtonStyle = cx(
85
+ buttonBaseStyle,
86
+ css`
87
+ margin-right: ${theme.margin.m16};
88
+ display: none;
89
+
90
+ @media (min-width: ${theme.breakpoints.tablet}px) {
91
+ display: inline-block;
92
+ }
93
+ `
94
+ );
95
+
96
+ const nextButtonStyle = cx(
97
+ buttonBaseStyle,
98
+ css`
99
+ margin-left: ${theme.margin.m16};
100
+ display: none;
101
+
102
+ @media (min-width: ${theme.breakpoints.tablet}px) {
103
+ display: inline-block;
104
+ }
105
+ `
106
+ );
107
+
108
+ const pageNumberButtonBaseStyle = cx(
109
+ buttonBaseStyle,
110
+ css`
111
+ height: 40px;
112
+ min-width: 40px;
113
+ padding: 0;
114
+
115
+ @media (min-width: ${theme.breakpoints.tablet}px) {
116
+ height: 48px;
117
+ min-width: 48px;
118
+ }
119
+ `
120
+ );
81
121
 
82
122
  const pageNumberButtonStyle = cx(
83
123
  pageNumberButtonBaseStyle,
@@ -102,7 +142,7 @@ const PaginationControls = ({
102
142
  return (
103
143
  <nav
104
144
  className={style}
105
- aria-label='Pagination'
145
+ aria-label={`Pagination, ${totalPages} pages total`}
106
146
  data-testid={testId}
107
147
  >
108
148
  <ul className={listStyle}>
@@ -110,6 +150,7 @@ const PaginationControls = ({
110
150
  <Button
111
151
  className={previousButtonStyle}
112
152
  variant='tertiary'
153
+ size={isTabletPlus ? 'default' : 'small'}
113
154
  aria-label='Go to previous page'
114
155
  onClick={() => handlePageChange(currentPage - 1)}
115
156
  disabled={currentPage === 1}
@@ -128,6 +169,7 @@ const PaginationControls = ({
128
169
  <Button
129
170
  className={pageNumberButtonStyle}
130
171
  variant='secondary'
172
+ size={isTabletPlus ? 'default' : 'small'}
131
173
  aria-label={`Page ${page}`}
132
174
  onClick={() => handlePageChange(page)}
133
175
  >
@@ -138,10 +180,9 @@ const PaginationControls = ({
138
180
  <Button
139
181
  className={currentPageNumberButtonStyle}
140
182
  variant='secondary'
183
+ size={isTabletPlus ? 'default' : 'small'}
141
184
  aria-label={`Page ${page}, current page`}
142
185
  aria-current='page'
143
- aria-setsize={totalPages}
144
- aria-posinset={page}
145
186
  disabled
146
187
  onClick={() => handlePageChange(page)}
147
188
  >
@@ -40,11 +40,15 @@ const PaginationInfo = ({
40
40
  }[format];
41
41
 
42
42
  const baseStyle = css`
43
- margin: ${theme.margin.m24} 0;
43
+ margin: ${theme.margin.m16} 0;
44
44
  text-align: center;
45
45
  color: ${theme.color.text.secondary};
46
46
  font-family: ${theme.font.family.primary};
47
47
  font-size: ${theme.font.size.f16};
48
+
49
+ @media (min-width: ${theme.breakpoints.tablet}px) {
50
+ margin: ${theme.margin.m24} 0;
51
+ }
48
52
  `;
49
53
 
50
54
  const style = cx(NAME, baseStyle, className);
@@ -3,7 +3,7 @@ import Paragraph from './Paragraph';
3
3
  import { Link } from '../';
4
4
 
5
5
  const meta = {
6
- title: 'Components/Ready to use/Paragraph',
6
+ title: 'Components/Paragraph',
7
7
  component: Paragraph,
8
8
  args: {
9
9
  children: 'Default paragraph text',