Skip to content

Commit

Permalink
feat(table)!: expandable rows (#759)
Browse files Browse the repository at this point in the history
* feat(table): expandable rows

* fix: accessibility and subrows

* fix: tests

* fix: story

* fix: force deploy storybook

* fix: post comments

* fix: comments

* fix: remove condition from cell render
  • Loading branch information
savutsang authored Apr 24, 2024
1 parent 4889251 commit 80006c1
Show file tree
Hide file tree
Showing 11 changed files with 727 additions and 1,177 deletions.
6 changes: 3 additions & 3 deletions packages/react/src/components/table/table-footer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@ import {
flexRender,
RowData,
} from '@tanstack/react-table';
import { CustomColumnDef } from './types';
import { TableColumn } from './types';

interface CustomFooter<TData extends RowData, TValue = unknown> extends Header<TData, TValue> {
column: Column<TData, TValue> & {
columnDef: CustomColumnDef<TData, TValue>;
columnDef: TableColumn<TData, TValue>;
};
}

Expand Down Expand Up @@ -73,7 +73,7 @@ export const TableFooter = <T extends object>({
footerGroup,
sticky,
}: TableFooterProps<T>): ReactElement => (
<StyleFooterRow key={footerGroup.id} $sticky={sticky}>
<StyleFooterRow $sticky={sticky}>
{footerGroup.headers.map((footer) => getFooter(footer as CustomFooter<T>, sticky))}
</StyleFooterRow>
);
11 changes: 6 additions & 5 deletions packages/react/src/components/table/table-header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,13 @@ import {
flexRender,
RowData,
} from '@tanstack/react-table';
import { devConsole } from '../../utils/dev-console';
import { SortButtonIcon, SortState } from './sort-button-icon';
import { CustomColumnDef } from './types';
import { TableColumn } from './types';

interface CustomHeader<TData extends RowData, TValue = unknown> extends Header<TData, TValue> {
column: Column<TData, TValue> & {
columnDef: CustomColumnDef<TData, TValue>;
columnDef: TableColumn<TData, TValue>;
};
}

Expand Down Expand Up @@ -77,12 +78,12 @@ function getHeading<TData extends object, TValue>(
}

if (!header.column.columnDef.header && !header.column.columnDef.headerAriaLabel) {
console.warn(
devConsole.warn(
`aria-label missing for column ${header.id} without text. please add headerAriaLabel to column.`,
);
}

if (header.column.getCanSort()) {
if (header.column.columnDef.sortable) {
return (
<StyledHeader
aria-label={header.column.columnDef.headerAriaLabel}
Expand Down Expand Up @@ -137,7 +138,7 @@ export const TableHeader = <T extends object>({
headerGroup,
sticky,
}: TableHeaderProps<T>): ReactElement => (
<StyleHeaderRow key={headerGroup.id} $sticky={sticky}>
<StyleHeaderRow $sticky={sticky}>
{headerGroup.headers.map((header) => getHeading(header as CustomHeader<T>))}
</StyleHeaderRow>
);
15 changes: 7 additions & 8 deletions packages/react/src/components/table/table-row.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,18 @@ import {
} from '@tanstack/react-table';
import styled, { css, FlattenInterpolation, ThemedStyledProps, ThemeProps } from 'styled-components';
import { ResolvedTheme } from '../../themes/theme';
import { CustomColumnDef } from './types';
import { TableColumn } from './types';

interface StyledTableRowProps {
$clickable: boolean;
$error: boolean;
$selected: boolean;
$clickable?: boolean;
$error?: boolean;
$selected?: boolean;
$striped?: boolean;
}

interface CustomCell<TData extends RowData, TValue = unknown> extends Cell<TData, TValue> {
column: Column<TData, TValue> & {
columnDef: CustomColumnDef<TData, TValue>;
columnDef: TableColumn<TData, TValue>;
};
}

Expand Down Expand Up @@ -66,7 +66,7 @@ function getCellBackgroundCss({
`;
}

const StyledTableRow = styled.tr<StyledTableRowProps>`
export const StyledTableRow = styled.tr<StyledTableRowProps>`
&:not(:first-child) {
border-top: 1px solid ${({ theme }) => theme.component['table-row-border-color']};
}
Expand Down Expand Up @@ -167,14 +167,13 @@ export const TableRow = <T extends object>({
}: TableRowProps<T>): ReactElement => (
<StyledTableRow
$clickable={!!onClick}
data-testid={`table-row-${row.index}`}
$error={error}
key={row.id}
$striped={striped}
$selected={row.getIsSelected()}
onClick={() => onClick && onClick(row)}
// eslint-disable-next-line react/jsx-props-no-spreading
{...(onClick ? { tabIndex: 0, role: 'button' } : null)}
data-testid={`table-row-${row.id}`}
>
{row.getVisibleCells().map((cell) => getCell(cell as CustomCell<T>))}
</StyledTableRow>
Expand Down
47 changes: 25 additions & 22 deletions packages/react/src/components/table/table.test.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { getByTestId } from '../../test-utils/enzyme-selectors';
import { mountWithProviders, mountWithTheme, renderWithProviders } from '../../test-utils/renderer';
import { DeviceType } from '../device-context-provider/device-context-provider';
import { Table, TableColumn, TableProps } from './table';
import { Table, TableProps } from './table';
import { TableColumn } from './types';

interface TestData {
column1: string;
Expand Down Expand Up @@ -33,17 +34,17 @@ const data: TestData[] = [
];

function renderTable(
columnsArray: TableColumn<TestData>,
columnsArray: TableColumn<TestData>[],
currentDevice?: DeviceType,
props?: TablePropsLite,
): cheerio.Cheerio {
return renderWithProviders(
<Table<TestData> columns={columnsArray} data={data} {...props} />,
<Table columns={columnsArray} data={data} {...props} />,
currentDevice,
);
}

const columnsWithHeaderAriaLabel: TableColumn<TestData> = [
const columnsWithHeaderAriaLabel: TableColumn<TestData>[] = [
{
header: 'Column 1',
headerAriaLabel: 'column 1 aria label',
Expand All @@ -56,7 +57,7 @@ const columnsWithHeaderAriaLabel: TableColumn<TestData> = [
},
];

const columns: TableColumn<TestData> = [
const columns: TableColumn<TestData>[] = [
{
header: 'Column 1',
accessorKey: 'column1',
Expand All @@ -67,7 +68,7 @@ const columns: TableColumn<TestData> = [
},
];

const columnsTextAligned: TableColumn<TestData> = [
const columnsTextAligned: TableColumn<TestData>[] = [
{
header: 'Column 1',
accessorKey: 'column1',
Expand All @@ -80,7 +81,7 @@ const columnsTextAligned: TableColumn<TestData> = [
},
];

const columnsSorted: TableColumn<TestData> = [
const columnsSorted: TableColumn<TestData>[] = [
{
header: 'Column 1',
accessorKey: 'column1',
Expand All @@ -93,7 +94,7 @@ const columnsSorted: TableColumn<TestData> = [
},
];

const columnsSticky: TableColumn<TestData3Columns> = [
const columnsSticky: TableColumn<TestData3Columns>[] = [
{
header: 'Column 1',
accessorKey: 'column1',
Expand Down Expand Up @@ -147,19 +148,21 @@ const stickyColumnsData: TestData3Columns[] = [

describe('Table', () => {
test('column sorting should be set to defaultSort value when defaultSort is set', () => {
const wrapper = mountWithProviders(<Table
columns={columnsSorted}
data={data}
defaultSort={{ id: 'column1', desc: false }}
/>);
const wrapper = mountWithProviders(
<Table
columns={columnsSorted}
data={data}
defaultSort={{ id: 'column1', desc: false }}
/>,
);

expect(getByTestId(wrapper, 'sort-icon').prop('sort')).toBe('ascending');
});

test('onRowClick callback is called when a row is clicked', () => {
const callback = jest.fn();
const wrapper = mountWithTheme(
<Table<TestData>
<Table
selectableRows
columns={columns}
data={data}
Expand All @@ -176,7 +179,7 @@ describe('Table', () => {
const callback = jest.fn();

mountWithTheme(
<Table<TestData>
<Table
selectableRows
columns={columns}
data={data}
Expand All @@ -191,7 +194,7 @@ describe('Table', () => {
test('onSelectedRowsChange callback is called when row-checkbox is checked', () => {
const callback = jest.fn();
const wrapper = mountWithTheme(
<Table<TestData>
<Table
selectableRows
columns={columns}
data={data}
Expand All @@ -207,7 +210,7 @@ describe('Table', () => {
test('onSelectedRowsChange callback is called with all rows when row-checkbox-all is checked', () => {
const callback = jest.fn();
const wrapper = mountWithTheme(
<Table<TestData>
<Table
selectableRows
columns={columns}
data={data}
Expand Down Expand Up @@ -275,32 +278,32 @@ describe('Table', () => {
});

test('has error rows styles', () => {
const tree = renderWithProviders(<Table<TestData> columns={columns} data={errorData} />);
const tree = renderWithProviders(<Table columns={columns} data={errorData} />);

expect(tree).toMatchSnapshot();
});

test('has selectable rows styles', () => {
const tree = renderWithProviders(<Table<TestData> selectableRows columns={columns} data={data} />);
const tree = renderWithProviders(<Table selectableRows columns={columns} data={data} />);

expect(tree).toMatchSnapshot();
});

test('has sticky header styles', () => {
const tree = renderWithProviders(<Table<TestData> stickyHeader columns={columns} data={data} />);
const tree = renderWithProviders(<Table stickyHeader columns={columns} data={data} />);

expect(tree).toMatchSnapshot();
});

test('has sticky column styles', () => {
const tree = renderWithProviders(<Table<TestData3Columns> columns={columnsSticky} data={stickyColumnsData} />);
const tree = renderWithProviders(<Table columns={columnsSticky} data={stickyColumnsData} />);

expect(tree).toMatchSnapshot();
});

test('has aria-label on header columns', () => {
const tree = renderWithProviders(
<Table<TestData>
<Table
columns={columnsWithHeaderAriaLabel}
data={data}
/>,
Expand Down
Loading

0 comments on commit 80006c1

Please sign in to comment.