Skip to content
Tier

Table

Pro

shadcn's table in Candor's theme: the plain table elements, for rows you lay out and order yourself. It doesn't sort, search, filter or page; for records a person does that to, use DataTable, which is built on these.

Table wraps the element in a box that scrolls sideways when the columns don't fit, and that box is a tab stop, so a keyboard user can scroll it. Give it a label and it is announced as a region by that name.

Markdown
Version 5.2.0· other versions

This page is for 5.2.0, the current release. An earlier release’s page is the Markdown that release published, so the docs match the version you have installed (candor-lock.json records it).

Not in the docs of 1.3.0, 1.4.0, 1.5.0, 1.5.1, 1.6.0, 1.7.0, 1.8.0, 1.8.1, 1.9.0, 1.9.1, 2.0.0, 2.1.0 and 2.2.0: the page came later, or had another name then.

Docs pages weren’t kept for 1.0.0, 1.0.1, 1.1.0, 1.1.1, 1.2.0 and 1.2.1: they are kept from 1.3.0 on, and before that only llms.txt was published.

Preview

Loading the preview

Install

With the Candor CLI

First time? Get started sets up the registry and theme. Or with shadcn directly: npx shadcn@latest add @candor/table

Brings in: tokens, utils

Usage

TSX · The example above
"use client"

import * as React from "react"
import { Table, TableBody, TableCaption, TableCell, TableEmpty, TableFooter, TableHead, TableHeader, TableRow } from "@/components/candor/ui/table"
import { useFormat } from "@/components/candor/locale"

const invoices = [
  { id: "INV-1042", status: "Paid", method: "Card", amount: 250 },
  { id: "INV-1043", status: "Pending", method: "Bank transfer", amount: 1200 },
  { id: "INV-1044", status: "Unpaid", method: "Card", amount: 89.5 },
]

export default function Example() {
  const fmt = useFormat()
  const [selected, setSelected] = React.useState<string | null>("INV-1043")
  const total = invoices.reduce((sum, i) => sum + i.amount, 0)
  const money = { style: "currency", currency: "USD" } as const
  return (
    <Table label="Invoices">
      <TableCaption>Invoices for October. Select a row to mark it.</TableCaption>
      <TableHeader>
        <TableRow>
          <TableHead>Invoice</TableHead>
          <TableHead>Status</TableHead>
          <TableHead>Method</TableHead>
          <TableHead numeric>Amount</TableHead>
        </TableRow>
      </TableHeader>
      <TableBody>
        {invoices.length === 0 ? (
          <TableEmpty colSpan={4}>No invoices yet.</TableEmpty>
        ) : (
          invoices.map((i) => (
            <TableRow key={i.id} data-state={selected === i.id ? "selected" : undefined} onClick={() => setSelected(i.id)}>
              <TableCell className="font-medium">{i.id}</TableCell>
              <TableCell>{i.status}</TableCell>
              <TableCell>{i.method}</TableCell>
              <TableCell numeric>{fmt.number(i.amount, money)}</TableCell>
            </TableRow>
          ))
        )}
      </TableBody>
      <TableFooter>
        <TableRow>
          <TableCell colSpan={3}>Total</TableCell>
          <TableCell numeric>{fmt.number(total, money)}</TableCell>
        </TableRow>
      </TableFooter>
    </Table>
  )
}

<Table>

PropTypeDefaultDescription
labelstring | undefined—A name for the scrolling box, announced as a region ("Migrations"). Without one the box is still a tab stop.
containerClassNamestring | undefined—Classes for the scrolling box around the table.

Also takes the props of React.ComponentProps<"table">.

<TableHeader>

The head of a Table, holding its column headings.

No props.

Also takes the props of React.ComponentProps<"thead">.

<TableBody>

The rows of a Table.

No props.

Also takes the props of React.ComponentProps<"tbody">.

<TableFooter>

The closing rows of a Table, such as totals.

No props.

Also takes the props of React.ComponentProps<"tfoot">.

<TableHead>

A column heading cell in a Table.

PropTypeDefaultDescription
numericboolean | undefinedfalseThe column holds numbers: its heading lines up with them at the end. Use `aria-sort` for a sorted column.

Also takes the props of React.ComponentProps<"th">.

<TableRow>

A row. Its background tints under the pointer and for the row marked data-state="selected".

No props.

Also takes the props of React.ComponentProps<"tr">.

<TableCell>

One cell of a Table row.

PropTypeDefaultDescription
numericboolean | undefinedfalseThe cell holds a number: it lines up at the end in tabular figures. Format the number with `useFormat`.

Also takes the props of React.ComponentProps<"td">.

<TableCaption>

The caption of a Table, saying what it lists; screen readers announce it first.

No props.

Also takes the props of React.ComponentProps<"caption">.

<TableEmpty>

A row that says why there are no rows: "No migrations yet." or "Nothing matches that filter." You write the words, because only the app knows which it is. Put it in TableBody in place of the rows.

PropTypeDefaultDescription
colSpanrequirednumber—How many columns the table has, so the message spans them.

Also takes the props of Omit<React.ComponentProps<"td">, "colSpan">.

Motion

MomentFamilyWhat it does
tinttintA row's background changes when the pointer is over it, and when the app marks it selected.

Set with --cd-motion-table-<moment>-* in your brand file; the families are in the design reference.