Siteplane UI

Tables and collections

Present records with sorting, filtering, selection, and useful empty states.

Markdown

Choose the interaction model

Use Table when records have comparable columns. Use ResourceList for flexible application rows and ListBox for choosing one item from a visible list. ResourceList has no built-in selection model: ResourceListItem only reflects the selected and interactive states your application sets.

Sorting and selection

ProjectRoleTeamBudget
Website RedesignOwnerFrontend Team$12,500
Mobile AppEditorMobile Team$8,750
API IntegrationEditorBackend Team$5,200
"use client";

import {
  Table,
  TableBody,
  TableCell,
  TableHead,
  TableHeader,
  TableRow,
  TableSelectionCheckbox,
} from "@/siteplane/components/table";
import { useState } from "react";
import type { Selection } from "react-aria-components";

const projects = [
  {
    id: "website-redesign",
    project: "Website Redesign",
    role: "Owner",
    team: "Frontend Team",
    budget: "$12,500",
  },
  {
    id: "mobile-app",
    project: "Mobile App",
    role: "Editor",
    team: "Mobile Team",
    budget: "$8,750",
  },
  {
    id: "api-integration",
    project: "API Integration",
    role: "Editor",
    team: "Backend Team",
    budget: "$5,200",
  },
];

export default function Example() {
  const [selectedKeys, setSelectedKeys] = useState<Selection>(
    new Set(["website-redesign"]),
  );
  return (
    <Table
      aria-label="Projects"
      selectionMode="multiple"
      selectionTrigger="checkbox"
      selectedKeys={selectedKeys}
      onSelectionChange={setSelectedKeys}
    >
      <TableHeader>
        <TableHead id="selection">
          <TableSelectionCheckbox />
        </TableHead>
        <TableHead id="project" isRowHeader>
          Project
        </TableHead>
        <TableHead id="role">Role</TableHead>
        <TableHead id="team">Team</TableHead>
        <TableHead id="budget" align="end">
          Budget
        </TableHead>
      </TableHeader>
      <TableBody>
        {projects.map((project) => (
          <TableRow
            key={project.id}
            id={project.id}
            textValue={project.project}
          >
            <TableCell>
              <TableSelectionCheckbox />
            </TableCell>
            <TableCell>{project.project}</TableCell>
            <TableCell>{project.role}</TableCell>
            <TableCell>{project.team}</TableCell>
            <TableCell align="end">{project.budget}</TableCell>
          </TableRow>
        ))}
      </TableBody>
    </Table>
  );
}

Table already exposes sorting and selection. Supply stable row ids, row textValue, a row-header column, and the correct state callbacks. A sort descriptor describes the requested order; sort the actual application data before rendering it. For controlled selection, account for both a Set of keys and "all".

Filtering

FilterBar supplies layout slots, not query execution. Connect Input, Select or other controls to application-owned state, derive visible rows, and expose a clear result count. Keep sort and selection stable when the filter changes, and decide whether bulk actions affect all records or only visible ones.

Loading, empty, and failure

Use TableBody renderEmptyState for an empty table. Table has no loading prop: while data loads, show a Skeleton and set aria-busy on the results region. For a richer empty screen, compose an EmptyState. “No records yet” differs from “No matches”; offer the relevant next action. Keep service errors visible instead of disguising them as an empty result.

On small screens, preserve column meaning and horizontal scrolling. Do not shrink all text or remove row actions to force a wide table into the viewport. Test interactive controls inside rows with the keyboard.

Complete application

Resource management includes local data, text and status filters, sortable columns, empty feedback, and a details/confirmation flow. Copy its full file after installation. Replace local data with your service; pagination, authorization, and server query semantics remain application responsibilities.