Skip to content

Commit

Permalink
Improve table component structure
Browse files Browse the repository at this point in the history
  • Loading branch information
johnvictorfs committed Mar 27, 2023
1 parent 578392d commit db1e580
Show file tree
Hide file tree
Showing 4 changed files with 153 additions and 176 deletions.
41 changes: 41 additions & 0 deletions src/components/table/TableGroupToggle.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import React from 'react'

import { Header } from '@tanstack/react-table'

import { AutoAwesomeMosaic } from '@mui/icons-material'
import { Badge, IconButton } from '@mui/material'

export type Props<T extends Record<string, any>> = {
header: Header<T, unknown>
showGroupingIndex?: boolean
}

const TableGroupToggle = <T extends Record<string, any>>({
header,
showGroupingIndex = false
}: Props<T>): React.ReactElement => {
return (
<React.Fragment>
{/* If the header can be grouped, let's add a toggle */}
<IconButton
onClick={header.column.getToggleGroupingHandler()}
sx={{ mr: 1 }}
>
<Badge
color='success'
badgeContent={
showGroupingIndex ? header.column.getGroupedIndex() + 1 : 0
}
>
<AutoAwesomeMosaic
sx={{
color: header.column.getIsGrouped() ? 'primary.main' : 'inherit'
}}
/>
</Badge>
</IconButton>{' '}
</React.Fragment>
)
}

export default TableGroupToggle
157 changes: 15 additions & 142 deletions src/components/table/YuTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,7 @@ import {
} from '@tanstack/react-table'
import { TableOptions } from '@tanstack/table-core'

import { AutoAwesomeMosaic, ExpandLess, ExpandMore } from '@mui/icons-material'
import {
Badge,
IconButton,
Table,
TableBody,
TableCell,
Expand All @@ -27,6 +24,9 @@ import {
Typography
} from '@mui/material'

import TableGroupToggle from './TableGroupToggle'
import YuTableCell from './YuTableCell'

export type Props<T extends Record<string, any>> = {
columns: ColumnDef<T>[]
data: T[]
Expand Down Expand Up @@ -101,29 +101,12 @@ const YuTable = <T extends Record<string, any>>({
{header.isPlaceholder ? null : (
<div>
{header.column.getCanGroup() ? (
// If the header can be grouped, let's add a toggle
<IconButton
onClick={header.column.getToggleGroupingHandler()}
sx={{ mr: 1 }}
>
<Badge
color='success'
badgeContent={
showGroupingIndex
? header.column.getGroupedIndex() + 1
: 0
}
>
<AutoAwesomeMosaic
sx={{
color: header.column.getIsGrouped()
? 'primary.main'
: 'inherit'
}}
/>
</Badge>
</IconButton>
) : null}{' '}
<TableGroupToggle
header={header}
showGroupingIndex={showGroupingIndex}
/>
) : null}

<Typography
variant='body1'
sx={{
Expand All @@ -150,129 +133,19 @@ const YuTable = <T extends Record<string, any>>({
<TableRow key={row.id}>
{row.getVisibleCells().map((cell) => {
return (
<TableCell key={cell.id}>
{cell.getIsGrouped() ? (
// If it's a grouped cell, add an expander and row count
<React.Fragment>
{/* If a manual grouping expand state was passed, don't allow manually changing it */}
{groupingExpand === undefined ? (
<React.Fragment>
<IconButton
size='small'
sx={{
mr: 1
}}
onClick={row.getToggleExpandedHandler()}
disabled={!row.getCanExpand()}
>
{row.getIsExpanded() ? (
<ExpandLess />
) : (
<ExpandMore />
)}{' '}
</IconButton>
{flexRender(
cell.column.columnDef.cell,
cell.getContext()
)}{' '}
({row.subRows.length})
</React.Fragment>
) : (
<React.Fragment>
{flexRender(
cell.column.columnDef.cell,
cell.getContext()
)}
</React.Fragment>
)}
</React.Fragment>
) : cell.getIsAggregated() ? (
// If the cell is aggregated, use the Aggregated
// renderer for cell
flexRender(
cell.column.columnDef.aggregatedCell ??
cell.column.columnDef.cell,
cell.getContext()
)
) : cell.getIsPlaceholder() ? null : ( // For cells with repeated values, render null
// Otherwise, just render the regular cell
flexRender(cell.column.columnDef.cell, cell.getContext())
)}
</TableCell>
<YuTableCell
row={row}
cell={cell}
key={cell.id}
groupingExpand={groupingExpand}
/>
)
})}
</TableRow>
)
})}
</TableBody>
</Table>
/* <div className='h-2' />
<div className='flex items-center gap-2'>
<button
className='border rounded p-1'
onClick={() => table.setPageIndex(0)}
disabled={!table.getCanPreviousPage()}
>
{'<<'}
</button>
<button
className='border rounded p-1'
onClick={() => table.previousPage()}
disabled={!table.getCanPreviousPage()}
>
{'<'}
</button>
<button
className='border rounded p-1'
onClick={() => table.nextPage()}
disabled={!table.getCanNextPage()}
>
{'>'}
</button>
<button
className='border rounded p-1'
onClick={() => table.setPageIndex(table.getPageCount() - 1)}
disabled={!table.getCanNextPage()}
>
{'>>'}
</button>
<span className='flex items-center gap-1'>
<div>Page</div>
<strong>
{table.getState().pagination.pageIndex + 1} of{' '}
{table.getPageCount()}
</strong>
</span>
<span className='flex items-center gap-1'>
| Go to page:
<input
type='number'
defaultValue={table.getState().pagination.pageIndex + 1}
onChange={(e) => {
const page = e.target.value ? Number(e.target.value) - 1 : 0
table.setPageIndex(page)
}}
className='border p-1 rounded w-16'
/>
</span>
<select
value={table.getState().pagination.pageSize}
onChange={(e) => {
table.setPageSize(Number(e.target.value))
}}
>
{[10, 20, 30, 40, 50].map((pageSize) => (
<option key={pageSize} value={pageSize}>
Show {pageSize}
</option>
))}
</select>
</div>
<div>{table.getRowModel().rows.length} Rows</div>
<div>
<button onClick={() => rerender()}>Force Rerender</button>
</div>
<pre>{JSON.stringify(grouping, null, 2)}</pre> */
)
}

Expand Down
61 changes: 61 additions & 0 deletions src/components/table/YuTableCell.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import React from 'react'

import { Cell, ExpandedState, Row, flexRender } from '@tanstack/react-table'

import { ExpandLess, ExpandMore } from '@mui/icons-material'
import { IconButton, TableCell } from '@mui/material'

export type Props<T extends Record<string, any>> = {
cell: Cell<T, unknown>
row: Row<T>
groupingExpand: ExpandedState | undefined
}

const YuTableCell = <T extends Record<string, any>>({
cell,
row,
groupingExpand
}: Props<T>): React.ReactElement => {
return (
<TableCell>
{cell.getIsGrouped() ? (
// If it's a grouped cell, add an expander and row count
<React.Fragment>
{/* If a manual grouping expand state was passed, don't allow manually changing it */}
{groupingExpand === undefined ? (
<React.Fragment>
<IconButton
size='small'
sx={{
mr: 1
}}
onClick={row.getToggleExpandedHandler()}
disabled={!row.getCanExpand()}
>
{row.getIsExpanded() ? <ExpandLess /> : <ExpandMore />}{' '}
</IconButton>
{flexRender(cell.column.columnDef.cell, cell.getContext())} (
{row.subRows.length})
</React.Fragment>
) : (
<React.Fragment>
{flexRender(cell.column.columnDef.cell, cell.getContext())}
</React.Fragment>
)}
</React.Fragment>
) : cell.getIsAggregated() ? (
// If the cell is aggregated, use the Aggregated
// renderer for cell
flexRender(
cell.column.columnDef.aggregatedCell ?? cell.column.columnDef.cell,
cell.getContext()
)
) : cell.getIsPlaceholder() ? null : ( // For cells with repeated values, render null
// Otherwise, just render the regular cell
flexRender(cell.column.columnDef.cell, cell.getContext())
)}
</TableCell>
)
}

export default YuTableCell
70 changes: 36 additions & 34 deletions src/stories/yu/YuTable.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import {
Cancel,
CheckCircleOutline
} from '@mui/icons-material'
import { Chip, Grid } from '@mui/material'
import { Card, Chip, Grid } from '@mui/material'

import { YuTable } from '../../index'

Expand Down Expand Up @@ -68,39 +68,41 @@ const getChipColor = (status: Application['status']) => {
const Template: StoryFn<typeof YuTable> = (args) => {
return (
<Grid container>
<YuTable
{...args}
columns={[
{
accessorKey: 'manager',
header: 'Manager',
cell: (info) => info.getValue(),
accessorFn: (row) => row.manager,
enableGrouping: false
},
{
accessorFn: (row) => row.name,
id: 'name',
header: () => <span>Name</span>,
cell: (info) => info.getValue(),
enableGrouping: false
},
{
accessorKey: 'status',
id: 'status',
header: () => <span>Status</span>,
cell: (info) => (
<Chip
label={info.getValue() as string}
icon={getStatusIcon(info.getValue() as Application['status'])}
color={getChipColor(info.getValue() as Application['status'])}
/>
),
enableGrouping: false
}
]}
data={data}
/>
<Card sx={{ width: '100%' }}>
<YuTable
{...args}
columns={[
{
accessorKey: 'manager',
header: 'Manager',
cell: (info) => info.getValue(),
accessorFn: (row) => row.manager,
enableGrouping: false
},
{
accessorFn: (row) => row.name,
id: 'name',
header: () => <span>Name</span>,
cell: (info) => info.getValue(),
enableGrouping: false
},
{
accessorKey: 'status',
id: 'status',
header: () => <span>Status</span>,
cell: (info) => (
<Chip
label={info.getValue() as string}
icon={getStatusIcon(info.getValue() as Application['status'])}
color={getChipColor(info.getValue() as Application['status'])}
/>
),
enableGrouping: false
}
]}
data={data}
/>
</Card>
</Grid>
)
}
Expand Down

0 comments on commit db1e580

Please sign in to comment.