Table is a low-level component for building custom table layouts. For a full-featured data table with sorting, filtering, and pagination, use the DataTable component.
Import
import {
Table,
TableHeader,
TableBody,
TableRow,
TableHead,
TableCell,
TableFooter,
TableCaption
} from 'popui'
Basic Usage
<script lang="ts">
import {
Table,
TableHeader,
TableBody,
TableRow,
TableHead,
TableCell
} from 'popui'
const invoices = [
{ id: 'INV001', status: 'Paid', method: 'Credit Card', amount: '$250.00' },
{ id: 'INV002', status: 'Pending', method: 'PayPal', amount: '$150.00' },
{ id: 'INV003', status: 'Unpaid', method: 'Bank Transfer', amount: '$350.00' }
]
</script>
<Table>
<TableHeader>
<TableRow>
<TableHead>Invoice</TableHead>
<TableHead>Status</TableHead>
<TableHead>Method</TableHead>
<TableHead>Amount</TableHead>
</TableRow>
</TableHeader>
<TableBody>
{#each invoices as invoice}
<TableRow>
<TableCell>{invoice.id}</TableCell>
<TableCell>{invoice.status}</TableCell>
<TableCell>{invoice.method}</TableCell>
<TableCell>{invoice.amount}</TableCell>
</TableRow>
{/each}
</TableBody>
</Table>
<script lang="ts">
import {
Table,
TableHeader,
TableBody,
TableFooter,
TableRow,
TableHead,
TableCell
} from 'popui'
</script>
<Table>
<TableHeader>
<TableRow>
<TableHead>Item</TableHead>
<TableHead>Quantity</TableHead>
<TableHead>Price</TableHead>
</TableRow>
</TableHeader>
<TableBody>
<TableRow>
<TableCell>Product A</TableCell>
<TableCell>5</TableCell>
<TableCell>$50.00</TableCell>
</TableRow>
<TableRow>
<TableCell>Product B</TableCell>
<TableCell>3</TableCell>
<TableCell>$30.00</TableCell>
</TableRow>
</TableBody>
<TableFooter>
<TableRow>
<TableCell colspan="2">Total</TableCell>
<TableCell>$80.00</TableCell>
</TableRow>
</TableFooter>
</Table>
With Caption
<script lang="ts">
import {
Table,
TableCaption,
TableHeader,
TableBody,
TableRow,
TableHead,
TableCell
} from 'popui'
</script>
<Table>
<TableCaption>A list of your recent invoices.</TableCaption>
<TableHeader>
<TableRow>
<TableHead>Invoice</TableHead>
<TableHead>Status</TableHead>
<TableHead>Amount</TableHead>
</TableRow>
</TableHeader>
<TableBody>
<TableRow>
<TableCell>INV001</TableCell>
<TableCell>Paid</TableCell>
<TableCell>$250.00</TableCell>
</TableRow>
</TableBody>
</Table>
Clickable Rows
<script lang="ts">
function handleRowClick(invoice) {
console.log('Clicked:', invoice)
}
</script>
<Table>
<TableHeader>
<TableRow>
<TableHead>Invoice</TableHead>
<TableHead>Status</TableHead>
</TableRow>
</TableHeader>
<TableBody>
{#each invoices as invoice}
<TableRow
onclick={() => handleRowClick(invoice)}
class="cursor-pointer"
>
<TableCell>{invoice.id}</TableCell>
<TableCell>{invoice.status}</TableCell>
</TableRow>
{/each}
</TableBody>
</Table>
Row States
Table rows support different visual states through data attributes:
<TableBody>
<TableRow data-state="selected">
<TableCell>Selected row</TableCell>
</TableRow>
<TableRow data-state="error">
<TableCell>Error state</TableCell>
</TableRow>
<TableRow data-state="warning">
<TableCell>Warning state</TableCell>
</TableRow>
<TableRow data-state="success">
<TableCell>Success state</TableCell>
</TableRow>
</TableBody>
Custom Styling
<Table class="border border-border">
<TableHeader class="bg-gray-50">
<TableRow>
<TableHead class="font-bold">Name</TableHead>
<TableHead class="font-bold text-right">Amount</TableHead>
</TableRow>
</TableHeader>
<TableBody>
<TableRow>
<TableCell class="font-medium">John Doe</TableCell>
<TableCell class="text-right font-mono">$250.00</TableCell>
</TableRow>
</TableBody>
</Table>
The TableHeader component is sticky by default and remains visible when scrolling:
<div class="h-96 overflow-auto">
<Table>
<TableHeader>
<TableRow>
<TableHead>Column 1</TableHead>
<TableHead>Column 2</TableHead>
</TableRow>
</TableHeader>
<TableBody>
{#each Array(50) as _, i}
<TableRow>
<TableCell>Row {i + 1}</TableCell>
<TableCell>Data {i + 1}</TableCell>
</TableRow>
{/each}
</TableBody>
</Table>
</div>
Responsive Table
<div class="overflow-x-auto">
<Table>
<TableHeader>
<TableRow>
<TableHead class="min-w-[100px]">ID</TableHead>
<TableHead class="min-w-[200px]">Name</TableHead>
<TableHead class="min-w-[150px]">Email</TableHead>
<TableHead class="min-w-[100px]">Status</TableHead>
</TableRow>
</TableHeader>
<TableBody>
{#each data as item}
<TableRow>
<TableCell>{item.id}</TableCell>
<TableCell>{item.name}</TableCell>
<TableCell>{item.email}</TableCell>
<TableCell>{item.status}</TableCell>
</TableRow>
{/each}
</TableBody>
</Table>
</div>
Components
Table
The root table container.
Reference to the underlying table element.
Table content (Header, Body, Footer, Caption).
The table header section (sticky by default).
Reference to the thead element.
TableRow components with TableHead cells.
TableBody
The table body section.
Reference to the tbody element.
The table footer section.
Reference to the tfoot element.
TableRow
A table row.
Reference to the tr element.
onclick
(event: MouseEvent) => void
Click handler.
onkeydown
(event: KeyboardEvent) => void
Keydown handler.
onmouseover
(event: MouseEvent) => void
Mouse over handler.
onfocus
(event: FocusEvent) => void
Focus handler.
data-state
'selected' | 'checked' | 'error' | 'warning' | 'success'
Row visual state.
Whether the row is focused.
TableCell or TableHead components.
TableHead
A header cell.
Reference to the th element.
Number of columns to span.
TableCell
A data cell.
Reference to the td element.
Number of columns to span.
TableCaption
A table caption.
Reference to the caption element.