'use client'
import { useState } from 'react'
import { Rows2Icon, Rows3Icon, Rows4Icon } from 'lucide-react'
import type { ColumnDef, ColumnFiltersState, SortingState, VisibilityState } from '@tanstack/react-table'
import {
flexRender,
getCoreRowModel,
getFilteredRowModel,
getPaginationRowModel,
getSortedRowModel,
useReactTable
} from '@tanstack/react-table'
import { Checkbox } from '@/registry/new-york/ui/checkbox'
import {
Select,
SelectContent,
SelectGroup,
SelectItem,
SelectLabel,
SelectTrigger,
SelectValue
} from '@/registry/new-york/ui/select'
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@/registry/new-york/ui/table'
import { cn } from '@/registry/new-york/lib/utils'
const data: Payment[] = [
{
id: '1',
name: 'Shang Chain',
amount: 699,
status: 'success',
email: 'shang07@yahoo.com'
},
{
id: '2',
name: 'Kevin Lincoln',
amount: 242,
status: 'success',
email: 'kevinli09@gmail.com'
},
{
id: '3',
name: 'Milton Rose',
amount: 655,
status: 'processing',
email: 'rose96@gmail.com'
},
{
id: '4',
name: 'Silas Ryan',
amount: 874,
status: 'success',
email: 'silas22@gmail.com'
},
{
id: '5',
name: 'Ben Tenison',
amount: 541,
status: 'failed',
email: 'bent@hotmail.com'
}
]
export type Payment = {
id: string
name: string
amount: number
status: 'pending' | 'processing' | 'success' | 'failed'
email: string
}
export const columns: ColumnDef<Payment>[] = [
{
id: 'select',
header: ({ table }) => (
<Checkbox
checked={table.getIsAllPageRowsSelected() || (table.getIsSomePageRowsSelected() && 'indeterminate')}
onCheckedChange={value => table.toggleAllPageRowsSelected(!!value)}
aria-label='Select all'
/>
),
cell: ({ row }) => (
<Checkbox
checked={row.getIsSelected()}
onCheckedChange={value => row.toggleSelected(!!value)}
aria-label='Select row'
/>
),
enableSorting: false,
enableHiding: false
},
{
header: 'Name',
accessorKey: 'name',
cell: ({ row }) => <div className='font-medium'>{row.getValue('name')}</div>
},
{
accessorKey: 'status',
header: 'Status',
cell: ({ row }) => <div className='capitalize'>{row.getValue('status')}</div>
},
{
accessorKey: 'email',
header: 'Email',
cell: ({ row }) => <div className='lowercase'>{row.getValue('email')}</div>
},
{
accessorKey: 'amount',
header: () => <div className='text-right'>Amount</div>,
cell: ({ row }) => {
const amount = parseFloat(row.getValue('amount'))
const formatted = new Intl.NumberFormat('en-US', {
style: 'currency',
currency: 'USD'
}).format(amount)
return <div className='text-right font-medium'>{formatted}</div>
}
}
]
const DataTableDensityDemo = () => {
const [density, setDensity] = useState<string>()
const [sorting, setSorting] = useState<SortingState>([])
const [columnFilters, setColumnFilters] = useState<ColumnFiltersState>([])
const [columnVisibility, setColumnVisibility] = useState<VisibilityState>({})
const [rowSelection, setRowSelection] = useState({})
const table = useReactTable({
data,
columns,
onSortingChange: setSorting,
onColumnFiltersChange: setColumnFilters,
getCoreRowModel: getCoreRowModel(),
getPaginationRowModel: getPaginationRowModel(),
getSortedRowModel: getSortedRowModel(),
getFilteredRowModel: getFilteredRowModel(),
onColumnVisibilityChange: setColumnVisibility,
onRowSelectionChange: setRowSelection,
state: {
sorting,
columnFilters,
columnVisibility,
rowSelection
}
})
return (
<div className='w-full'>
<div className='py-4'>
<Select value={density} onValueChange={setDensity}>
<SelectTrigger className='w-full max-w-3xs' aria-label='Density select'>
<SelectValue placeholder='Density' />
</SelectTrigger>
<SelectContent>
<SelectGroup>
<SelectLabel>Density</SelectLabel>
<SelectItem value='compact'>
<div className='flex items-center gap-2'>
<Rows4Icon className='size-4' />
Compact
</div>
</SelectItem>
<SelectItem value='standard' className='flex items-center gap-2'>
<div className='flex items-center gap-2'>
<Rows3Icon className='size-4' /> Standard
</div>
</SelectItem>
<SelectItem value='flexible' className='flex items-center gap-2'>
<div className='flex items-center gap-2'>
<Rows2Icon className='size-4' />
Flexible
</div>
</SelectItem>
</SelectGroup>
</SelectContent>
</Select>
</div>
<div className='rounded-md border'>
<Table
className={cn({
'[&_td]:py-px [&_th]:py-px': density === 'compact',
'[&_td]:py-1 [&_th]:py-1': density === 'standard',
'[&_td]:py-2 [&_th]:py-1': density === 'flexible'
})}
>
<TableHeader>
{table.getHeaderGroups().map(headerGroup => (
<TableRow key={headerGroup.id}>
{headerGroup.headers.map(header => {
return (
<TableHead key={header.id}>
{header.isPlaceholder ? null : flexRender(header.column.columnDef.header, header.getContext())}
</TableHead>
)
})}
</TableRow>
))}
</TableHeader>
<TableBody>
{table.getRowModel().rows?.length ? (
table.getRowModel().rows.map(row => (
<TableRow key={row.id} data-state={row.getIsSelected() && 'selected'}>
{row.getVisibleCells().map(cell => (
<TableCell key={cell.id}>{flexRender(cell.column.columnDef.cell, cell.getContext())}</TableCell>
))}
</TableRow>
))
) : (
<TableRow>
<TableCell colSpan={columns.length} className='h-24 text-center'>
No results.
</TableCell>
</TableRow>
)}
</TableBody>
</Table>
</div>
<p className='text-muted-foreground mt-4 text-center text-sm'>
Density data table{' '}
<a
href='https://www.shadcnui-blocks.com/components/table'
className='hover:text-primary underline'
target='_blank'
>
Shadcn UI Blocks
</a>
</p>
</div>
)
}
export default DataTableDensityDemo