Skip to content

Commit 4f11e93

Browse files
KRRISH96rishichawda
authored andcommitted
fix(table): improve table accessibility (#300)
* feat(Table): Add functionality to sort by clicking table header #287
1 parent de21936 commit 4f11e93

File tree

3 files changed

+110
-8
lines changed

3 files changed

+110
-8
lines changed

doc/src/components/common/componentData/Table/index.js

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,12 @@ export const componentData = {
6464
defaultValue: 'false',
6565
description: 'Prop to be sent, If sorting functionality is required.',
6666
},
67+
{
68+
prop: 'sortByTitle',
69+
type: 'Boolean',
70+
defaultValue: 'false',
71+
description: 'Prop to be sent, If sorting functionality by clicking column header is required.',
72+
},
6773
],
6874
themesData: [
6975
{
@@ -106,6 +112,10 @@ export const componentData = {
106112
name: 'sortArrow',
107113
description: 'Class used for the sorting arrows in table header cells.',
108114
},
115+
{
116+
name: 'sortableTitle',
117+
description: 'Class used for the title when sortByTitle is enabled.',
118+
},
109119
],
110120
basicComponent: `
111121
class Demo extends React.Component {
@@ -163,7 +173,7 @@ export const componentData = {
163173
render() {
164174
const columns = [
165175
{ title: 'Name', key: 'name', colWidth: '150px' },
166-
{ title: 'Default Value', key: 'defaultValue' },
176+
{ title: 'Default Value', key: 'defaultValue', colWidth: '180px' },
167177
{ title: 'Description', key: 'description' },
168178
];
169179
const data = [
@@ -194,12 +204,20 @@ export const componentData = {
194204
},
195205
];
196206
return (
197-
<PreviewElements>
207+
<div>
208+
<PreviewBlock header="Table, Sortable with buttons">
198209
199-
{/* Default table component with sort functionality */}
200-
<Table columns={columns} data={data} sort />
201-
202-
</PreviewElements>
210+
{/* Default table component with sort functionality */}
211+
<Table columns={columns} data={data} sort />
212+
213+
</PreviewBlock>
214+
<PreviewBlock header="Table, sortable by clicking header cell">
215+
216+
{/* Default table component with sort functionality on clicking header */}
217+
<Table columns={columns} data={data} sortByTitle />
218+
219+
</PreviewBlock>
220+
</div>
203221
)
204222
}
205223
}

lib/table/index.js

Lines changed: 58 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
1+
/* eslint-disable react/destructuring-assignment */
12
import React from 'react';
23
import classnames from 'classnames';
34
import { themr } from 'react-css-themr';
5+
import { FaArrowDown } from 'react-icons/fa';
46
import PropTypes from 'prop-types';
57
import defaultTheme from './theme.module.scss';
68

@@ -12,6 +14,14 @@ class Table extends React.Component {
1214
};
1315
}
1416

17+
componentDidMount() {
18+
const { columns } = this.props;
19+
this.setState({
20+
sortTitle: columns[0].key,
21+
[`${columns[0].key}Ascending`]: true,
22+
});
23+
}
24+
1525
componentDidUpdate() {
1626
const { data } = this.props;
1727
const { tableData } = this.state;
@@ -80,13 +90,57 @@ class Table extends React.Component {
8090
);
8191
}
8292

93+
handleTitleSort = (key) => {
94+
// eslint-disable-next-line react/destructuring-assignment
95+
this.setState(prevState => ({
96+
[`${key}TitleToggle`]: !prevState[[`${key}TitleToggle`]],
97+
}));
98+
if (this.state[`${key}TitleToggle`]) {
99+
this.sortAscending(key);
100+
} else {
101+
this.sortDescending(key);
102+
}
103+
}
104+
105+
renderArrowIcon = (isCurrentKey, key) => {
106+
const { theme } = this.props;
107+
return (
108+
<FaArrowDown
109+
className={classnames(
110+
theme.arrow,
111+
!isCurrentKey && theme.hidden,
112+
this.state[`${key}Ascending`] ? theme.downArrow : theme.upArrow,
113+
)}
114+
/>
115+
);
116+
}
117+
118+
renderSortableTitle = (title, key) => {
119+
const { sortTitle } = this.state;
120+
const { theme } = this.props;
121+
const isCurrentKey = sortTitle === key;
122+
return (
123+
<div
124+
className={theme.sortableTitle}
125+
onClick={() => this.handleTitleSort(key)}
126+
>
127+
{title}
128+
<span className={theme.sortableTitleIcon}>
129+
{this.renderArrowIcon(isCurrentKey, key)}
130+
</span>
131+
</div>
132+
);
133+
}
134+
83135
/*
84136
* the table header content will be rendered from accepting columns prop as array,
85137
* the number of columns in table is directly proportional to
86138
* length of columns array from prop
87139
*/
88140
renderTableHeader = () => {
89-
const { columns, theme, sort } = this.props;
141+
const {
142+
columns, theme, sort, sortByTitle,
143+
} = this.props;
90144
return (
91145
<div className={theme.tableHeader} aria-label="table-header">
92146
{ columns && columns.map(({
@@ -99,7 +153,7 @@ class Table extends React.Component {
99153
{...other}
100154
>
101155
<div className={theme.tableHeadCellContent}>
102-
{title}
156+
{sortByTitle ? this.renderSortableTitle(title, key) : title}
103157
{sort && this.renderSortArrow(key)}
104158
</div>
105159
</div>
@@ -170,11 +224,13 @@ Table.propTypes = {
170224
columns: PropTypes.oneOfType([PropTypes.array]).isRequired,
171225
data: PropTypes.oneOfType([PropTypes.array]).isRequired,
172226
sort: PropTypes.bool,
227+
sortByTitle: PropTypes.bool,
173228
};
174229

175230
Table.defaultProps = {
176231
theme: defaultTheme,
177232
sort: false,
233+
sortByTitle: false,
178234
};
179235

180236
export default themr('CBTable', defaultTheme)(Table);

lib/table/theme.module.scss

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,35 @@
4545
}
4646
:local(.tableHeadCellContent) {
4747
justify-content: space-between;
48+
:local(.sortableTitle) {
49+
cursor: pointer;
50+
:local(.hidden) {
51+
opacity: 0;
52+
}
53+
&:hover {
54+
:local(.hidden) {
55+
opacity: 1;
56+
}
57+
}
58+
}
59+
:local(.sortableTitleIcon) {
60+
font-size: 0.8em;
61+
margin-left: 0.7em;
62+
}
63+
}
64+
65+
:local(.arrow) {
66+
transition: all 0.2s linear;
67+
}
68+
69+
:local(.upArrow) {
70+
transform: rotate(0deg);
4871
}
72+
73+
:local(.downArrow) {
74+
transform: rotate(180deg);
75+
}
76+
4977
:local(.sortArrow) {
5078
position: relative;
5179
width: 12px;

0 commit comments

Comments
 (0)