Skip to content

Commit

Permalink
[DateRangePicker] Add accessible name to calendar grid (#13538)
Browse files Browse the repository at this point in the history
  • Loading branch information
LukasTy authored Jun 19, 2024
1 parent 5ef1694 commit 05dd41f
Show file tree
Hide file tree
Showing 12 changed files with 40 additions and 8 deletions.
1 change: 1 addition & 0 deletions docs/pages/x/api/date-pickers/pickers-calendar-header.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
"type": { "name": "string" },
"default": "`${adapter.formats.month} ${adapter.formats.year}`"
},
"labelId": { "type": { "name": "string" } },
"slotProps": { "type": { "name": "object" }, "default": "{}" },
"slots": {
"type": { "name": "object" },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
"type": { "name": "string" },
"default": "`${adapter.formats.month} ${adapter.formats.year}`"
},
"labelId": { "type": { "name": "string" } },
"slotProps": { "type": { "name": "object" }, "default": "{}" },
"slots": {
"type": { "name": "object" },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
"propDescriptions": {
"classes": { "description": "Override or extend the styles applied to the component." },
"format": { "description": "Format used to display the date." },
"labelId": {
"description": "Id of the calendar text element. It is used to establish an <code>aria-labelledby</code> relationship with the calendar <code>grid</code> element."
},
"slotProps": { "description": "The props used for each component slot." },
"slots": { "description": "Overridable component slots." },
"sx": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@
"calendars": { "description": "The number of calendars rendered." },
"classes": { "description": "Override or extend the styles applied to the component." },
"format": { "description": "Format used to display the date." },
"labelId": {
"description": "Id of the calendar text element. It is used to establish an <code>aria-labelledby</code> relationship with the calendar <code>grid</code> element."
},
"month": { "description": "Month used for this header." },
"monthIndex": { "description": "Index of the month used for this header." },
"slotProps": { "description": "The props used for each component slot." },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import { describeConformance } from 'test/utils/describeConformance';
import { RangePosition } from '../models';

const getPickerDay = (name: string, picker = 'January 2018') =>
getByRole(screen.getByText(picker)?.parentElement?.parentElement!, 'gridcell', { name });
getByRole(screen.getByRole('grid', { name: picker }), 'gridcell', { name });

const dynamicShouldDisableDate = (date, position: RangePosition) => {
if (position === 'end') {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ import useEventCallback from '@mui/utils/useEventCallback';
import useMediaQuery from '@mui/material/useMediaQuery';
import { resolveComponentProps, useSlotProps } from '@mui/base/utils';
import { styled, useThemeProps } from '@mui/material/styles';
import { unstable_composeClasses as composeClasses } from '@mui/utils';
import composeClasses from '@mui/utils/composeClasses';
import useId from '@mui/utils/useId';
import { Watermark } from '@mui/x-license';
import {
applyDefaultDate,
Expand Down Expand Up @@ -231,6 +232,7 @@ const DateRangeCalendar = React.forwardRef(function DateRangeCalendar<

const utils = useUtils<TDate>();
const now = useNow<TDate>(timezone);
const id = useId();

const { rangePosition, onRangePositionChange } = useRangePosition({
rangePosition: rangePositionProp,
Expand Down Expand Up @@ -548,10 +550,16 @@ const DateRangeCalendar = React.forwardRef(function DateRangeCalendar<
<Watermark packageName="x-date-pickers-pro" releaseInfo={releaseInfo} />
{calendarMonths.map((monthIndex) => {
const month = visibleMonths[monthIndex];
const labelId = `${id}-grid-${monthIndex}-label`;

return (
<DateRangeCalendarMonthContainer key={monthIndex} className={classes.monthContainer}>
<CalendarHeader<TDate> {...calendarHeaderProps} month={month} monthIndex={monthIndex} />
<CalendarHeader<TDate>
{...calendarHeaderProps}
month={month}
monthIndex={monthIndex}
labelId={labelId}
/>
<DayCalendarForRange<TDate>
className={classes.dayCalendar}
{...calendarState}
Expand All @@ -575,6 +583,7 @@ const DateRangeCalendar = React.forwardRef(function DateRangeCalendar<
fixedWeekNumber={fixedWeekNumber}
displayWeekNumber={displayWeekNumber}
timezone={timezone}
gridLabelId={labelId}
/>
</DateRangeCalendarMonthContainer>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ import {

const isJSDOM = /jsdom/.test(window.navigator.userAgent);

const getPickerDay = (name: string, picker = 'January 2018'): HTMLButtonElement =>
getByRole(screen.getByText(picker)?.parentElement?.parentElement!, 'gridcell', { name });
const getPickerDay = (name: string, picker = 'January 2018') =>
getByRole(screen.getByRole('grid', { name: picker }), 'gridcell', { name });

describe('<DesktopDateRangePicker />', () => {
const { render, clock } = createPickerRenderer({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ const PickersRangeCalendarHeader = React.forwardRef(function PickersRangeCalenda
const utils = useUtils<TDate>();
const localeText = useLocaleText<TDate>();

const { calendars, month, monthIndex, ...other } = props;
const { calendars, month, monthIndex, labelId, ...other } = props;
const {
format,
slots,
Expand All @@ -56,7 +56,7 @@ const PickersRangeCalendarHeader = React.forwardRef(function PickersRangeCalenda
});

if (calendars === 1) {
return <PickersCalendarHeader {...other} ref={ref} />;
return <PickersCalendarHeader {...other} labelId={labelId} ref={ref} />;
}

const selectNextMonth = () => onMonthChange(utils.addMonths(currentMonth, 1), 'left');
Expand All @@ -76,6 +76,7 @@ const PickersRangeCalendarHeader = React.forwardRef(function PickersRangeCalenda
nextLabel={localeText.nextMonth}
slots={slots}
slotProps={slotProps}
labelId={labelId}
>
{utils.formatByString(month, format ?? `${utils.formats.month} ${utils.formats.year}`)}
</PickersRangeCalendarHeaderContentMultipleCalendars>
Expand Down Expand Up @@ -105,6 +106,10 @@ PickersRangeCalendarHeader.propTypes = {
* @default `${adapter.formats.month} ${adapter.formats.year}`
*/
format: PropTypes.string,
/**
* Id of the calendar text element.
* It is used to establish an `aria-labelledby` relationship with the calendar `grid` element.
*/
labelId: PropTypes.string,
maxDate: PropTypes.object.isRequired,
minDate: PropTypes.object.isRequired,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,10 @@ PickersCalendarHeader.propTypes = {
* @default `${adapter.formats.month} ${adapter.formats.year}`
*/
format: PropTypes.string,
/**
* Id of the calendar text element.
* It is used to establish an `aria-labelledby` relationship with the calendar `grid` element.
*/
labelId: PropTypes.string,
maxDate: PropTypes.object.isRequired,
minDate: PropTypes.object.isRequired,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,10 @@ export interface PickersCalendarHeaderProps<TDate extends PickerValidDate>
view: DateView;
reduceAnimations: boolean;
onViewChange?: (view: DateView) => void;
/**
* Id of the calendar text element.
* It is used to establish an `aria-labelledby` relationship with the calendar `grid` element.
*/
labelId?: string;
/**
* Override or extend the styles applied to the component.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ export const PickersArrowSwitcher = React.forwardRef(function PickersArrowSwitch
isPreviousHidden,
onGoToPrevious,
previousLabel,
labelId,
...other
} = props;

Expand Down Expand Up @@ -169,7 +170,7 @@ export const PickersArrowSwitcher = React.forwardRef(function PickersArrowSwitch
)}
</PreviousIconButton>
{children ? (
<Typography variant="subtitle1" component="span">
<Typography variant="subtitle1" component="span" id={labelId}>
{children}
</Typography>
) : (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ export interface PickersArrowSwitcherProps
isNextHidden?: boolean;
onGoToNext: () => void;
nextLabel: string;
labelId?: string;
}

export type PickersArrowSwitcherOwnerState = PickersArrowSwitcherProps;
Expand Down

0 comments on commit 05dd41f

Please sign in to comment.