Skip to content

Commit

Permalink
Merge pull request mui#980 from dmtrKovalenko/feature/toolbar-keybrd-…
Browse files Browse the repository at this point in the history
…accessibility

Toolbar keyboard accessibility
  • Loading branch information
dmtrKovalenko authored Apr 9, 2019
2 parents 6569a6a + 60fa7d0 commit 2c0505f
Show file tree
Hide file tree
Showing 10 changed files with 144 additions and 43 deletions.
2 changes: 1 addition & 1 deletion docs/pages/regression/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import RightArrowIcon from '@material-ui/icons/KeyboardArrowRight';

function Regression() {
const utils = useContext(MuiPickersContext);
const [date, changeDate] = useState(new Date('2019-01-01T00:00:00.000Z'));
const [date, changeDate] = useState(new Date('2019-01-01T00:00:00.000'));

const sharedProps = {
value: date,
Expand Down
3 changes: 1 addition & 2 deletions lib/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@
"react-text-mask": "^5.4.3",
"react-transition-group": "^2.5.3",
"rifm": "^0.7.0",
"ts-jest": "^24.0.1",
"tslib": "^1.9.3"
},
"size-limit": [
Expand Down Expand Up @@ -111,7 +110,7 @@
"rollup-plugin-typescript": "^1.0.0",
"rollup-plugin-uglify": "^6.0.2",
"size-limit": "^0.21.1",
"ts-jest": "^23.10.5",
"ts-jest": "^24.0.1",
"ts-lib": "0.0.5",
"tslint": "^5.12.1",
"tslint-config-prettier": "^1.18.0",
Expand Down
18 changes: 13 additions & 5 deletions lib/src/DateTimePicker/components/DateTimePickerHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import createStyles from '@material-ui/core/styles/createStyles';
import withStyles, { WithStyles } from '@material-ui/core/styles/withStyles';
import PickerToolbar from '../../_shared/PickerToolbar';
import ToolbarButton from '../../_shared/ToolbarButton';
import ToolbarText from '../../_shared/ToolbarText';
import { withUtils, WithUtilsProps } from '../../_shared/WithUtils';
import DateTimePickerView, { DateTimePickerViewType } from '../../constants/DateTimePickerView';
import { MaterialUiPickersDate } from '../../typings/date';
Expand Down Expand Up @@ -39,6 +40,10 @@ export const styles = (theme: Theme) =>
height: 60,
minWidth: 110,
marginRight: 4,
display: 'flex',
flexDirection: 'column',
alignItems: 'flex-start',
justifyContent: 'flex-start',
},
timeHeader: {
height: 65,
Expand All @@ -50,6 +55,9 @@ export const styles = (theme: Theme) =>
ampmSelection: {
top: 11,
position: 'relative',
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
marginLeft: 10,
marginRight: -10,
},
Expand Down Expand Up @@ -105,7 +113,7 @@ export const DateTimePickerHeader: React.SFC<DateTimePickerHeaderProps> = ({
label={utils.getHourText(date, ampm!)}
/>

<ToolbarButton variant="h3" label=":" selected={false} className={classes.separator} />
<ToolbarText variant="h3" label=":" selected={false} className={classes.separator} />

<ToolbarButton
variant="h3"
Expand All @@ -118,17 +126,17 @@ export const DateTimePickerHeader: React.SFC<DateTimePickerHeaderProps> = ({
{ampm && (
<div className={classes.ampmSelection}>
<ToolbarButton
className={classes.ampmLabel}
selected={meridiemMode === 'am'}
variant="subtitle1"
typographyClassName={classes.ampmLabel}
selected={meridiemMode === 'am'}
label={utils.getMeridiemText('am')}
onClick={setMeridiemMode('am')}
/>

<ToolbarButton
className={classes.ampmLabel}
selected={meridiemMode === 'pm'}
variant="subtitle1"
typographyClassName={classes.ampmLabel}
selected={meridiemMode === 'pm'}
label={utils.getMeridiemText('pm')}
onClick={setMeridiemMode('pm')}
/>
Expand Down
23 changes: 16 additions & 7 deletions lib/src/TimePicker/TimePickerRoot.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import ClockType from '../constants/ClockType';
import { MeridiemMode } from '../DateTimePicker/components/DateTimePickerHeader';
import { MaterialUiPickersDate } from '../typings/date';
import TimePickerView from './components/TimePickerView';
import ToolbarText from '../_shared/ToolbarText';

export interface BaseTimePickerProps {
/** 12h/24h view for hour selection clock */
Expand Down Expand Up @@ -167,7 +168,7 @@ export class TimePickerRoot extends React.Component<TimePickerProps> {
label={utils.getHourText(date, Boolean(ampm))}
/>

<ToolbarButton variant="h2" label=":" selected={false} className={classes.separator} />
<ToolbarText variant="h2" label=":" selected={false} className={classes.separator} />

<ToolbarButton
variant="h2"
Expand All @@ -178,7 +179,7 @@ export class TimePickerRoot extends React.Component<TimePickerProps> {

{seconds && (
<React.Fragment>
<ToolbarButton
<ToolbarText
variant="h2"
label=":"
selected={false}
Expand All @@ -196,19 +197,25 @@ export class TimePickerRoot extends React.Component<TimePickerProps> {
</div>

{ampm && (
<div className={seconds ? classes.ampmSelectionWithSeconds : classes.ampmSelection}>
<div
className={clsx(classes.ampmSelection, {
[classes.ampmSelectionWithSeconds]: seconds,
})}
>
<ToolbarButton
className={classes.ampmLabel}
selected={meridiemMode === 'am'}
disableRipple
variant="subtitle1"
selected={meridiemMode === 'am'}
typographyClassName={classes.ampmLabel}
label={utils.getMeridiemText('am')}
onClick={this.setMeridiemMode('am')}
/>

<ToolbarButton
className={classes.ampmLabel}
selected={meridiemMode === 'pm'}
disableRipple
variant="subtitle1"
selected={meridiemMode === 'pm'}
typographyClassName={classes.ampmLabel}
label={utils.getMeridiemText('pm')}
onClick={this.setMeridiemMode('pm')}
/>
Expand Down Expand Up @@ -248,6 +255,8 @@ export const styles = () =>
ampmSelection: {
marginLeft: 20,
marginRight: -20,
display: 'flex',
flexDirection: 'column',
},
ampmSelectionWithSeconds: {
marginLeft: 15,
Expand Down
16 changes: 16 additions & 0 deletions lib/src/__tests__/_shared/ToolbarText.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { ShallowWrapper } from 'enzyme';
import * as React from 'react';
import ToolbarText, { ToolbarTextProps } from '../../_shared/ToolbarText';
import { shallow } from '../test-utils';

describe('Toolbar Text', () => {
let component: ShallowWrapper<ToolbarTextProps>;

beforeEach(() => {
component = shallow(<ToolbarText selected={true} label="hello" />);
});

it('Should render', () => {
expect(component).toBeTruthy();
});
});
10 changes: 9 additions & 1 deletion lib/src/__tests__/e2e/DatePicker.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,15 @@ describe('e2e - DatePicker default year format', () => {
const date = utilsToUse.date('2018-01-01T00:00:00.000Z');

beforeEach(() => {
component = mount(<DatePicker onChange={onChangeMock} value={date} views={['year']} />);
jest.clearAllMocks();
component = mount(
<DatePicker
animateYearScrolling={false}
value={utilsToUse.date('2018-01-01T00:00:00.000')}
onChange={onChangeMock}
views={['year']}
/>
);
});

it('Should use year format by default for year only view', () => {
Expand Down
6 changes: 3 additions & 3 deletions lib/src/__tests__/e2e/DateTimePickerRoot.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ describe('e2e - DateTimePicker', () => {
<DateTimePicker
date={utilsToUse.date('2018-01-01T00:00:00.000Z')}
onChange={onChangeMock}
openTo="date"
openTo="hours"
leftArrowIcon="keyboard_arrow_left"
rightArrowIcon="keyboard_arrow_right"
dateRangeIcon="date_range"
Expand Down Expand Up @@ -52,15 +52,15 @@ describe('e2e - DateTimePicker', () => {
it('Should render minutes view', () => {
component
.find('ToolbarButton')
.at(4)
.at(3)
.simulate('click');
expect(component.find('TimePickerView').props().type).toBe('minutes');
});

it('Should change meridiem', () => {
component
.find('ToolbarButton')
.at(6)
.at(5)
.simulate('click');

if (process.env.UTILS === 'moment') {
Expand Down
2 changes: 1 addition & 1 deletion lib/src/__tests__/e2e/TimePicker.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ describe('e2e - TimePicker', () => {
beforeEach(() => {
jest.clearAllMocks();
component = mount(
<TimePicker date={utilsToUse.date('2018-01-01T00:00:00.000Z')} onChange={onChangeMock} />
<TimePicker date={utilsToUse.date('2018-01-01T00:00:00.000')} onChange={onChangeMock} />
);
});

Expand Down
54 changes: 31 additions & 23 deletions lib/src/_shared/ToolbarButton.tsx
Original file line number Diff line number Diff line change
@@ -1,32 +1,42 @@
import { Theme } from '@material-ui/core';
import withStyles, { WithStyles } from '@material-ui/core/styles/withStyles';
import Typography, { TypographyProps } from '@material-ui/core/Typography';
import { createStyles, withStyles, WithStyles } from '@material-ui/core';
import Button, { ButtonProps } from '@material-ui/core/Button';
import { TypographyProps } from '@material-ui/core/Typography';
import clsx from 'clsx';
import * as PropTypes from 'prop-types';
import * as React from 'react';

import { ExtendMui } from '../typings/extendMui';
import ToolbarText from './ToolbarText';

export interface ToolbarButtonProps extends ExtendMui<TypographyProps>, WithStyles<typeof styles> {
export interface ToolbarButtonProps
extends ExtendMui<ButtonProps, 'variant'>,
WithStyles<typeof styles> {
variant: TypographyProps['variant'];
selected: boolean;
label: string;
typographyClassName?: string;
}

const ToolbarButton: React.SFC<ToolbarButtonProps> = ({
const ToolbarButton: React.FunctionComponent<ToolbarButtonProps> = ({
classes,
selected,
label,
className = null,
label,
selected,
variant,
typographyClassName,
...other
}) => (
<Typography
className={clsx(classes.toolbarBtn, className, {
[classes.toolbarBtnSelected]: selected,
})}
{...other}
>
{label}
</Typography>
);
}) => {
return (
<Button className={clsx(classes.toolbarBtn, className)} {...other}>
<ToolbarText
className={typographyClassName}
variant={variant}
label={label}
selected={selected}
/>
</Button>
);
};

(ToolbarButton as any).propTypes = {
selected: PropTypes.bool.isRequired,
Expand All @@ -40,13 +50,11 @@ ToolbarButton.defaultProps = {
className: '',
};

export const styles = (theme: Theme) => ({
export const styles = createStyles({
toolbarBtn: {
cursor: 'pointer',
color: 'rgba(255, 255, 255, 0.54)',
},
toolbarBtnSelected: {
color: theme.palette.common.white,
padding: 0,
minWidth: '16px',
textTransform: 'none',
},
});

Expand Down
53 changes: 53 additions & 0 deletions lib/src/_shared/ToolbarText.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import { Theme } from '@material-ui/core';
import withStyles, { WithStyles } from '@material-ui/core/styles/withStyles';
import Typography, { TypographyProps } from '@material-ui/core/Typography';
import clsx from 'clsx';
import * as PropTypes from 'prop-types';
import * as React from 'react';
import { ExtendMui } from '../typings/extendMui';

export interface ToolbarTextProps extends ExtendMui<TypographyProps>, WithStyles<typeof styles> {
selected: boolean;
label: string;
}

// TODO make a styled(Typography) when updated to material-ui
const ToolbarText: React.FunctionComponent<ToolbarTextProps> = ({
classes,
selected,
label,
className = null,
...other
}) => (
<Typography
className={clsx(classes.toolbarTxt, className, {
[classes.toolbarBtnSelected]: selected,
})}
{...other}
>
{label}
</Typography>
);

(ToolbarText as any).propTypes = {
selected: PropTypes.bool.isRequired,
label: PropTypes.string.isRequired,
classes: PropTypes.any.isRequired,
className: PropTypes.string,
innerRef: PropTypes.any,
};

ToolbarText.defaultProps = {
className: '',
};

export const styles = (theme: Theme) => ({
toolbarTxt: {
color: 'rgba(255, 255, 255, 0.54)',
},
toolbarBtnSelected: {
color: theme.palette.common.white,
},
});

export default withStyles(styles, { name: 'MuiPickersToolbarText' })(ToolbarText);

0 comments on commit 2c0505f

Please sign in to comment.