Skip to content
This repository was archived by the owner on Jul 19, 2025. It is now read-only.
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
a7ee4ff
Implement dom-based keyboard navigation for year selection
dmtrKovalenko Feb 3, 2020
6c1c7df
Make calendar keyboard navigation also focus-based
dmtrKovalenko Feb 4, 2020
501a8ad
Fix animation freesing because of .focus() in Calendar
dmtrKovalenko Feb 5, 2020
1f05deb
Add proper aria-label's for calendar
dmtrKovalenko Feb 5, 2020
60813cc
Properly handle focus when switching months
dmtrKovalenko Feb 7, 2020
dfbce44
Announce month and year switching
dmtrKovalenko Feb 7, 2020
8be5e08
Make props for customizing aria-label texts
dmtrKovalenko Feb 8, 2020
98916ea
Fix type for useKeyDown handler
dmtrKovalenko Feb 8, 2020
c4ce41f
Add aria-label for mobile keyboard input button
dmtrKovalenko Feb 8, 2020
6166587
Fix Prop inference after changing interfaces
dmtrKovalenko Feb 8, 2020
a387460
Implement force quitting picker onKeyDown
dmtrKovalenko Feb 10, 2020
80cad80
Aria-labels and live regions for date & time picker
dmtrKovalenko Feb 10, 2020
d70de96
Fix day and clock numbers not autofocusing on appear
dmtrKovalenko Feb 10, 2020
cbf87eb
Fix missing container if `reduceAnimations`
dmtrKovalenko Feb 11, 2020
5badc9d
Better default focus management
dmtrKovalenko Feb 11, 2020
12965cd
Add more keyboard shorcats
dmtrKovalenko Feb 11, 2020
e7398fd
Add accessibility guide
dmtrKovalenko Feb 11, 2020
685224b
Fix styles of markdown table
dmtrKovalenko Feb 11, 2020
4d700e5
Fix grammar in accessibility guideline
dmtrKovalenko Feb 11, 2020
9d82f42
Fix crashing on openning invalid date
dmtrKovalenko Feb 13, 2020
dfc2c24
Make focus visible when root element of wrapper is focused
dmtrKovalenko Feb 13, 2020
0c94104
Fix not closing mobile dialog with esc
dmtrKovalenko Feb 13, 2020
0492aef
Better match material design accessibility spec
dmtrKovalenko Feb 13, 2020
7f03584
Fix ts error and linters
dmtrKovalenko Feb 13, 2020
92e399e
Add keyboard navigation cypress tests
dmtrKovalenko Feb 13, 2020
7716d26
Skip flaky test
dmtrKovalenko Feb 13, 2020
52809e3
Experiment with cypress coverage
dmtrKovalenko Feb 13, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Better default focus management
  • Loading branch information
dmtrKovalenko committed Feb 11, 2020
commit 5badc9dc3f74d1d04334a6e060e5d6996c688896
1 change: 0 additions & 1 deletion lib/src/constants/prop-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ export const datePickerDefaultProps = {
invalidDateMessage: 'Invalid Date Format',
minDateMessage: 'Date should not be before minimal date',
maxDateMessage: 'Date should not be after maximal date',
allowKeyboardControl: true,
} as BaseDatePickerProps;

export const dateTimePickerDefaultProps = {
Expand Down
10 changes: 6 additions & 4 deletions lib/src/views/Calendar/Calendar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import { useUtils, useNow } from '../../_shared/hooks/useUtils';
import { PickerOnChangeFn } from '../../_shared/hooks/useViews';
import { findClosestEnabledDate } from '../../_helpers/date-utils';
import { makeStyles, useTheme, Typography } from '@material-ui/core';
import { FORCE_FINISH_PICKER } from '../../_shared/hooks/usePickerState';
import { useGlobalKeyDown, keycode } from '../../_shared/hooks/useKeyDown';

export interface ExportedCalendarProps {
Expand All @@ -35,7 +34,7 @@ export interface ExportedCalendarProps {
) => JSX.Element;
/**
* Enables keyboard listener for moving between days in calendar
* @default true
* @default currentWrapper !== 'static'
*/
allowKeyboardControl?: boolean;
/** Custom loading indicator */
Expand Down Expand Up @@ -143,14 +142,17 @@ export const Calendar: React.FC<CalendarProps> = ({
}, []); // eslint-disable-line

const nowFocusedDay = focusedDay || date;
useGlobalKeyDown(Boolean(allowKeyboardControl && wrapperVariant !== 'static'), {
[keycode.Enter]: () => handleDaySelect(nowFocusedDay, FORCE_FINISH_PICKER),
useGlobalKeyDown(Boolean(allowKeyboardControl ?? wrapperVariant !== 'static'), {
[keycode.ArrowUp]: () => changeFocusedDay(utils.addDays(nowFocusedDay, -7)),
[keycode.ArrowDown]: () => changeFocusedDay(utils.addDays(nowFocusedDay, 7)),
[keycode.ArrowLeft]: () =>
changeFocusedDay(utils.addDays(nowFocusedDay, theme.direction === 'ltr' ? -1 : 1)),
[keycode.ArrowRight]: () =>
changeFocusedDay(utils.addDays(nowFocusedDay, theme.direction === 'ltr' ? 1 : -1)),
[keycode.Home]: () =>
changeFocusedDay(utils.addDays(nowFocusedDay, -utils.toJsDate(nowFocusedDay).getDay())),
[keycode.End]: () =>
changeFocusedDay(utils.addDays(nowFocusedDay, 6 - utils.toJsDate(nowFocusedDay).getDay())),
});

const selectedDate = utils.startOfDay(date);
Expand Down
6 changes: 3 additions & 3 deletions lib/src/views/Calendar/YearSelection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,8 @@ export const YearSelection: React.FC<YearSelectionProps> = ({
const theme = useTheme();
const utils = useUtils();
const classes = useStyles();
const [focusedYear, setFocused] = React.useState<number | null>(null);
const currentYear = utils.getYear(date);
const [focusedYear, setFocused] = React.useState<number | null>(currentYear);
const wrapperVariant = React.useContext(WrapperVariantContext);
const selectedYearRef = React.useRef<HTMLDivElement>(null);

Expand All @@ -63,7 +64,6 @@ export const YearSelection: React.FC<YearSelectionProps> = ({
}
}, []); // eslint-disable-line

const currentYear = utils.getYear(date);
const handleYearSelection = React.useCallback(
(year: number, isFinish = true) => {
const newDate = utils.setYear(date, year);
Expand All @@ -82,7 +82,7 @@ export const YearSelection: React.FC<YearSelectionProps> = ({

const yearsInRow = wrapperVariant === 'desktop' ? 4 : 3;
const nowFocusedYear = focusedYear || currentYear;
useGlobalKeyDown(wrapperVariant !== 'static' && Boolean(allowKeyboardControl), {
useGlobalKeyDown(Boolean(allowKeyboardControl ?? wrapperVariant !== 'static'), {
[keys.ArrowUp]: () => setFocused(nowFocusedYear - yearsInRow),
[keys.ArrowDown]: () => setFocused(nowFocusedYear + yearsInRow),
[keys.ArrowLeft]: () => setFocused(nowFocusedYear + (theme.direction === 'ltr' ? -1 : 1)),
Expand Down
15 changes: 9 additions & 6 deletions lib/src/views/Clock/Clock.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import { PickerOnChangeFn } from '../../_shared/hooks/useViews';
import { getHours, getMinutes } from '../../_helpers/time-utils';
import { useMeridiemMode } from '../../TimePicker/TimePickerToolbar';
import { IconButton, Typography, makeStyles } from '@material-ui/core';
import { FORCE_FINISH_PICKER } from '../../_shared/hooks/usePickerState';
import { useGlobalKeyDown, keycode } from '../../_shared/hooks/useKeyDown';
import { WrapperVariantContext } from '../../wrappers/WrapperVariantContext';

Expand All @@ -24,6 +23,7 @@ export interface ClockProps {
ampm?: boolean;
minutesStep?: number;
ampmInClock?: boolean;
allowKeyboardControl?: boolean;
}

export const useStyles = makeStyles(
Expand Down Expand Up @@ -99,6 +99,7 @@ export const Clock: React.FC<ClockProps> = ({
type,
ampm,
minutesStep = 1,
allowKeyboardControl,
onChange,
}) => {
const utils = useUtils();
Expand Down Expand Up @@ -168,11 +169,13 @@ export const Clock: React.FC<ClockProps> = ({
}, [type, value]);

const keyboardControlStep = type === 'minutes' ? minutesStep : 1;
useGlobalKeyDown(!isMoving.current, {
[keycode.ArrowUp]: () => onChange(value + keyboardControlStep, false),
[keycode.ArrowDown]: () => onChange(value - keyboardControlStep, false),
[keycode.Enter]: () => onChange(value, FORCE_FINISH_PICKER),
});
useGlobalKeyDown(
Boolean(allowKeyboardControl ?? wrapperVariant !== 'static') && !isMoving.current,
{
[keycode.ArrowUp]: () => onChange(value + keyboardControlStep, false),
[keycode.ArrowDown]: () => onChange(value - keyboardControlStep, false),
}
);

return (
<div className={classes.container}>
Expand Down
7 changes: 7 additions & 0 deletions lib/src/views/Clock/ClockView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,11 @@ export interface ClockViewProps extends BaseClockViewProps {
getMinutesClockNumberText?: (minutesText: string) => string;
/** Get clock number aria-text for seconds */
getSecondsClockNumberText?: (secondsText: string) => string;
/**
* Enables keyboard listener for moving between days in calendar
* @default currentWrapper !== 'static'
*/
allowKeyboardControl?: boolean;
}

const getHoursAriaText = (hour: string) => `${hour} hours`;
Expand All @@ -53,6 +58,7 @@ export const ClockView: React.FC<ClockViewProps> = ({
date,
minutesStep,
ampmInClock,
allowKeyboardControl,
getHoursClockNumberText = getHoursAriaText,
getMinutesClockNumberText = getMinutesAriaText,
getSecondsClockNumberText = getSecondsAriaText,
Expand Down Expand Up @@ -145,6 +151,7 @@ export const ClockView: React.FC<ClockViewProps> = ({
type={type}
ampm={ampm}
minutesStep={minutesStep}
allowKeyboardControl={allowKeyboardControl}
{...viewProps}
/>
);
Expand Down