uikit-react-public 0.14.21 → 0.21.8
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.
- package/README.md +2 -2
- package/dist/components/Accordion/Accordion.Heading.d.ts +5 -4
- package/dist/components/Accordion/Accordion.Panel.d.ts +2 -2
- package/dist/components/Accordion/Accordion.d.ts +1 -1
- package/dist/components/Accordion/Accordion.stories.d.ts +57 -0
- package/dist/components/Accordion/index.d.ts +2 -0
- package/dist/components/AppHeader/AppHeader.d.ts +1 -1
- package/dist/components/AppHeader/AppHeaderBottom.d.ts +1 -1
- package/dist/components/AppHeader/AppHeaderNav.d.ts +1 -1
- package/dist/components/AppHeader/AppHeaderTop.d.ts +1 -1
- package/dist/components/Avatar/Avatar.stories.d.ts +107 -1
- package/dist/components/Breadcrumbs/Breadcrumb.d.ts +3 -4
- package/dist/components/Breadcrumbs/Breadcrumbs.d.ts +1 -1
- package/dist/components/Breadcrumbs/Breadcrumbs.stories.d.ts +1 -1
- package/dist/components/Button/Button.d.ts +8 -3
- package/dist/components/Button/Button.stories.d.ts +17 -7
- package/dist/components/Button/style/buttonAccentStyle.d.ts +4 -0
- package/dist/components/Button/style/buttonPrimaryDestructiveStyle.d.ts +4 -0
- package/dist/components/Button/style/buttonPrimaryStyle.d.ts +4 -0
- package/dist/components/Button/style/buttonPrimarySubtleStyle.d.ts +4 -0
- package/dist/components/Button/style/buttonPrimaryWarningStyle.d.ts +4 -0
- package/dist/components/Button/style/buttonSecondaryDestructiveStyle.d.ts +4 -0
- package/dist/components/Button/style/buttonSecondaryStyle.d.ts +4 -0
- package/dist/components/Button/style/buttonSecondarySubtleStyle.d.ts +4 -0
- package/dist/components/Button/style/buttonTertiaryDestructiveStyle.d.ts +4 -0
- package/dist/components/Button/style/buttonTertiaryNoPaddingStyle.d.ts +4 -0
- package/dist/components/Button/style/buttonTertiaryStyle.d.ts +4 -0
- package/dist/components/Calendar/index.d.ts +1 -1
- package/dist/components/Checkbox/Checkbox.d.ts +1 -0
- package/dist/components/Datepicker/Datepicker.d.ts +1 -1
- package/dist/components/Datepicker/Datepicker.stories.d.ts +4 -3
- package/dist/components/Datepicker/Datepicker.types.d.ts +4 -5
- package/dist/components/Datepicker/subcomponents/CustomDatepicker.d.ts +4 -1
- package/dist/components/Datepicker/subcomponents/DatepickerInput.d.ts +15 -2
- package/dist/components/Datepicker/subcomponents/Panel.d.ts +1 -1
- package/dist/components/Datepicker/subcomponents/VisibleField.d.ts +6 -1
- package/dist/components/Datepicker/subcomponents/index.d.ts +0 -1
- package/dist/components/Datepicker/utils/index.d.ts +0 -1
- package/dist/components/Dialog/BaseDialog.d.ts +2 -1
- package/dist/components/Dialog/Dialog.d.ts +2 -0
- package/dist/components/FooterNew/BackToTop.d.ts +8 -0
- package/dist/components/FooterNew/Footer.d.ts +23 -0
- package/dist/components/FooterNew/FooterColumn.d.ts +8 -0
- package/dist/components/FooterNew/FooterLinks.d.ts +7 -0
- package/dist/components/FooterNew/FooterNavLink.d.ts +8 -0
- package/dist/components/FooterNew/LegalAndCopyright.d.ts +14 -0
- package/dist/components/FooterNew/LogoAddressAndSocial.d.ts +10 -0
- package/dist/components/FooterNew/SocialLink.d.ts +8 -0
- package/dist/components/FooterNew/index.d.ts +2 -0
- package/dist/components/Header/Header.d.ts +4 -1
- package/dist/components/Header/Header.stories.d.ts +40 -0
- package/dist/components/HeaderNew/Header.d.ts +18 -0
- package/dist/components/HeaderNew/HeaderBorder.d.ts +7 -0
- package/dist/components/HeaderNew/HeaderLogo.d.ts +9 -0
- package/dist/components/HeaderNew/HeaderMenuContainer.d.ts +7 -0
- package/dist/components/HeaderNew/HeaderTitle.d.ts +9 -0
- package/dist/components/HeaderNew/__tests__/Header.test.d.ts +1 -0
- package/dist/components/HeaderNew/constants.d.ts +3 -0
- package/dist/components/HeaderNew/index.d.ts +3 -0
- package/dist/components/HeadingNew/Heading.d.ts +13 -0
- package/dist/components/HeadingNew/index.d.ts +2 -0
- package/dist/components/Icon/svgImports.d.ts +7 -881
- package/dist/components/Link/BaseLink.d.ts +14 -5
- package/dist/components/Link/Link.d.ts +8 -3
- package/dist/components/Link/Link.stories.d.ts +3 -1
- package/dist/components/Main/Main.d.ts +21 -0
- package/dist/components/Main/Main.stories.d.ts +15 -0
- package/dist/components/Main/__tests__/Main.test.d.ts +1 -0
- package/dist/components/Main/index.d.ts +2 -0
- package/dist/components/MenuNew/Menu.context.d.ts +14 -0
- package/dist/components/MenuNew/Menu.d.ts +20 -0
- package/dist/components/MenuNew/MenuContent.d.ts +9 -0
- package/dist/components/MenuNew/MenuItem.d.ts +10 -0
- package/dist/components/MenuNew/MenuSection.d.ts +7 -0
- package/dist/components/MenuNew/index.d.ts +6 -0
- package/dist/components/MenuNew/trigger/ButtonMenuTrigger.d.ts +8 -0
- package/dist/components/MenuNew/trigger/IconMenuTrigger.d.ts +8 -0
- package/dist/components/NativeDatepicker/NativeDatepicker.d.ts +3 -0
- package/dist/components/NativeDatepicker/NativeDatepicker.stories.d.ts +36 -0
- package/dist/components/NativeDatepicker/NativeDatepicker.types.d.ts +10 -0
- package/dist/components/NativeDatepicker/index.d.ts +2 -0
- package/dist/components/{Datepicker → NativeDatepicker}/utils/dateToLocaleISOString/dateToLocaleISOString.d.ts +1 -1
- package/dist/components/NativeDatepicker/utils/dateToLocaleISOString/dateToLocaleISOString.test.d.ts +1 -0
- package/dist/components/NativeDatepicker/utils/index.d.ts +1 -0
- package/dist/components/Overlay/Overlay.stories.d.ts +12 -12
- package/dist/components/ParagraphNew/Paragraph.d.ts +13 -0
- package/dist/components/ParagraphNew/index.d.ts +4 -0
- package/dist/components/Select/Select.d.ts +2 -1
- package/dist/components/Select/Select.stories.d.ts +167 -3
- package/dist/components/Select/Select.types.d.ts +75 -19
- package/dist/components/Select/subcomponents/CustomOption.d.ts +1 -1
- package/dist/components/Select/subcomponents/CustomSelect.d.ts +3 -2
- package/dist/components/Select/subcomponents/FilterInput.d.ts +16 -0
- package/dist/components/Select/subcomponents/NativeSelect.d.ts +5 -1
- package/dist/components/Select/subcomponents/VisibleField.d.ts +6 -1
- package/dist/components/Select/subcomponents/index.d.ts +1 -0
- package/dist/components/Spinner/Spinner.d.ts +2 -0
- package/dist/components/StandaloneLink/StandaloneLink.d.ts +8 -5
- package/dist/components/StandaloneLink/StandaloneLink.stories.d.ts +3 -1
- package/dist/components/Table/Table.d.ts +3 -3
- package/dist/components/Table/Table.stories.d.ts +3 -3
- package/dist/components/Table/Table.types.d.ts +1 -0
- package/dist/components/Table/subcomponents/Cell/Cell.d.ts +5 -1
- package/dist/components/Table/subcomponents/Cell/Cell.stories.d.ts +15 -13
- package/dist/components/Table/subcomponents/Cell/CellContent.d.ts +5 -1
- package/dist/components/Table/subcomponents/HeadCell/HeadCell.d.ts +2 -1
- package/dist/components/Table/subcomponents/HeadCell/HeadCell.stories.d.ts +14 -13
- package/dist/components/Table/subcomponents/HeadCell/HeadCellContent.d.ts +2 -1
- package/dist/components/Table/subcomponents/__tests__/Row.test.d.ts +1 -0
- package/dist/components/UclLogoNew/UclLogo.d.ts +8 -0
- package/dist/components/UclLogoNew/index.d.ts +2 -0
- package/dist/components/WeekPicker/WeekPicker.d.ts +2 -2
- package/dist/components/WeekPicker/WeekPicker.stories.d.ts +41 -0
- package/dist/components/WeekPicker/WeekPicker.types.d.ts +16 -0
- package/dist/components/WeekPicker/index.d.ts +1 -0
- package/dist/components/WeekPicker/subcomponents/CustomDatepicker.d.ts +1 -1
- package/dist/components/index.d.ts +20 -0
- package/dist/hooks/useFocusTrap.d.ts +2 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +22204 -16719
- package/dist/theme/__tests__/fonts.test.d.ts +1 -0
- package/dist/theme/common/themeCommon.d.ts +904 -0
- package/dist/theme/fonts.d.ts +18 -0
- package/dist/theme/index.d.ts +6 -3
- package/dist/theme/light/lightColour.d.ts +126 -0
- package/dist/theme/light/lightTheme.d.ts +3 -0
- package/dist/theme/original/color.d.ts +166 -0
- package/dist/theme/original/defaultTheme.d.ts +1340 -0
- package/dist/theme/original/originalColourNewStructure.d.ts +126 -0
- package/dist/theme/useTheme.d.ts +2174 -0
- package/dist/utils/__tests__/announce.test.d.ts +1 -0
- package/dist/utils/addAlphaToHex.d.ts +5 -0
- package/dist/utils/announce.d.ts +6 -0
- package/dist/utils/index.d.ts +1 -0
- package/dist/utils/scrollToTop.d.ts +2 -0
- package/lib/components/Accordion/Accordion.Heading.tsx +65 -34
- package/lib/components/Accordion/Accordion.Panel.tsx +11 -7
- package/lib/components/Accordion/Accordion.stories.tsx +139 -0
- package/lib/components/Accordion/Accordion.tsx +39 -31
- package/lib/components/Accordion/__tests__/__snapshots__/Accordion.test.tsx.snap +15 -13
- package/lib/components/Accordion/index.ts +2 -0
- package/lib/components/Alert/Alert.stories.tsx +1 -1
- package/lib/components/Alert/Alert.tsx +12 -12
- package/lib/components/Alert/__tests__/__snapshots__/Alert.test.tsx.snap +13 -39
- package/lib/components/AppHeader/AppHeader.tsx +6 -11
- package/lib/components/AppHeader/AppHeaderBottom.tsx +2 -3
- package/lib/components/AppHeader/AppHeaderNav.tsx +2 -3
- package/lib/components/AppHeader/AppHeaderTop.tsx +1 -1
- package/lib/components/AppHeader/__tests__/__snapshots__/AppHeader.test.tsx.snap +2 -2
- package/lib/components/AppMenu/__tests__/__snapshots__/AppMenu.test.tsx.snap +6 -19
- package/lib/components/Avatar/Avatar.mdx +117 -0
- package/lib/components/Avatar/Avatar.stories.tsx +110 -2
- package/lib/components/Badge/Badge.stories.tsx +1 -1
- package/lib/components/Blanket/Blanket.stories.tsx +1 -1
- package/lib/components/Breadcrumbs/Breadcrumb.tsx +26 -12
- package/lib/components/Breadcrumbs/Breadcrumbs.tsx +1 -1
- package/lib/components/Breadcrumbs/__tests__/Breadcrumbs.test.tsx +9 -27
- package/lib/components/Breadcrumbs/__tests__/__snapshots__/Breadcrumbs.test.tsx.snap +24 -20
- package/lib/components/Button/Button.mdx +32 -279
- package/lib/components/Button/Button.stories.tsx +44 -51
- package/lib/components/Button/Button.tsx +166 -25
- package/lib/components/Button/__tests__/Button.test.tsx +49 -15
- package/lib/components/Button/__tests__/__snapshots__/Button.test.tsx.snap +80 -73
- package/lib/components/Button/style/buttonAccentStyle.ts +53 -0
- package/lib/components/Button/style/buttonPrimaryDestructiveStyle.ts +55 -0
- package/lib/components/Button/style/buttonPrimaryStyle.ts +53 -0
- package/lib/components/Button/style/buttonPrimarySubtleStyle.ts +64 -0
- package/lib/components/Button/style/buttonPrimaryWarningStyle.ts +56 -0
- package/lib/components/Button/style/buttonSecondaryDestructiveStyle.ts +63 -0
- package/lib/components/Button/style/buttonSecondaryStyle.ts +62 -0
- package/lib/components/Button/style/buttonSecondarySubtleStyle.ts +72 -0
- package/lib/components/Button/style/buttonTertiaryDestructiveStyle.ts +65 -0
- package/lib/components/Button/style/buttonTertiaryNoPaddingStyle.ts +52 -0
- package/lib/components/Button/style/buttonTertiaryStyle.ts +62 -0
- package/lib/components/Calendar/Calendar.stories.tsx +1 -1
- package/lib/components/Calendar/Calendar.tsx +2 -2
- package/lib/components/Calendar/__tests__/Calendar.test.tsx +23 -15
- package/lib/components/Calendar/__tests__/__snapshots__/Calendar.test.tsx.snap +99 -95
- package/lib/components/Calendar/index.ts +1 -5
- package/lib/components/Calendar/subcomponents/AcademicWeek.tsx +2 -1
- package/lib/components/Calendar/subcomponents/AcademicWeeks.tsx +1 -1
- package/lib/components/Calendar/subcomponents/ColumnHeading.tsx +2 -2
- package/lib/components/Calendar/subcomponents/Controls.tsx +1 -1
- package/lib/components/Calendar/subcomponents/Day.stories.tsx +1 -1
- package/lib/components/Calendar/subcomponents/Day.tsx +7 -9
- package/lib/components/Calendar/subcomponents/EventDot.tsx +3 -6
- package/lib/components/Calendar/subcomponents/index.ts +1 -1
- package/lib/components/Calendar/utils/getDatesForCalendarGrid/getDatesForCalendarGrid.ts +43 -11
- package/lib/components/Calendar/utils/normaliseMonth/normaliseMonth.test.ts +5 -5
- package/lib/components/Checkbox/Checkbox.stories.tsx +1 -1
- package/lib/components/Checkbox/Checkbox.tsx +12 -10
- package/lib/components/Checkbox/__tests__/Checkbox.test.tsx +29 -0
- package/lib/components/Checkbox/__tests__/__snapshots__/Checkbox.test.tsx.snap +4 -4
- package/lib/components/Datepicker/Datepicker.lld.md +108 -0
- package/lib/components/Datepicker/Datepicker.stories.tsx +44 -5
- package/lib/components/Datepicker/Datepicker.tsx +14 -36
- package/lib/components/Datepicker/Datepicker.types.ts +5 -14
- package/lib/components/Datepicker/__tests__/Datepicker.test.tsx +267 -8
- package/lib/components/Datepicker/__tests__/__snapshots__/Datepicker.test.tsx.snap +20 -42
- package/lib/components/Datepicker/subcomponents/CustomDatepicker.tsx +48 -5
- package/lib/components/Datepicker/subcomponents/DatepickerInput.tsx +30 -17
- package/lib/components/Datepicker/subcomponents/Panel.tsx +6 -2
- package/lib/components/Datepicker/subcomponents/VisibleField.tsx +46 -8
- package/lib/components/Datepicker/subcomponents/index.ts +0 -1
- package/lib/components/Datepicker/utils/index.ts +0 -1
- package/lib/components/Dialog/BaseDialog.tsx +13 -2
- package/lib/components/Dialog/Dialog.stories.tsx +1 -1
- package/lib/components/Dialog/Dialog.tsx +8 -1
- package/lib/components/Dialog/DialogBody.tsx +5 -1
- package/lib/components/Dialog/DialogHeader.tsx +2 -1
- package/lib/components/Divider/Divider.stories.tsx +1 -1
- package/lib/components/Divider/__tests__/__snapshots__/Breadcrumbs.test.tsx.snap +12 -12
- package/lib/components/FeedbackDialog/FeedbackDialog.stories.tsx +1 -1
- package/lib/components/FeedbackDialog/FeedbackDialog.tsx +4 -6
- package/lib/components/Field/CharacterCount.tsx +2 -2
- package/lib/components/Field/ErrorText.tsx +2 -1
- package/lib/components/Field/Field.stories.tsx +1 -1
- package/lib/components/Field/Field.tsx +1 -1
- package/lib/components/Field/HelperText.tsx +3 -1
- package/lib/components/Field/__tests__/Field.test.tsx +13 -0
- package/lib/components/FileInput/FileInput.stories.tsx +1 -1
- package/lib/components/FileInput/__tests__/__snapshots__/FileInput.test.tsx.snap +4 -20
- package/lib/components/Footer/Footer.stories.tsx +1 -1
- package/lib/components/Footer/__tests__/__snapshots__/Footer.test.tsx.snap +73 -82
- package/lib/components/FooterNew/BackToTop.tsx +83 -0
- package/lib/components/FooterNew/Footer.tsx +110 -0
- package/lib/components/FooterNew/FooterColumn.tsx +79 -0
- package/lib/components/FooterNew/FooterLinks.tsx +44 -0
- package/lib/components/FooterNew/FooterNavLink.tsx +63 -0
- package/lib/components/FooterNew/LegalAndCopyright.tsx +150 -0
- package/lib/components/FooterNew/LogoAddressAndSocial.tsx +154 -0
- package/lib/components/FooterNew/SocialLink.tsx +108 -0
- package/lib/components/FooterNew/__tests__/Footer.test.tsx +51 -0
- package/lib/components/FooterNew/__tests__/__snapshots__/Footer.test.tsx.snap +1107 -0
- package/lib/components/FooterNew/index.ts +2 -0
- package/lib/components/Header/Header.mdx +52 -0
- package/lib/components/Header/Header.stories.tsx +98 -0
- package/lib/components/Header/Header.tsx +51 -6
- package/lib/components/Header/__tests__/Header.test.tsx +17 -1
- package/lib/components/HeaderDraft/__tests__/__snapshots__/Header.test.tsx.snap +3 -2
- package/lib/components/HeaderNew/Header.tsx +93 -0
- package/lib/components/HeaderNew/HeaderBorder.tsx +55 -0
- package/lib/components/HeaderNew/HeaderLogo.tsx +70 -0
- package/lib/components/HeaderNew/HeaderMenuContainer.tsx +35 -0
- package/lib/components/HeaderNew/HeaderTitle.tsx +53 -0
- package/lib/components/HeaderNew/__tests__/Header.test.tsx +42 -0
- package/lib/components/HeaderNew/__tests__/__snapshots__/Header.test.tsx.snap +79 -0
- package/lib/components/HeaderNew/constants.ts +3 -0
- package/lib/components/HeaderNew/index.ts +7 -0
- package/lib/components/Heading/Heading.stories.tsx +1 -1
- package/lib/components/HeadingNew/Heading.tsx +208 -0
- package/lib/components/HeadingNew/index.ts +2 -0
- package/lib/components/Icon/Icon.stories.tsx +1 -1
- package/lib/components/Icon/__tests__/__snapshots__/Icon.test.tsx.snap +16 -12
- package/lib/components/Icon/svgImports.ts +318 -296
- package/lib/components/IconButton/IconButton.stories.tsx +1 -1
- package/lib/components/IconButton/IconButton.tsx +3 -4
- package/lib/components/IconButton/__tests__/__snapshots__/IconButton.test.tsx.snap +12 -9
- package/lib/components/Input/Input.stories.tsx +1 -1
- package/lib/components/Label/Label.stories.tsx +1 -1
- package/lib/components/Link/BaseLink.tsx +114 -71
- package/lib/components/Link/Link.stories.tsx +1 -1
- package/lib/components/Link/Link.tsx +120 -109
- package/lib/components/Link/__tests__/__snapshots__/link.test.tsx.snap +2 -2
- package/lib/components/Main/Main.stories.tsx +36 -0
- package/lib/components/Main/Main.tsx +46 -0
- package/lib/components/Main/__tests__/Main.test.tsx +80 -0
- package/lib/components/Main/__tests__/__snapshots__/Main.test.tsx.snap +33 -0
- package/lib/components/Main/index.ts +2 -0
- package/lib/components/MenuNew/Menu.context.tsx +149 -0
- package/lib/components/MenuNew/Menu.tsx +75 -0
- package/lib/components/MenuNew/MenuContent.tsx +140 -0
- package/lib/components/MenuNew/MenuItem.tsx +101 -0
- package/lib/components/MenuNew/MenuSection.tsx +47 -0
- package/lib/components/MenuNew/index.ts +8 -0
- package/lib/components/MenuNew/trigger/ButtonMenuTrigger.tsx +42 -0
- package/lib/components/MenuNew/trigger/IconMenuTrigger.tsx +40 -0
- package/lib/components/NativeDatepicker/NativeDatepicker.stories.tsx +100 -0
- package/lib/components/{Datepicker/subcomponents → NativeDatepicker}/NativeDatepicker.tsx +14 -15
- package/lib/components/NativeDatepicker/NativeDatepicker.types.ts +19 -0
- package/lib/components/NativeDatepicker/index.ts +2 -0
- package/lib/components/{Datepicker → NativeDatepicker}/utils/dateToLocaleISOString/dateToLocaleISOString.ts +1 -1
- package/lib/components/NativeDatepicker/utils/index.ts +1 -0
- package/lib/components/Pagination/Pagination.stories.tsx +1 -1
- package/lib/components/Pagination/PaginationControls.tsx +59 -17
- package/lib/components/Pagination/PaginationInfo.tsx +7 -4
- package/lib/components/Paragraph/Paragraph.stories.tsx +1 -1
- package/lib/components/ParagraphNew/Paragraph.tsx +200 -0
- package/lib/components/ParagraphNew/index.ts +6 -0
- package/lib/components/Radio/Radio.stories.tsx +1 -1
- package/lib/components/Radio/Radio.tsx +8 -8
- package/lib/components/Radio/__tests__/__snapshots__/Radio.test.tsx.snap +4 -4
- package/lib/components/Search/Search.stories.tsx +1 -1
- package/lib/components/Search/Search.tsx +4 -1
- package/lib/components/Search/__tests__/Search.test.tsx +19 -1
- package/lib/components/Search/__tests__/__snapshots__/Search.test.tsx.snap +12 -32
- package/lib/components/Select/Select.mdx +192 -0
- package/lib/components/Select/Select.stories.tsx +229 -48
- package/lib/components/Select/Select.tsx +50 -15
- package/lib/components/Select/Select.types.ts +99 -44
- package/lib/components/Select/__tests__/Select.test.tsx +698 -8
- package/lib/components/Select/__tests__/__snapshots__/Select.test.tsx.snap +5 -4
- package/lib/components/Select/subcomponents/CustomOption.tsx +12 -4
- package/lib/components/Select/subcomponents/CustomSelect.tsx +411 -41
- package/lib/components/Select/subcomponents/FilterInput.tsx +90 -0
- package/lib/components/Select/subcomponents/NativeSelect.tsx +21 -17
- package/lib/components/Select/subcomponents/Panel.tsx +2 -2
- package/lib/components/Select/subcomponents/VisibleField.tsx +59 -6
- package/lib/components/Select/subcomponents/index.tsx +1 -0
- package/lib/components/Snackbar/Snackbar.stories.tsx +1 -1
- package/lib/components/Snackbar/__tests__/__snapshots__/Snackbar.test.tsx.snap +9 -15
- package/lib/components/Spinner/Spinner.stories.tsx +1 -1
- package/lib/components/Spinner/Spinner.tsx +24 -5
- package/lib/components/Spinner/__tests__/Spinner.test.tsx +35 -5
- package/lib/components/Spinner/__tests__/__snapshots__/Spinner.test.tsx.snap +40 -16
- package/lib/components/StandaloneLink/StandaloneLink.stories.tsx +1 -1
- package/lib/components/StandaloneLink/StandaloneLink.tsx +180 -163
- package/lib/components/StandaloneLink/__tests__/__snapshots__/StandaloneLink.test.tsx.snap +2 -2
- package/lib/components/Table/Table.stories.tsx +1 -1
- package/lib/components/Table/Table.tsx +2 -0
- package/lib/components/Table/Table.types.ts +1 -0
- package/lib/components/Table/__tests__/Table.test.tsx +19 -0
- package/lib/components/Table/__tests__/__snapshots__/Table.test.tsx.snap +7 -3
- package/lib/components/Table/subcomponents/Cell/Cell.stories.tsx +1 -1
- package/lib/components/Table/subcomponents/Cell/Cell.tsx +23 -2
- package/lib/components/Table/subcomponents/Cell/CellContent.tsx +12 -1
- package/lib/components/Table/subcomponents/Cell/__tests__/Cell.test.tsx +106 -0
- package/lib/components/Table/subcomponents/Cell/__tests__/__snapshots__/Cell.test.tsx.snap +4 -3
- package/lib/components/Table/subcomponents/HeadCell/HeadCell.stories.tsx +1 -1
- package/lib/components/Table/subcomponents/HeadCell/HeadCell.tsx +28 -6
- package/lib/components/Table/subcomponents/HeadCell/HeadCellContent.tsx +3 -0
- package/lib/components/Table/subcomponents/HeadCell/__tests__/HeadCell.test.tsx +221 -2
- package/lib/components/Table/subcomponents/HeadCell/__tests__/__snapshots__/HeadCell.test.tsx.snap +6 -4
- package/lib/components/Table/subcomponents/Row.tsx +2 -2
- package/lib/components/Table/subcomponents/SortIcon.tsx +1 -0
- package/lib/components/Table/subcomponents/__tests__/Row.test.tsx +59 -0
- package/lib/components/Tabs/Tab.tsx +3 -3
- package/lib/components/Tabs/Tabs.stories.tsx +1 -1
- package/lib/components/Tabs/Tabs.tsx +5 -3
- package/lib/components/Tabs/__tests__/__snapshots__/Tabs.test.tsx.snap +4 -4
- package/lib/components/Textarea/Textarea.stories.tsx +1 -1
- package/lib/components/Timepicker/Timepicker.stories.tsx +1 -1
- package/lib/components/Timepicker/Timepicker.tsx +4 -0
- package/lib/components/Timepicker/__tests__/__snapshots__/Timepicker.test.tsx.snap +2 -2
- package/lib/components/Toggle/Toggle.stories.tsx +1 -1
- package/lib/components/Toggle/Toggle.tsx +5 -5
- package/lib/components/Toggle/ToggleHandle.tsx +2 -3
- package/lib/components/Tooltip/Tooltip.stories.tsx +1 -1
- package/lib/components/Tooltip/Tooltip.tsx +2 -2
- package/lib/components/Tooltip/__tests__/__snapshots__/tooltip.test.tsx.snap +2 -2
- package/lib/components/UclLogoNew/UclLogo.tsx +42 -0
- package/lib/components/UclLogoNew/index.ts +2 -0
- package/lib/components/WeekPicker/WeekPicker.stories.tsx +145 -0
- package/lib/components/WeekPicker/WeekPicker.tsx +2 -2
- package/lib/components/WeekPicker/WeekPicker.types.ts +21 -0
- package/lib/components/WeekPicker/index.ts +1 -0
- package/lib/components/WeekPicker/subcomponents/CustomDatepicker.tsx +1 -1
- package/lib/components/common/Common.mdx +1 -2
- package/lib/components/index.ts +30 -3
- package/lib/hooks/useFocusTrap.ts +40 -4
- package/lib/index.ts +1 -0
- package/lib/theme/Colours.mdx +1 -1
- package/lib/theme/Theme.mdx +1 -1
- package/lib/theme/Typography.mdx +1 -1
- package/lib/theme/__tests__/fonts.test.ts +37 -0
- package/lib/theme/common/themeCommon.ts +515 -0
- package/lib/theme/fonts.ts +110 -0
- package/lib/theme/index.ts +6 -6
- package/lib/theme/light/lightColour.ts +232 -0
- package/lib/theme/light/lightTheme.ts +37 -0
- package/lib/theme/{defaultTheme.ts → original/color.ts} +17 -199
- package/lib/theme/original/defaultTheme.ts +207 -0
- package/lib/theme/original/originalColourNewStructure.ts +185 -0
- package/lib/theme/useTheme.tsx +72 -15
- package/lib/types/assets.d.ts +10 -0
- package/lib/utils/__tests__/announce.test.ts +121 -0
- package/lib/utils/addAlphaToHex.ts +29 -0
- package/lib/utils/announce.ts +134 -0
- package/lib/utils/index.ts +1 -0
- package/lib/utils/scrollToTop.ts +5 -0
- package/package.json +11 -9
- package/dist/components/Button/buttonPrimaryStyle.d.ts +0 -4
- package/dist/components/Button/buttonSecondaryStyle.d.ts +0 -4
- package/dist/components/Button/buttonTertiaryStyle.d.ts +0 -4
- package/dist/components/Datepicker/subcomponents/NativeDatepicker.d.ts +0 -6
- package/dist/theme/defaultTheme.d.ts +0 -274
- package/lib/components/Accordion/Accordion.stories.tsx.NOT_READY +0 -93
- package/lib/components/Button/buttonPrimaryStyle.ts +0 -62
- package/lib/components/Button/buttonSecondaryStyle.ts +0 -65
- package/lib/components/Button/buttonTertiaryStyle.ts +0 -54
- /package/dist/components/{Datepicker/utils/dateToLocaleISOString/dateToLocaleISOString.test.d.ts → FooterNew/__tests__/Footer.test.d.ts} +0 -0
- /package/lib/components/{Datepicker → NativeDatepicker}/utils/dateToLocaleISOString/dateToLocaleISOString.test.ts +0 -0
|
@@ -18,7 +18,8 @@ const AcademicWeek = ({ weekNumber }: AcademicWeekProps) => {
|
|
|
18
18
|
height: 40px;
|
|
19
19
|
font-family: ${theme.font.family.primary};
|
|
20
20
|
font-size: ${theme.font.size.f14};
|
|
21
|
-
color: #6345a5;
|
|
21
|
+
/* color: #6345a5; */
|
|
22
|
+
color: ${theme.colour.text.brandPrimary};
|
|
22
23
|
`;
|
|
23
24
|
|
|
24
25
|
const style = cx(NAME, baseStyle);
|
|
@@ -22,7 +22,7 @@ const AcademicWeeks = ({ date, weeks }: AcademicWeeksProps) => {
|
|
|
22
22
|
flex-direction: column;
|
|
23
23
|
padding-top: 32px;
|
|
24
24
|
width: 50px;
|
|
25
|
-
background-color: ${theme.
|
|
25
|
+
background-color: ${theme.colour.surface.brand};
|
|
26
26
|
user-select: none;
|
|
27
27
|
`;
|
|
28
28
|
|
|
@@ -19,8 +19,8 @@ const ColumnHeading = ({ index, day, isWeekend }: ColumnHeadingProps) => {
|
|
|
19
19
|
width: 40px;
|
|
20
20
|
height: 32px;
|
|
21
21
|
color: ${isWeekend
|
|
22
|
-
? theme.
|
|
23
|
-
: theme.
|
|
22
|
+
? theme.colour.text.warningOnBgFill
|
|
23
|
+
: theme.colour.text.secondary};
|
|
24
24
|
font-weight: 700;
|
|
25
25
|
`;
|
|
26
26
|
|
|
@@ -42,25 +42,24 @@ const Day = ({
|
|
|
42
42
|
position: relative;
|
|
43
43
|
width: 40px;
|
|
44
44
|
height: 40px;
|
|
45
|
-
background-color: ${theme.
|
|
45
|
+
background-color: ${theme.colour.fill.inverse};
|
|
46
46
|
cursor: pointer;
|
|
47
47
|
outline: none;
|
|
48
48
|
|
|
49
49
|
&:hover {
|
|
50
|
-
background-color: ${theme.
|
|
50
|
+
background-color: ${theme.colour.fill.hover};
|
|
51
51
|
}
|
|
52
52
|
|
|
53
53
|
${isSelected &&
|
|
54
54
|
css`
|
|
55
|
-
/* background-color: ${theme.color.interaction.blue70}; */
|
|
56
55
|
background-color: ${isDisabled
|
|
57
|
-
? theme.
|
|
58
|
-
: theme.
|
|
56
|
+
? theme.colour.fill.disabled
|
|
57
|
+
: theme.colour.fill.brand};
|
|
59
58
|
|
|
60
|
-
color: ${theme.
|
|
59
|
+
color: ${theme.colour.text.inverse};
|
|
61
60
|
|
|
62
61
|
&:hover {
|
|
63
|
-
background-color: ${theme.
|
|
62
|
+
background-color: ${theme.colour.fill.brandHover};
|
|
64
63
|
}
|
|
65
64
|
`}
|
|
66
65
|
${isDisabled &&
|
|
@@ -68,7 +67,6 @@ const Day = ({
|
|
|
68
67
|
cursor: not-allowed;
|
|
69
68
|
|
|
70
69
|
&:hover {
|
|
71
|
-
/* background-color: ${theme.color.neutral.white}; */
|
|
72
70
|
background-color: ${isSelected
|
|
73
71
|
? theme.color.neutral.grey10
|
|
74
72
|
: theme.color.neutral.white};
|
|
@@ -91,7 +89,7 @@ const Day = ({
|
|
|
91
89
|
`}
|
|
92
90
|
${isDisabled &&
|
|
93
91
|
css`
|
|
94
|
-
color: ${theme.
|
|
92
|
+
color: ${theme.colour.text.disabled};
|
|
95
93
|
`}
|
|
96
94
|
`;
|
|
97
95
|
|
|
@@ -11,14 +11,11 @@ interface EventDotProps {
|
|
|
11
11
|
const EventDot = ({ inverted, inCurrentMonth }: EventDotProps) => {
|
|
12
12
|
const [theme] = useTheme();
|
|
13
13
|
|
|
14
|
-
const invertedColour = theme.color.neutral.white;
|
|
15
|
-
const outOfCurrentMonthColour = '#8C8C8C'; // TODO: Needs adding to `defaultTheme.ts`, as a design token
|
|
16
|
-
|
|
17
14
|
const backgroundColour = inCurrentMonth
|
|
18
15
|
? inverted
|
|
19
|
-
?
|
|
20
|
-
: theme.
|
|
21
|
-
:
|
|
16
|
+
? theme.colour.icon.inverse
|
|
17
|
+
: theme.colour.icon.brand
|
|
18
|
+
: theme.colour.icon.tertiary;
|
|
22
19
|
|
|
23
20
|
const baseStyle = css`
|
|
24
21
|
width: 6px;
|
|
@@ -4,4 +4,4 @@ export { default as AcademicWeek } from './AcademicWeek';
|
|
|
4
4
|
export { default as Grid } from './Grid';
|
|
5
5
|
export { default as ColumnHeading } from './ColumnHeading';
|
|
6
6
|
export { default as Day } from './Day';
|
|
7
|
-
export { default as EventDot } from './EventDot';
|
|
7
|
+
export { default as EventDot } from './EventDot';
|
|
@@ -17,15 +17,24 @@
|
|
|
17
17
|
* ```
|
|
18
18
|
*/
|
|
19
19
|
const getDatesForCalendarGrid = (date: Date): Date[] => {
|
|
20
|
-
if (!date || !(date instanceof Date))
|
|
20
|
+
if (!date || !(date instanceof Date))
|
|
21
|
+
throw new Error('No date provided');
|
|
21
22
|
|
|
22
23
|
const month = date.getMonth();
|
|
23
|
-
const daysInMonth = new Date(
|
|
24
|
+
const daysInMonth = new Date(
|
|
25
|
+
date.getFullYear(),
|
|
26
|
+
month + 1,
|
|
27
|
+
0
|
|
28
|
+
).getDate();
|
|
24
29
|
|
|
25
30
|
// Get all days in current month
|
|
26
31
|
const dates: Date[] = [];
|
|
27
32
|
for (let day = 1; day <= daysInMonth; day++) {
|
|
28
|
-
const newDate = new Date(
|
|
33
|
+
const newDate = new Date(
|
|
34
|
+
date.getFullYear(),
|
|
35
|
+
month,
|
|
36
|
+
day
|
|
37
|
+
);
|
|
29
38
|
if (newDate.getMonth() !== month) break;
|
|
30
39
|
dates.push(newDate);
|
|
31
40
|
}
|
|
@@ -34,14 +43,28 @@ const getDatesForCalendarGrid = (date: Date): Date[] => {
|
|
|
34
43
|
// Sunday (0) should become 6
|
|
35
44
|
// Monday (1) should become 0
|
|
36
45
|
// Tuesday (2) should become 1, etc.
|
|
37
|
-
const adjustDay = (day: number): number =>
|
|
46
|
+
const adjustDay = (day: number): number =>
|
|
47
|
+
day === 0 ? 6 : day - 1;
|
|
38
48
|
|
|
39
49
|
// Calculate previous month's "grey days"
|
|
40
50
|
const prevMonthGreyDays = [];
|
|
41
|
-
const prevMonth = new Date(
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
51
|
+
const prevMonth = new Date(
|
|
52
|
+
date.getFullYear(),
|
|
53
|
+
month - 1,
|
|
54
|
+
1
|
|
55
|
+
);
|
|
56
|
+
const firstDayOfMonth = new Date(
|
|
57
|
+
date.getFullYear(),
|
|
58
|
+
month,
|
|
59
|
+
1
|
|
60
|
+
).getDay();
|
|
61
|
+
const numberOfDaysFromPrevMonth =
|
|
62
|
+
adjustDay(firstDayOfMonth);
|
|
63
|
+
const totalDaysInPrevMonth = new Date(
|
|
64
|
+
date.getFullYear(),
|
|
65
|
+
month,
|
|
66
|
+
0
|
|
67
|
+
).getDate();
|
|
45
68
|
|
|
46
69
|
for (let i = numberOfDaysFromPrevMonth; i > 0; i--) {
|
|
47
70
|
prevMonthGreyDays.push(
|
|
@@ -55,17 +78,26 @@ const getDatesForCalendarGrid = (date: Date): Date[] => {
|
|
|
55
78
|
|
|
56
79
|
// Calculate next month's "grey days"
|
|
57
80
|
const nextMonthGreyDays = [];
|
|
58
|
-
const nextMonth = new Date(
|
|
81
|
+
const nextMonth = new Date(
|
|
82
|
+
date.getFullYear(),
|
|
83
|
+
month + 1,
|
|
84
|
+
1
|
|
85
|
+
);
|
|
59
86
|
const lastDayOfMonth = new Date(
|
|
60
87
|
date.getFullYear(),
|
|
61
88
|
month,
|
|
62
89
|
daysInMonth
|
|
63
90
|
).getDay();
|
|
64
|
-
const numberOfDaysFromNextMonth =
|
|
91
|
+
const numberOfDaysFromNextMonth =
|
|
92
|
+
6 - adjustDay(lastDayOfMonth);
|
|
65
93
|
|
|
66
94
|
for (let i = 1; i <= numberOfDaysFromNextMonth; i++) {
|
|
67
95
|
nextMonthGreyDays.push(
|
|
68
|
-
new Date(
|
|
96
|
+
new Date(
|
|
97
|
+
nextMonth.getFullYear(),
|
|
98
|
+
nextMonth.getMonth(),
|
|
99
|
+
i
|
|
100
|
+
)
|
|
69
101
|
);
|
|
70
102
|
}
|
|
71
103
|
|
|
@@ -2,15 +2,15 @@ import { describe, expect, test } from 'vitest';
|
|
|
2
2
|
import normaliseMonth from './normaliseMonth';
|
|
3
3
|
|
|
4
4
|
describe('Calendar: normaliseMonth', () => {
|
|
5
|
-
test(
|
|
5
|
+
test("Should return null if given undefined", () => {
|
|
6
6
|
expect(normaliseMonth(undefined)).toBeNull();
|
|
7
7
|
});
|
|
8
8
|
|
|
9
|
-
test(
|
|
9
|
+
test("Should return null if given null", () => {
|
|
10
10
|
expect(normaliseMonth(null)).toBeNull();
|
|
11
11
|
});
|
|
12
12
|
|
|
13
|
-
test(
|
|
13
|
+
test("Returns a Date object set to the first of the month", () => {
|
|
14
14
|
const date = new Date('2025-03-10');
|
|
15
15
|
const normalisedDate = normaliseMonth(date);
|
|
16
16
|
expect(normalisedDate).toBeInstanceOf(Date);
|
|
@@ -19,7 +19,7 @@ describe('Calendar: normaliseMonth', () => {
|
|
|
19
19
|
expect(normalisedDate?.getDate()).toBe(1);
|
|
20
20
|
});
|
|
21
21
|
|
|
22
|
-
test(
|
|
22
|
+
test("Works for a date within daylight saving time", () => {
|
|
23
23
|
const date = new Date('2025-06-15');
|
|
24
24
|
const normalisedDate = normaliseMonth(date);
|
|
25
25
|
expect(normalisedDate).toBeInstanceOf(Date);
|
|
@@ -28,7 +28,7 @@ describe('Calendar: normaliseMonth', () => {
|
|
|
28
28
|
expect(normalisedDate?.getDate()).toBe(1);
|
|
29
29
|
});
|
|
30
30
|
|
|
31
|
-
test(
|
|
31
|
+
test("Returned date is normalised for midnight", () => {
|
|
32
32
|
const date = new Date('2025-01-01T12:34:56');
|
|
33
33
|
const normalisedDate = normaliseMonth(date);
|
|
34
34
|
expect(normalisedDate).toBeInstanceOf(Date);
|
|
@@ -4,7 +4,7 @@ import { useArgs } from '@storybook/preview-api';
|
|
|
4
4
|
import Checkbox from './Checkbox';
|
|
5
5
|
|
|
6
6
|
const meta = {
|
|
7
|
-
title: 'Components/
|
|
7
|
+
title: 'Components/Checkbox',
|
|
8
8
|
component: Checkbox,
|
|
9
9
|
argTypes: {
|
|
10
10
|
checked: { control: { type: 'boolean' } },
|
|
@@ -12,10 +12,10 @@ import marginsStyle, { MarginProps } from '../common/marginsStyle';
|
|
|
12
12
|
|
|
13
13
|
export const NAME = 'ucl-uikit-checkbox';
|
|
14
14
|
|
|
15
|
-
export interface CheckboxBaseProps
|
|
16
|
-
extends InputHTMLAttributes<HTMLInputElement> {
|
|
15
|
+
export interface CheckboxBaseProps extends InputHTMLAttributes<HTMLInputElement> {
|
|
17
16
|
indeterminate?: boolean;
|
|
18
17
|
testId?: string;
|
|
18
|
+
ariaLabel?: string;
|
|
19
19
|
}
|
|
20
20
|
|
|
21
21
|
export type CheckboxProps = CheckboxBaseProps & MarginProps;
|
|
@@ -30,6 +30,7 @@ const Checkbox = forwardRef<Ref, CheckboxProps>(
|
|
|
30
30
|
defaultChecked,
|
|
31
31
|
disabled,
|
|
32
32
|
testId = NAME,
|
|
33
|
+
ariaLabel,
|
|
33
34
|
className,
|
|
34
35
|
...props
|
|
35
36
|
},
|
|
@@ -61,7 +62,7 @@ const Checkbox = forwardRef<Ref, CheckboxProps>(
|
|
|
61
62
|
border-radius: ${theme.radius.r2};
|
|
62
63
|
outline: none;
|
|
63
64
|
box-sizing: border-box;
|
|
64
|
-
color: ${theme.
|
|
65
|
+
color: ${theme.colour.icon.inverse};
|
|
65
66
|
transition:
|
|
66
67
|
background-color 0.15s ease-out,
|
|
67
68
|
border-color 0.15s ease-out;
|
|
@@ -75,19 +76,19 @@ const Checkbox = forwardRef<Ref, CheckboxProps>(
|
|
|
75
76
|
`;
|
|
76
77
|
|
|
77
78
|
const checkedStyle = css`
|
|
78
|
-
background-color: ${theme.
|
|
79
|
-
border-color: ${theme.
|
|
80
|
-
color: ${theme.
|
|
79
|
+
background-color: ${theme.colour.icon.brand};
|
|
80
|
+
border-color: ${theme.colour.icon.brand};
|
|
81
|
+
color: ${theme.colour.icon.inverse};
|
|
81
82
|
`;
|
|
82
83
|
|
|
83
84
|
const uncheckedStyle = css`
|
|
84
|
-
background-color: ${theme.
|
|
85
|
-
border-color: ${theme.
|
|
85
|
+
background-color: ${theme.colour.icon.inverse};
|
|
86
|
+
border-color: ${theme.colour.speciality.inputDefault};
|
|
86
87
|
`;
|
|
87
88
|
|
|
88
89
|
const disabledStyle = css`
|
|
89
|
-
background-color: ${theme.
|
|
90
|
-
border-color: ${theme.
|
|
90
|
+
background-color: ${theme.colour.icon.disabled};
|
|
91
|
+
border-color: ${theme.colour.icon.disabled};
|
|
91
92
|
cursor: not-allowed;
|
|
92
93
|
`;
|
|
93
94
|
|
|
@@ -140,6 +141,7 @@ const Checkbox = forwardRef<Ref, CheckboxProps>(
|
|
|
140
141
|
ref={ref}
|
|
141
142
|
className={hiddenInputStyle}
|
|
142
143
|
data-testid={testId}
|
|
144
|
+
aria-label={ariaLabel}
|
|
143
145
|
{...(isControlled ? { checked } : { defaultChecked })}
|
|
144
146
|
disabled={disabled}
|
|
145
147
|
onChange={handleChange}
|
|
@@ -96,4 +96,33 @@ describe('Checkbox', () => {
|
|
|
96
96
|
await user.click(checkbox);
|
|
97
97
|
expect(checkbox.checked).toBe(false);
|
|
98
98
|
});
|
|
99
|
+
|
|
100
|
+
// Accessibility tests
|
|
101
|
+
|
|
102
|
+
test('ariaLabel prop is applied to the input as aria-label', () => {
|
|
103
|
+
render(
|
|
104
|
+
<ThemeContextProvider>
|
|
105
|
+
<Checkbox ariaLabel='Select John Smith' />
|
|
106
|
+
</ThemeContextProvider>
|
|
107
|
+
);
|
|
108
|
+
expect(screen.getByRole('checkbox')).toHaveAttribute(
|
|
109
|
+
'aria-label',
|
|
110
|
+
'Select John Smith'
|
|
111
|
+
);
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
test('aria-label passed via spread props overrides ariaLabel', () => {
|
|
115
|
+
render(
|
|
116
|
+
<ThemeContextProvider>
|
|
117
|
+
<Checkbox
|
|
118
|
+
ariaLabel='Default label'
|
|
119
|
+
aria-label='Override label'
|
|
120
|
+
/>
|
|
121
|
+
</ThemeContextProvider>
|
|
122
|
+
);
|
|
123
|
+
expect(screen.getByRole('checkbox')).toHaveAttribute(
|
|
124
|
+
'aria-label',
|
|
125
|
+
'Override label'
|
|
126
|
+
);
|
|
127
|
+
});
|
|
99
128
|
});
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
exports[`Checkbox > snapshot: checked prop 1`] = `
|
|
4
4
|
<span
|
|
5
|
-
class="ucl-uikit-checkbox css-
|
|
5
|
+
class="ucl-uikit-checkbox css-xzd91z"
|
|
6
6
|
>
|
|
7
7
|
<input
|
|
8
8
|
checked=""
|
|
@@ -32,7 +32,7 @@ exports[`Checkbox > snapshot: checked prop 1`] = `
|
|
|
32
32
|
|
|
33
33
|
exports[`Checkbox > snapshot: indeterminate prop 1`] = `
|
|
34
34
|
<span
|
|
35
|
-
class="ucl-uikit-checkbox css-
|
|
35
|
+
class="ucl-uikit-checkbox css-xzd91z"
|
|
36
36
|
>
|
|
37
37
|
<input
|
|
38
38
|
class="css-nzy7im"
|
|
@@ -64,7 +64,7 @@ exports[`Checkbox > snapshot: indeterminate prop 1`] = `
|
|
|
64
64
|
|
|
65
65
|
exports[`Checkbox > snapshot: no props 1`] = `
|
|
66
66
|
<span
|
|
67
|
-
class="ucl-uikit-checkbox css-
|
|
67
|
+
class="ucl-uikit-checkbox css-tumlz"
|
|
68
68
|
>
|
|
69
69
|
<input
|
|
70
70
|
class="css-nzy7im"
|
|
@@ -76,7 +76,7 @@ exports[`Checkbox > snapshot: no props 1`] = `
|
|
|
76
76
|
|
|
77
77
|
exports[`Checkbox > snapshot: testId prop 1`] = `
|
|
78
78
|
<span
|
|
79
|
-
class="ucl-uikit-checkbox css-
|
|
79
|
+
class="ucl-uikit-checkbox css-tumlz"
|
|
80
80
|
>
|
|
81
81
|
<input
|
|
82
82
|
class="css-nzy7im"
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
# Datepicker - Low-level design documentation
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
The `<Datepicker>` allows the user to enter a date into the system.
|
|
6
|
+
|
|
7
|
+
By default, it is a 'custom' implementation built using React logic.
|
|
8
|
+
|
|
9
|
+
A 'browser-native' implementation is also available from this component, using prop `native={true}`.
|
|
10
|
+
|
|
11
|
+
## Design specifications
|
|
12
|
+
|
|
13
|
+
- Figma: [UCL Design System - UIKit Datepicker](https://www.figma.com/design/8Sm5PxWOWJYpYXAzhRzUzt/UCL-Design-System-UI-Kit?node-id=6531-3397)
|
|
14
|
+
|
|
15
|
+
## Conceptual model
|
|
16
|
+
|
|
17
|
+
The Calendar displayed is a separate UI 'unit' in the Design System, so it is imported rather than defined in this component.
|
|
18
|
+
|
|
19
|
+
There are additional useful features, such as displaying when 'events' are in the calendar. The Datepicker needs to pass these to the Calendar.
|
|
20
|
+
|
|
21
|
+
The Datepicker supports minimum & maximum dates, and validates against a date being outside this range.
|
|
22
|
+
|
|
23
|
+
### User interaction
|
|
24
|
+
|
|
25
|
+
The user wants to enter a date into the system. They do this by clicking on the datepicker and typing. This is the **primary** interaction model.
|
|
26
|
+
|
|
27
|
+
The user might also want to see and then select a date from the calendar view. This is the **secondary** interaction model.
|
|
28
|
+
|
|
29
|
+
## Implementation details
|
|
30
|
+
|
|
31
|
+
As much as possible, all core logic should be defined in `<CustomDatepicker>`. Subcomponents should be simple and focused on a single responsibility.
|
|
32
|
+
|
|
33
|
+
### Props
|
|
34
|
+
|
|
35
|
+
The Datepicker receives a `Date` object via `value`, and returns a `Date` object via `onValueChange`. `onValueChange` also returns the raw event object as its second argument, in case the consumer needs to access it. This aligns with the props pattern used by other form-field-level components in `uikit-react`.
|
|
36
|
+
|
|
37
|
+
### Subcomponents
|
|
38
|
+
|
|
39
|
+
- `<CustomDatepicker>`: The default implementation of the Datepicker, built using React logic.
|
|
40
|
+
- `<VisibleField>`: Handles the part of the Datepicker that is _always_ visible to the user -- as a 'form field' input. Composes the controlled input and buttons for opening the calendar and clearing the field.
|
|
41
|
+
- `<DatepickerInput>`: The input field for the Datepicker, used in the custom implementation.
|
|
42
|
+
- `<Panel>`: Wrapper component that handles positioning.
|
|
43
|
+
- `<NativeDatepicker>`: An alternative implementation of the Datepicker, using the browser's native date input.
|
|
44
|
+
|
|
45
|
+
**Additional components:**
|
|
46
|
+
- `<Calendar>`: Imported as a separate component and passed as child to `<Panel>`.
|
|
47
|
+
|
|
48
|
+
#### Subcomponent hierarchy
|
|
49
|
+
|
|
50
|
+
```mermaid
|
|
51
|
+
graph TD
|
|
52
|
+
A[Datepicker] -->| native=false | B[CustomDatepicker]
|
|
53
|
+
A -->| native=true | C[NativeDatepicker]
|
|
54
|
+
B --> D[VisibleField]
|
|
55
|
+
D --> E[DatepickerInput]
|
|
56
|
+
B --> F[Panel]
|
|
57
|
+
F --> G[Calendar]
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### Date parsing
|
|
61
|
+
|
|
62
|
+
After the user types a date into the input, they need to press ENTER or TAB to parse the date.
|
|
63
|
+
|
|
64
|
+
### Accessibility
|
|
65
|
+
|
|
66
|
+
Utility function [`announce`](../../utils/announce.ts) is used to provide screen-reader feedback when a date is selected. Places where this is used:
|
|
67
|
+
|
|
68
|
+
- When a date is 'picked' with the Calendar
|
|
69
|
+
- When a date is entered into the input field and successfully parsed.
|
|
70
|
+
|
|
71
|
+
`announce` is only called in `CustomDatepicker`.
|
|
72
|
+
|
|
73
|
+
Automatic association of `<Label>` with `DatepickerInput` when `<Datepicker>` is in a `<Field>` would improve default accessibility -- described in [Datepicker_improv_004].
|
|
74
|
+
|
|
75
|
+
## Known issues
|
|
76
|
+
|
|
77
|
+
- **[Datepicker_issue_001]**: The Calendar itself, when rendered in the Panel, may not pass Accessibility tests. However, we expect users with Accessibility needs are able to successfully enter a date using the controlled input.
|
|
78
|
+
- The Calendar panel lacks ARIA roles (`role="dialog"`, `role="grid"`, `aria-selected`, etc.), keyboard navigation (arrow keys between days, Escape to close), and the calendar toggle in `<VisibleField>` is a `<div>` with `role="button"` rather than a native `<button>`. This is a WCAG 2.2 AA compliance risk.
|
|
79
|
+
- **[Datepicker_issue_002]**: The Panel only appears below the Datepicker's visible field. If the Datepicker is close to the bottom of the browser viewport, this increases the viewport size while the Panel is open (temporarily).
|
|
80
|
+
- **[Datepicker_issue_003]**: `minDate` and `maxDate` are ISO date strings (`'YYYY-MM-DD'`), which are parsed via `new Date(string)` in several places (`CustomDatepicker.tsx`, `parseInputValue.ts`). This creates UTC dates, not local dates, causing off-by-one day bugs in timezones behind UTC. Options:
|
|
81
|
+
- **Option A**: Create a `parseISODateLocal` utility that splits the string and uses `new Date(year, month - 1, day)`, and use it everywhere.
|
|
82
|
+
- **Option B**: Change `minDate`/`maxDate` to accept `Date` objects instead of strings, aligning with the `value` prop. This would push the parsing responsibility to the consumer and eliminate the UTC ambiguity entirely.
|
|
83
|
+
- **[Datepicker_issue_004]**: The Calendar panel renders inside the component's DOM tree, so it can be clipped by `overflow: hidden` ancestors. Fix: [Datepicker_improv_002].
|
|
84
|
+
- **[Datepicker_issue_005]**: Date handling uses raw `Date` objects with no timezone awareness or locale-aware formatting. Input parsing is hardcoded to `DD/MM/YYYY`.
|
|
85
|
+
|
|
86
|
+
## Suggested future improvements
|
|
87
|
+
|
|
88
|
+
- **[Datepicker_improv_001]**: Extract `<Panel>` into a shared utility component.
|
|
89
|
+
- `<Select>` also uses a similar Panel (etc).
|
|
90
|
+
- **[Datepicker_improv_002]**: Use library [Floating UI](https://floating-ui.com/) to handle Panel positioning and portalling (via `FloatingPortal`).
|
|
91
|
+
- Fix for [Datepicker_issue_002] and [Datepicker_issue_004].
|
|
92
|
+
- **[Datepicker_improv_003]**: Extract `<NativeDatepicker>` into a separate component.
|
|
93
|
+
- This would simplify props typing.
|
|
94
|
+
- This would remove the need for `Datepicker.tsx` itself to act as a 'routing' component.
|
|
95
|
+
- **[Datepicker_improv_004]**: Integrate `<Datepicker>` with `<Field>` and `<Label>`, to use the shared context solution already used in `<Input>` & `<Textarea>`.
|
|
96
|
+
- This would simplify the API for consumers, and ensure consistent behaviour across form-field-level components.
|
|
97
|
+
- Developers using these components get automatic label->input association without having to manually pass `id` and `htmlFor` props.
|
|
98
|
+
- **[Datepicker_improv_005]**: Separate the button that opens the Calendar and the button that clears the input field, so they can be seen & used independently -- currently they are conditionally rendered with joined logic.
|
|
99
|
+
- **[Datepicker_improv_006]**: Extract the button that opens the Calendar into a separate subcomponent, for cleaner composition in the return statement of `VisibleField`.
|
|
100
|
+
- **[Datepicker_improv_007]**: Extract the button that clears the input field into a separate subcomponent, for cleaner composition in the return statement of `VisibleField`.
|
|
101
|
+
- **[Datepicker_improv_008]**: Extract core logic from `<CustomDatepicker>` into a `useDatepicker` hook. Benefits:
|
|
102
|
+
- **Testability**: Hook logic can be tested in isolation with `renderHook()`, without rendering the full component tree.
|
|
103
|
+
- **Reusability**: Logic can be shared across variants (e.g. date range picker, inline calendar, mobile-specific version).
|
|
104
|
+
- **Composition**: Consumers could use the hook directly for advanced/custom layouts.
|
|
105
|
+
- **Debugging**: Cleanly separates logic bugs from rendering bugs.
|
|
106
|
+
- **Performance**: Allows more granular control over which state changes trigger re-renders.
|
|
107
|
+
- **[Datepicker_improv_009]**: Adopt a date utility library (`date-fns` or `dayjs`) to replace manual string parsing and provide timezone/locale support.
|
|
108
|
+
- Fix for [Datepicker_issue_005].
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import type { Meta, StoryObj } from '@storybook/react';
|
|
2
2
|
import { useArgs } from '@storybook/preview-api';
|
|
3
3
|
import Datepicker from './Datepicker';
|
|
4
|
+
import Field from '../Field';
|
|
5
|
+
import Label from '../Label';
|
|
4
6
|
|
|
5
7
|
const meta = {
|
|
6
|
-
title: 'Components/
|
|
8
|
+
title: 'Components/Datepicker',
|
|
7
9
|
component: Datepicker,
|
|
8
10
|
parameters: { layout: 'padded' },
|
|
9
11
|
argTypes: {
|
|
@@ -11,7 +13,7 @@ const meta = {
|
|
|
11
13
|
minDate: { control: { type: 'date' } },
|
|
12
14
|
maxDate: { control: { type: 'date' } },
|
|
13
15
|
disabled: { control: { type: 'boolean' } },
|
|
14
|
-
|
|
16
|
+
clearable: { control: { type: 'boolean' } },
|
|
15
17
|
showAcademicWeeks: { control: { type: 'boolean' } },
|
|
16
18
|
},
|
|
17
19
|
tags: ['autodocs'],
|
|
@@ -49,6 +51,42 @@ export const Default: Story = {
|
|
|
49
51
|
},
|
|
50
52
|
};
|
|
51
53
|
|
|
54
|
+
export const InAField: Story = {
|
|
55
|
+
render: () => {
|
|
56
|
+
const [args, updateArgs] = useArgs();
|
|
57
|
+
|
|
58
|
+
// Storybook controls provide UNIX timestamps for dates, need to convert
|
|
59
|
+
// https://storybook.js.org/docs/essentials/controls#annotation
|
|
60
|
+
args.value = args.value ? new Date(args.value) : null;
|
|
61
|
+
args.minDate = args.minDate
|
|
62
|
+
? new Date(args.minDate).toLocaleDateString('sv-SE')
|
|
63
|
+
: null;
|
|
64
|
+
args.maxDate = args.maxDate
|
|
65
|
+
? new Date(args.maxDate).toLocaleDateString('sv-SE')
|
|
66
|
+
: null;
|
|
67
|
+
|
|
68
|
+
const onValueChange = (value: Date | null | undefined) =>
|
|
69
|
+
updateArgs({ value: value });
|
|
70
|
+
|
|
71
|
+
// Could be `useId` or a hardcoded string..
|
|
72
|
+
const datepickerInputId = 'datepicker-input';
|
|
73
|
+
// TODO: Associate <Label> and <DatepickerInput> via <Field> context automatically -- [Datepicker_improv_004]
|
|
74
|
+
return (
|
|
75
|
+
<Field>
|
|
76
|
+
<Label htmlFor={datepickerInputId}>Date of event</Label>
|
|
77
|
+
<Field.HelperText>
|
|
78
|
+
Please enter your preferred date for the event
|
|
79
|
+
</Field.HelperText>
|
|
80
|
+
<Datepicker
|
|
81
|
+
{...args}
|
|
82
|
+
onValueChange={onValueChange}
|
|
83
|
+
inputProps={{ id: datepickerInputId }}
|
|
84
|
+
/>
|
|
85
|
+
</Field>
|
|
86
|
+
);
|
|
87
|
+
},
|
|
88
|
+
};
|
|
89
|
+
|
|
52
90
|
// Story repeated in Calendar.stories.tsx
|
|
53
91
|
export const WithEvents: Story = {
|
|
54
92
|
name: 'With events',
|
|
@@ -237,10 +275,11 @@ export const MinMaxDates: Story = {
|
|
|
237
275
|
},
|
|
238
276
|
};
|
|
239
277
|
|
|
240
|
-
export const
|
|
241
|
-
name: '
|
|
278
|
+
export const Clearable: Story = {
|
|
279
|
+
name: 'With clearable',
|
|
242
280
|
args: {
|
|
243
|
-
|
|
281
|
+
clearable: true,
|
|
282
|
+
value: new Date(), // Start with a value to show the clear button
|
|
244
283
|
},
|
|
245
284
|
render: () => {
|
|
246
285
|
const [args, updateArgs] = useArgs();
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { dateToLocaleISOString } from './utils';
|
|
1
|
+
import { CustomDatepicker } from './subcomponents';
|
|
3
2
|
import type { DatepickerProps } from './Datepicker.types';
|
|
4
3
|
|
|
5
4
|
const Datepicker = ({
|
|
@@ -9,42 +8,21 @@ const Datepicker = ({
|
|
|
9
8
|
maxDate,
|
|
10
9
|
disabled,
|
|
11
10
|
className,
|
|
12
|
-
|
|
13
|
-
nativeRef,
|
|
14
|
-
nativeHTMLAttributes,
|
|
11
|
+
clearable,
|
|
15
12
|
...props
|
|
16
13
|
}: DatepickerProps) => {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
disabled={disabled}
|
|
30
|
-
className={className}
|
|
31
|
-
ref={nativeRef}
|
|
32
|
-
{...nativeHTMLAttributes}
|
|
33
|
-
/>
|
|
34
|
-
);
|
|
35
|
-
} else {
|
|
36
|
-
return (
|
|
37
|
-
<CustomDatepicker
|
|
38
|
-
value={value}
|
|
39
|
-
onValueChange={onValueChange}
|
|
40
|
-
minDate={minDate}
|
|
41
|
-
maxDate={maxDate}
|
|
42
|
-
className={className}
|
|
43
|
-
disabled={disabled}
|
|
44
|
-
{...props}
|
|
45
|
-
/>
|
|
46
|
-
);
|
|
47
|
-
}
|
|
14
|
+
return (
|
|
15
|
+
<CustomDatepicker
|
|
16
|
+
value={value}
|
|
17
|
+
onValueChange={onValueChange}
|
|
18
|
+
minDate={minDate}
|
|
19
|
+
maxDate={maxDate}
|
|
20
|
+
className={className}
|
|
21
|
+
disabled={disabled}
|
|
22
|
+
clearable={clearable}
|
|
23
|
+
{...props}
|
|
24
|
+
/>
|
|
25
|
+
);
|
|
48
26
|
};
|
|
49
27
|
|
|
50
28
|
export default Datepicker;
|