Table
Semantic table with header, body, footer, rows, cells and a caption, inside a container that scrolls sideways.
"use client"
/*
* Adapted from shadcn/ui (https://github.com/shadcn-ui/ui).
*
* MIT License
*
* Copyright (c) 2023 shadcn
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
import * as React from "react"
import { cn } from "@/lib/utils"
function Table({ className, ...props }: React.ComponentProps<"table">) {
return (
<div
data-slot="table-container"
className="relative w-full overflow-x-auto"
>
<table
data-slot="table"
className={cn("w-full caption-bottom text-sm", className)}
{...props}
/>
</div>
)
}
function TableHeader({ className, ...props }: React.ComponentProps<"thead">) {
return (
<thead
data-slot="table-header"
className={cn("[&_tr]:border-b", className)}
{...props}
/>
)
}
function TableBody({ className, ...props }: React.ComponentProps<"tbody">) {
return (
<tbody
data-slot="table-body"
className={cn("[&_tr:last-child]:border-0", className)}
{...props}
/>
)
}
function TableFooter({ className, ...props }: React.ComponentProps<"tfoot">) {
return (
<tfoot
data-slot="table-footer"
className={cn(
"border-t border-border bg-muted/50 font-medium [&>tr]:last:border-b-0",
className
)}
{...props}
/>
)
}
function TableRow({ className, ...props }: React.ComponentProps<"tr">) {
return (
<tr
data-slot="table-row"
className={cn(
"border-b border-border transition-colors hover:bg-muted/50 has-aria-expanded:bg-muted/50 data-[state=selected]:bg-muted",
className
)}
{...props}
/>
)
}
function TableHead({ className, ...props }: React.ComponentProps<"th">) {
return (
<th
data-slot="table-head"
className={cn(
"h-10 px-2 text-left align-middle font-medium whitespace-nowrap text-foreground [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]",
className
)}
{...props}
/>
)
}
function TableCell({ className, ...props }: React.ComponentProps<"td">) {
return (
<td
data-slot="table-cell"
className={cn(
"p-2 align-middle whitespace-nowrap [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]",
className
)}
{...props}
/>
)
}
function TableCaption({
className,
...props
}: React.ComponentProps<"caption">) {
return (
<caption
data-slot="table-caption"
className={cn("mt-4 text-sm text-muted-foreground", className)}
{...props}
/>
)
}
export {
Table,
TableHeader,
TableBody,
TableFooter,
TableHead,
TableRow,
TableCell,
TableCaption,
}Installation
pnpm dlx shadcn@latest add @ward/tablenpx shadcn@latest add @ward/tableyarn dlx shadcn@latest add @ward/tablebunx --bun shadcn@latest add @ward/tableAdd the Ward registry to components.json once:
"registries": {
"@ward": "https://ward.so/r/{name}.json"
}Or install from the URL with no configuration: npx shadcn@latest add https://ward.so/r/table.json
Copy each file from the Code tab into:
components/ui/table.tsx
Update the import paths to match your project.
Usage
import { Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableRow } from "@/components/ui/table";<Table>
<TableCaption>Saved this week</TableCaption>
<TableHeader>
<TableRow>
<TableHead>Collection</TableHead>
<TableHead className="text-right">Sites</TableHead>
</TableRow>
</TableHeader>
<TableBody>
<TableRow><TableCell>Landing pages</TableCell><TableCell className="text-right">24</TableCell></TableRow>
<TableRow data-state="selected"><TableCell>Pricing tables</TableCell><TableCell className="text-right">9</TableCell></TableRow>
</TableBody>
<TableFooter>
<TableRow><TableCell>Total</TableCell><TableCell className="text-right">33</TableCell></TableRow>
</TableFooter>
</Table>Props
| Prop | Type | Default | Description |
|---|---|---|---|
className | string | - | Extra classes for the table itself; it sits in a container that scrolls sideways when the columns do not fit. |
TableRow data-state | "selected" | - | Set to selected to tint the row, for example when its checkbox is ticked. |
TableHead className | string | - | Add text-right to line a numeric column up with its cells. |
TableCell className | string | - | Cells do not wrap; add whitespace-normal to let long text run onto more lines. |
TableCaption | ReactNode | - | Short description of the table, shown below it and read out by screen readers. |
Ward · Version 1.0.0 · Registry manifest