fix: keyboard accessibility for time picker (#2613)

This commit is contained in:
Areeb Sajjad
2025-12-18 05:56:54 +05:00
committed by GitHub
parent 9c70fd9216
commit 8b9f156149
3 changed files with 71 additions and 2 deletions

View File

@@ -32,9 +32,21 @@ 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`;
}
return (
<Form.Group className="form-group-custom datepicker-custom">
<Form.Group controlId={controlName} className="form-group-custom datepicker-custom">
<Form.Label className="d-flex justify-content-between">
{label}
{showUTC && (
@@ -52,6 +64,7 @@ const DatepickerControl = ({
/>
)}
<DatePicker
id={controlName}
name={controlName}
selected={formattedDate}
disabled={readonly}
@@ -67,6 +80,7 @@ const DatepickerControl = ({
showTimeSelectOnly={type === DATEPICKER_TYPES.time}
placeholderText={inputFormat[type].toLocaleUpperCase()}
showPopperArrow={false}
aria-describedby={describedByIds}
onChange={(date) => {
if (isValidDate(date)) {
onChange(convertToStringFromDate(date));
@@ -74,7 +88,18 @@ const DatepickerControl = ({
}}
/>
</div>
{helpText && <Form.Control.Feedback>{helpText}</Form.Control.Feedback>}
{isTimePicker && (
<Form.Text id={`${controlName}-timehint`} className="sr-only">
{intl.formatMessage(messages.timepickerScreenreaderHint, {
timeFormat: inputFormat[type].toLocaleUpperCase(),
})}
</Form.Text>
)}
{helpText && (
<Form.Control.Feedback id={`${controlName}-helptext`}>
{helpText}
</Form.Control.Feedback>
)}
</Form.Group>
);
};

View File

@@ -48,4 +48,40 @@ describe('<DatepickerControl />', () => {
convertToStringFromDate('06/16/2023'),
);
});
it('renders time picker with accessibility hint', () => {
const { getByText, getByPlaceholderText } = render(
<RootWrapper
{...props}
type={DATEPICKER_TYPES.time}
value="2025-01-01T10:00:00Z"
helpText=""
/>,
);
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');
});
it('renders time picker with accessibility hint and help text', () => {
const { getByText, getByPlaceholderText } = render(
<RootWrapper
{...props}
type={DATEPICKER_TYPES.time}
value="2025-01-01T10:00:00Z"
helpText="This is help text"
/>,
);
const input = getByPlaceholderText('HH:MM');
expect(
getByText('Enter time in HH:MM or twelve-hour format, for example 6:00 PM.'),
).toBeInTheDocument();
expect(getByText('This is help text')).toBeInTheDocument();
expect(input.getAttribute('aria-describedby')).toContain('fooControlName-timehint');
expect(input.getAttribute('aria-describedby')).toContain('fooControlName-helptext');
});
});

View File

@@ -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;