feat(date): align with fusion ds - #8085
Conversation
8f43e38 to
2a3dfd1
Compare
There was a problem hiding this comment.
Warning
- Copilot's review of this pull request may be incomplete because some of the changed files are excluded by your Copilot content exclusion settings. See Excluding content from Copilot for details.
Pull request overview
Aligns the DateInput/DateRange experience with Fusion DS by introducing a new default “typical” date input variant and a rebuilt, accessibility-focused calendar popover, while retaining the legacy variant for backward compatibility.
Changes:
- Introduces
variant="typical" | "legacy"(defaulting totypical) and updates DateInput rendering/behavior accordingly, including a dedicated trigger control. - Replaces legacy DayPicker navbar/weekday custom components with a new calendar + navigation/selectors architecture and supporting hooks/utilities.
- Updates locales, docs, Storybook stories, and Jest/Playwright coverage to reflect new accessibility labels and interactions.
Reviewed changes
Copilot reviewed 93 out of 93 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| src/style/utils/add-scrollbar-styling.ts | Adds reusable scrollbar styling helper for new select/calendar UI. |
| src/style/utils/add-inner-focus-styling.ts | Adds reusable inner-focus styling helper used by new select UI. |
| src/locales/pt-pt.ts | Adds new date-picker aria labels (month/year/close). |
| src/locales/locale.ts | Extends Locale date ariaLabels contract for new controls. |
| src/locales/fr-fr.ts | Adds new date-picker aria labels (month/year/close). |
| src/locales/fr-ca.ts | Adds new date-picker aria labels (month/year/close). |
| src/locales/es-es.ts | Adds new date-picker aria labels (month/year/close). |
| src/locales/en-us.ts | Adds new date-picker aria labels (month/year/close). |
| src/locales/en-gb.ts | Adds new date-picker aria labels (month/year/close). |
| src/locales/en-ca.ts | Adds new date-picker aria labels (month/year/close). |
| src/locales/de-de.ts | Adds new date-picker aria labels (month/year/close). |
| src/components/textbox/textbox.test.tsx | Adds test coverage for ReactNode inputIcon. |
| src/components/textbox/textbox.component.tsx | Allows rendering custom ReactNode as inputIcon. |
| src/components/flat-table/flat-table.test.tsx | Updates FlatTable/date-picker interaction test to use keydown dispatch semantics. |
| src/components/date/date.style.ts | Updates sizing tokens and inline-label spacing for redesigned DateInput. |
| src/components/date/date.stories.tsx | Reworks stories to show typical vs legacy variants and expanded scenarios. |
| src/components/date/date.pw.tsx | Updates Playwright tests to new UI structure (selectors, close button, sizing). |
| src/components/date/date.mdx | Documents typical/legacy compatibility, new behaviors, and updated examples. |
| src/components/date/date.component.tsx | Adds variant support; refactors state, trigger, and picker integration. |
| src/components/date/date-interaction.stories.tsx | Updates interaction stories to cover both variants and new navigation model. |
| src/components/date/components.test-pw.tsx | Adds typical test component and pins legacy where required for existing tests. |
| src/components/date/internal/weekday/weekday.test.tsx | Removes legacy weekday renderer tests. |
| src/components/date/internal/weekday/weekday.style.ts | Removes legacy weekday styling. |
| src/components/date/internal/weekday/weekday.component.tsx | Removes legacy weekday component. |
| src/components/date/internal/weekday/index.ts | Removes legacy weekday exports. |
| src/components/date/internal/weekday/abbr.style.ts | Removes legacy abbr styling for weekdays. |
| src/components/date/internal/utils/utils.ts | Adjusts internal date-fns/fp import wiring for shared utils. |
| src/components/date/internal/utils/utils.test.ts | Minor test tidy (unused param naming). |
| src/components/date/internal/utils/date-input-value.utils.ts | Extracts/centralizes DateInput value parsing/normalization/event building. |
| src/components/date/internal/utils/date-input-value.utils.test.ts | Adds tests for extracted DateInput value utilities. |
| src/components/date/internal/utils/date-input-value.invalid.test.ts | Adds invalid-date regression test for matched-but-invalid parsed dates. |
| src/components/date/internal/navbar/navbar.test.tsx | Removes legacy navbar tests. |
| src/components/date/internal/navbar/navbar.style.ts | Removes legacy navbar styling. |
| src/components/date/internal/navbar/navbar.component.tsx | Removes legacy navbar component. |
| src/components/date/internal/navbar/index.ts | Removes legacy navbar exports. |
| src/components/date/internal/navbar/button.style.ts | Removes legacy navbar button styling. |
| src/components/date/internal/hooks/useDatePickerState.ts | New hook for open/close/toggle picker state with lifecycle callbacks. |
| src/components/date/internal/hooks/useDatePickerState.test.ts | Tests for picker state hook behavior. |
| src/components/date/internal/hooks/useDatePickerMonthYearSelection.ts | New hook for month/year selector logic and bounds handling. |
| src/components/date/internal/hooks/useDatePickerMonthYearSelection.test.ts | Tests for month/year selection behavior and bounds edge cases. |
| src/components/date/internal/hooks/useDatePickerMonthSync.ts | Syncs focused month with selected date on open/close/updates. |
| src/components/date/internal/hooks/useDatePickerMonthSync.test.ts | Tests focused-month synchronization logic. |
| src/components/date/internal/hooks/useDatePickerLocale.ts | Centralizes locale-derived weekday labels and close label. |
| src/components/date/internal/hooks/useDatePickerLocale.test.ts | Tests locale hook output for multiple locales. |
| src/components/date/internal/hooks/useDatePickerKeyboardNavigation.ts | New keyboard/tab-cycle management for picker controls and custom focusables. |
| src/components/date/internal/hooks/useDatePickerInFlatTable.ts | Integrates picker open state with FlatTable to avoid interaction conflicts. |
| src/components/date/internal/hooks/useDatePickerInFlatTable.test.tsx | Tests FlatTable integration hook behavior. |
| src/components/date/internal/hooks/useDatePickerFocus.ts | Ensures initial day focus and resets selector-change state. |
| src/components/date/internal/hooks/useDatePickerFocus.test.ts | Tests focus behavior using timers. |
| src/components/date/internal/hooks/useDatePickerAccessibility.ts | Applies aria-labelledby to calendar grids when open/month changes. |
| src/components/date/internal/hooks/useDatePickerAccessibility.test.ts | Tests aria-labelledby application to all grids. |
| src/components/date/internal/hooks/useDateInputState.ts | New hook for “pristine vs edited” formatting + event creation. |
| src/components/date/internal/hooks/useDateInputState.test.ts | Tests DateInput state normalization and event behavior. |
| src/components/date/internal/date-picker/index.ts | Updates public exports/types for the new date picker internals. |
| src/components/date/internal/date-picker/day-picker.style.ts | Removes legacy DayPicker styling wrapper. |
| src/components/date/internal/date-picker/date-picker.utils.ts | New utilities for date bounds parsing, year ranges, and transitions. |
| src/components/date/internal/date-picker/date-picker.utils.test.ts | Tests new date-picker utility functions. |
| src/components/date/internal/date-picker/date-picker.types.ts | Introduces typed DatePickerProps/PickerProps and size typing. |
| src/components/date/internal/date-picker/date-picker.style.ts | New popover/dialog styling aligned to DS tokens. |
| src/components/date/internal/date-picker/date-picker.component.tsx | Rewrites picker to use new calendar/navigation components and hooks. |
| src/components/date/internal/date-picker/date-picker-guard.test.tsx | Regression test for undefined day clicks not closing picker. |
| src/components/date/internal/date-picker-trigger/date-picker-trigger.style.ts | Adds styles for typical variant trigger button/divider. |
| src/components/date/internal/date-picker-trigger/date-picker-trigger.component.tsx | Adds the typical variant calendar trigger button with a11y attributes. |
| src/components/date/internal/calendar/calendar.test.tsx | Adds unit tests for calendar subcomponents/helpers. |
| src/components/date/internal/calendar/calendar.component.tsx | Introduces calendar wrapper with default renderers and className merging. |
| src/components/date/internal/calendar/calendar-weekday.style.ts | Adds weekday header styling aligned to DS tokens. |
| src/components/date/internal/calendar/calendar-weekday.component.tsx | Adds accessible weekday header markup (visible short + SR long). |
| src/components/date/internal/calendar/calendar-select/useCustomizableSelectMarkup.ts | Adds hook to inject standardized customizable-select markup in React 18. |
| src/components/date/internal/calendar/calendar-select/useCustomizableSelectMarkup.server.test.ts | Ensures hook can be imported in SSR environments. |
| src/components/date/internal/calendar/calendar-select/index.ts | Exports calendar select component/types. |
| src/components/date/internal/calendar/calendar-select/calendar-select.test.tsx | Adds comprehensive tests for calendar select behavior and markup injection. |
| src/components/date/internal/calendar/calendar-select/calendar-select.style.ts | Styles the month/year selects including base-select and scrollbar/focus styling. |
| src/components/date/internal/calendar/calendar-select/calendar-select.config.ts | Adds size-based configuration for calendar selects. |
| src/components/date/internal/calendar/calendar-select/calendar-select.component.tsx | Implements the month/year select component with tagging and icon. |
| src/components/date/internal/calendar/calendar-navigation.style.ts | Styles container for month/year selectors. |
| src/components/date/internal/calendar/calendar-navigation.component.tsx | Implements month/year navigation selectors with bounds disabling and locale labels. |
| src/components/date/internal/calendar/calendar-day-button.component.tsx | Adds accessible day button renderer with SR label and “today” indicator. |
| src/components/date/internal/calendar/calendar-close-button.style.ts | Styles the picker close button, including mobile behavior. |
| src/components/date/internal/calendar/calendar-close-button.component.tsx | Adds close button component with data-role for focus management. |
| src/components/date-range/date-range.test.tsx | Updates DateRange tests for new trigger, dialog role, and aria-labelledby expectations. |
| src/components/date-range/date-range.stories.tsx | Updates locale override stories to include new aria label keys. |
| src/components/date-range/date-range.component.tsx | Adjusts internal date utils import path for refactor. |
| src/components/date-range/date-range-interaction.stories.tsx | Updates interaction stories to use new trigger and revised navigation behaviors. |
| src/internal/label/label.test.tsx | Adds test ensuring small label font applies to required indicator. |
| src/internal/label/label.style.ts | Adjusts required indicator styling for better inline behavior and logical properties. |
| src/internal/input/input-style-overrides.style.ts | Updates Date input overrides for typical/legacy icon and focus-within behavior. |
| skills/carbon-react/components/date-range.md | Documentation update (content excluded from diff). |
| skills/carbon-react/components/date-input.md | Documentation update (content excluded from diff). |
Files excluded by content exclusion policy (2)
- skills/carbon-react/components/date-input.md
- skills/carbon-react/components/date-range.md
Comments suppressed due to low confidence (1)
src/components/date/date.component.tsx:490
- The MDX compatibility table says
tooltipPositionandhelpAriaLabelare not supported by the typical variant, but they are still passed through toTextboxunconditionally. This can re-enable legacy tooltip/help behavior in the typical variant. Only pass these props forvariant="legacy".
| inputWidth={inputWidth} | ||
| labelWidth={labelWidth} | ||
| maxWidth={maxWidth ?? datePickerWidth[actualSize]} | ||
| maxWidth={maxWidth ?? dateInputWidthBySize[actualSize]} |
edleeks87
left a comment
There was a problem hiding this comment.
I notice when using the dropdowns in the calendar the input value is changing, it should only update if the user selects a new date.
It looks like typical also doesn't have the vertical divider
I don't mind the separation of concerns you've implemented with all the hooks etc but I think it might be useful to add a top level comment to them to help maintainability
There was a problem hiding this comment.
comment: we shouldn't be overriding the scrollbar styling, accessibility have steered that using the browser default is preferred
| className="date" | ||
| className={`date date-${variant}`} | ||
| > | ||
| <Textbox |
There was a problem hiding this comment.
comment: we should be using TextInput as once all the inputs using Textbox have been updated we will be removing it
| ); | ||
| expect(select.querySelector("selectedcontent")).toBeInTheDocument(); | ||
| }); | ||
| /* eslint-enable testing-library/no-node-access */ |
There was a problem hiding this comment.
question: Is this es-lint comment required here? It looks like it's the end of the file.
| test("renders a day without an accessible label", () => { | ||
| render( | ||
| <CalendarDayButton | ||
| day={{} as never} |
There was a problem hiding this comment.
suggestion: Instead of casting this as never, you might be able to do something like this:
const mockDay = new CalendarDay(new Date(2025, 0, 15), new Date(2025, 0, 1));
and use mockDay like this:
| day={{} as never} | |
| day={mockDay} |
I'm not too precious about this though, I just try to avoid using the type never where possible.
| min-width: var(--date-picker-trigger-size); | ||
| height: var(--date-picker-trigger-size); | ||
| min-height: var(--date-picker-trigger-size); | ||
| padding: 0; |
There was a problem hiding this comment.
suggestion: There are a selection of ...-none tokens we could use here.
| padding: 0; | |
| padding: var(--global-space-none); |
| height: var(--date-picker-trigger-size); | ||
| min-height: var(--date-picker-trigger-size); | ||
| padding: 0; | ||
| border-radius: 0; |
There was a problem hiding this comment.
Same here too.
| border-radius: 0; | |
| border-radius: var(--global-size-none); |
There was a problem hiding this comment.
if tokens then border-radius: var(--global-radius-none); fits better)
|
|
||
| .rdp-root { | ||
| width: 100%; | ||
| padding: 0; |
There was a problem hiding this comment.
**suggestion: ** You could probably the same ...-none tokens here too.
| const detailLabel = labelDetail ? ` - ${labelDetail}` : ""; | ||
|
|
||
| return ( | ||
| <Box display="flex" flexDirection="column" gap="var(--spacing300)"> |
There was a problem hiding this comment.
nitpick: The var(--spacing300) is an old design-token. If this is a new example, we should probably use the equivalent Fusion DS token.
| value={state} | ||
| onChange={setValue} | ||
| /> | ||
| <Box display="flex" flexDirection="column" gap="var(--spacing300)"> |
There was a problem hiding this comment.
Same thing here too with var(--spacing300).
| /> | ||
| ) : null; | ||
| ) : ( | ||
| inputIcon || null |
There was a problem hiding this comment.
question: Do we need this change if the new date input will use the new Text Input component?
There was a problem hiding this comment.
Forget to remove while resolving the comment about using TextInput, not Textbox
| warning={warning} | ||
| /> | ||
| ) : ( | ||
| <Textbox |
There was a problem hiding this comment.
Comment: both variants should use TextInput. We need to remove the uses of Textbox so we can deprecate it and replace it with the internal TextInput
There was a problem hiding this comment.
Things like the help, tooltip and legacy validation should not be supported etc
There was a problem hiding this comment.
TextInput is now used for both legacy and typical
|
|
||
| /* Legacy Date renders its calendar as an Input icon. Typical Date owns its | ||
| * trigger colors in date-picker-trigger.style.ts. */ | ||
| .date-legacy & { |
There was a problem hiding this comment.
There was a problem hiding this comment.
I left legacy without divider, removed extra styles
| ariaLabels: { | ||
| previousMonthButton: () => "Vorheriger Monat", | ||
| nextMonthButton: () => "Nächster Monat", | ||
| chooseMonth: () => "Monat wählen", |
There was a problem hiding this comment.
question: can I just clarify, have these come from the translation team? If not we should only include the en-GB translation file
There was a problem hiding this comment.
I fell back to en-gb
There was a problem hiding this comment.
comment: we don't need this, there is already a util that supports the inset styling.
| @@ -122,11 +128,21 @@ export const DateInput = React.forwardRef<HTMLInputElement, DateInputProps>( | |||
| adaptiveLabelBreakpoint, | |||
There was a problem hiding this comment.
comment: support for adaptiveBreakpoint should be removed but left on the interface to avoid a breaking change. If the TextInput doesn't support it then anything rendering it should drop it as well. The intention is that implementation teams will handle this themselves rather than baking the behaviour into the component library
There was a problem hiding this comment.
question: is there any code coverage being missed without these tests? This feels like an implementation test that we can just remove if we aren't needing it for coverage
| | `validationIconId` | Not supported | Inline validation message ids are generated automatically | | ||
| | `validationOnLabel` | Not supported | Inline `warning` or `error` messages | | ||
|
|
||
| ### Custom calendar renderers |
There was a problem hiding this comment.
Comment: whilst we do support the pickerProps I'd prefer to not explicitly document the overriding of the internals. I suspect in the long run the DS will want us to remove support and we may be creating a larger migration hurdle if we do
There was a problem hiding this comment.
Unsupported props now distructured and discarded
| ariaLabels: { | ||
| previousMonthButton: () => "Mois précédent", | ||
| nextMonthButton: () => "Mois prochain", | ||
| chooseMonth: () => "Choisir le mois", |
There was a problem hiding this comment.
comment: if these haven't come from the translation teams I think we should leave them to fall back to en-GB
225a9f8 to
11b0a63
Compare
edleeks87
left a comment
There was a problem hiding this comment.
Happy with the changes, think we've lost the click away behaviour but going to approve for now and we can confirm next week with DS as it's trivial to add in
11b0a63 to
bc47784
Compare

Proposed behaviour
Aligns DatePicker component 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
Testing instructions