Skip to main content

Table

Prerequisite

npm install classnames
root file style.css
@layer base;
@layer components;
@layer utilities;

@layer base {
th,
td {
@apply px-6 py-3 border-b border-r;
}
tr {
@apply border-b last:border-b-0;
}
th:first-child input[type='checkbox'],
td:first-child input[type='checkbox'] {
@apply w-5 h-5 cursor-pointer align-middle disabled:cursor-not-allowed;
}
tbody tr {
@apply hover:bg-sky-50 even:bg-gray-50;
}
}

Code

containers/Table/index.tsx
import type { ReactNode } from 'react'
import { Spinner } from 'components'
import classnames from 'classnames'

import TableCheckbox from './Checkbox'

export interface Props<T> {
list: T[]
columns: ReactNode
renderItem: (item: T, index: number) => ReactNode
loading?: boolean
}

function Table<T>({ columns, list, renderItem, loading }: Props<T>) {
return (
<div
className={classnames(
'relative border-t border-l border-gray-200',
loading ? 'overflow-hidden' : 'overflow-auto'
)}
>
{loading && (
<Spinner className="w-6 h-6 text-primary absolute left-1/2 top-1/2 z-[12]" />
)}
<table
className={classnames(
'w-full text-xs text-gray-500 whitespace-nowrap text-center',
{
'opacity-60 cursor-not-allowed select-none pointer-events-none':
loading
}
)}
>
<thead className="bg-gray-100 sticky top-0 tracking-wider">
{columns}
</thead>
<tbody>
{!!list.length ? (
list.map((item: T, key) => renderItem(item, key))
) : (
<tr>
<td colSpan={99}>No data.</td>
</tr>
)}
</tbody>
</table>
</div>
)
}

Table.Checkbox = TableCheckbox

export default Table

Props

Table

NameTypeDefault
list*any array
columns*node
renderItem*function
loadingbooleanfalse

Table.Checkbox

NameTypeDefault
checked*booleanfalse
onChange*function
indeterminatebooleanfalse
disabledbooleanfalse

Usage

import { Table } from 'components'

interface State {}

const TablePage = () => {
return (
<div>
<Table
loading
columns={
<>
<tr>
<th rowSpan={2}>
<input type="checkbox" />
</th>
<th colSpan={2}>Name</th>
<th rowSpan={2}>Gender</th>
<th colSpan={3}>Address</th>
</tr>
<tr>
<th>First</th>
<th>Last</th>
<th>zipCode</th>
<th>address</th>
<th>detail</th>
</tr>
</>
}
list={[{}, {}, {}]}
renderItem={(item, key) => (
<tr key={key}>
<td>
<input type="checkbox" />
</td>
<td>a</td>
<td>a</td>
<td>a</td>
<td>a</td>
<td>a</td>
<td>a</td>
</tr>
)}
/>
</div>
)
}

export default TablePage

Example