Table

Table

The Table component displays structured data in rows and columns. It provides components for defining the table, header, body, rows, and cells while supporting dense layouts, selected rows, and cell alignment.

A basic Table can be used to display tabular data with a header and multiple rows.

import Table from "rocksolidjs/Table";
import TableBody from "rocksolidjs/TableBody";
import TableCell from "rocksolidjs/TableCell";
import TableHead from "rocksolidjs/TableHead";
import TableRow from "rocksolidjs/TableRow";

const users = [
  {
    name: "Olivia Martin",
    email: "olivia@example.com",
    role: "Admin",
    status: "Active",
    joined: "Jan 12, 2025",
  },
  {
    name: "Jackson Lee",
    email: "jackson@example.com",
    role: "Member",
    status: "Active",
    joined: "Feb 08, 2025",
  },
  {
    name: "Sophia Brown",
    email: "sophia@example.com",
    role: "Member",
    status: "Inactive",
    joined: "Mar 21, 2025",
  },
];

export default function Example() {
  return (
    <div class="w-full overflow-x-auto">
      <Table class="min-w-200">
        <TableHead>
          <TableRow>
            <TableCell>Name</TableCell>
            <TableCell>Email</TableCell>
            <TableCell>Role</TableCell>
            <TableCell>Status</TableCell>
            <TableCell>Joined</TableCell>
          </TableRow>
        </TableHead>
        <TableBody>
          {users.map((user) => (
            <TableRow>
              <TableCell>{user.name}</TableCell>
              <TableCell>{user.email}</TableCell>
              <TableCell>{user.role}</TableCell>
              <TableCell>{user.status}</TableCell>
              <TableCell>{user.joined}</TableCell>
            </TableRow>
          ))}
        </TableBody>
      </Table>
    </div>
  );
}

Examples

Dense

Use the dense prop to reduce the spacing within table rows and cells when displaying a larger amount of data.

import Table from "rocksolidjs/Table";
import TableBody from "rocksolidjs/TableBody";
import TableCell from "rocksolidjs/TableCell";
import TableHead from "rocksolidjs/TableHead";
import TableRow from "rocksolidjs/TableRow";

const users = [
  { name: "Olivia Martin", email: "olivia@example.com", role: "Admin" },
  { name: "Jackson Lee", email: "jackson@example.com", role: "Member" },
  { name: "Sophia Brown", email: "sophia@example.com", role: "Member" },
  { name: "Noah Wilson", email: "noah@example.com", role: "Member" },
];

export default function Example() {
  return (
    <Table dense>
      <TableHead>
        <TableRow>
          <TableCell>Name</TableCell>
          <TableCell>Email</TableCell>
          <TableCell>Role</TableCell>
        </TableRow>
      </TableHead>
      <TableBody>
        {users.map((user) => (
          <TableRow>
            <TableCell>{user.name}</TableCell>
            <TableCell>{user.email}</TableCell>
            <TableCell>{user.role}</TableCell>
          </TableRow>
        ))}
      </TableBody>
    </Table>
  );
}

Selected Row

Use the selected prop on TableRow to indicate the currently selected row.

import { createSignal, For } from "solid-js";
import Checkbox from "rocksolidjs/Checkbox";
import Table from "rocksolidjs/Table";
import TableBody from "rocksolidjs/TableBody";
import TableCell from "rocksolidjs/TableCell";
import TableHead from "rocksolidjs/TableHead";
import TableRow from "rocksolidjs/TableRow";

const users = [
  { id: 1, name: "Olivia Martin", email: "olivia@example.com", role: "Admin" },
  { id: 2, name: "Jackson Lee", email: "jackson@example.com", role: "Member" },
  { id: 3, name: "Sophia Brown", email: "sophia@example.com", role: "Member" },
];

export default function Example() {
  const [selected, setSelected] = createSignal<number[]>([]);

  const toggleRow = (id: number) => {
    setSelected((current) =>
      current.includes(id)
        ? current.filter((selectedId) => selectedId !== id)
        : [...current, id],
    );
  };

  const handleSelectAll = (e: Event) => {
    if ((e.currentTarget as HTMLInputElement).checked) {
      setSelected(users.map(user => user.id));
    } else {
      setSelected([]);
    }
  };

  return (
    <Table>
      <TableHead>
        <TableRow>
          <TableCell class="w-12">
            <Checkbox
              aria-label="Select all users"
              checked={selected().length === users.length}
              onChange={handleSelectAll}
            />
          </TableCell>
          <TableCell>Name</TableCell>
          <TableCell>Email</TableCell>
          <TableCell>Role</TableCell>
        </TableRow>
      </TableHead>
      <TableBody>
        <For each={users}>
          {(user) => (
            <TableRow selected={selected().includes(user.id)}>
              <TableCell>
                <Checkbox
                  checked={selected().includes(user.id)}
                  onChange={() => toggleRow(user.id)}
                  aria-label={`Select ${user.name}`}
                />
              </TableCell>
              <TableCell>{user.name}</TableCell>
              <TableCell>{user.email}</TableCell>
              <TableCell>{user.role}</TableCell>
            </TableRow>
          )}
        </For>
      </TableBody>
    </Table>
  );
}

Cell Alignment

Use the align prop on TableCell to control the horizontal alignment of cell content.

import Table from "rocksolidjs/Table";
import TableBody from "rocksolidjs/TableBody";
import TableCell from "rocksolidjs/TableCell";
import TableHead from "rocksolidjs/TableHead";
import TableRow from "rocksolidjs/TableRow";

const orders = [
  { product: "Wireless Headphones", quantity: 2, price: "$199.00" },
  { product: "Mechanical Keyboard", quantity: 1, price: "$149.00" },
  { product: "USB-C Hub", quantity: 3, price: "$89.00" },
];

export default function Example() {
  return (
    <Table>
      <TableHead>
        <TableRow>
          <TableCell align="left">Product</TableCell>
          <TableCell align="right">Quantity</TableCell>
          <TableCell align="right">Price</TableCell>
        </TableRow>
      </TableHead>
      <TableBody>
        {orders.map((order) => (
          <TableRow>
            <TableCell align="left">{order.product}</TableCell>
            <TableCell align="right">{order.quantity}</TableCell>
            <TableCell align="right">{order.price}</TableCell>
          </TableRow>
        ))}
      </TableBody>
    </Table>
  );
}

Use TableFooter to display summary information, totals, or other content associated with the table data.

import Table from "rocksolidjs/Table";
import TableBody from "rocksolidjs/TableBody";
import TableCell from "rocksolidjs/TableCell";
import TableFooter from "rocksolidjs/TableFooter";
import TableHead from "rocksolidjs/TableHead";
import TableRow from "rocksolidjs/TableRow";

const orders = [
  { product: "Wireless Headphones", quantity: 2, total: "$398.00" },
  { product: "Mechanical Keyboard", quantity: 1, total: "$149.00" },
  { product: "USB-C Hub", quantity: 3, total: "$267.00" },
];

export default function Example() {
  const total = orders.reduce(
    (sum, order) => sum + Number(order.total.replace("$", "")),
    0,
  );

  return (
    <Table>
      <TableHead>
        <TableRow>
          <TableCell>Product</TableCell>
          <TableCell align="right">Quantity</TableCell>
          <TableCell align="right">Total</TableCell>
        </TableRow>
      </TableHead>
      <TableBody>
        {orders.map((order) => (
          <TableRow>
            <TableCell>{order.product}</TableCell>
            <TableCell align="right">{order.quantity}</TableCell>
            <TableCell align="right">{order.total}</TableCell>
          </TableRow>
        ))}
      </TableBody>
      <TableFooter class="bg-neutral-100 dark:bg-neutral-900">
        <TableRow>
          <TableCell class="font-semibold">Total</TableCell>
          <TableCell align="right" class="font-semibold">
            {orders.reduce((sum, order) => sum + order.quantity, 0)}
          </TableCell>
          <TableCell align="right" class="font-semibold">
            ${total.toFixed(2)}
          </TableCell>
        </TableRow>
      </TableFooter>
    </Table>
  );
}

Custom Styling

Use the class prop on Table components to add custom CSS classes.

import Table from "rocksolidjs/Table";
import TableBody from "rocksolidjs/TableBody";
import TableCell from "rocksolidjs/TableCell";
import TableHead from "rocksolidjs/TableHead";
import TableRow from "rocksolidjs/TableRow";

const orders = [
  {
    id: "#1024",
    customer: "Olivia Martin",
    product: "Wireless Headphones",
    status: "Completed",
    total: "$398.00",
  },
  {
    id: "#1025",
    customer: "Jackson Lee",
    product: "Mechanical Keyboard",
    status: "Processing",
    total: "$149.00",
  },
  {
    id: "#1026",
    customer: "Sophia Brown",
    product: "USB-C Hub",
    status: "Pending",
    total: "$267.00",
  },
];

export default function CustomStyling() {
  return (
    <Table class="rounded-lg shadow-sm">
      <TableHead class="bg-muted/50">
        <TableRow>
          <TableCell class="font-semibold">Order</TableCell>
          <TableCell class="font-semibold">Customer</TableCell>
          <TableCell class="font-semibold">Product</TableCell>
          <TableCell class="font-semibold">Status</TableCell>
          <TableCell align="right" class="font-semibold">
            Total
          </TableCell>
        </TableRow>
      </TableHead>
      <TableBody>
        {orders.map((order) => (
          <TableRow class="hover:bg-neutral-100/80 dark:hover:bg-neutral-900">
            <TableCell class="font-medium">{order.id}</TableCell>
            <TableCell>{order.customer}</TableCell>
            <TableCell>{order.product}</TableCell>
            <TableCell>{order.status}</TableCell>
            <TableCell align="right" class="font-medium">
              {order.total}
            </TableCell>
          </TableRow>
        ))}
      </TableBody>
    </Table>
  );
}

Accessibility

  • Use TableHead for column headings and TableBody for table data.
  • Keep column headings concise and descriptive.
  • Use TableCell for both header and data cells. Header cells are automatically rendered as th elements when used inside TableHead.
  • Use selected to provide a visual indication of the selected row, but ensure the selection state is also understandable without relying on color alone.
  • Keep the table structure consistent so that assistive technologies can correctly understand the relationship between headers and cells.

API

Table

The Table component supports dense layouts and custom styling.

Prop Type Required Default Description
class string No Adds custom CSS classes to the table.
dense boolean No false Reduces the spacing within the table for a more compact layout.

TableHead

The TableHead component defines the header section of a table.

Prop Type Required Default Description
class string No Adds custom CSS classes to the table header.

TableBody

The TableBody component defines the body section of a table.

Prop Type Required Default Description
class string No Adds custom CSS classes to the table body.

TableRow

The TableRow component represents a row within the table and can indicate a selected state.

Prop Type Required Default Description
class string No Adds custom CSS classes to the table row.
selected boolean No false Indicates whether the row is selected.

TableCell

The TableCell component represents a header or data cell. When used inside TableHead, it is automatically rendered as a th element. Otherwise, it renders as a td element.

Prop Type Required Default Description
as "th" | "td" No Automatic Controls the HTML element used for the cell. Defaults to th inside TableHead and td otherwise.
class string No Adds custom CSS classes to the table cell.
align "left" | "center" | "right" | "justify" No "left" Controls the horizontal alignment of the cell content.

TableFooter

The TableFooter component defines the footer section of a table. It can be used to display summary information, totals, or other content related to the table data.

Prop Type Required Default Description
class string No Adds custom CSS classes to the table footer.
  • Checkbox — Use for row selection or bulk selection within a table.