Skip to content

Commit

Permalink
Adds Table component
Browse files Browse the repository at this point in the history
And supporting sub parts

See #81
Fixes #117
  • Loading branch information
stuarthendren committed Jun 11, 2021
1 parent 780f098 commit ca6ba60
Show file tree
Hide file tree
Showing 7 changed files with 523 additions and 2 deletions.
26 changes: 26 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@
"@testing-library/jest-dom": "^5.12.0",
"@testing-library/react": "^11.2.6",
"@testing-library/user-event": "^13.1.5",
"@types/faker": "^5.5.6",
"@types/parse-color": "^1.0.0",
"@types/react": "^17.0.3",
"@types/react-dom": "^17.0.3",
Expand All @@ -135,6 +136,7 @@
"danger-plugin-spellcheck": "^1.2.3",
"eslint-import-resolver-typescript": "^2.4.0",
"eslint-plugin-react-hooks": "^4.2.0",
"faker": "^5.5.3",
"husky": "^6.0.0",
"jest": "^26.6.3",
"jest-sonar-reporter": "^2.0.0",
Expand Down
299 changes: 299 additions & 0 deletions src/components/Table/Table.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,299 @@
import React from 'react'
import { Story, Meta } from '@storybook/react'
import {
Table,
TableHead,
TableBody,
TableFoot,
TableRow,
TableCell,
TableCaption,
} from '.'
import { Avatar, Chip, Link, Box } from '..'
import faker from 'faker'

export default {
title: 'Components/Table',
component: Table,
subcomponents: {
TableHead,
TableBody,
TableFoot,
TableRow,
TableCell,
TableCaption,
},
argTypes: {
striped: {
control: {
type: 'boolean',
},
defaultValue: false,
description: 'Set the table to have a striped background',
},
sticky: {
control: {
type: 'boolean',
},
defaultValue: false,
description: 'Set the header to be sticky',
},
hover: {
control: {
type: 'boolean',
},
defaultValue: false,
description: 'Set to highlight the hovered row',
},
},
} as Meta

type User = {
id: string
avatar: string
username: string
email: string
age: number
visits: number
progress: number
status: React.ReactNode
}

function buildUser(): User {
const statusChance = Math.random()
return {
id: faker.datatype.uuid(),
avatar: faker.internet.avatar(),
username: faker.internet.userName(),
email: faker.internet.email(),
age: faker.datatype.number(100),
visits: faker.datatype.number(1000),
progress: faker.datatype.number(100),
status:
statusChance > 0.75 ? (
<Chip variant="success">active</Chip>
) : statusChance > 0.5 ? (
<Chip variant="warning">dormant</Chip>
) : statusChance > 0.25 ? (
<Chip variant="info">new</Chip>
) : (
<Chip variant="error">suspended</Chip>
),
}
}

export const Default: Story<React.ComponentProps<typeof Table>> = (args) => {
const users = new Array(5).fill(0).map(buildUser)
return (
<Table {...args}>
<thead>
<tr>
<th></th>
<th>Username</th>
<th>email</th>
<th>age</th>
<th>visits</th>
<th>progress</th>
<th>status</th>
<th></th>
</tr>
</thead>
<tbody>
{users.map((user) => (
<tr key={user.id}>
<td>
<Avatar
alt={user.username as string}
src={user.avatar as string}
/>
</td>
<td>{user.username}</td>
<td>{user.email}</td>
<td>{user.age}</td>
<td>{user.visits}</td>
<td>{user.progress}</td>
<td>{user.status}</td>
<td>
<Link href="#">Edit</Link>
</td>
</tr>
))}
</tbody>
</Table>
)
}

/**
* Table has props to make the table header sticky, the table rows striped and the rows highlight on hover.
*
* This example is in a fixed height box to demonstrate.
* */
export const StickyAndStriped = Default.bind({})
StickyAndStriped.args = { sticky: true, striped: true, hover: true }
StickyAndStriped.decorators = [
(Story) => <Box css={{ height: 200, overflow: 'auto' }}>{Story()}</Box>,
]

/**
* The table supports the standard html subcomponents, as in the first example.
* However, there are more features available on supplied subcomponents.
*
* The `TableCaption`, `TableHead`, `TableBody` and `TableFoot` simply support the `as` and `css` props incase a
* particular component makes more sense or particular styling for that part is required. See contrived example.
*
*/
export const UtilityClasses: Story<React.ComponentProps<typeof Table>> = (
args
) => {
const users = new Array(5).fill(0).map(buildUser)
return (
<Table {...args}>
<TableCaption css={{ fontWeight: '$light' }}>
A Caption for the table
</TableCaption>
<TableHead css={{ fontFamily: '$monospace' }}>
<TableRow>
<TableCell></TableCell>
<TableCell>Username</TableCell>
<TableCell>email</TableCell>
<TableCell>age</TableCell>
<TableCell>visits</TableCell>
<TableCell>progress</TableCell>
<TableCell>status</TableCell>
<TableCell></TableCell>
</TableRow>
</TableHead>
<TableBody>
{users.map((user) => (
<TableRow key={user.id}>
<TableCell>
<Avatar
alt={user.username as string}
src={user.avatar as string}
/>
</TableCell>
<TableCell>{user.username}</TableCell>
<TableCell>{user.email}</TableCell>
<TableCell>{user.age}</TableCell>
<TableCell>{user.visits}</TableCell>
<TableCell>{user.progress}</TableCell>
<TableCell>{user.status}</TableCell>
<TableCell>
<Link href="#">Edit</Link>
</TableCell>
</TableRow>
))}
</TableBody>
<TableFoot
as={Link}
href="#"
css={{
backgroundColor: '$black',
color: '$white',
textAlign: 'center',
}}
>
<TableRow>
<TableCell colSpan={8}>Documentation</TableCell>
</TableRow>
</TableFoot>
</Table>
)
}

// TODO make example interactive

/**
* `TableCell` and `TableRow` have a selected prop to support indicate selection.
* This must be controlled.
*
*/
export const Selection: Story<React.ComponentProps<typeof Table>> = (args) => {
const users = new Array(5).fill(0).map(buildUser)
return (
<Table {...args}>
<TableHead>
<TableRow>
<TableCell></TableCell>
<TableCell>Username</TableCell>
<TableCell>email</TableCell>
<TableCell>age</TableCell>
<TableCell>visits</TableCell>
<TableCell>progress</TableCell>
<TableCell>status</TableCell>
<TableCell></TableCell>
</TableRow>
</TableHead>
<TableBody>
<TableRow key={users[0].id}>
<TableCell>
<Avatar
alt={users[0].username as string}
src={users[0].avatar as string}
/>
</TableCell>
<TableCell selected>{users[0].username}</TableCell>
<TableCell>{users[0].email}</TableCell>
<TableCell>{users[0].age}</TableCell>
<TableCell selected>{users[0].visits}</TableCell>
<TableCell>{users[0].progress}</TableCell>
<TableCell>{users[0].status}</TableCell>
<TableCell>
<Link href="#">Edit</Link>
</TableCell>
</TableRow>
<TableRow key={users[1].id}>
<TableCell>
<Avatar
alt={users[1].username as string}
src={users[1].avatar as string}
/>
</TableCell>
<TableCell>{users[1].username}</TableCell>
<TableCell>{users[1].email}</TableCell>
<TableCell>{users[1].age}</TableCell>
<TableCell>{users[1].visits}</TableCell>
<TableCell>{users[1].progress}</TableCell>
<TableCell>{users[1].status}</TableCell>
<TableCell>
<Link href="#">Edit</Link>
</TableCell>
</TableRow>
<TableRow key={users[2].id} selected>
<TableCell>
<Avatar
alt={users[2].username as string}
src={users[2].avatar as string}
/>
</TableCell>
<TableCell>{users[2].username}</TableCell>
<TableCell>{users[2].email}</TableCell>
<TableCell>{users[2].age}</TableCell>
<TableCell>{users[2].visits}</TableCell>
<TableCell>{users[2].progress}</TableCell>
<TableCell>{users[2].status}</TableCell>
<TableCell>
<Link href="#">Edit</Link>
</TableCell>
</TableRow>
<TableRow key={users[3].id}>
<TableCell>
<Avatar
alt={users[3].username as string}
src={users[3].avatar as string}
/>
</TableCell>
<TableCell>{users[3].username}</TableCell>
<TableCell>{users[3].email}</TableCell>
<TableCell>{users[3].age}</TableCell>
<TableCell>{users[3].visits}</TableCell>
<TableCell>{users[3].progress}</TableCell>
<TableCell>{users[3].status}</TableCell>
<TableCell>
<Link href="#">Edit</Link>
</TableCell>
</TableRow>
</TableBody>
</Table>
)
}
Loading

0 comments on commit ca6ba60

Please sign in to comment.