Skip to content

Commit

Permalink
feat(react-grid): support expanding/collapsing detail rows with keybo…
Browse files Browse the repository at this point in the history
…ard (#446)
  • Loading branch information
MaximKudriavtsev authored Oct 27, 2017
1 parent 4176d9a commit 47ab49d
Show file tree
Hide file tree
Showing 5 changed files with 133 additions and 40 deletions.
Original file line number Diff line number Diff line change
@@ -1,26 +1,44 @@
import React from 'react';
import PropTypes from 'prop-types';

export const TableDetailToggleCell = ({ style, expanded, toggleExpanded }) => (
<td
style={{
cursor: 'pointer',
...style,
}}
onClick={(e) => {
e.stopPropagation();
const ENTER_KEY_CODE = 13;
const SPACE_KEY_CODE = 32;

const handleMouseDown = (e) => { e.target.style.outline = 'none'; };
const handleBlur = (e) => { e.target.style.outline = ''; };

export const TableDetailToggleCell = ({ style, expanded, toggleExpanded }) => {
const handleKeyDown = (event) => {
if (event.keyCode === ENTER_KEY_CODE || event.keyCode === SPACE_KEY_CODE) {
event.preventDefault();
toggleExpanded();
}}
>
<i
className={`glyphicon glyphicon-triangle-${expanded ? 'bottom' : 'right'}`}
}
};
return (
<td
style={{
fontSize: '9px',
top: '0',
cursor: 'pointer',
...style,
}}
onClick={() => {
toggleExpanded();
}}
/>
</td>
);

>
<i
className={`glyphicon glyphicon-triangle-${expanded ? 'bottom' : 'right'}`}
style={{
fontSize: '9px',
top: '0',
}}
tabIndex={0} // eslint-disable-line jsx-a11y/no-noninteractive-tabindex
onKeyDown={handleKeyDown}
onMouseDown={handleMouseDown}
onBlur={handleBlur}
/>
</td>
);
};

TableDetailToggleCell.propTypes = {
style: PropTypes.object,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import React from 'react';
import { mount } from 'enzyme';
import { TableDetailToggleCell } from './table-detail-toggle-cell';

const ENTER_KEY_CODE = 13;
const SPACE_KEY_CODE = 32;

describe('TableDetailToggleCell', () => {
it('can get focus', () => {
const tree = mount((
<TableDetailToggleCell />
));

expect(tree.find('i').prop('tabIndex'))
.toBe(0);
});

it('should handle the "Enter" and "Space" keys down', () => {
const toggleExpanded = jest.fn();
const tree = mount((
<TableDetailToggleCell
toggleExpanded={toggleExpanded}
/>
));

const targetElement = tree.find('i');
targetElement.simulate('keydown', { keyCode: ENTER_KEY_CODE });
expect(toggleExpanded)
.toHaveBeenCalled();

toggleExpanded.mockClear();
targetElement.simulate('keydown', { keyCode: SPACE_KEY_CODE });
expect(toggleExpanded)
.toHaveBeenCalled();

toggleExpanded.mockClear();
targetElement.simulate('keydown', { keyCode: 51 });
expect(toggleExpanded)
.not.toHaveBeenCalled();
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ export class TableRowDetail extends React.PureComponent {
detailRowTemplate,
defaultDetailRowTemplate,
)}
detailToggleCellWidth={38}
detailToggleCellWidth={32}
{...restProps}
/>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,41 +5,48 @@ import { withStyles } from 'material-ui/styles';

import ChevronRight from 'material-ui-icons/ChevronRight';
import ExpandMore from 'material-ui-icons/ExpandMore';
import IconButton from 'material-ui/IconButton';

const styles = theme => ({
toggleCell: {
textAlign: 'center',
cursor: 'pointer',
textOverflow: 'initial',
paddingTop: 0,
paddingBottom: 0,
paddingLeft: theme.spacing.unit,
},
toggleCellIcon: {
toggleCellButton: {
verticalAlign: 'middle',
display: 'inline-block',
height: theme.spacing.unit * 3,
marginLeft: '-6px',
height: theme.spacing.unit * 5,
width: theme.spacing.unit * 5,
},
});

const TableDetailToggleCellBase = ({
style, expanded, classes, toggleExpanded,
}) => (
<TableCell
className={classes.toggleCell}
style={style}
onClick={(e) => {
e.stopPropagation();
toggleExpanded();
}}
>
<span className={classes.toggleCellIcon}>
{
expanded
? <ExpandMore />
: <ChevronRight />
}
</span>
</TableCell>
);
}) => {
const handleClick = () => {
toggleExpanded();
};
return (
<TableCell
className={classes.toggleCell}
style={style}
>
<IconButton
className={classes.toggleCellButton}
onClick={handleClick}
>
{
expanded
? <ExpandMore />
: <ChevronRight />
}
</IconButton>
</TableCell>
);
};

TableDetailToggleCellBase.propTypes = {
style: PropTypes.object,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import React from 'react';
import { mount } from 'enzyme';
import { TableDetailToggleCell } from './table-detail-toggle-cell';

describe('TableDetailToggleCell', () => {
it('should render IconButton', () => {
const tree = mount((
<TableDetailToggleCell />
));

expect(tree.find('IconButton').exists())
.toBeTruthy();
});

it('should handle click', () => {
const toggleExpanded = jest.fn();
const tree = mount((
<TableDetailToggleCell
toggleExpanded={toggleExpanded}
/>
));

tree.find('IconButton').simulate('click');
expect(toggleExpanded)
.toHaveBeenCalled();
});
});

0 comments on commit 47ab49d

Please sign in to comment.