Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
192 changes: 192 additions & 0 deletions src/components/Table/Table.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,192 @@
import React from 'react';
import { render, screen } from '@testing-library/react';

import Table from '@components/Table';

describe('Table tests', () => {
describe('Variant styling', () => {
test('Default Style', () => {
render(
<Table>
<Table.Header>
<Table.Row>
<Table.Cell>Stuff</Table.Cell>
</Table.Row>
</Table.Header>
</Table>
);
expect(screen.getByText('Stuff')).toHaveClass('default');
});
test('Active Style', () => {
render(
<Table>
<Table.Header>
<Table.Row>
<Table.Cell variant="active">Stuff</Table.Cell>
</Table.Row>
</Table.Header>
</Table>
);
expect(screen.getByText('Stuff')).toHaveClass('active');
});
test('Danger Style', () => {
render(
<Table>
<Table.Header>
<Table.Row>
<Table.Cell variant="danger">Stuff</Table.Cell>
</Table.Row>
</Table.Header>
</Table>
);
expect(screen.getByText('Stuff')).toHaveClass('danger');
});
test('Warning Style', () => {
render(
<Table>
<Table.Header>
<Table.Row>
<Table.Cell variant="warning">Stuff</Table.Cell>
</Table.Row>
</Table.Header>
</Table>
);
expect(screen.getByText('Stuff')).toHaveClass('warning');
});
test('Success Style', () => {
render(
<Table>
<Table.Header>
<Table.Row>
<Table.Cell variant="success">Stuff</Table.Cell>
</Table.Row>
</Table.Header>
</Table>
);
expect(screen.getByText('Stuff')).toHaveClass('success');
});
});
describe('Test Table styling', () => {
test('Striped Style', () => {
render(
<Table striped>
<Table.Header>
<Table.Row>
<Table.Cell variant="active">Stuff</Table.Cell>
</Table.Row>
</Table.Header>
</Table>
);
expect(
screen.getByText('Stuff').parentElement?.parentElement?.parentElement
).toHaveClass('table-striped');
});
test('Bordered Style', () => {
render(
<Table bordered>
<Table.Header>
<Table.Row>
<Table.Cell variant="active">Stuff</Table.Cell>
</Table.Row>
</Table.Header>
</Table>
);
expect(
screen.getByText('Stuff').parentElement?.parentElement?.parentElement
).toHaveClass('table-bordered');
});
test('Responsive Style', () => {
render(
<Table responsive>
<Table.Header>
<Table.Row>
<Table.Cell variant="active">Stuff</Table.Cell>
</Table.Row>
</Table.Header>
</Table>
);
expect(
screen.getByText('Stuff').parentElement?.parentElement?.parentElement
?.parentElement
).toHaveClass('table-responsive');
});
test('Condensed Style', () => {
render(
<Table condensed>
<Table.Header>
<Table.Row>
<Table.Cell>Stuff</Table.Cell>
</Table.Row>
</Table.Header>
</Table>
);
expect(
screen.getByText('Stuff').parentElement?.parentElement?.parentElement
).toHaveClass('table-condensed');
});
test('Hover Style', () => {
render(
<Table hover>
<Table.Header>
<Table.Row>
<Table.Cell variant="active">Stuff</Table.Cell>
</Table.Row>
</Table.Header>
</Table>
);
expect(
screen.getByText('Stuff').parentElement?.parentElement?.parentElement
).toHaveClass('table-hover');
});
});
describe('Row variants', () => {
test('Active row style', () => {
render(
<Table>
<Table.Header>
<Table.Row variant="active">
<Table.Cell>Stuff</Table.Cell>
</Table.Row>
</Table.Header>
</Table>
);
expect(screen.getByText('Stuff').parentElement).toHaveClass('active');
});
test('Success row style', () => {
render(
<Table>
<Table.Header>
<Table.Row variant="success">
<Table.Cell>Stuff</Table.Cell>
</Table.Row>
</Table.Header>
</Table>
);
expect(screen.getByText('Stuff').parentElement).toHaveClass('success');
});
test('Warning row style', () => {
render(
<Table>
<Table.Header>
<Table.Row variant="warning">
<Table.Cell>Stuff</Table.Cell>
</Table.Row>
</Table.Header>
</Table>
);
expect(screen.getByText('Stuff').parentElement).toHaveClass('warning');
});
test('Danger row style', () => {
render(
<Table>
<Table.Header>
<Table.Row variant="danger">
<Table.Cell>Stuff</Table.Cell>
</Table.Row>
</Table.Header>
</Table>
);
expect(screen.getByText('Stuff').parentElement).toHaveClass('danger');
});
});
});
54 changes: 54 additions & 0 deletions src/components/Table/Table.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import React from 'react';
import TableRB from 'react-bootstrap/Table';
import '../../style.css';

export interface TableProps extends React.HTMLAttributes<HTMLTableElement> {
/** Adds borders on all sides of the table and cells. */
bordered?: boolean;
/** The content of the table */
children?: React.ReactNode;
/** Enable a hover state on table rows within a <tbody>. */
hover?: boolean;
/** Responsive tables allow tables to be scrolled horizontally with ease.
* Across every breakpoint, use responsive for horizontally scrolling tables.
* Responsive tables are wrapped automatically in a div. Use responsive="sm",
* responsive="md", responsive="lg", or responsive="xl" as needed to create
* responsive tables up to a particular breakpoint. From that breakpoint and
* up, the table will behave normally and not scroll horizontally. */
responsive?: string | boolean;
/** Adds zebra-striping to any table row within the <tbody>. Makes it easier to read large tables */
striped?: boolean;
/** Narrows the height of rows */
condensed?: boolean;
/** Set additional classnames for the table */
className?: string;
}

const Table = ({
bordered,
condensed,
children,
responsive,
striped,
hover,
className,
...rest
}: TableProps) => {
const condensedClass = condensed === true ? 'table-condensed' : '';
return (
<TableRB
bordered={bordered}
responsive={responsive}
striped={striped}
className={`${className} ${condensedClass}`}
hover={hover}
{...rest}
>
{children}
</TableRB>
);
};

Table.displayName = 'Table';

export default Table;
36 changes: 36 additions & 0 deletions src/components/Table/TableCell.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import React from 'react';
import '../../style.css';

/** Types */
type variantType =
| 'default'
| 'success'
| 'warning'
| 'danger'
| 'active'
| undefined;

export interface TableCellProps
extends React.HTMLAttributes<HTMLTableCellElement> {
/** The content of the table */
children?: React.ReactNode;
/** Invert the colors of the table — with light text on dark backgrounds by setting variant as dark. */
variant?: variantType;
/** Set additional classnames for the table */
className?: string;
}

const TableCell = ({
children,
variant = 'default',
className,
...rest
}: TableCellProps) => (
<td className={`${className} ${variant}`} {...rest}>
{children}
</td>
);

TableCell.displayName = 'Table.Cell';

export default TableCell;
36 changes: 36 additions & 0 deletions src/components/Table/TableHeader.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import React from 'react';
import '../../style.css';

/** Types */
type variantType =
| 'default'
| 'success'
| 'warning'
| 'danger'
| 'active'
| undefined;

export interface TableHeaderProps
extends React.HTMLAttributes<HTMLTableSectionElement> {
/** The content of the table. Each child should be a column title in a <th> tag */
children?: React.ReactNode;
/** Invert the colors of the table — with light text on dark backgrounds by setting variant as dark. */
variant?: variantType;
/** Set additional classnames for the table */
className?: string;
}

const TableHeader = ({
children,
variant = 'default',
className,
...rest
}: TableHeaderProps) => (
<thead className={`${className} ${variant}`} {...rest}>
{children}
</thead>
);

TableHeader.displayName = 'Table.Header';

export default TableHeader;
36 changes: 36 additions & 0 deletions src/components/Table/TableRow.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import React from 'react';
import '../../style.css';

/** Types */
type variantType =
| 'default'
| 'success'
| 'warning'
| 'danger'
| 'active'
| undefined;

export interface TableRowProps
extends React.HTMLAttributes<HTMLTableRowElement> {
/** The content of the table */
children?: React.ReactNode;
/** Invert the colors of the table — with light text on dark backgrounds by setting variant as dark. */
variant?: variantType;
/** Set additional classnames for the table */
className?: string;
}

const TableRow = ({
children,
variant = 'default',
className,
...rest
}: TableRowProps) => (
<tr className={`${className} ${variant}`} {...rest}>
{children}
</tr>
);

TableRow.displayName = 'Table.Row';

export default TableRow;
18 changes: 18 additions & 0 deletions src/components/Table/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import OriginTable from './Table';
import TableCell from './TableCell';
import TableHeader from './TableHeader';
import TableRow from './TableRow';

export type TableProps = typeof OriginTable & {
Header: typeof TableHeader;
Row: typeof TableRow;
Cell: typeof TableCell;
};

const Table = OriginTable as TableProps;

Table.Header = TableHeader;
Table.Row = TableRow;
Table.Cell = TableCell;

export default Table;
Loading