Make | Model | Year | Price | Mileage | Fuel Type | |
|---|---|---|---|---|---|---|
| Toyota | Camry | 2024 | $28,400 | 0 mi | Gasoline | |
| Honda | Accord | 2023 | $26,800 | 15,000 mi | Hybrid | |
| Ford | F-150 | 2024 | $35,200 | 5,000 mi | Gasoline | |
| Tesla | Model 3 | 2023 | $42,000 | 8,000 mi | Electric |
"use client"
import {
Table,
TableBody,
TableCell,
TableColumn,
TableHeader,
TableRow,
} from "@/components/ui/preskok-ui/table"
interface Vehicle {
id: string
make: string
model: string
year: number
price: number
mileage: number
fuelType: string
}
const vehicles: Array<Vehicle> = [
{
id: "1",
make: "Toyota",
model: "Camry",
year: 2024,
price: 28_400,
mileage: 0,
fuelType: "Gasoline",
},
{
id: "2",
make: "Honda",
model: "Accord",
year: 2023,
price: 26_800,
mileage: 15_000,
fuelType: "Hybrid",
},
{
id: "3",
make: "Ford",
model: "F-150",
year: 2024,
price: 35_200,
mileage: 5000,
fuelType: "Gasoline",
},
{
id: "4",
make: "Tesla",
model: "Model 3",
year: 2023,
price: 42_000,
mileage: 8000,
fuelType: "Electric",
},
]
const columns = [
{ key: "make", name: "Make", isRowHeader: true },
{ key: "model", name: "Model" },
{ key: "year", name: "Year" },
{ key: "price", name: "Price" },
{ key: "mileage", name: "Mileage" },
{ key: "fuelType", name: "Fuel Type" },
]
export function TableDemo() {
return (
<div className="rounded-md border">
<Table aria-label="Vehicle inventory" selectionMode="multiple">
<TableHeader columns={columns}>
{(column) => (
<TableColumn key={column.key} isRowHeader={column.isRowHeader}>
{column.name}
</TableColumn>
)}
</TableHeader>
<TableBody items={vehicles}>
{(item) => (
<TableRow key={item.id}>
<TableCell>{item.make}</TableCell>
<TableCell>{item.model}</TableCell>
<TableCell>{item.year}</TableCell>
<TableCell>${item.price.toLocaleString()}</TableCell>
<TableCell>{item.mileage.toLocaleString()} mi</TableCell>
<TableCell>{item.fuelType}</TableCell>
</TableRow>
)}
</TableBody>
</Table>
</div>
)
}
Sortable table
ID | Name | Type | Level | Description |
|---|---|---|---|---|
| 2 | Blastoise | Water | 56 | A water dragon that can swim and breathe water. |
| 6 | Blastoise | Water | 56 | A water dragon that can swim and breathe water. |
| 1 | Charizard | Fire, Flying | 67 | A fire dragon that can fly and breathe fire. |
| 5 | Charizard | Fire, Flying | 67 | A fire dragon that can fly and breathe fire. |
| 4 | Pikachu | Electric | 100 | An electric dragon that can charge and breathe electricity. |
| 8 | Pikachu | Electric | 100 | An electric dragon that can charge and breathe electricity. |
| 3 | Venusaur | Grass, Poison | 83 | A grass dragon that can grow and breathe grass. |
| 7 | Venusaur | Grass, Poison | 83 | A grass dragon that can grow and breathe grass. |
"use client"
import { useState } from "react"
import type { SortDescriptor } from "react-aria-components"
import {
Table,
TableBody,
TableCell,
TableColumn,
TableHeader,
TableRow,
} from "@/components/ui/preskok-ui/table"
const rows = [
{
id: 1,
name: "Charizard",
type: "Fire, Flying",
level: 67,
description: "A fire dragon that can fly and breathe fire.",
},
{
id: 2,
name: "Blastoise",
type: "Water",
level: 56,
description: "A water dragon that can swim and breathe water.",
},
{
id: 3,
name: "Venusaur",
type: "Grass, Poison",
level: 83,
description: "A grass dragon that can grow and breathe grass.",
},
{
id: 4,
name: "Pikachu",
type: "Electric",
level: 100,
description: "An electric dragon that can charge and breathe electricity.",
},
{
id: 5,
name: "Charizard",
type: "Fire, Flying",
level: 67,
description: "A fire dragon that can fly and breathe fire.",
},
{
id: 6,
name: "Blastoise",
type: "Water",
level: 56,
description: "A water dragon that can swim and breathe water.",
},
{
id: 7,
name: "Venusaur",
type: "Grass, Poison",
level: 83,
description: "A grass dragon that can grow and breathe grass.",
},
{
id: 8,
name: "Pikachu",
type: "Electric",
level: 100,
description: "An electric dragon that can charge and breathe electricity.",
},
]
export function TableDemoSort() {
const [sortDescriptor, setSortDescriptor] = useState<SortDescriptor>({
column: "name",
direction: "ascending",
})
let sortedRows = rows
if (sortDescriptor) {
sortedRows = rows.toSorted((a, b) => {
let first = a[sortDescriptor.column]
let second = b[sortDescriptor.column]
let cmp = first < second ? -1 : 1
if (sortDescriptor.direction === "descending") {
cmp = -cmp
}
return cmp
})
}
return (
<div className="overflow-auto rounded-lg border p-4">
<Table
aria-label="Favorite pokemon"
sortDescriptor={sortDescriptor}
onSortChange={setSortDescriptor}
>
<TableHeader>
<TableColumn id="id" allowsSorting>
ID
</TableColumn>
<TableColumn id="name" isRowHeader allowsSorting>
Name
</TableColumn>
<TableColumn id="type" allowsSorting>
Type
</TableColumn>
<TableColumn id="level" allowsSorting>
Level
</TableColumn>
<TableColumn id="description" allowsSorting>
Description
</TableColumn>
</TableHeader>
<TableBody items={sortedRows}>
{(item) => (
<TableRow>
<TableCell>{item.id}</TableCell>
<TableCell>{item.name}</TableCell>
<TableCell>{item.type}</TableCell>
<TableCell>{item.level}</TableCell>
<TableCell>{item.description}</TableCell>
</TableRow>
)}
</TableBody>
</Table>
</div>
)
}
Resizable table
ID | Name | Email | Age | Role | Band | Status |
|---|---|---|---|---|---|---|
| 1 | Randy Blythe | randy.blythe@example.com | 52 | Vocalist | Lamb of God | Active |
| 2 | Phil Anselmo | phil.anselmo@example.com | 55 | Vocalist | Pantera | Active |
| 3 | George Fisher | george.fisher@example.com | 53 | Vocalist | Cannibal Corpse | Active |
| 4 | Corey Taylor | corey.taylor@example.com | 50 | Vocalist | Slipknot | Active |
| 5 | Trevor Strnad | trevor.strnad@example.com | 41 | Vocalist | The Black Dahlia Murder | Inactive |
| 6 | Chuck Schuldiner | chuck.schuldiner@example.com | 34 | Vocalist | Death | Deceased |
| 7 | Mitch Lucker | mitch.lucker@example.com | 28 | Vocalist | Suicide Silence | Deceased |
"use client"
import {
Table,
TableBody,
TableCell,
TableColumn,
TableHeader,
TableRow,
} from "@/components/ui/preskok-ui/table"
export function TableDemoResizable() {
return (
<div className="overflow-auto rounded-lg border p-4">
<Table allowResize aria-label="Vocalists">
<TableHeader>
<TableColumn className="max-w-10">ID</TableColumn>
<TableColumn isRowHeader isResizable>
Name
</TableColumn>
<TableColumn isResizable>Email</TableColumn>
<TableColumn>Age</TableColumn>
<TableColumn>Role</TableColumn>
<TableColumn isResizable>Band</TableColumn>
<TableColumn>Status</TableColumn>
</TableHeader>
<TableBody items={items}>
{(item) => (
<TableRow id={item.id}>
<TableCell>{item.id}</TableCell>
<TableCell>{item.name}</TableCell>
<TableCell>{item.email}</TableCell>
<TableCell>{item.age}</TableCell>
<TableCell>{item.role}</TableCell>
<TableCell>{item.band}</TableCell>
<TableCell>{item.status}</TableCell>
</TableRow>
)}
</TableBody>
</Table>
</div>
)
}
const items = [
{
id: 1,
name: "Randy Blythe",
email: "randy.blythe@example.com",
age: 52,
role: "Vocalist",
band: "Lamb of God",
status: "Active",
},
{
id: 2,
name: "Phil Anselmo",
email: "phil.anselmo@example.com",
age: 55,
role: "Vocalist",
band: "Pantera",
status: "Active",
},
{
id: 3,
name: "George Fisher",
email: "george.fisher@example.com",
age: 53,
role: "Vocalist",
band: "Cannibal Corpse",
status: "Active",
},
{
id: 4,
name: "Corey Taylor",
email: "corey.taylor@example.com",
age: 50,
role: "Vocalist",
band: "Slipknot",
status: "Active",
},
{
id: 5,
name: "Trevor Strnad",
email: "trevor.strnad@example.com",
age: 41,
role: "Vocalist",
band: "The Black Dahlia Murder",
status: "Inactive",
},
{
id: 6,
name: "Chuck Schuldiner",
email: "chuck.schuldiner@example.com",
age: 34,
role: "Vocalist",
band: "Death",
status: "Deceased",
},
{
id: 7,
name: "Mitch Lucker",
email: "mitch.lucker@example.com",
age: 28,
role: "Vocalist",
band: "Suicide Silence",
status: "Deceased",
},
]
Drag and drop table
Name | Type | Date Modified | ||
|---|---|---|---|---|
| Games | File folder | 6/7/2020 | ||
| Program Files | File folder | 4/7/2021 | ||
| bootmgr | System file | 11/20/2010 | ||
| log.txt | Text Document | 1/18/2016 |
"use client"
import { useDragAndDrop, useListData } from "react-aria-components"
import {
Table,
TableBody,
TableCell,
TableColumn,
TableHeader,
TableRow,
} from "@/components/ui/preskok-ui/table"
export function ReorderableTable() {
const list = useListData({
initialItems: [
{ id: 1, name: "Games", date: "6/7/2020", type: "File folder" },
{ id: 2, name: "Program Files", date: "4/7/2021", type: "File folder" },
{ id: 3, name: "bootmgr", date: "11/20/2010", type: "System file" },
{ id: 4, name: "log.txt", date: "1/18/2016", type: "Text Document" },
],
})
const { dragAndDropHooks } = useDragAndDrop({
getItems: (keys, items: typeof list.items) =>
items.map((item) => ({
"text/plain": item.name,
})),
onReorder(e) {
if (e.target.dropPosition === "before") {
list.moveBefore(e.target.key, e.keys)
} else if (e.target.dropPosition === "after") {
list.moveAfter(e.target.key, e.keys)
}
},
})
return (
<div className="w-full overflow-x-auto rounded-lg border">
<Table
aria-label="Files"
selectionMode="multiple"
dragAndDropHooks={dragAndDropHooks}
>
<TableHeader>
<TableColumn isRowHeader>Name</TableColumn>
<TableColumn>Type</TableColumn>
<TableColumn>Date Modified</TableColumn>
</TableHeader>
<TableBody items={list.items}>
{(item) => (
<TableRow>
<TableCell>{item.name}</TableCell>
<TableCell>{item.type}</TableCell>
<TableCell>{item.date}</TableCell>
</TableRow>
)}
</TableBody>
</Table>
</div>
)
}
Installation
CLI
Manual
pnpmnpmyarnbunpnpm dlx @preskok-org/ui@latest add table
Usage
import { Table } from "@/registry/preskok/ui/preskok-ui/table"
export function TableDemo() {
return <Table rows={[]} columns={[]} />
}