diff --git a/src/generic/datepicker-control/DatepickerControl.jsx b/src/generic/datepicker-control/DatepickerControl.jsx index 91306f2f11..84329f65de 100644 --- a/src/generic/datepicker-control/DatepickerControl.jsx +++ b/src/generic/datepicker-control/DatepickerControl.jsx @@ -32,6 +32,22 @@ const DatepickerControl = ({ [DATEPICKER_TYPES.date]: DATE_FORMAT, [DATEPICKER_TYPES.time]: TIME_FORMAT, }; + const isTimePicker = type === DATEPICKER_TYPES.time; + + let describedByIds; + if (isTimePicker) { + const ids = [`${controlName}-timehint`]; + if (helpText) { + ids.push(`${controlName}-helptext`); + } + describedByIds = ids.filter(Boolean).join(' ') || undefined; + } else if (helpText) { + describedByIds = `${controlName}-helptext`; + } + + const ariaLabel = isTimePicker + ? intl.formatMessage(messages.timepickerAriaLabel) + : undefined; return ( @@ -67,6 +83,8 @@ const DatepickerControl = ({ showTimeSelectOnly={type === DATEPICKER_TYPES.time} placeholderText={inputFormat[type].toLocaleUpperCase()} showPopperArrow={false} + ariaLabel={ariaLabel} + ariaDescribedBy={describedByIds} onChange={(date) => { if (isValidDate(date)) { onChange(convertToStringFromDate(date)); @@ -74,7 +92,18 @@ const DatepickerControl = ({ }} /> - {helpText && {helpText}} + {isTimePicker && ( + + {intl.formatMessage(messages.timepickerScreenreaderHint, { + timeFormat: inputFormat[type].toLocaleUpperCase(), + })} + + )} + {helpText && ( + + {helpText} + + )} ); }; diff --git a/src/generic/datepicker-control/DatepickerControl.test.jsx b/src/generic/datepicker-control/DatepickerControl.test.jsx index 509fc0cf8b..df158cc2b6 100644 --- a/src/generic/datepicker-control/DatepickerControl.test.jsx +++ b/src/generic/datepicker-control/DatepickerControl.test.jsx @@ -48,4 +48,21 @@ describe('', () => { convertToStringFromDate('06/16/2023'), ); }); + + it('renders time picker with accessibility hint', () => { + const { getByText, getByPlaceholderText } = render( + , + ); + const input = getByPlaceholderText('HH:MM'); + + expect( + getByText('Enter time in HH:MM or twelve-hour format, for example 6:00 PM.'), + ).toBeInTheDocument(); + expect(input.getAttribute('aria-describedby')).toContain('fooControlName-timehint'); + }); }); diff --git a/src/generic/datepicker-control/messages.js b/src/generic/datepicker-control/messages.js index b6139f7b57..38446a69ac 100644 --- a/src/generic/datepicker-control/messages.js +++ b/src/generic/datepicker-control/messages.js @@ -9,6 +9,14 @@ const messages = defineMessages({ id: 'course-authoring.schedule.schedule-section.datepicker.utc', defaultMessage: 'UTC', }, + timepickerAriaLabel: { + id: 'course-authoring.schedule.schedule-section.timepicker.aria-label', + defaultMessage: 'Time input field. Enter a time or use the arrow keys to adjust.', + }, + timepickerScreenreaderHint: { + id: 'course-authoring.schedule.schedule-section.timepicker.screenreader-hint', + defaultMessage: 'Enter time in {timeFormat} or twelve-hour format, for example 6:00 PM.', + }, }); export default messages;