Skip to content

Commit

Permalink
[a11y] Open picker by space click (mui#1266)
Browse files Browse the repository at this point in the history
* Open picker by space/enter click

* Change new prop name to not conflict with current onOpen

* Use only enter to open

* Fix comment
  • Loading branch information
dmtrKovalenko committed Aug 17, 2019
1 parent 142cb5f commit f8a4b63
Show file tree
Hide file tree
Showing 6 changed files with 34 additions and 13 deletions.
6 changes: 3 additions & 3 deletions lib/src/_shared/KeyboardDateInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export interface KeyboardDateInputProps
extends ExtendMui<BaseTextFieldProps, 'variant' | 'onError' | 'onChange' | 'value'> {
format: string;
onChange: (value: string | null) => void;
onClick?: () => void;
openPicker?: () => void;
validationError?: React.ReactNode;
inputValue: string;
inputProps?: TextFieldProps['inputProps'];
Expand Down Expand Up @@ -56,7 +56,7 @@ export const KeyboardDateInput: React.FunctionComponent<KeyboardDateInputProps>
validationError,
KeyboardButtonProps,
InputAdornmentProps,
onClick,
openPicker: onOpen,
onChange,
InputProps,
mask,
Expand Down Expand Up @@ -105,7 +105,7 @@ export const KeyboardDateInput: React.FunctionComponent<KeyboardDateInputProps>
...InputProps,
[`${position}Adornment`]: (
<InputAdornment position={position} {...InputAdornmentProps}>
<IconButton disabled={disabled} {...KeyboardButtonProps} onClick={onClick}>
<IconButton disabled={disabled} {...KeyboardButtonProps} onClick={onOpen}>
{keyboardIcon}
</IconButton>
</InputAdornment>
Expand Down
19 changes: 19 additions & 0 deletions lib/src/_shared/PureDateInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,15 @@ import * as React from 'react';
import TextField, { BaseTextFieldProps, TextFieldProps } from '@material-ui/core/TextField';
import { ExtendMui } from '../typings/extendMui';

export type NotOverridableProps =
| 'openPicker'
| 'inputValue'
| 'onChange'
| 'format'
| 'validationError'
| 'format'
| 'forwardedRef';

export interface PureDateInputProps
extends ExtendMui<BaseTextFieldProps, 'variant' | 'onError' | 'onChange' | 'value'> {
/** Pass material-ui text field variant down, bypass internal variant prop */
Expand All @@ -12,13 +21,15 @@ export interface PureDateInputProps
inputProps?: TextFieldProps['inputProps'];
inputValue: string;
validationError?: React.ReactNode;
openPicker: () => void;
}

export const PureDateInput: React.FC<PureDateInputProps> = ({
inputValue,
inputVariant,
validationError,
InputProps,
openPicker: onOpen,
TextFieldComponent = TextField,
...other
}) => {
Expand All @@ -36,9 +47,17 @@ export const PureDateInput: React.FC<PureDateInputProps> = ({
helperText={validationError}
{...other}
// do not overridable
onClick={onOpen}
value={inputValue}
variant={inputVariant as any}
InputProps={PureDateInputProps}
onKeyDown={e => {
// space
if (e.keyCode === 32) {
e.stopPropagation();
onOpen();
}
}}
/>
);
};
Expand Down
10 changes: 4 additions & 6 deletions lib/src/_shared/hooks/useKeyDown.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,19 +16,17 @@ export function runKeyHandler(e: KeyboardEvent, keyHandlers: KeyHandlers) {

export function useKeyDown(active: boolean, keyHandlers: KeyHandlers) {
const keyHandlersRef = React.useRef(keyHandlers);
useIsomorphicEffect(() => {
keyHandlersRef.current = keyHandlers;
});
keyHandlersRef.current = keyHandlers;

React.useEffect(() => {
useIsomorphicEffect(() => {
if (active) {
const handleKeyDown = (event: KeyboardEvent) => {
runKeyHandler(event, keyHandlers);
runKeyHandler(event, keyHandlersRef.current);
};
window.addEventListener('keydown', handleKeyDown);
return () => {
window.removeEventListener('keydown', handleKeyDown);
};
}
}, [active, keyHandlers]);
}, [active]);
}
2 changes: 1 addition & 1 deletion lib/src/_shared/hooks/usePickerState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ export function usePickerState(props: BasePickerProps, options: StateHookOptions
() => ({
inputValue,
validationError,
onClick: () => !disabled && setIsOpen(true),
openPicker: () => !disabled && setIsOpen(true),
}),
[disabled, inputValue, setIsOpen, validationError]
);
Expand Down
6 changes: 5 additions & 1 deletion lib/src/views/Calendar/Calendar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import CalendarHeader from './CalendarHeader';
import CircularProgress from '@material-ui/core/CircularProgress';
import SlideTransition, { SlideDirection } from './SlideTransition';
import { Theme } from '@material-ui/core/styles';
import { VariantContext } from '../../wrappers/Wrapper';
import { MaterialUiPickersDate } from '../../typings/date';
import { runKeyHandler } from '../../_shared/hooks/useKeyDown';
import { IconButtonProps } from '@material-ui/core/IconButton';
Expand Down Expand Up @@ -85,6 +86,7 @@ const KeyDownListener = ({ onKeyDown }: { onKeyDown: (e: KeyboardEvent) => void
};

export class Calendar extends React.Component<CalendarProps, CalendarState> {
static contextType = VariantContext;
static propTypes: any = {
renderDay: PropTypes.func,
shouldDisableDate: PropTypes.func,
Expand Down Expand Up @@ -306,7 +308,9 @@ export class Calendar extends React.Component<CalendarProps, CalendarState> {

return (
<React.Fragment>
{allowKeyboardControl && <KeyDownListener onKeyDown={this.handleKeyDown} />}
{allowKeyboardControl && this.context !== 'static' && (
<KeyDownListener onKeyDown={this.handleKeyDown} />
)}

<CalendarHeader
currentMonth={currentMonth!}
Expand Down
4 changes: 2 additions & 2 deletions lib/src/wrappers/Wrapper.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import * as React from 'react';
import { Omit } from '@material-ui/core';
import { StaticWrapper } from './StaticWrapper';
import { PureDateInputProps } from '../_shared/PureDateInput';
import { ModalWrapper, ModalWrapperProps } from './ModalWrapper';
import { InlineWrapper, InlineWrapperProps } from './InlineWrapper';
import { KeyboardDateInputProps } from '../_shared/KeyboardDateInput';
import { PureDateInputProps, NotOverridableProps } from '../_shared/PureDateInput';

export type WrapperVariant = 'dialog' | 'inline' | 'static';

Expand Down Expand Up @@ -38,7 +38,7 @@ export type ExtendWrapper<TInput extends PureDateInputProps | KeyboardDateInputP
variant?: WrapperVariant
} & ModalRoot
& InlineRoot
& Omit<TInput, 'inputValue' | 'onChange' | 'format' | 'validationError' | 'format' | 'forwardedRef'>
& Omit<TInput, NotOverridableProps>

export function getWrapperFromVariant<T>(
variant?: WrapperVariant
Expand Down

0 comments on commit f8a4b63

Please sign in to comment.