Browse components

Table

import Table, {
  TableContainer,
  TableHead,
  TableBody,
  TableFooter,
  TableRow,
  TableCell,
  TableSortLabel,
} from "@shpaw415/mui-lite/Table";
import { TablePagination } from "@shpaw415/mui-lite/Pagination";

Why use it

Table renders structured tabular data with Material density, sticky headers, hover/selected rows, and sort labels. Use it for admin lists, invoices, and comparison grids where columns align better than cards.

Wrap in TableContainer for horizontal scroll (and optional maxHeight + stickyHeader). Use TableSortLabel for accessible sort affordances and TablePagination for large datasets.

Demo

The interactive demo shows common product patterns:

  • Column sorting (click headers; toggles asc/desc)
  • Row selection (checkbox column + click row; select-all on page)
  • Pagination (page + rows-per-page)
  • Dense / comfortable density toggle
  • Sticky header while scrolling
  • Footer with page totals
Interactive: sort, select, paginate

12 desserts

DessertCaloriesFat (g)Carbs (g)Protein (g)
Frozen yoghurt1596244
Ice cream sandwich2379374.3
Eclair26216246
Cupcake3053.7674.3
Marshmallow3180.2811.8
Gingerbread35616493.9
Nougat36019457
Jelly bean3750940
Lollipop3920.2980
Honeycomb4083.2876.5

Rows per page:

10

1-10 of 12

Basic (static)
DessertCaloriesFat (g)
Frozen yoghurt1596
Ice cream sandwich2379
Eclair26216

Example — basic

import Table, {
  TableBody,
  TableCell,
  TableContainer,
  TableHead,
  TableRow,
} from "@shpaw415/mui-lite/Table";
 
export function BasicTable() {
  return (
    <TableContainer>
      <Table size="small">
        <TableHead>
          <TableRow>
            <TableCell>Name</TableCell>
            <TableCell align="right">Calories</TableCell>
          </TableRow>
        </TableHead>
        <TableBody>
          <TableRow hover>
            <TableCell>Frozen yoghurt</TableCell>
            <TableCell align="right">159</TableCell>
          </TableRow>
        </TableBody>
      </Table>
    </TableContainer>
  );
}

Example — sortable columns

const [orderBy, setOrderBy] = useState<"name" | "calories">("name");
const [order, setOrder] = useState<"asc" | "desc">("asc");
 
const handleSort = (key: "name" | "calories") => {
  if (orderBy === key) setOrder((d) => (d === "asc" ? "desc" : "asc"));
  else {
    setOrderBy(key);
    setOrder("asc");
  }
};
 
// ...
<TableCell sortDirection={orderBy === "calories" ? order : false}>
  <TableSortLabel
    active={orderBy === "calories"}
    direction={orderBy === "calories" ? order : "asc"}
    onClick={() => handleSort("calories")}
  >
    Calories
  </TableSortLabel>
</TableCell>

Example — selection + pagination

const [selected, setSelected] = useState<string[]>([]);
const [page, setPage] = useState(0);
const [rowsPerPage, setRowsPerPage] = useState<10 | 25 | 50 | 100>(10);
 
// slice sorted rows for the current page, then:
<TableRow
  hover
  selected={selected.includes(row.id)}
  onClick={() => toggleRow(row.id)}
>
  <TableCell padding="checkbox">
    <CheckBox
      checked={selected.includes(row.id)}
      onChange={() => toggleRow(row.id)}
    />
  </TableCell>
  {/* ... */}
</TableRow>
 
<TablePagination
  count={rows.length}
  page={page}
  rowsPerPage={rowsPerPage}
  onPageChange={(_e, p) => setPage(p)}
  onRowsPerPageChange={(r) => {
    setRowsPerPage(r);
    setPage(0);
  }}
/>

Composition

PieceRole
TableContainerScroll wrapper (set maxHeight for sticky header)
Tablesize, stickyHeader, padding
TableHead / TableBody / TableFooterSections
TableRowhover, selected
TableCellalign, padding="checkbox", sortDirection
TableSortLabelClickable sort control in header cells
TablePaginationFooter paging (@shpaw415/mui-lite/Pagination)