feat(date-picker): align with fusion DS - #8067
Conversation
2a32f23 to
71e6671
Compare
71e6671 to
e4a59f5
Compare
e629ab4 to
15cc36f
Compare
15cc36f to
623c25f
Compare
There was a problem hiding this comment.
Pull request overview
This PR updates the DateInput/DatePicker experience to align with Fusion DS designs and accessibility requirements by introducing a new “typical” implementation while retaining the existing behavior as a “legacy” variant for compatibility.
Changes:
- Introduces a new
DateInputvariantAPI (legacydefault,typicalnew) and extracts the legacy implementation intodate-legacy.component.tsx. - Adds a new “typical” date picker implementation (semantic structure, focus management, month/year native
<select>controls, updated keyboard behavior). - Updates i18n aria-labels, Storybook stories, Jest tests, Playwright CT tests, and generated skills docs to cover/describe the new variant.
Reviewed changes
Copilot reviewed 78 out of 78 changed files in this pull request and generated 15 comments.
Show a summary per file
| File | Description |
|---|---|
| src/style/utils/add-scrollbar-styling.ts | New shared CSS helper for consistent scrollbar styling (used by typical select picker UI). |
| src/style/utils/add-inner-focus-styling.ts | New shared CSS helper for inner focus ring styling. |
| src/locales/pt-pt.ts | Adds new date picker aria labels; updates existing month navigation labels. |
| src/locales/locale.ts | Extends Locale.date.ariaLabels with chooseMonth, chooseYear, closeButton. |
| src/locales/fr-fr.ts | Adds new date picker aria labels; updates existing month navigation labels. |
| src/locales/fr-ca.ts | Adds new date picker aria labels; updates existing month navigation labels. |
| src/locales/es-es.ts | Adds new date picker aria labels. |
| src/locales/en-us.ts | Adds new date picker aria labels. |
| src/locales/en-gb.ts | Adds new date picker aria labels. |
| src/locales/en-ca.ts | Adds new date picker aria labels. |
| src/locales/de-de.ts | Adds new date picker aria labels; updates existing month navigation labels. |
| src/components/date/date.test.tsx | Adjusts legacy tests to explicitly render variant="legacy"; updates ariaLabels test data. |
| src/components/date/date.style.ts | Updates date picker width tokens to new DS sizes. |
| src/components/date/date.pw.tsx | Adds accessibility checks for the typical picker (including range-mode fixture scenario). |
| src/components/date/date.component.tsx | Refactors DateInput into a variant switch delegating to legacy vs typical implementations. |
| src/components/date/date-typical.stories.tsx | Adds Storybook stories and documentation for the typical variant (incl. browser compatibility notes). |
| src/components/date/date-legacy.stories.tsx | Reorganizes legacy stories under Date Input/Legacy and pins variant="legacy". |
| src/components/date/date-legacy.mdx | Updates docs to point at the legacy story file and minor formatting cleanups. |
| src/components/date/date-legacy.component.tsx | New extracted legacy implementation (previous date.component.tsx logic). |
| src/components/date/date-legacy-test.stories.tsx | Updates legacy test stories to pin variant="legacy" and reorganizes story path. |
| src/components/date/date-legacy-interaction.stories.tsx | Updates legacy interaction stories to pin variant="legacy" and reorganizes story path. |
| src/components/date/components.test-pw.tsx | Adds a typical DateInput test fixture and ensures legacy fixtures explicitly set variant. |
| src/components/date/internal/utils.test.ts | Minor test param rename cleanup. |
| src/components/date/internal/date-picker/date-picker.test.tsx | Updates test locale objects to include new aria label keys. |
| src/components/date/internal/date-picker/date-picker.component.tsx | Minor typing + floating-ui middleware changes; wraps eslint disables for tab guard. |
| src/components/date/internal/next/index.ts | Adds __next__ exports for typical DateInput and types. |
| src/components/date/internal/next/date-typical.test.tsx | Adds Jest coverage for typical focus/navigation/semantics and interactions. |
| src/components/date/internal/next/date-typical.component.tsx | New typical DateInput implementation (semantic layout + picker integration). |
| src/components/date/internal/next/date-typical-test.stories.tsx | Adds a typical test story entry for tooling/tests. |
| src/components/date/internal/next/date-typical-interaction.stories.tsx | Adds an interaction story for typical variant. |
| src/components/date/internal/next/internal/utils.ts | New shared utilities for typical date parsing/formatting/event creation. |
| src/components/date/internal/next/internal/utils.test.ts | Unit tests for the new typical utilities. |
| src/components/date/internal/next/internal/subtle-select/use-customizable-select-markup.ts | Hook inserting customizable-select markup for supported browsers (React 18 limitation workaround). |
| src/components/date/internal/next/internal/subtle-select/subtle-select.test.tsx | Unit tests for the new subtle select component. |
| src/components/date/internal/next/internal/subtle-select/subtle-select.style.ts | Styling for native/customizable select picker, including picker pseudo-element styling. |
| src/components/date/internal/next/internal/subtle-select/subtle-select.config.ts | Size config tokens for subtle select. |
| src/components/date/internal/next/internal/subtle-select/subtle-select.component.tsx | New subtle select component used for month/year controls. |
| src/components/date/internal/next/internal/subtle-select/index.ts | Barrel export for subtle select. |
| src/components/date/internal/next/internal/hooks/useDatePickerMonthYearSelection.ts | Month/year selection logic + min/max clamping and year range generation. |
| src/components/date/internal/next/internal/hooks/useDatePickerMonthSync.ts | Keeps focused month in sync with selection/open state. |
| src/components/date/internal/next/internal/hooks/useDatePickerLocale.ts | Typical picker weekday localization helpers. |
| src/components/date/internal/next/internal/hooks/useDatePickerKeyboardNavigation.ts | Implements picker focus trap + keyboard navigation. |
| src/components/date/internal/next/internal/hooks/useDatePickerInFlatTable.ts | Coordinates with FlatTable to avoid interaction conflicts while picker is open. |
| src/components/date/internal/next/internal/hooks/useDatePickerFocus.ts | Initial focus behavior when opening picker. |
| src/components/date/internal/next/internal/hooks/useDatePickerAccessibility.ts | Wires grid labelling to month/year controls. |
| src/components/date/internal/next/internal/hooks/useDateInputPickerInteractions.ts | Typical DateInput open/close and event orchestration. |
| src/components/date/internal/next/internal/hooks/useDateInputAccessibility.ts | Typical DateInput IDs/aria-describedby/validation wiring. |
| src/components/date/internal/next/internal/date-picker/index.ts | Barrel export for typical picker. |
| src/components/date/internal/next/internal/date-picker/date-picker.utils.ts | Shared date picker utility functions (bounds parsing/clamping). |
| src/components/date/internal/next/internal/date-picker/date-picker.utils.test.ts | Unit tests for typical date picker utilities. |
| src/components/date/internal/next/internal/date-picker/date-picker.types.ts | Types for typical date picker component/props. |
| src/components/date/internal/next/internal/date-picker/date-picker.style.ts | Typical date picker styling (Fusion DS-aligned). |
| src/components/date/internal/next/internal/date-picker/date-picker.component.tsx | Typical popover date picker implementation using floating-ui + Popover. |
| src/components/date/internal/next/internal/date-input-field/date-input-validation.component.tsx | Typical inline validation rendering for DateInput. |
| src/components/date/internal/next/internal/date-input-field/date-input-field.style.ts | Typical DateInput field layout/styling (label + input + trigger). |
| src/components/date/internal/next/internal/date-input-field/date-input-field.config.ts | Typical DateInput sizing config tokens. |
| src/components/date/internal/next/internal/date-input-field/date-input-field.component.tsx | Typical DateInput field composition using internal Input. |
| src/components/date/internal/next/internal/date-input-field/date-input-field-label.style.ts | Typical label/hint styling for DateInput. |
| src/components/date/internal/next/internal/date-input-field/date-input-field-label.component.tsx | Typical label/hint component for DateInput. |
| src/components/date/internal/next/internal/date-input-field/date-input-calendar-trigger.component.tsx | Typical calendar trigger button + ARIA wiring. |
| src/components/date/internal/next/internal/calendar/calendar.component.tsx | Typical calendar wrapper around react-day-picker with custom components. |
| src/components/date/internal/next/internal/calendar/calendar-weekday.style.ts | Typical weekday header cell styling. |
| src/components/date/internal/next/internal/calendar/calendar-weekday.component.tsx | Typical weekday header rendering (SR-only full names). |
| src/components/date/internal/next/internal/calendar/calendar-header.style.ts | Header layout styling for month/year selectors. |
| src/components/date/internal/next/internal/calendar/calendar-header.component.tsx | Typical month/year selector header implementation. |
| src/components/date/internal/next/internal/calendar/calendar-footer.style.ts | Typical footer styling for Close action. |
| src/components/date/internal/next/internal/calendar/calendar-day-button.component.tsx | Typical day button markup (SR text + today indicator). |
| src/components/date-range/date-range.test.tsx | Updates locale override test data to include new aria label keys. |
| src/components/date-range/date-range.stories.tsx | Updates locale override stories to include new aria label keys. |
| src/components/date-range/date-range-interaction.stories.tsx | Updates interaction stories to include new aria label keys. |
| src/internal/input/input-style-overrides.style.ts | Splits legacy vs typical date input styling overrides. |
| skills/carbon-react/index.md | Adds new “next” docs entries for typical date components. |
| skills/carbon-react/components/date-picker-weekday-next.md | New generated docs for next weekday component export. |
| skills/carbon-react/components/date-picker-typical-next.md | New generated docs for next typical date picker export. |
| skills/carbon-react/components/date-labelset-next.md | New generated docs for next date labelset export. |
| skills/carbon-react/components/date-input.md | Updates generated DateInput docs (props list changes + examples removed). |
| skills/carbon-react/components/date-input-typical-component-next.md | New generated docs for next typical date input component export. |
| const canvas = within(canvasElement); | ||
| const calendarIcon = canvas.getByTestId("icon"); | ||
| await userEvent.click(calendarIcon); | ||
| const navigationIcon = canvas.getByRole("button", { name: "Next month" }); | ||
| await userEvent.click(navigationIcon); | ||
| }, |
| const dateInoutTypicalMinWidth = { | ||
| small: "128px", | ||
| medium: "144px", | ||
| large: "176px", | ||
| } as const; |
| type DateInputPickerProps = NonNullable<DateInputLegacyProps["pickerProps"]> & { | ||
| mode?: DayPickerProps["mode"]; | ||
| }; |
There was a problem hiding this comment.
comment: we don't need this component, you should get all this for free by using the textbox/__internal__/__next__/text-input component
There was a problem hiding this comment.
Full text-input reuse is not drop-in. it requires date-specific overrides for several layout rules, interactive calendar button and focus-model difference is also present. I can reuse Hint, ValidationMessage as input primitives, but I think date-specific field wrapper should be present for typical. Let it own split control focus, button semantic, dimensions
There was a problem hiding this comment.
We need to reuse the TextInput as any updates to it going forward will need to be reflected in all the other text based inputs. You should be able to pass the button via the inputIcon prop to pass a node
There was a problem hiding this comment.
comment: we don't need this component, you should get all this for free by using the textbox/internal/next/text-input component
There was a problem hiding this comment.
comment: As far as I was aware the only difference between the legacy and typical variants was how keyboard navigation works. If that's the case a whole component seem excessive as there's likely a lot of code that's duplicated. I think the ticket is poorly worded and we can just add a variant and guard the specific differences etc
There was a problem hiding this comment.
comment: I believe the intention was to use the native selects here not build another custom one
There was a problem hiding this comment.
You mean the earlier decision was to accept native select presentation until styling the list is supported across browsers? This is not another custom select, it is enhanced native customizable select where supported
There was a problem hiding this comment.
Yes the original decision was to not add any custom styling as we didn't want to rely on styling that might not gain full cross-browser support. As it's a progressive enhancement I'm happy to defer to other reviewers
| }: DateInputTypicalProps, | ||
| ref, | ||
| ) => { | ||
| const wrapperRef = useRef<HTMLDivElement>(null); |
There was a problem hiding this comment.
comment: as mentioned above there's a lot of duplication between this and legacy, I think the only difference between the two is whether you can open it via keyboard so I dont' think it all needs to be separate components (don't mind if they are as long as they're DRY etc)
There was a problem hiding this comment.
Thanks. I agree, there is duplication. but sharing logic would require refactoring the existing legacy implementation rather than simply reusing.
One strong difference is the required dom composition. Legacy navigation is supplied through rdp and rendered via .rdp-months, but Typical treats year/month controls outside rdp tree, where month/year selection, calendar and close button are separate sections. So, my preference was to share that controller logic while retaining separate navigation rather than adding variant conditions throughout the markup, accessibility logic, focus handling, styles, etc.
I think I can reuse duplicated 1) utils (date parsing and values) - the ones I already copied and extracted to typical utils - as no rendering involved, no variant prop treatment. 2) date picker locale can be shared. 3) probably month synchronization (let me re-check). If both variants are expected to be maintained long-term< I can follow up extracting pure utils to be sharable
There was a problem hiding this comment.
The legacy part is how the keyboard navigation works for the component (it can't be opened via keyboard etc) the rest of it should be the same as far as I'm aware. The legacy version still needs the new dropdowns and calendar/picker layout and styling.
There was a problem hiding this comment.
comment: We should really only have one skill file for the a Date component, a lot of these (typical-component, labelset-next, date-pickerptypical, date-picker-weekday) don't have any real useful skill information
| dateFnsLocale: () => frFRDateLocale, | ||
| ariaLabels: { | ||
| previousMonthButton: () => "Mois précédent", | ||
| previousMonthButton: () => "Mois prcdent", |
There was a problem hiding this comment.
comment: this is incorrect
| dateFnsLocale: () => frCADateLocale, | ||
| ariaLabels: { | ||
| previousMonthButton: () => "Mois précédent", | ||
| previousMonthButton: () => "Mois prcdent", |
There was a problem hiding this comment.
comment: this is incorrect
There was a problem hiding this comment.
I messed up with accent marks. fixed
| previousMonthButton: () => "Mois précédent", | ||
| previousMonthButton: () => "Mois prcdent", | ||
| nextMonthButton: () => "Mois suivant", | ||
| chooseMonth: () => "Choisir le mois", |
There was a problem hiding this comment.
question: have these additional locale values come from the translation team?
There was a problem hiding this comment.
I messed up with accent marks and rolled back these changes. Translation team is a total mystery for me) I'll find out
| and operating-system fallback behaviour without recreating a select with | ||
| JavaScript and ARIA. | ||
|
|
||
| Carbon applies the customizable-select experience where the browser supports |
There was a problem hiding this comment.
comment: I think the decision was that we were okay with using native select until support for styling the list is introduced across browser
There was a problem hiding this comment.
That's just a comment about what developer can and what can not customize. Let me know if I should remove it
tomdavies73
left a comment
There was a problem hiding this comment.
I've had a look over this @ibutakova, I think we may have to pivot the approach here to be a lot simpler with the use of a native <select> doing most of the heavy lifting with styling only being applied to the closed input.
The dropdown can remain unstyled and be handled by the respective OS. We may be able to remove a lot of the additional internal components/hooks added here and revert to the original component. With some small enhancement and adjustments made, to achieve the design or close to the design without a large overhaul.
We need to try and use already available internal componentry where possible here, some of the stuff added does already exist in Carbon somewhere.
On the locales, we typically only add en-gb locales as default if you do need to add any locales. We can then help you request additional translations from the translations team who will send these over to you when they're ready.
Happy to have a chat with you on this if needed to explore your options. Also agree with all of @edleeks87's comments, I just thought I'd leave a larger more general comment here instead 👍
|
Closed in favor of #8085 |
Proposed behaviour
Aligns
DatePickercomponent component with fusion DS designs and accessibility requirements:Current behaviour
Currently, the Profile component is not aligned with fusion DS.
Checklist
d.tsfile added or updated if requiredQA
Additional context
The Typical date picker's month and year controls use native HTML
<select>elements. This preserves built-in keyboard navigation, accessibility semantics, and operating-system fallback behaviour without recreating a select with JavaScript and ARIA. Carbon applies the customizable-select experience where the browser supportsappearance: base-select. Other browsers display a functional native select, but its opened menu follows the browser and operating-system appearance rather than full Carbon styling.