Skip to content

Commit

Permalink
fix(table): improve table accessibility (#300)
Browse files Browse the repository at this point in the history
* feat(Table): Add functionality to sort by clicking table header
#287
  • Loading branch information
KRRISH96 authored and rishichawda committed Jan 1, 2019
1 parent de21936 commit 4f11e93
Show file tree
Hide file tree
Showing 3 changed files with 110 additions and 8 deletions.
30 changes: 24 additions & 6 deletions doc/src/components/common/componentData/Table/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,12 @@ export const componentData = {
defaultValue: 'false',
description: 'Prop to be sent, If sorting functionality is required.',
},
{
prop: 'sortByTitle',
type: 'Boolean',
defaultValue: 'false',
description: 'Prop to be sent, If sorting functionality by clicking column header is required.',
},
],
themesData: [
{
Expand Down Expand Up @@ -106,6 +112,10 @@ export const componentData = {
name: 'sortArrow',
description: 'Class used for the sorting arrows in table header cells.',
},
{
name: 'sortableTitle',
description: 'Class used for the title when sortByTitle is enabled.',
},
],
basicComponent: `
class Demo extends React.Component {
Expand Down Expand Up @@ -163,7 +173,7 @@ export const componentData = {
render() {
const columns = [
{ title: 'Name', key: 'name', colWidth: '150px' },
{ title: 'Default Value', key: 'defaultValue' },
{ title: 'Default Value', key: 'defaultValue', colWidth: '180px' },
{ title: 'Description', key: 'description' },
];
const data = [
Expand Down Expand Up @@ -194,12 +204,20 @@ export const componentData = {
},
];
return (
<PreviewElements>
<div>
<PreviewBlock header="Table, Sortable with buttons">
{/* Default table component with sort functionality */}
<Table columns={columns} data={data} sort />
</PreviewElements>
{/* Default table component with sort functionality */}
<Table columns={columns} data={data} sort />
</PreviewBlock>
<PreviewBlock header="Table, sortable by clicking header cell">
{/* Default table component with sort functionality on clicking header */}
<Table columns={columns} data={data} sortByTitle />
</PreviewBlock>
</div>
)
}
}
Expand Down
60 changes: 58 additions & 2 deletions lib/table/index.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
/* eslint-disable react/destructuring-assignment */
import React from 'react';
import classnames from 'classnames';
import { themr } from 'react-css-themr';
import { FaArrowDown } from 'react-icons/fa';
import PropTypes from 'prop-types';
import defaultTheme from './theme.module.scss';

Expand All @@ -12,6 +14,14 @@ class Table extends React.Component {
};
}

componentDidMount() {
const { columns } = this.props;
this.setState({
sortTitle: columns[0].key,
[`${columns[0].key}Ascending`]: true,
});
}

componentDidUpdate() {
const { data } = this.props;
const { tableData } = this.state;
Expand Down Expand Up @@ -80,13 +90,57 @@ class Table extends React.Component {
);
}

handleTitleSort = (key) => {
// eslint-disable-next-line react/destructuring-assignment
this.setState(prevState => ({
[`${key}TitleToggle`]: !prevState[[`${key}TitleToggle`]],
}));
if (this.state[`${key}TitleToggle`]) {
this.sortAscending(key);
} else {
this.sortDescending(key);
}
}

renderArrowIcon = (isCurrentKey, key) => {
const { theme } = this.props;
return (
<FaArrowDown
className={classnames(
theme.arrow,
!isCurrentKey && theme.hidden,
this.state[`${key}Ascending`] ? theme.downArrow : theme.upArrow,
)}
/>
);
}

renderSortableTitle = (title, key) => {
const { sortTitle } = this.state;
const { theme } = this.props;
const isCurrentKey = sortTitle === key;
return (
<div
className={theme.sortableTitle}
onClick={() => this.handleTitleSort(key)}
>
{title}
<span className={theme.sortableTitleIcon}>
{this.renderArrowIcon(isCurrentKey, key)}
</span>
</div>
);
}

/*
* the table header content will be rendered from accepting columns prop as array,
* the number of columns in table is directly proportional to
* length of columns array from prop
*/
renderTableHeader = () => {
const { columns, theme, sort } = this.props;
const {
columns, theme, sort, sortByTitle,
} = this.props;
return (
<div className={theme.tableHeader} aria-label="table-header">
{ columns && columns.map(({
Expand All @@ -99,7 +153,7 @@ class Table extends React.Component {
{...other}
>
<div className={theme.tableHeadCellContent}>
{title}
{sortByTitle ? this.renderSortableTitle(title, key) : title}
{sort && this.renderSortArrow(key)}
</div>
</div>
Expand Down Expand Up @@ -170,11 +224,13 @@ Table.propTypes = {
columns: PropTypes.oneOfType([PropTypes.array]).isRequired,
data: PropTypes.oneOfType([PropTypes.array]).isRequired,
sort: PropTypes.bool,
sortByTitle: PropTypes.bool,
};

Table.defaultProps = {
theme: defaultTheme,
sort: false,
sortByTitle: false,
};

export default themr('CBTable', defaultTheme)(Table);
28 changes: 28 additions & 0 deletions lib/table/theme.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,35 @@
}
:local(.tableHeadCellContent) {
justify-content: space-between;
:local(.sortableTitle) {
cursor: pointer;
:local(.hidden) {
opacity: 0;
}
&:hover {
:local(.hidden) {
opacity: 1;
}
}
}
:local(.sortableTitleIcon) {
font-size: 0.8em;
margin-left: 0.7em;
}
}

:local(.arrow) {
transition: all 0.2s linear;
}

:local(.upArrow) {
transform: rotate(0deg);
}

:local(.downArrow) {
transform: rotate(180deg);
}

:local(.sortArrow) {
position: relative;
width: 12px;
Expand Down

0 comments on commit 4f11e93

Please sign in to comment.