Getting Started
Components
- Accordion
- Alert
- Alert Dialog
- Avatar
- Badge
- Button
- Calendar
- Card
- Carousel
- Chart
- Checkbox
- Circular Progress
- Collapsible
- Compare Slider
- Dialog
- Dropdown Menu
- Gauge
- Input
- Label
- Marquee
- Navigation Menu
- Number Field
- Pagination
- Popover
- Progress
- Radio Group
- Scroll Area
- Select
- Separator
- Sheet
- Sidebar
- Skeleton
- Slider
- Switch
- Table
- Tabs
- Textarea
- Toggle
- Tooltip
Demos
Biomarker results with reference ranges and a status.
| Biomarker | Result | Reference | Status |
|---|---|---|---|
| LDL-C | 96 mg/dL | < 100 | In range |
| HDL-C | 58 mg/dL | > 40 | In range |
| Triglycerides | 182 mg/dL | < 150 | Out of range |
| HbA1c | 5.4 % | < 5.7 | In range |
| hs-CRP | 3.4 mg/L | < 1.0 | Out of range |
"use client"
import { Badge } from "@workspace/ui/components/badge"
import {
Table,
TableBody,
TableCaption,
TableCell,
TableHead,
TableHeader,
TableRow,
} from "@workspace/ui/components/table"
const results = [
{ name: "LDL-C", value: "96", unit: "mg/dL", range: "< 100", inRange: true },
{ name: "HDL-C", value: "58", unit: "mg/dL", range: "> 40", inRange: true },
{ name: "Triglycerides", value: "182", unit: "mg/dL", range: "< 150", inRange: false },
{ name: "HbA1c", value: "5.4", unit: "%", range: "< 5.7", inRange: true },
{ name: "hs-CRP", value: "3.4", unit: "mg/L", range: "< 1.0", inRange: false },
]
export function TableDemo() {
return (
<Table>
<TableCaption>Results from your October panel.</TableCaption>
<TableHeader>
<TableRow>
<TableHead>Biomarker</TableHead>
<TableHead className="text-end">Result</TableHead>
<TableHead>Reference</TableHead>
<TableHead className="text-end">Status</TableHead>
</TableRow>
</TableHeader>
<TableBody>
{results.map((result) => (
<TableRow key={result.name}>
<TableCell className="font-medium">{result.name}</TableCell>
<TableCell className="text-end tabular-nums">
{result.value} {result.unit}
</TableCell>
<TableCell className="text-muted-foreground">{result.range}</TableCell>
<TableCell className="text-end">
<Badge variant={result.inRange ? "outline" : "destructive"}>
{result.inRange ? "In range" : "Out of range"}
</Badge>
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
)
}
Usage
Use a table when the reader needs to compare values across rows, such as results, invoices, or appointments. The parts are styled HTML table elements, so you write the rows yourself.
Import it from @workspace/ui/components/table.
Anatomy
- Table — The
table, inside a wrapper that scrolls sideways on narrow screens. - TableHeader, TableBody, and TableFooter —
thead,tbody, andtfoot. - TableRow — A row with a hover style.
- TableHead — A header cell.
- TableCell — A data cell.
- TableCaption — A caption below the table.
Notes
- Right-align numbers with
text-endand addtabular-numsso digits line up. - Put the unit in the cell or the header, never only in a tooltip.
- Add
data-state="selected"to a row to highlight it. - Add a
TableCaptionso screen readers know what the table holds.
Examples
With footer
A footer row for totals.
| Invoice | Item | Amount |
|---|---|---|
| INV-1042 | Core panel | £149.00 |
| INV-1043 | Clinician review | £49.00 |
| INV-1044 | Home collection | £25.00 |
| Total | £223.00 | |
"use client"
import {
Table,
TableBody,
TableCell,
TableFooter,
TableHead,
TableHeader,
TableRow,
} from "@workspace/ui/components/table"
const orders = [
{ id: "INV-1042", item: "Core panel", amount: 149 },
{ id: "INV-1043", item: "Clinician review", amount: 49 },
{ id: "INV-1044", item: "Home collection", amount: 25 },
]
const formatter = new Intl.NumberFormat("en-GB", {
style: "currency",
currency: "GBP",
})
export function TableWithFooter() {
const total = orders.reduce((sum, order) => sum + order.amount, 0)
return (
<Table>
<TableHeader>
<TableRow>
<TableHead>Invoice</TableHead>
<TableHead>Item</TableHead>
<TableHead className="text-end">Amount</TableHead>
</TableRow>
</TableHeader>
<TableBody>
{orders.map((order) => (
<TableRow key={order.id}>
<TableCell className="font-medium">{order.id}</TableCell>
<TableCell>{order.item}</TableCell>
<TableCell className="text-end tabular-nums">
{formatter.format(order.amount)}
</TableCell>
</TableRow>
))}
</TableBody>
<TableFooter>
<TableRow>
<TableCell colSpan={2}>Total</TableCell>
<TableCell className="text-end tabular-nums">
{formatter.format(total)}
</TableCell>
</TableRow>
</TableFooter>
</Table>
)
}
Props
Each part takes the props of its HTML element, plus className.