Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(tools): Implement basic functionality of table component #47263

Merged
merged 9 commits into from Nov 2, 2022
15 changes: 15 additions & 0 deletions tools/ui-components/src/base.css
Expand Up @@ -7,6 +7,21 @@
@apply underline;
}
}
@layer components {
/* Table component */
JordanMooree marked this conversation as resolved.
Show resolved Hide resolved
.bordered > thead > tr > th,
.bordered > tbody > tr > th,
.bordered > tfoot > tr > th,
.bordered > thead > tr > td,
.bordered > tbody > tr > td,
.bordered > tfoot > tr > td {
border: 1px solid #ddd;
}
.table-hover > tbody > tr:hover {
background-color: #f5f5f5;
/* color: black; -- Used for storybook use case only */
}
}

@tailwind components;
@tailwind utilities;
3 changes: 3 additions & 0 deletions tools/ui-components/src/table/index.ts
@@ -0,0 +1,3 @@

export { Table } from './table';
export type { TableProps } from './types';
87 changes: 87 additions & 0 deletions tools/ui-components/src/table/table.stories.tsx
@@ -0,0 +1,87 @@
import React from 'react';
import { Story } from '@storybook/react';
import { Table, TableProps } from '.';

const exampleTable = (
<>
<thead>
<tr>
<th>#</th>
<th>First Name</th>
<th>Last Name</th>
<th>Username</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>Mark</td>
<td>Otto</td>
<td>@mdo</td>
</tr>
<tr>
<td>2</td>
<td>John</td>
<td>Loos</td>
<td>@mlos</td>
</tr>
<tr>
<td>3</td>
<td>Joe</td>
<td>Kot</td>
<td>@mko</td>
</tr>
</tbody>
</>
);

const story = {
title: 'Example/Table',
component: Table,
parameters: {
controls: {
include: ['variant', 'size', 'bordered', 'borderless', 'hover', 'striped']
}
},
argTypes: {
variant: {
options: ['light', 'dark']
},
bordered: {
options: [true, false],
control: { type: 'radio' }
},
striped: {
options: [true, false],
control: { type: 'radio' }
},
hover: {
options: [true, false],
control: { type: 'radio' }
},
borderless: {
options: [true, false],
control: { type: 'radio'},
// Used to avoid conflict with borders
if: {arg: 'bordered', truthy: false}
},
size: {
options: ['small', 'medium', 'large']
}

}

};

const Template: Story<TableProps> = args => (
<Table {...args}>{exampleTable}</Table>
);
export const Default = Template.bind({});
Default.args = {
// default props go here
bordered: true,
size: 'medium',
variant: 'light'
};

export default story;
10 changes: 10 additions & 0 deletions tools/ui-components/src/table/table.test.tsx
@@ -0,0 +1,10 @@

import React from 'react';
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';

import { Table } from '.';

describe('<Table />', () => {
it('should render correctly', () => {});
});
59 changes: 59 additions & 0 deletions tools/ui-components/src/table/table.tsx
@@ -0,0 +1,59 @@
import React from 'react';
import '../../../../client/src/components/layouts/global.css'

import { TableProps, TableVariant } from './types';

const defaultClassNames = ['table','table-auto', 'w-full', 'border-collapse',
'text-left', 'bg-transparent'];
const MAX_MOBILE_WIDTH = 767;

const computeWindowSize = window.innerWidth <= MAX_MOBILE_WIDTH

const variantClasses: Record<TableVariant, string> = {
light: 'bg-light-theme-background',
dark: 'bg-dark-theme-background text-gray-0'
}

const computeClassNames = (size: string) => {
switch (size) {
case 'large':
return 'text-lg'
case 'small':
return 'text-sm'
// default is medium
default:
return 'text-md'
}
}

export const Table = React.forwardRef<HTMLTableElement, TableProps>(
(
{ borderless, bordered, className, hover, striped, responsive, variant, size, ...props },
ref
) => {
props.cellPadding = 10 // Default cell padding for visual clarity in Storybook

if (borderless && bordered) bordered = false;

const borderClass = bordered ? "bordered" : ""
const stripedClass = striped ? "table-striped" : ""
const hoverClass = hover ? "table-hover" : ""

const classes = [...defaultClassNames, borderClass, stripedClass, computeClassNames(size || ''), hoverClass].join(' ');


const table = <table {...props} ref={ref} className={classes}/>;

if (responsive) {
let responsiveClass = computeWindowSize ? 'sm' : 'lg';
return <div className={responsiveClass}>{table}</div>
}

// For storybook use cases. Table should remain transparent to the background color
// if (variant == 'light') {
// return <div className={variantClasses[variant]}>{table}</div>
// } else return <div className={variantClasses[variant]}>{table}</div>

return table;
}
);
14 changes: 14 additions & 0 deletions tools/ui-components/src/table/types.ts
@@ -0,0 +1,14 @@
import React from "react";

export type TableVariant = 'light' | 'dark';

export interface TableProps extends React.TableHTMLAttributes<HTMLTableElement> {
bordered?: boolean;
borderless?: boolean;
className?: string;
hover?: boolean;
size?: string;
striped?: boolean | string;
variant?: TableVariant;
responsive?: boolean;
}