Skip to content

Commit

Permalink
feat: add Table component
Browse files Browse the repository at this point in the history
  • Loading branch information
bacali95 committed Apr 14, 2022
1 parent 09cfef4 commit 7568ccc
Show file tree
Hide file tree
Showing 13 changed files with 602 additions and 0 deletions.
42 changes: 42 additions & 0 deletions public/images/tables-dark.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
42 changes: 42 additions & 0 deletions public/images/tables-light.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
88 changes: 88 additions & 0 deletions src/components/Table/Table.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
import { Meta, Story } from '@storybook/react/types-6-0';

import { Table, TableProps } from '.';

export default {
title: 'Components/Tables',
component: Table,
} as Meta;

const Template: Story<TableProps> = (args) => (
<Table {...args}>
<Table.Head>
<Table.HeadCell>Product name</Table.HeadCell>
<Table.HeadCell>Color</Table.HeadCell>
<Table.HeadCell>Category</Table.HeadCell>
<Table.HeadCell>Price</Table.HeadCell>
<Table.HeadCell>
<span className="sr-only">Edit</span>
</Table.HeadCell>
</Table.Head>
<Table.Body className="divide-y">
<Table.Row className="bg-white dark:border-gray-700 dark:bg-gray-800">
<Table.Cell className="whitespace-nowrap font-medium text-gray-900 dark:text-white">
{'Apple MacBook Pro 17"'}
</Table.Cell>
<Table.Cell>Sliver</Table.Cell>
<Table.Cell>Laptop</Table.Cell>
<Table.Cell>$2999</Table.Cell>
<Table.Cell>
<a href="#/tables" className="font-medium text-blue-600 hover:underline dark:text-blue-500">
Edit
</a>
</Table.Cell>
</Table.Row>
<Table.Row className="bg-white dark:border-gray-700 dark:bg-gray-800">
<Table.Cell className="whitespace-nowrap font-medium text-gray-900 dark:text-white">
Microsoft Surface Pro
</Table.Cell>
<Table.Cell>White</Table.Cell>
<Table.Cell>Laptop PC</Table.Cell>
<Table.Cell>$1999</Table.Cell>
<Table.Cell>
<a href="#/tables" className="font-medium text-blue-600 hover:underline dark:text-blue-500">
Edit
</a>
</Table.Cell>
</Table.Row>
<Table.Row className="bg-white dark:border-gray-700 dark:bg-gray-800">
<Table.Cell className="whitespace-nowrap font-medium text-gray-900 dark:text-white">Magic Mouse 2</Table.Cell>
<Table.Cell>Black</Table.Cell>
<Table.Cell>Accessories</Table.Cell>
<Table.Cell>$99</Table.Cell>
<Table.Cell>
<a href="#/tables" className="font-medium text-blue-600 hover:underline dark:text-blue-500">
Edit
</a>
</Table.Cell>
</Table.Row>
<Table.Row className="bg-white dark:border-gray-700 dark:bg-gray-800">
<Table.Cell className="whitespace-nowrap font-medium text-gray-900 dark:text-white">
Google Pixel Phone
</Table.Cell>
<Table.Cell>Gray</Table.Cell>
<Table.Cell>Phone</Table.Cell>
<Table.Cell>$799</Table.Cell>
<Table.Cell>
<a href="#/tables" className="font-medium text-blue-600 hover:underline dark:text-blue-500">
Edit
</a>
</Table.Cell>
</Table.Row>
<Table.Row className="bg-white dark:border-gray-700 dark:bg-gray-800">
<Table.Cell className="whitespace-nowrap font-medium text-gray-900 dark:text-white">Apple Watch 5</Table.Cell>
<Table.Cell>Red</Table.Cell>
<Table.Cell>Wearables</Table.Cell>
<Table.Cell>$999</Table.Cell>
<Table.Cell>
<a href="#/tables" className="font-medium text-blue-600 hover:underline dark:text-blue-500">
Edit
</a>
</Table.Cell>
</Table.Row>
</Table.Body>
</Table>
);

export const DefaultTable = Template.bind({});
DefaultTable.storyName = 'Default';
7 changes: 7 additions & 0 deletions src/components/Table/TableBody.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { ComponentProps, FC, PropsWithChildren } from 'react';

export type TableBodyProps = PropsWithChildren<ComponentProps<'tbody'>>;

export const TableBody: FC<TableBodyProps> = ({ children, ...props }) => {
return <tbody {...props}>{children}</tbody>;
};
12 changes: 12 additions & 0 deletions src/components/Table/TableCell.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { ComponentProps, FC, PropsWithChildren } from 'react';
import classNames from 'classnames';

export type TableCellProps = PropsWithChildren<ComponentProps<'td'>>;

export const TableCell: FC<TableCellProps> = ({ children, className, ...props }) => {
return (
<td className={classNames('px-6 py-4', className)} {...props}>
{children}
</td>
);
};
18 changes: 18 additions & 0 deletions src/components/Table/TableContext.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { createContext, useContext } from 'react';

export type TableContext = {
striped?: boolean;
hoverable?: boolean;
};

export const TableContext = createContext<TableContext | undefined>(undefined);

export function useTableContext(): TableContext {
const context = useContext(TableContext);

if (!context) {
throw new Error('useTableContext should be used within the TableContext provider!');
}

return context;
}
18 changes: 18 additions & 0 deletions src/components/Table/TableHead.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { ComponentProps, FC, PropsWithChildren } from 'react';
import classNames from 'classnames';

export type TableHeadProps = PropsWithChildren<ComponentProps<'thead'>>;

export const TableHead: FC<TableHeadProps> = ({ children, className, ...props }) => {
return (
<thead
className={classNames(
'bg-gray-50 text-xs uppercase text-gray-700 dark:bg-gray-700 dark:text-gray-400',
className,
)}
{...props}
>
<tr>{children}</tr>
</thead>
);
};
12 changes: 12 additions & 0 deletions src/components/Table/TableHeadCell.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { ComponentProps, FC, PropsWithChildren } from 'react';
import classNames from 'classnames';

export type TableHeadCellProps = PropsWithChildren<ComponentProps<'th'>>;

export const TableHeadCell: FC<TableHeadCellProps> = ({ children, className, ...props }) => {
return (
<th className={classNames('px-6 py-3', className)} {...props}>
{children}
</th>
);
};
25 changes: 25 additions & 0 deletions src/components/Table/TableRow.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import classNames from 'classnames';
import { ComponentProps, FC, PropsWithChildren } from 'react';

import { useTableContext } from './TableContext';

export type TableRowProps = PropsWithChildren<ComponentProps<'tr'>>;

export const TableRow: FC<TableRowProps> = ({ children, className, ...props }) => {
const { striped, hoverable } = useTableContext();

return (
<tr
className={classNames(
{
'odd:bg-white even:bg-gray-50 odd:dark:bg-gray-800 even:dark:bg-gray-700': striped,
'hover:bg-gray-50 dark:hover:bg-gray-600': hoverable,
},
className,
)}
{...props}
>
{children}
</tr>
);
};
41 changes: 41 additions & 0 deletions src/components/Table/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { ComponentProps, FC, PropsWithChildren } from 'react';
import classNames from 'classnames';

import { TableHead } from './TableHead';
import { TableBody } from './TableBody';
import { TableRow } from './TableRow';
import { TableHeadCell } from './TableHeadCell';
import { TableCell } from './TableCell';
import { TableContext } from './TableContext';

export type TableProps = PropsWithChildren<ComponentProps<'table'> & TableContext>;

const TableComponent: FC<TableProps> = ({ children, striped, hoverable, className, ...props }) => {
return (
<div className="relative overflow-x-auto shadow-md sm:rounded-lg">
<TableContext.Provider value={{ striped, hoverable }}>
<table
className={classNames('w-full text-left text-sm text-gray-500 dark:text-gray-400', className)}
{...props}
>
{children}
</table>
</TableContext.Provider>
</div>
);
};

TableComponent.displayName = 'Table';
TableHead.displayName = 'Table.Head';
TableBody.displayName = 'Table.Body';
TableRow.displayName = 'Table.Row';
TableCell.displayName = 'Table.Cell';
TableHeadCell.displayName = 'Table.HeadCell';

export const Table = Object.assign(TableComponent, {
Head: TableHead,
Body: TableBody,
Row: TableRow,
Cell: TableCell,
HeadCell: TableHeadCell,
});
1 change: 1 addition & 0 deletions src/components/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,5 @@ export * from './Progress';
export * from './Rating';
export * from './Sidebar';
export * from './Spinner';
export * from './Table';
export * from './Tooltip';
Loading

0 comments on commit 7568ccc

Please sign in to comment.