diff --git a/src/components/date-range/date-range-test.stories.tsx b/src/components/date-range/date-range-test.stories.tsx index f0c2eb7577..f2176d88c2 100644 --- a/src/components/date-range/date-range-test.stories.tsx +++ b/src/components/date-range/date-range-test.stories.tsx @@ -64,6 +64,10 @@ DateRangeStory.args = { allowEmptyValueOnStartDate: undefined, allowEmptyValueOnEndDate: undefined, labelsInline: false, + datePickerStartAriaLabel: "start aria-label", + datePickerStartAriaLabelledBy: "start aria-labelledby", + datePickerEndAriaLabel: "end aria-label", + datePickerEndAriaLabelledBy: "end aria-labelledby", }; export const DateRangeCustom = ({ diff --git a/src/components/date-range/date-range.component.tsx b/src/components/date-range/date-range.component.tsx index ff1dde9a08..fa3bd5e2e4 100644 --- a/src/components/date-range/date-range.component.tsx +++ b/src/components/date-range/date-range.component.tsx @@ -118,6 +118,14 @@ export interface DateRangeProps isOptional?: boolean; /** Date format string to be applied to the date inputs */ dateFormatOverride?: string; + /** Prop to specify the aria-label attribute of the start date picker */ + datePickerStartAriaLabel?: string; + /** Prop to specify the aria-labelledby attribute of the start date picker */ + datePickerStartAriaLabelledBy?: string; + /** Prop to specify the aria-label attribute of the end date picker */ + datePickerEndAriaLabel?: string; + /** Prop to specify the aria-labelledby attribute of the end date picker */ + datePickerEndAriaLabelledBy?: string; } export const DateRange = ({ @@ -135,6 +143,10 @@ export const DateRange = ({ endRef, required, isOptional, + datePickerStartAriaLabel, + datePickerStartAriaLabelledBy, + datePickerEndAriaLabel, + datePickerEndAriaLabelledBy, ...rest }: DateRangeProps) => { const { validationRedesignOptIn } = useContext(NewValidationContext); @@ -373,6 +385,8 @@ export const DateRange = ({ labelWidth={inlineLabelWidth} // Textbox only applies this when labelsInLine prop is true tooltipPosition={tooltipPosition} ref={startRef} + datePickerAriaLabel={datePickerStartAriaLabel} + datePickerAriaLabelledBy={datePickerStartAriaLabelledBy} /> diff --git a/src/components/date-range/date-range.test.tsx b/src/components/date-range/date-range.test.tsx index b52d4a946a..98909b4d8f 100644 --- a/src/components/date-range/date-range.test.tsx +++ b/src/components/date-range/date-range.test.tsx @@ -679,6 +679,50 @@ test("should close the open 'start' picker when the user moves focus to the `end expect(within(startDate).queryByRole("grid")).not.toBeInTheDocument(); }); +test("should apply aria-label and aria-labelledby to the date picker region", async () => { + const user = userEvent.setup(); + render( + {}} + startDateProps={{ disablePortal: true, "data-role": "start" }} + endDateProps={{ disablePortal: true, "data-role": "end" }} + datePickerStartAriaLabel="start aria-label" + datePickerStartAriaLabelledBy="start aria-labelledby" + datePickerEndAriaLabel="end aria-label" + datePickerEndAriaLabelledBy="end aria-labelledby" + />, + ); + const startDate = screen.getByTestId("start"); + const endDate = screen.getByTestId("end"); + + await user.click(screen.getByRole("textbox", { name: "start" })); + + expect(within(startDate).getByRole("region")).toBeVisible(); + expect(within(startDate).getByRole("region")).toHaveAttribute( + "aria-label", + "start aria-label", + ); + expect(within(startDate).getByRole("region")).toHaveAttribute( + "aria-labelledby", + "start aria-labelledby", + ); + + await user.click(screen.getByRole("textbox", { name: "end" })); + + expect(within(endDate).getByRole("region")).toBeVisible(); + expect(within(endDate).getByRole("region")).toHaveAttribute( + "aria-label", + "end aria-label", + ); + expect(within(endDate).getByRole("region")).toHaveAttribute( + "aria-labelledby", + "end aria-labelledby", + ); +}); + test("should close the open 'end' picker when the user moves focus to the `start` input", async () => { const user = userEvent.setup(); render( diff --git a/src/components/date/__internal__/date-picker/date-picker.component.tsx b/src/components/date/__internal__/date-picker/date-picker.component.tsx index 14a7890b08..b76ee78993 100644 --- a/src/components/date/__internal__/date-picker/date-picker.component.tsx +++ b/src/components/date/__internal__/date-picker/date-picker.component.tsx @@ -63,6 +63,10 @@ export interface DatePickerProps { pickerTabGuardId?: string; /** Callback triggered when the picker is closed */ onPickerClose?: () => void; + /** Prop to specify the aria-label attribute of the date picker */ + ariaLabel?: string; + /** Prop to specify the aria-labelledby attribute of the date picker */ + ariaLabelledBy?: string; } const popoverMiddleware = [ @@ -85,6 +89,8 @@ export const DatePicker = ({ setOpen, pickerTabGuardId, onPickerClose, + ariaLabel: datePickerAriaLabel, + ariaLabelledBy: datePickerAriaLabelledBy, }: DatePickerProps) => { const [focusedMonth, setFocusedMonth] = useState( selectedDays || new Date(), @@ -226,6 +232,9 @@ export const DatePicker = ({ onMouseDown={pickerMouseDown} onKeyUp={handleKeyUp} onKeyDown={handleOnKeyDown} + role="region" + aria-label={datePickerAriaLabel} + aria-labelledby={datePickerAriaLabelledBy} >
void; /** Date format string to be applied to the date inputs */ dateFormatOverride?: string; + /** Prop to specify the aria-label attribute of the date picker */ + datePickerAriaLabel?: string; + /** Prop to specify the aria-labelledby attribute of the date picker */ + datePickerAriaLabelledBy?: string; } export const DateInput = React.forwardRef( @@ -137,6 +141,8 @@ export const DateInput = React.forwardRef( inputName, onPickerClose, onPickerOpen, + datePickerAriaLabel, + datePickerAriaLabelledBy, ...rest }: DateInputProps, ref, @@ -541,6 +547,8 @@ export const DateInput = React.forwardRef( setOpen={setOpen} pickerTabGuardId={pickerTabGuardId.current} onPickerClose={onPickerClose} + ariaLabel={datePickerAriaLabel} + ariaLabelledBy={datePickerAriaLabelledBy} /> );