Table
Tables display sets of data across rows and columns.
Simple Example
A table can be created using the following components:
Table
- A styled<table>
TableHeader
- A styled<thead>
TableBody
- A<tbody>
with some additional behavior defined laterTableFooter
- A styled<tfoot>
with some additional behavior defined laterTableRow
- A styled<tr>
with some additional behavior defined laterTableCell
- A styledth
ortd
. Rendered as ath
when a child of theTableHeader
and atd
otherwise.
The TableRow
will default to rendering a border on the bottom and a different
background color while hovered when in the TableBody
.
A caption
can be added by using the Typography
component.
Header 1 | Header 2 |
---|---|
Cell 1 | Cell 2 |
Cell 1 | Cell 2 |
Footer 1 | Footer 2 |
import { Table } from "@react-md/core/table/Table";
import { TableBody } from "@react-md/core/table/TableBody";
import { TableCell } from "@react-md/core/table/TableCell";
import { TableFooter } from "@react-md/core/table/TableFooter";
import { TableHeader } from "@react-md/core/table/TableHeader";
import { TableRow } from "@react-md/core/table/TableRow";
import { Typography } from "@react-md/core/typography/Typography";
import { type ReactElement } from "react";
export default function SimpleTableExample(): ReactElement {
return (
<Table>
<Typography type="caption">This is a caption.</Typography>
<TableHeader>
<TableRow>
<TableCell>Header 1</TableCell>
<TableCell>Header 2</TableCell>
</TableRow>
</TableHeader>
<TableBody>
<TableRow>
<TableCell>Cell 1</TableCell>
<TableCell>Cell 2</TableCell>
</TableRow>
<TableRow>
<TableCell>Cell 1</TableCell>
<TableCell>Cell 2</TableCell>
</TableRow>
</TableBody>
<TableFooter>
<TableRow>
<TableCell>Footer 1</TableCell>
<TableCell>Footer 2</TableCell>
</TableRow>
</TableFooter>
</Table>
);
}
Disable Hover Styles
The row hover styles that appear on all the TableRow
in the TableBody
can be
configured on the Table
, TableBody
, or TableRow
components with
thedisableHover
prop. The TableRow
will inherit this value or override the
inherited value if defined.
Hover is disabled |
Hover is disabled |
Hover is enabled |
import { Table } from "@react-md/core/table/Table";
import { TableBody } from "@react-md/core/table/TableBody";
import { TableCell } from "@react-md/core/table/TableCell";
import { TableRow } from "@react-md/core/table/TableRow";
import { type ReactElement } from "react";
export default function DisableHoverExample(): ReactElement {
// try moving the `disableHover` from the `Table` to the `TableBody`
return (
<Table disableHover>
<TableBody>
<TableRow>
<TableCell>Hover is disabled</TableCell>
</TableRow>
<TableRow>
<TableCell>Hover is disabled</TableCell>
</TableRow>
<TableRow disableHover={false}>
<TableCell>Hover is enabled</TableCell>
</TableRow>
</TableBody>
</Table>
);
}
Disable Border Styles
The bottom border that appears on all TableRow
in the TableBody
can be
removed by enabling the disableBorders
prop on the Table
, TableBody
, or
TableRow
components. The TableRow
will inherit this value or override the
inherited value if defined.
Borders are disabled |
Borders are disabled |
Borders are enabled |
Borders don't apply |
import { Table } from "@react-md/core/table/Table";
import { TableBody } from "@react-md/core/table/TableBody";
import { TableCell } from "@react-md/core/table/TableCell";
import { TableRow } from "@react-md/core/table/TableRow";
import { type ReactElement } from "react";
export default function DisableBordersExample(): ReactElement {
// try moving the `disableBorders` from the `Table` to the `TableBody`
return (
<Table disableBorders>
<TableBody>
<TableRow>
<TableCell>Borders are disabled</TableCell>
</TableRow>
<TableRow>
<TableCell>Borders are disabled</TableCell>
</TableRow>
<TableRow disableBorders={false}>
<TableCell>Borders are enabled</TableCell>
</TableRow>
<TableRow>
<TableCell>{"Borders don't apply"}</TableCell>
</TableRow>
</TableBody>
</Table>
);
}
Scrollable Tables
If a table should be scrollable, wrap it in a TableContainer
. The
TableContainer
allows scrolling horizontally and vertically by adding:
.rmd-table-container {
max-width: 100%;
overflow: auto;
}
Header 1 | Header 2 | Header 3 | Header 4 | Header 5 | Header 6 | Header 7 | Header 8 | Header 9 | Header 10 | Header 11 | Header 12 | Header 13 | Header 14 | Header 15 | Header 16 | Header 17 | Header 18 | Header 19 | Header 20 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Cell 1 | Cell 2 | Cell 3 | Cell 4 | Cell 5 | Cell 6 | Cell 7 | Cell 8 | Cell 9 | Cell 10 | Cell 11 | Cell 12 | Cell 13 | Cell 14 | Cell 15 | Cell 16 | Cell 17 | Cell 18 | Cell 19 | Cell 20 |
Cell 1 | Cell 2 | Cell 3 | Cell 4 | Cell 5 | Cell 6 | Cell 7 | Cell 8 | Cell 9 | Cell 10 | Cell 11 | Cell 12 | Cell 13 | Cell 14 | Cell 15 | Cell 16 | Cell 17 | Cell 18 | Cell 19 | Cell 20 |
Cell 1 | Cell 2 | Cell 3 | Cell 4 | Cell 5 | Cell 6 | Cell 7 | Cell 8 | Cell 9 | Cell 10 | Cell 11 | Cell 12 | Cell 13 | Cell 14 | Cell 15 | Cell 16 | Cell 17 | Cell 18 | Cell 19 | Cell 20 |
Cell 1 | Cell 2 | Cell 3 | Cell 4 | Cell 5 | Cell 6 | Cell 7 | Cell 8 | Cell 9 | Cell 10 | Cell 11 | Cell 12 | Cell 13 | Cell 14 | Cell 15 | Cell 16 | Cell 17 | Cell 18 | Cell 19 | Cell 20 |
Cell 1 | Cell 2 | Cell 3 | Cell 4 | Cell 5 | Cell 6 | Cell 7 | Cell 8 | Cell 9 | Cell 10 | Cell 11 | Cell 12 | Cell 13 | Cell 14 | Cell 15 | Cell 16 | Cell 17 | Cell 18 | Cell 19 | Cell 20 |
Cell 1 | Cell 2 | Cell 3 | Cell 4 | Cell 5 | Cell 6 | Cell 7 | Cell 8 | Cell 9 | Cell 10 | Cell 11 | Cell 12 | Cell 13 | Cell 14 | Cell 15 | Cell 16 | Cell 17 | Cell 18 | Cell 19 | Cell 20 |
Cell 1 | Cell 2 | Cell 3 | Cell 4 | Cell 5 | Cell 6 | Cell 7 | Cell 8 | Cell 9 | Cell 10 | Cell 11 | Cell 12 | Cell 13 | Cell 14 | Cell 15 | Cell 16 | Cell 17 | Cell 18 | Cell 19 | Cell 20 |
Cell 1 | Cell 2 | Cell 3 | Cell 4 | Cell 5 | Cell 6 | Cell 7 | Cell 8 | Cell 9 | Cell 10 | Cell 11 | Cell 12 | Cell 13 | Cell 14 | Cell 15 | Cell 16 | Cell 17 | Cell 18 | Cell 19 | Cell 20 |
Cell 1 | Cell 2 | Cell 3 | Cell 4 | Cell 5 | Cell 6 | Cell 7 | Cell 8 | Cell 9 | Cell 10 | Cell 11 | Cell 12 | Cell 13 | Cell 14 | Cell 15 | Cell 16 | Cell 17 | Cell 18 | Cell 19 | Cell 20 |
Cell 1 | Cell 2 | Cell 3 | Cell 4 | Cell 5 | Cell 6 | Cell 7 | Cell 8 | Cell 9 | Cell 10 | Cell 11 | Cell 12 | Cell 13 | Cell 14 | Cell 15 | Cell 16 | Cell 17 | Cell 18 | Cell 19 | Cell 20 |
Cell 1 | Cell 2 | Cell 3 | Cell 4 | Cell 5 | Cell 6 | Cell 7 | Cell 8 | Cell 9 | Cell 10 | Cell 11 | Cell 12 | Cell 13 | Cell 14 | Cell 15 | Cell 16 | Cell 17 | Cell 18 | Cell 19 | Cell 20 |
Cell 1 | Cell 2 | Cell 3 | Cell 4 | Cell 5 | Cell 6 | Cell 7 | Cell 8 | Cell 9 | Cell 10 | Cell 11 | Cell 12 | Cell 13 | Cell 14 | Cell 15 | Cell 16 | Cell 17 | Cell 18 | Cell 19 | Cell 20 |
Cell 1 | Cell 2 | Cell 3 | Cell 4 | Cell 5 | Cell 6 | Cell 7 | Cell 8 | Cell 9 | Cell 10 | Cell 11 | Cell 12 | Cell 13 | Cell 14 | Cell 15 | Cell 16 | Cell 17 | Cell 18 | Cell 19 | Cell 20 |
Cell 1 | Cell 2 | Cell 3 | Cell 4 | Cell 5 | Cell 6 | Cell 7 | Cell 8 | Cell 9 | Cell 10 | Cell 11 | Cell 12 | Cell 13 | Cell 14 | Cell 15 | Cell 16 | Cell 17 | Cell 18 | Cell 19 | Cell 20 |
Cell 1 | Cell 2 | Cell 3 | Cell 4 | Cell 5 | Cell 6 | Cell 7 | Cell 8 | Cell 9 | Cell 10 | Cell 11 | Cell 12 | Cell 13 | Cell 14 | Cell 15 | Cell 16 | Cell 17 | Cell 18 | Cell 19 | Cell 20 |
Cell 1 | Cell 2 | Cell 3 | Cell 4 | Cell 5 | Cell 6 | Cell 7 | Cell 8 | Cell 9 | Cell 10 | Cell 11 | Cell 12 | Cell 13 | Cell 14 | Cell 15 | Cell 16 | Cell 17 | Cell 18 | Cell 19 | Cell 20 |
Cell 1 | Cell 2 | Cell 3 | Cell 4 | Cell 5 | Cell 6 | Cell 7 | Cell 8 | Cell 9 | Cell 10 | Cell 11 | Cell 12 | Cell 13 | Cell 14 | Cell 15 | Cell 16 | Cell 17 | Cell 18 | Cell 19 | Cell 20 |
Cell 1 | Cell 2 | Cell 3 | Cell 4 | Cell 5 | Cell 6 | Cell 7 | Cell 8 | Cell 9 | Cell 10 | Cell 11 | Cell 12 | Cell 13 | Cell 14 | Cell 15 | Cell 16 | Cell 17 | Cell 18 | Cell 19 | Cell 20 |
Cell 1 | Cell 2 | Cell 3 | Cell 4 | Cell 5 | Cell 6 | Cell 7 | Cell 8 | Cell 9 | Cell 10 | Cell 11 | Cell 12 | Cell 13 | Cell 14 | Cell 15 | Cell 16 | Cell 17 | Cell 18 | Cell 19 | Cell 20 |
Cell 1 | Cell 2 | Cell 3 | Cell 4 | Cell 5 | Cell 6 | Cell 7 | Cell 8 | Cell 9 | Cell 10 | Cell 11 | Cell 12 | Cell 13 | Cell 14 | Cell 15 | Cell 16 | Cell 17 | Cell 18 | Cell 19 | Cell 20 |
Selectable Rows
A common pattern with tables are to make the rows selectable so different
actions can be applied. A TableRow
can be updated to have a selected
state
which will add a different background color and a clickable
state that updates
the cursor to be a pointer.
Header 1 | Header 2 | Header 3 |
---|---|---|
Cell 1 | Cell 2 | Cell 3 |
Cell 1 | Cell 2 | Cell 3 |
Cell 1 | Cell 2 | Cell 3 |
"use client";
import { Table } from "@react-md/core/table/Table";
import { TableBody } from "@react-md/core/table/TableBody";
import { TableCell } from "@react-md/core/table/TableCell";
import { TableContainer } from "@react-md/core/table/TableContainer";
import { TableHeader } from "@react-md/core/table/TableHeader";
import { TableRow } from "@react-md/core/table/TableRow";
import { type ReactElement, useState } from "react";
export default function SelectableRowsExample(): ReactElement {
const [selectedRows, setSelectedRows] = useState<readonly number[]>([]);
const toggleRow = (index: number): void => {
setSelectedRows((prevSelectedRows) => {
if (prevSelectedRows.includes(index)) {
return prevSelectedRows.filter((i) => i !== index);
}
return [...prevSelectedRows, index];
});
};
return (
<TableContainer>
<Table fullWidth>
<TableHeader>
<TableRow>
<TableCell>Header 1</TableCell>
<TableCell>Header 2</TableCell>
<TableCell>Header 3</TableCell>
</TableRow>
</TableHeader>
<TableBody>
<TableRow
clickable
onClick={() => {
toggleRow(0);
}}
selected={selectedRows.includes(0)}
>
<TableCell>Cell 1</TableCell>
<TableCell>Cell 2</TableCell>
<TableCell>Cell 3</TableCell>
</TableRow>
<TableRow
clickable
onClick={() => {
toggleRow(1);
}}
selected={selectedRows.includes(1)}
>
<TableCell>Cell 1</TableCell>
<TableCell>Cell 2</TableCell>
<TableCell>Cell 3</TableCell>
</TableRow>
<TableRow
clickable
onClick={() => {
toggleRow(2);
}}
selected={selectedRows.includes(2)}
>
<TableCell>Cell 1</TableCell>
<TableCell>Cell 2</TableCell>
<TableCell>Cell 3</TableCell>
</TableRow>
</TableBody>
</Table>
</TableContainer>
);
}
Selectable Rows with Checkbox
It is recommended to use the TableCheckbox
component as the first cell in each
row to help show the row can be selected and the
useCheckboxGroup hook to control the selected
state.
"use client";
import { Form } from "@react-md/core/form/Form";
import { useCheckboxGroup } from "@react-md/core/form/useCheckboxGroup";
import { Table } from "@react-md/core/table/Table";
import { TableBody } from "@react-md/core/table/TableBody";
import { TableCell } from "@react-md/core/table/TableCell";
import { TableCheckbox } from "@react-md/core/table/TableCheckbox";
import { TableContainer } from "@react-md/core/table/TableContainer";
import { TableHeader } from "@react-md/core/table/TableHeader";
import { TableRow } from "@react-md/core/table/TableRow";
import { type ReactElement } from "react";
export default function SelectableRowsWithCheckboxExample(): ReactElement {
const { getCheckboxProps, getIndeterminateProps } = useCheckboxGroup({
name: "desserts",
values: desserts.map(({ name }) => name),
});
return (
<TableContainer>
<Form>
<Table fullWidth>
<TableHeader>
<TableRow>
<TableCheckbox {...getIndeterminateProps()} />
{columns.map((name, i) => (
<TableCell key={name} grow={i === 0}>
{name}
</TableCell>
))}
</TableRow>
</TableHeader>
<TableBody hAlign="right">
{desserts.map((dessert) => {
const {
name,
type,
calories,
fat,
carbs,
protein,
sodium,
calcium,
iron,
} = dessert;
const checkboxProps = getCheckboxProps(name);
const { checked, onChange } = checkboxProps;
return (
<TableRow
key={name}
selected={checked}
onClick={onChange}
clickable
>
<TableCheckbox {...checkboxProps} />
<TableCell hAlign="left">{name}</TableCell>
<TableCell>{type}</TableCell>
<TableCell>{calories}</TableCell>
<TableCell>{fat}</TableCell>
<TableCell>{carbs}</TableCell>
<TableCell>{protein}</TableCell>
<TableCell>{sodium}</TableCell>
<TableCell>{calcium}</TableCell>
<TableCell>{iron}</TableCell>
</TableRow>
);
})}
</TableBody>
</Table>
</Form>
</TableContainer>
);
}
const columns = [
"Dessert (100g serving)",
"Type",
"Calories",
"Fat (g)",
"Carbs (g)",
"Protein (g)",
"Sodium (mg)",
"Calcium (mg)",
"Icon (mg)",
] as const;
export interface Dessert {
name: string;
calories: number;
fat: number;
carbs: number;
protein: number;
sodium: number;
calcium: number;
iron: number;
type: "Ice cream" | "Pastry" | "Other";
}
export type DessertKey = keyof Dessert;
export const desserts: readonly Dessert[] = [
{
name: "Frozen yogurt",
type: "Ice cream",
calories: 159,
fat: 6.0,
carbs: 24,
protein: 4.0,
sodium: 87,
calcium: 14,
iron: 1,
},
{
name: "Ice cream sandwich",
type: "Ice cream",
calories: 237,
fat: 9.0,
carbs: 37,
protein: 4.3,
sodium: 129,
calcium: 8,
iron: 1,
},
{
name: "Eclair",
type: "Pastry",
calories: 262,
fat: 16.0,
carbs: 37,
protein: 6.0,
sodium: 337,
calcium: 6,
iron: 7,
},
{
name: "Cupcake",
type: "Pastry",
calories: 305,
fat: 3.7,
carbs: 67,
protein: 4.3,
sodium: 413,
calcium: 3,
iron: 8,
},
{
name: "Gingerbread",
type: "Pastry",
calories: 356,
fat: 16.0,
carbs: 49,
protein: 3.9,
sodium: 327,
calcium: 7,
iron: 16,
},
{
name: "Jelly bean",
type: "Other",
calories: 375,
fat: 0.0,
carbs: 94,
protein: 0.0,
sodium: 50,
calcium: 0,
iron: 0,
},
{
name: "Lollipop",
type: "Other",
calories: 392,
fat: 0.2,
carbs: 98,
protein: 0.0,
sodium: 38,
calcium: 0,
iron: 2,
},
{
name: "Honeycomb",
type: "Other",
calories: 408,
fat: 3.2,
carbs: 87,
protein: 6.5,
sodium: 562,
calcium: 0,
iron: 45,
},
{
name: "Donut",
type: "Pastry",
calories: 52,
fat: 25.0,
carbs: 51,
protein: 4.9,
sodium: 326,
calcium: 2,
iron: 22,
},
{
name: "KitKat",
type: "Other",
calories: 16,
fat: 6.0,
carbs: 65,
protein: 7.0,
sodium: 54,
calcium: 12,
iron: 6,
},
];
export const dessertColumns = Object.keys(desserts[0]) as readonly DessertKey[];
Selectable Rows with Radio
If only one row can be selected at a time, the TableRadio
component can be
used instead.
"use client";
import { Form } from "@react-md/core/form/Form";
import { Table } from "@react-md/core/table/Table";
import { TableBody } from "@react-md/core/table/TableBody";
import { TableCell } from "@react-md/core/table/TableCell";
import { TableContainer } from "@react-md/core/table/TableContainer";
import { TableHeader } from "@react-md/core/table/TableHeader";
import { TableRadio } from "@react-md/core/table/TableRadio";
import { TableRow } from "@react-md/core/table/TableRow";
import { type ReactElement, useState } from "react";
export default function TableRadioExample(): ReactElement {
const [value, setValue] = useState<string | null>(null);
return (
<TableContainer>
<Form>
<Table fullWidth>
<TableHeader>
<TableRow>
<TableCell header={false} />
{columns.map((name, i) => (
<TableCell key={name} grow={i === 0}>
{name}
</TableCell>
))}
</TableRow>
</TableHeader>
<TableBody hAlign="right">
{desserts.map((dessert) => {
const {
name,
type,
calories,
fat,
carbs,
protein,
sodium,
calcium,
iron,
} = dessert;
const selected = value === name;
const onChange = (): void => {
setValue((prevValue) => {
if (name === prevValue) {
return null;
}
return name;
});
};
return (
<TableRow
key={name}
onClick={onChange}
selected={selected}
clickable
>
<TableRadio
name="selections"
checked={selected}
onChange={onChange}
/>
<TableCell hAlign="left">{name}</TableCell>
<TableCell>{type}</TableCell>
<TableCell>{calories}</TableCell>
<TableCell>{fat}</TableCell>
<TableCell>{carbs}</TableCell>
<TableCell>{protein}</TableCell>
<TableCell>{sodium}</TableCell>
<TableCell>{calcium}</TableCell>
<TableCell>{iron}</TableCell>
</TableRow>
);
})}
</TableBody>
</Table>
</Form>
</TableContainer>
);
}
const columns = [
"Dessert (100g serving)",
"Type",
"Calories",
"Fat (g)",
"Carbs (g)",
"Protein (g)",
"Sodium (mg)",
"Calcium (mg)",
"Icon (mg)",
] as const;
export interface Dessert {
name: string;
calories: number;
fat: number;
carbs: number;
protein: number;
sodium: number;
calcium: number;
iron: number;
type: "Ice cream" | "Pastry" | "Other";
}
export type DessertKey = keyof Dessert;
export const desserts: readonly Dessert[] = [
{
name: "Frozen yogurt",
type: "Ice cream",
calories: 159,
fat: 6.0,
carbs: 24,
protein: 4.0,
sodium: 87,
calcium: 14,
iron: 1,
},
{
name: "Ice cream sandwich",
type: "Ice cream",
calories: 237,
fat: 9.0,
carbs: 37,
protein: 4.3,
sodium: 129,
calcium: 8,
iron: 1,
},
{
name: "Eclair",
type: "Pastry",
calories: 262,
fat: 16.0,
carbs: 37,
protein: 6.0,
sodium: 337,
calcium: 6,
iron: 7,
},
{
name: "Cupcake",
type: "Pastry",
calories: 305,
fat: 3.7,
carbs: 67,
protein: 4.3,
sodium: 413,
calcium: 3,
iron: 8,
},
{
name: "Gingerbread",
type: "Pastry",
calories: 356,
fat: 16.0,
carbs: 49,
protein: 3.9,
sodium: 327,
calcium: 7,
iron: 16,
},
{
name: "Jelly bean",
type: "Other",
calories: 375,
fat: 0.0,
carbs: 94,
protein: 0.0,
sodium: 50,
calcium: 0,
iron: 0,
},
{
name: "Lollipop",
type: "Other",
calories: 392,
fat: 0.2,
carbs: 98,
protein: 0.0,
sodium: 38,
calcium: 0,
iron: 2,
},
{
name: "Honeycomb",
type: "Other",
calories: 408,
fat: 3.2,
carbs: 87,
protein: 6.5,
sodium: 562,
calcium: 0,
iron: 45,
},
{
name: "Donut",
type: "Pastry",
calories: 52,
fat: 25.0,
carbs: 51,
protein: 4.9,
sodium: 326,
calcium: 2,
iron: 22,
},
{
name: "KitKat",
type: "Other",
calories: 16,
fat: 6.0,
carbs: 65,
protein: 7.0,
sodium: 54,
calcium: 12,
iron: 6,
},
];
export const dessertColumns = Object.keys(desserts[0]) as readonly DessertKey[];
Updating Selected Row Color
The selected background color defaults to
core.interaction-get-var(selected-background-color). This can be
configured by the core.$table-row-selected-color Sass variable or the
--rmd-table-selected-background-color
custom property.
If the text color and hover colors also need to change while selected, it is
recommended to just add a custom className
while selected instead. Here's a
quick example of using the primary color while selected.
Cell 1 | Cell 2 |
Cell 1 | Cell 2 |
Cell 1 | Cell 2 |
Sortable Columns
To create a sortable header cell, provide the aria-sort
prop to a TableCell
as one of the following values:
"ascending"
- The data has been sorted in ascending order. So A-z, 0-9, and earlier dates before later dates."descending"
The data has been sorted in descending order. So z-A, 9-0, and later dates before earlier dates."other"
- The data has been sorted in another programmatic order."none"
- The data has not been sorted ("aria-sort" default)
When the aria-sort
prop has been set to one of these values, the cell will
automatically update the children to be rendered within a button element so that
it can be tab-focused and clickable for keyboard users. However when the sort
behavior has been set to none
, only the button element will be rendered
without the current sort icon to show that it is not currently sorted, but can
be.
Cupcake | Pastry | 305 | 3.7 | 67 | 4.3 | 413 | 3 | 8 |
Donut | Pastry | 52 | 25 | 51 | 4.9 | 326 | 2 | 22 |
Eclair | Pastry | 262 | 16 | 37 | 6 | 337 | 6 | 7 |
Frozen yogurt | Ice cream | 159 | 6 | 24 | 4 | 87 | 14 | 1 |
Gingerbread | Pastry | 356 | 16 | 49 | 3.9 | 327 | 7 | 16 |
Honeycomb | Other | 408 | 3.2 | 87 | 6.5 | 562 | 0 | 45 |
Ice cream sandwich | Ice cream | 237 | 9 | 37 | 4.3 | 129 | 8 | 1 |
Jelly bean | Other | 375 | 0 | 94 | 0 | 50 | 0 | 0 |
KitKat | Other | 16 | 6 | 65 | 7 | 54 | 12 | 6 |
Lollipop | Other | 392 | 0.2 | 98 | 0 | 38 | 0 | 2 |
"use client";
import { cssUtils } from "@react-md/core/cssUtils";
import { Table } from "@react-md/core/table/Table";
import { TableBody } from "@react-md/core/table/TableBody";
import { TableCell } from "@react-md/core/table/TableCell";
import { TableContainer } from "@react-md/core/table/TableContainer";
import { TableHeader } from "@react-md/core/table/TableHeader";
import { TableRow } from "@react-md/core/table/TableRow";
import { type SortOrder } from "@react-md/core/table/types";
import { type ReactElement, useState } from "react";
export default function SortableColumnsExample(): ReactElement {
const { data, sortKey, sortOrder, update } = useSortedColumns();
return (
<TableContainer>
<Table fullWidth>
<TableHeader>
<TableRow>
{dessertColumns.map((name, i) => (
<TableCell
key={name}
aria-sort={name === sortKey ? sortOrder : "none"}
onClick={() => {
update(name);
}}
grow={i === 0}
contentProps={{
className: cssUtils({ textTransform: "capitalize" }),
}}
>
{name}
</TableCell>
))}
</TableRow>
</TableHeader>
<TableBody>
{data.map((dessert) => (
<TableRow key={dessert.name}>
{dessertColumns.map((key) => {
const value = dessert[key];
return (
<TableCell
key={key}
grow={key === "name"}
hAlign={value === "number" ? "right" : undefined}
>
{value}
</TableCell>
);
})}
</TableRow>
))}
</TableBody>
</Table>
</TableContainer>
);
}
/**
* A custom sort function for the list of desserts.
*/
const sort = (key: DessertKey, ascending: boolean): readonly Dessert[] => {
const sorted = desserts.slice();
sorted.sort((a, b) => {
const aValue = a[key];
const bValue = b[key];
const value =
typeof aValue === "number"
? aValue - (bValue as number)
: aValue.localeCompare(bValue as string);
return value * (ascending ? 1 : -1);
});
return sorted;
};
interface SortState {
data: readonly Dessert[];
sortKey: DessertKey;
sortOrder: SortOrder;
}
interface SortedColumnsHookResult extends SortState {
update: (sortKey: DessertKey) => void;
}
function useSortedColumns(): SortedColumnsHookResult {
const [state, setState] = useState<SortState>(() => ({
data: sort("name", true),
sortKey: "name",
sortOrder: "ascending",
}));
const update = (sortKey: DessertKey): void => {
setState((prevState) => {
const prevSortKey = prevState.sortKey;
const prevSortOrder = prevState.sortOrder;
let sortOrder: SortOrder;
if (sortKey === prevSortKey) {
// it's the same column, so toggle the sort order
sortOrder = prevSortOrder === "ascending" ? "descending" : "ascending";
} else {
// it's a new column to sort by, so default to ascending for the name column
// but descending for all the rest.
sortOrder = sortKey === "name" ? "ascending" : "descending";
}
return {
data: sort(sortKey, sortOrder === "ascending"),
sortKey,
sortOrder,
};
});
};
return {
...state,
update,
};
}
export interface Dessert {
name: string;
calories: number;
fat: number;
carbs: number;
protein: number;
sodium: number;
calcium: number;
iron: number;
type: "Ice cream" | "Pastry" | "Other";
}
export type DessertKey = keyof Dessert;
export const desserts: readonly Dessert[] = [
{
name: "Frozen yogurt",
type: "Ice cream",
calories: 159,
fat: 6.0,
carbs: 24,
protein: 4.0,
sodium: 87,
calcium: 14,
iron: 1,
},
{
name: "Ice cream sandwich",
type: "Ice cream",
calories: 237,
fat: 9.0,
carbs: 37,
protein: 4.3,
sodium: 129,
calcium: 8,
iron: 1,
},
{
name: "Eclair",
type: "Pastry",
calories: 262,
fat: 16.0,
carbs: 37,
protein: 6.0,
sodium: 337,
calcium: 6,
iron: 7,
},
{
name: "Cupcake",
type: "Pastry",
calories: 305,
fat: 3.7,
carbs: 67,
protein: 4.3,
sodium: 413,
calcium: 3,
iron: 8,
},
{
name: "Gingerbread",
type: "Pastry",
calories: 356,
fat: 16.0,
carbs: 49,
protein: 3.9,
sodium: 327,
calcium: 7,
iron: 16,
},
{
name: "Jelly bean",
type: "Other",
calories: 375,
fat: 0.0,
carbs: 94,
protein: 0.0,
sodium: 50,
calcium: 0,
iron: 0,
},
{
name: "Lollipop",
type: "Other",
calories: 392,
fat: 0.2,
carbs: 98,
protein: 0.0,
sodium: 38,
calcium: 0,
iron: 2,
},
{
name: "Honeycomb",
type: "Other",
calories: 408,
fat: 3.2,
carbs: 87,
protein: 6.5,
sodium: 562,
calcium: 0,
iron: 45,
},
{
name: "Donut",
type: "Pastry",
calories: 52,
fat: 25.0,
carbs: 51,
protein: 4.9,
sodium: 326,
calcium: 2,
iron: 22,
},
{
name: "KitKat",
type: "Other",
calories: 16,
fat: 6.0,
carbs: 65,
protein: 7.0,
sodium: 54,
calcium: 12,
iron: 6,
},
];
export const dessertColumns = Object.keys(desserts[0]) as readonly DessertKey[];
Customizing Sort Icon
The sortable TableCell
component will use the
sort icon from the ICON_CONFIG
by default
but can also be configured by providing the sortIcon
prop.
The sort icon can also be placed after the children by enabling the
sortIconAfter
prop and disable the rotation transition by enabling
disableTransition
to the iconRotatorProps
.
import { Table } from "@react-md/core/table/Table";
import { TableCell } from "@react-md/core/table/TableCell";
import { TableContainer } from "@react-md/core/table/TableContainer";
import { TableHeader } from "@react-md/core/table/TableHeader";
import { TableRow } from "@react-md/core/table/TableRow";
import { type SortOrder } from "@react-md/core/table/types";
import { useToggle } from "@react-md/core/useToggle";
import ChevronLeftIcon from "@react-md/material-icons/ChevronLeftIcon";
import { type ReactElement } from "react";
export default function CustomizingSortIconExample(): ReactElement {
const { toggled, toggle } = useToggle();
const sort: SortOrder = toggled ? "ascending" : "descending";
return (
<TableContainer>
<Table>
<TableHeader>
<TableRow>
<TableCell aria-sort={sort} sortIconAfter onClick={toggle}>
Sort Icon After
</TableCell>
<TableCell
aria-sort={sort}
sortIcon={<ChevronLeftIcon />}
onClick={toggle}
>
Custom Sort Icon
</TableCell>
<TableCell
aria-sort={sort}
onClick={toggle}
iconRotatorProps={{
disableTransition: true,
}}
>
Disable Rotate Transition
</TableCell>
</TableRow>
</TableHeader>
</Table>
</TableContainer>
);
}
Sticky Tables
Tables within react-md
can be updated to have sticky headers, footers, and
columns by using
sticky positioning.
When an element has position: sticky
set, it will be fixed within the
closest scroll container based on the top
, right
, bottom
, and left
properties. If there are no parent elements that have overflow: auto
or
overflow: scroll
, the sticky elements can be positioned relative to the
entire document.
Container Based Sticky Table
To create a sticky TableHeader
or TableFooter
, use the StickyTableSection
component with type="header"
or type="footer"
which will add top: 0
and
bottom: 0
as the sticky positioning. This will make it so the header and
footer are stuck to the top and bottom of the TableContainer
component.
Header 1 | Header 2 |
---|---|
Row 1 Cell 1 | Row 1 Cell 2 |
Row 2 Cell 1 | Row 2 Cell 2 |
Row 3 Cell 1 | Row 3 Cell 2 |
Row 4 Cell 1 | Row 4 Cell 2 |
Row 5 Cell 1 | Row 5 Cell 2 |
Row 6 Cell 1 | Row 6 Cell 2 |
Row 7 Cell 1 | Row 7 Cell 2 |
Row 8 Cell 1 | Row 8 Cell 2 |
Row 9 Cell 1 | Row 9 Cell 2 |
Row 10 Cell 1 | Row 10 Cell 2 |
Row 11 Cell 1 | Row 11 Cell 2 |
Row 12 Cell 1 | Row 12 Cell 2 |
Row 13 Cell 1 | Row 13 Cell 2 |
Row 14 Cell 1 | Row 14 Cell 2 |
Row 15 Cell 1 | Row 15 Cell 2 |
Row 16 Cell 1 | Row 16 Cell 2 |
Row 17 Cell 1 | Row 17 Cell 2 |
Row 18 Cell 1 | Row 18 Cell 2 |
Row 19 Cell 1 | Row 19 Cell 2 |
Row 20 Cell 1 | Row 20 Cell 2 |
Content |
Viewport Based Sticky Table
To create a sticky TableHeader
and TableFooter
relative to the viewport, do
not wrap the Table
with the TableContainer
and ensure no parent elements
have overflow: auto
set. If there is a fixed header in the app, the header
will also need to update it's position so it is stuck below that header. This
can be done by updating the --rmd-table-sticky-header
custom property or
setting the top
style.
Header 1 | Header 2 | ||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Row 1 Cell 1 | Row 1 Cell 2 | ||||||||||||||||||||||||||||||||||||||
Row 2 Cell 1 | Row 2 Cell 2 | ||||||||||||||||||||||||||||||||||||||
Row 3 Cell 1 | Row 3 Cell 2 | ||||||||||||||||||||||||||||||||||||||
Row 4 Cell 1 | Row 4 Cell 2 | ||||||||||||||||||||||||||||||||||||||
Row 5 Cell 1 | Row 5 Cell 2 | ||||||||||||||||||||||||||||||||||||||
Row 6 Cell 1 | Row 6 Cell 2 | ||||||||||||||||||||||||||||||||||||||
Row 7 Cell 1 | Row 7 Cell 2 | ||||||||||||||||||||||||||||||||||||||
Row 8 Cell 1 | Row 8 Cell 2 | ||||||||||||||||||||||||||||||||||||||
Row 9 Cell 1 | Row 9 Cell 2 | ||||||||||||||||||||||||||||||||||||||
Row 10 Cell 1 | Row 10 Cell 2 | ||||||||||||||||||||||||||||||||||||||
Row 11 Cell 1 | Row 11 Cell 2 | ||||||||||||||||||||||||||||||||||||||
Row 12 Cell 1 | Row 12 Cell 2 | ||||||||||||||||||||||||||||||||||||||
Row 13 Cell 1 | Row 13 Cell 2 | ||||||||||||||||||||||||||||||||||||||
Row 14 Cell 1 | Row 14 Cell 2 | ||||||||||||||||||||||||||||||||||||||
Row 15 Cell 1 | Row 15 Cell 2 | ||||||||||||||||||||||||||||||||||||||
Row 16 Cell 1 | Row 16 Cell 2 | ||||||||||||||||||||||||||||||||||||||
Row 17 Cell 1 | Row 17 Cell 2 | ||||||||||||||||||||||||||||||||||||||
Row 18 Cell 1 | Row 18 Cell 2 | ||||||||||||||||||||||||||||||||||||||
Row 19 Cell 1 | Row 19 Cell 2 | ||||||||||||||||||||||||||||||||||||||
Row 20 Cell 1 | Row 20 Cell 2 | ||||||||||||||||||||||||||||||||||||||
Row 21 Cell 1 | Row 21 Cell 2 | ||||||||||||||||||||||||||||||||||||||
Row 22 Cell 1 | Row 22 Cell 2 | ||||||||||||||||||||||||||||||||||||||
Row 23 Cell 1 | Row 23 Cell 2 | ||||||||||||||||||||||||||||||||||||||
Row 24 Cell 1 | Row 24 Cell 2 | ||||||||||||||||||||||||||||||||||||||
Row 25 Cell 1 | Row 25 Cell 2 | ||||||||||||||||||||||||||||||||||||||
Row 26 Cell 1 | Row 26 Cell 2 | ||||||||||||||||||||||||||||||||||||||
Row 27 Cell 1 | Row 27 Cell 2 | ||||||||||||||||||||||||||||||||||||||
Row 28 Cell 1 | Row 28 Cell 2 | ||||||||||||||||||||||||||||||||||||||
Row 29 Cell 1 | Row 29 Cell 2 | ||||||||||||||||||||||||||||||||||||||
Row 30 Cell 1 | Row 30 Cell 2 | ||||||||||||||||||||||||||||||||||||||
Row 31 Cell 1 | Row 31 Cell 2 | ||||||||||||||||||||||||||||||||||||||
Row 32 Cell 1 | Row 32 Cell 2 | ||||||||||||||||||||||||||||||||||||||
Row 33 Cell 1 | Row 33 Cell 2 | ||||||||||||||||||||||||||||||||||||||
Row 34 Cell 1 | Row 34 Cell 2 | ||||||||||||||||||||||||||||||||||||||
Row 35 Cell 1 | Row 35 Cell 2 | ||||||||||||||||||||||||||||||||||||||
Row 36 Cell 1 | Row 36 Cell 2 | ||||||||||||||||||||||||||||||||||||||
Row 37 Cell 1 | Row 37 Cell 2 | ||||||||||||||||||||||||||||||||||||||
Row 38 Cell 1 | Row 38 Cell 2 | ||||||||||||||||||||||||||||||||||||||
Row 39 Cell 1 | Row 39 Cell 2 | ||||||||||||||||||||||||||||||||||||||
Row 40 Cell 1 | Row 40 Cell 2 | ||||||||||||||||||||||||||||||||||||||
Footer |
Sticky Columns Example
A column of TableCell
can also become sticky horizontally by enabling the
sticky
prop on each TableCell
in that column. It defaults to using left: 0
(right: 0
when RTL) but can be configured by the --rmd-table-sticky-cell
custom property.
This example will showcase a sticky checkbox cell followed by a sticky row header cell with sticky headers and footers.
Header 1 | Header 2 | Header 3 | Header 4 | Header 5 | Header 6 | Header 7 | Header 8 | Header 9 | Header 10 | Header 11 | Header 12 | Header 13 | Header 14 | Header 15 | Header 16 | Header 17 | Header 18 | Header 19 | Header 20 | ||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Row Header | Cell 1 - 1 | Cell 1 - 2 | Cell 1 - 3 | Cell 1 - 4 | Cell 1 - 5 | Cell 1 - 6 | Cell 1 - 7 | Cell 1 - 8 | Cell 1 - 9 | Cell 1 - 10 | Cell 1 - 11 | Cell 1 - 12 | Cell 1 - 13 | Cell 1 - 14 | Cell 1 - 15 | Cell 1 - 16 | Cell 1 - 17 | Cell 1 - 18 | Cell 1 - 19 | Cell 1 - 20 | |
Row Header | Cell 2 - 1 | Cell 2 - 2 | Cell 2 - 3 | Cell 2 - 4 | Cell 2 - 5 | Cell 2 - 6 | Cell 2 - 7 | Cell 2 - 8 | Cell 2 - 9 | Cell 2 - 10 | Cell 2 - 11 | Cell 2 - 12 | Cell 2 - 13 | Cell 2 - 14 | Cell 2 - 15 | Cell 2 - 16 | Cell 2 - 17 | Cell 2 - 18 | Cell 2 - 19 | Cell 2 - 20 | |
Row Header | Cell 3 - 1 | Cell 3 - 2 | Cell 3 - 3 | Cell 3 - 4 | Cell 3 - 5 | Cell 3 - 6 | Cell 3 - 7 | Cell 3 - 8 | Cell 3 - 9 | Cell 3 - 10 | Cell 3 - 11 | Cell 3 - 12 | Cell 3 - 13 | Cell 3 - 14 | Cell 3 - 15 | Cell 3 - 16 | Cell 3 - 17 | Cell 3 - 18 | Cell 3 - 19 | Cell 3 - 20 | |
Row Header | Cell 4 - 1 | Cell 4 - 2 | Cell 4 - 3 | Cell 4 - 4 | Cell 4 - 5 | Cell 4 - 6 | Cell 4 - 7 | Cell 4 - 8 | Cell 4 - 9 | Cell 4 - 10 | Cell 4 - 11 | Cell 4 - 12 | Cell 4 - 13 | Cell 4 - 14 | Cell 4 - 15 | Cell 4 - 16 | Cell 4 - 17 | Cell 4 - 18 | Cell 4 - 19 | Cell 4 - 20 | |
Row Header | Cell 5 - 1 | Cell 5 - 2 | Cell 5 - 3 | Cell 5 - 4 | Cell 5 - 5 | Cell 5 - 6 | Cell 5 - 7 | Cell 5 - 8 | Cell 5 - 9 | Cell 5 - 10 | Cell 5 - 11 | Cell 5 - 12 | Cell 5 - 13 | Cell 5 - 14 | Cell 5 - 15 | Cell 5 - 16 | Cell 5 - 17 | Cell 5 - 18 | Cell 5 - 19 | Cell 5 - 20 | |
Row Header | Cell 6 - 1 | Cell 6 - 2 | Cell 6 - 3 | Cell 6 - 4 | Cell 6 - 5 | Cell 6 - 6 | Cell 6 - 7 | Cell 6 - 8 | Cell 6 - 9 | Cell 6 - 10 | Cell 6 - 11 | Cell 6 - 12 | Cell 6 - 13 | Cell 6 - 14 | Cell 6 - 15 | Cell 6 - 16 | Cell 6 - 17 | Cell 6 - 18 | Cell 6 - 19 | Cell 6 - 20 | |
Row Header | Cell 7 - 1 | Cell 7 - 2 | Cell 7 - 3 | Cell 7 - 4 | Cell 7 - 5 | Cell 7 - 6 | Cell 7 - 7 | Cell 7 - 8 | Cell 7 - 9 | Cell 7 - 10 | Cell 7 - 11 | Cell 7 - 12 | Cell 7 - 13 | Cell 7 - 14 | Cell 7 - 15 | Cell 7 - 16 | Cell 7 - 17 | Cell 7 - 18 | Cell 7 - 19 | Cell 7 - 20 | |
Row Header | Cell 8 - 1 | Cell 8 - 2 | Cell 8 - 3 | Cell 8 - 4 | Cell 8 - 5 | Cell 8 - 6 | Cell 8 - 7 | Cell 8 - 8 | Cell 8 - 9 | Cell 8 - 10 | Cell 8 - 11 | Cell 8 - 12 | Cell 8 - 13 | Cell 8 - 14 | Cell 8 - 15 | Cell 8 - 16 | Cell 8 - 17 | Cell 8 - 18 | Cell 8 - 19 | Cell 8 - 20 | |
Row Header | Cell 9 - 1 | Cell 9 - 2 | Cell 9 - 3 | Cell 9 - 4 | Cell 9 - 5 | Cell 9 - 6 | Cell 9 - 7 | Cell 9 - 8 | Cell 9 - 9 | Cell 9 - 10 | Cell 9 - 11 | Cell 9 - 12 | Cell 9 - 13 | Cell 9 - 14 | Cell 9 - 15 | Cell 9 - 16 | Cell 9 - 17 | Cell 9 - 18 | Cell 9 - 19 | Cell 9 - 20 | |
Row Header | Cell 10 - 1 | Cell 10 - 2 | Cell 10 - 3 | Cell 10 - 4 | Cell 10 - 5 | Cell 10 - 6 | Cell 10 - 7 | Cell 10 - 8 | Cell 10 - 9 | Cell 10 - 10 | Cell 10 - 11 | Cell 10 - 12 | Cell 10 - 13 | Cell 10 - 14 | Cell 10 - 15 | Cell 10 - 16 | Cell 10 - 17 | Cell 10 - 18 | Cell 10 - 19 | Cell 10 - 20 | |
Row Header | Cell 11 - 1 | Cell 11 - 2 | Cell 11 - 3 | Cell 11 - 4 | Cell 11 - 5 | Cell 11 - 6 | Cell 11 - 7 | Cell 11 - 8 | Cell 11 - 9 | Cell 11 - 10 | Cell 11 - 11 | Cell 11 - 12 | Cell 11 - 13 | Cell 11 - 14 | Cell 11 - 15 | Cell 11 - 16 | Cell 11 - 17 | Cell 11 - 18 | Cell 11 - 19 | Cell 11 - 20 | |
Row Header | Cell 12 - 1 | Cell 12 - 2 | Cell 12 - 3 | Cell 12 - 4 | Cell 12 - 5 | Cell 12 - 6 | Cell 12 - 7 | Cell 12 - 8 | Cell 12 - 9 | Cell 12 - 10 | Cell 12 - 11 | Cell 12 - 12 | Cell 12 - 13 | Cell 12 - 14 | Cell 12 - 15 | Cell 12 - 16 | Cell 12 - 17 | Cell 12 - 18 | Cell 12 - 19 | Cell 12 - 20 | |
Row Header | Cell 13 - 1 | Cell 13 - 2 | Cell 13 - 3 | Cell 13 - 4 | Cell 13 - 5 | Cell 13 - 6 | Cell 13 - 7 | Cell 13 - 8 | Cell 13 - 9 | Cell 13 - 10 | Cell 13 - 11 | Cell 13 - 12 | Cell 13 - 13 | Cell 13 - 14 | Cell 13 - 15 | Cell 13 - 16 | Cell 13 - 17 | Cell 13 - 18 | Cell 13 - 19 | Cell 13 - 20 | |
Row Header | Cell 14 - 1 | Cell 14 - 2 | Cell 14 - 3 | Cell 14 - 4 | Cell 14 - 5 | Cell 14 - 6 | Cell 14 - 7 | Cell 14 - 8 | Cell 14 - 9 | Cell 14 - 10 | Cell 14 - 11 | Cell 14 - 12 | Cell 14 - 13 | Cell 14 - 14 | Cell 14 - 15 | Cell 14 - 16 | Cell 14 - 17 | Cell 14 - 18 | Cell 14 - 19 | Cell 14 - 20 | |
Row Header | Cell 15 - 1 | Cell 15 - 2 | Cell 15 - 3 | Cell 15 - 4 | Cell 15 - 5 | Cell 15 - 6 | Cell 15 - 7 | Cell 15 - 8 | Cell 15 - 9 | Cell 15 - 10 | Cell 15 - 11 | Cell 15 - 12 | Cell 15 - 13 | Cell 15 - 14 | Cell 15 - 15 | Cell 15 - 16 | Cell 15 - 17 | Cell 15 - 18 | Cell 15 - 19 | Cell 15 - 20 | |
Row Header | Cell 16 - 1 | Cell 16 - 2 | Cell 16 - 3 | Cell 16 - 4 | Cell 16 - 5 | Cell 16 - 6 | Cell 16 - 7 | Cell 16 - 8 | Cell 16 - 9 | Cell 16 - 10 | Cell 16 - 11 | Cell 16 - 12 | Cell 16 - 13 | Cell 16 - 14 | Cell 16 - 15 | Cell 16 - 16 | Cell 16 - 17 | Cell 16 - 18 | Cell 16 - 19 | Cell 16 - 20 | |
Row Header | Cell 17 - 1 | Cell 17 - 2 | Cell 17 - 3 | Cell 17 - 4 | Cell 17 - 5 | Cell 17 - 6 | Cell 17 - 7 | Cell 17 - 8 | Cell 17 - 9 | Cell 17 - 10 | Cell 17 - 11 | Cell 17 - 12 | Cell 17 - 13 | Cell 17 - 14 | Cell 17 - 15 | Cell 17 - 16 | Cell 17 - 17 | Cell 17 - 18 | Cell 17 - 19 | Cell 17 - 20 | |
Row Header | Cell 18 - 1 | Cell 18 - 2 | Cell 18 - 3 | Cell 18 - 4 | Cell 18 - 5 | Cell 18 - 6 | Cell 18 - 7 | Cell 18 - 8 | Cell 18 - 9 | Cell 18 - 10 | Cell 18 - 11 | Cell 18 - 12 | Cell 18 - 13 | Cell 18 - 14 | Cell 18 - 15 | Cell 18 - 16 | Cell 18 - 17 | Cell 18 - 18 | Cell 18 - 19 | Cell 18 - 20 | |
Row Header | Cell 19 - 1 | Cell 19 - 2 | Cell 19 - 3 | Cell 19 - 4 | Cell 19 - 5 | Cell 19 - 6 | Cell 19 - 7 | Cell 19 - 8 | Cell 19 - 9 | Cell 19 - 10 | Cell 19 - 11 | Cell 19 - 12 | Cell 19 - 13 | Cell 19 - 14 | Cell 19 - 15 | Cell 19 - 16 | Cell 19 - 17 | Cell 19 - 18 | Cell 19 - 19 | Cell 19 - 20 | |
Row Header | Cell 20 - 1 | Cell 20 - 2 | Cell 20 - 3 | Cell 20 - 4 | Cell 20 - 5 | Cell 20 - 6 | Cell 20 - 7 | Cell 20 - 8 | Cell 20 - 9 | Cell 20 - 10 | Cell 20 - 11 | Cell 20 - 12 | Cell 20 - 13 | Cell 20 - 14 | Cell 20 - 15 | Cell 20 - 16 | Cell 20 - 17 | Cell 20 - 18 | Cell 20 - 19 | Cell 20 - 20 | |
Row Header | Cell 21 - 1 | Cell 21 - 2 | Cell 21 - 3 | Cell 21 - 4 | Cell 21 - 5 | Cell 21 - 6 | Cell 21 - 7 | Cell 21 - 8 | Cell 21 - 9 | Cell 21 - 10 | Cell 21 - 11 | Cell 21 - 12 | Cell 21 - 13 | Cell 21 - 14 | Cell 21 - 15 | Cell 21 - 16 | Cell 21 - 17 | Cell 21 - 18 | Cell 21 - 19 | Cell 21 - 20 | |
Row Header | Cell 22 - 1 | Cell 22 - 2 | Cell 22 - 3 | Cell 22 - 4 | Cell 22 - 5 | Cell 22 - 6 | Cell 22 - 7 | Cell 22 - 8 | Cell 22 - 9 | Cell 22 - 10 | Cell 22 - 11 | Cell 22 - 12 | Cell 22 - 13 | Cell 22 - 14 | Cell 22 - 15 | Cell 22 - 16 | Cell 22 - 17 | Cell 22 - 18 | Cell 22 - 19 | Cell 22 - 20 | |
Row Header | Cell 23 - 1 | Cell 23 - 2 | Cell 23 - 3 | Cell 23 - 4 | Cell 23 - 5 | Cell 23 - 6 | Cell 23 - 7 | Cell 23 - 8 | Cell 23 - 9 | Cell 23 - 10 | Cell 23 - 11 | Cell 23 - 12 | Cell 23 - 13 | Cell 23 - 14 | Cell 23 - 15 | Cell 23 - 16 | Cell 23 - 17 | Cell 23 - 18 | Cell 23 - 19 | Cell 23 - 20 | |
Row Header | Cell 24 - 1 | Cell 24 - 2 | Cell 24 - 3 | Cell 24 - 4 | Cell 24 - 5 | Cell 24 - 6 | Cell 24 - 7 | Cell 24 - 8 | Cell 24 - 9 | Cell 24 - 10 | Cell 24 - 11 | Cell 24 - 12 | Cell 24 - 13 | Cell 24 - 14 | Cell 24 - 15 | Cell 24 - 16 | Cell 24 - 17 | Cell 24 - 18 | Cell 24 - 19 | Cell 24 - 20 | |
Row Header | Cell 25 - 1 | Cell 25 - 2 | Cell 25 - 3 | Cell 25 - 4 | Cell 25 - 5 | Cell 25 - 6 | Cell 25 - 7 | Cell 25 - 8 | Cell 25 - 9 | Cell 25 - 10 | Cell 25 - 11 | Cell 25 - 12 | Cell 25 - 13 | Cell 25 - 14 | Cell 25 - 15 | Cell 25 - 16 | Cell 25 - 17 | Cell 25 - 18 | Cell 25 - 19 | Cell 25 - 20 | |
Row Header | Cell 26 - 1 | Cell 26 - 2 | Cell 26 - 3 | Cell 26 - 4 | Cell 26 - 5 | Cell 26 - 6 | Cell 26 - 7 | Cell 26 - 8 | Cell 26 - 9 | Cell 26 - 10 | Cell 26 - 11 | Cell 26 - 12 | Cell 26 - 13 | Cell 26 - 14 | Cell 26 - 15 | Cell 26 - 16 | Cell 26 - 17 | Cell 26 - 18 | Cell 26 - 19 | Cell 26 - 20 | |
Row Header | Cell 27 - 1 | Cell 27 - 2 | Cell 27 - 3 | Cell 27 - 4 | Cell 27 - 5 | Cell 27 - 6 | Cell 27 - 7 | Cell 27 - 8 | Cell 27 - 9 | Cell 27 - 10 | Cell 27 - 11 | Cell 27 - 12 | Cell 27 - 13 | Cell 27 - 14 | Cell 27 - 15 | Cell 27 - 16 | Cell 27 - 17 | Cell 27 - 18 | Cell 27 - 19 | Cell 27 - 20 | |
Row Header | Cell 28 - 1 | Cell 28 - 2 | Cell 28 - 3 | Cell 28 - 4 | Cell 28 - 5 | Cell 28 - 6 | Cell 28 - 7 | Cell 28 - 8 | Cell 28 - 9 | Cell 28 - 10 | Cell 28 - 11 | Cell 28 - 12 | Cell 28 - 13 | Cell 28 - 14 | Cell 28 - 15 | Cell 28 - 16 | Cell 28 - 17 | Cell 28 - 18 | Cell 28 - 19 | Cell 28 - 20 | |
Row Header | Cell 29 - 1 | Cell 29 - 2 | Cell 29 - 3 | Cell 29 - 4 | Cell 29 - 5 | Cell 29 - 6 | Cell 29 - 7 | Cell 29 - 8 | Cell 29 - 9 | Cell 29 - 10 | Cell 29 - 11 | Cell 29 - 12 | Cell 29 - 13 | Cell 29 - 14 | Cell 29 - 15 | Cell 29 - 16 | Cell 29 - 17 | Cell 29 - 18 | Cell 29 - 19 | Cell 29 - 20 | |
Row Header | Cell 30 - 1 | Cell 30 - 2 | Cell 30 - 3 | Cell 30 - 4 | Cell 30 - 5 | Cell 30 - 6 | Cell 30 - 7 | Cell 30 - 8 | Cell 30 - 9 | Cell 30 - 10 | Cell 30 - 11 | Cell 30 - 12 | Cell 30 - 13 | Cell 30 - 14 | Cell 30 - 15 | Cell 30 - 16 | Cell 30 - 17 | Cell 30 - 18 | Cell 30 - 19 | Cell 30 - 20 | |
Sticky Footer |
Sticky Active Styles
When the TableHeader
/TableFooter
have the sticky
prop enabled, some magic
happens behind the scenes to automatically raise the elevation for the
TableHeader
/TableFooter
when covering rows of content by scroll position.
These styles can be configured globally by the
core.$table-sticky-header-inactive-styles,
core.$table-sticky-header-active-styles,
core.$table-sticky-footer-inactive-styles, and
core.$table-sticky-footer-active-styles Sass variables.
If the styles should not be configured globally, provide a custom
stickyActiveClassName
and optionally className
to override the styling.
Header 1 | Header 2 |
---|---|
Row 1 Cell 1 | Row 1 Cell 2 |
Row 2 Cell 1 | Row 2 Cell 2 |
Row 3 Cell 1 | Row 3 Cell 2 |
Row 4 Cell 1 | Row 4 Cell 2 |
Row 5 Cell 1 | Row 5 Cell 2 |
Row 6 Cell 1 | Row 6 Cell 2 |
Row 7 Cell 1 | Row 7 Cell 2 |
Row 8 Cell 1 | Row 8 Cell 2 |
Row 9 Cell 1 | Row 9 Cell 2 |
Row 10 Cell 1 | Row 10 Cell 2 |
Row 11 Cell 1 | Row 11 Cell 2 |
Row 12 Cell 1 | Row 12 Cell 2 |
Row 13 Cell 1 | Row 13 Cell 2 |
Row 14 Cell 1 | Row 14 Cell 2 |
Row 15 Cell 1 | Row 15 Cell 2 |
Row 16 Cell 1 | Row 16 Cell 2 |
Row 17 Cell 1 | Row 17 Cell 2 |
Row 18 Cell 1 | Row 18 Cell 2 |
Row 19 Cell 1 | Row 19 Cell 2 |
Row 20 Cell 1 | Row 20 Cell 2 |
Content |
Disable Sticky Active Styles
The sticky active styles can also be disabled by enabling the
disableStickyStyles
or using the TableHeader
/TableFooter
components
instead with the sticky
prop enabled.
Header 1 | Header 2 |
---|---|
Row 1 Cell 1 | Row 1 Cell 2 |
Row 2 Cell 1 | Row 2 Cell 2 |
Row 3 Cell 1 | Row 3 Cell 2 |
Row 4 Cell 1 | Row 4 Cell 2 |
Row 5 Cell 1 | Row 5 Cell 2 |
Row 6 Cell 1 | Row 6 Cell 2 |
Row 7 Cell 1 | Row 7 Cell 2 |
Row 8 Cell 1 | Row 8 Cell 2 |
Row 9 Cell 1 | Row 9 Cell 2 |
Row 10 Cell 1 | Row 10 Cell 2 |
Row 11 Cell 1 | Row 11 Cell 2 |
Row 12 Cell 1 | Row 12 Cell 2 |
Row 13 Cell 1 | Row 13 Cell 2 |
Row 14 Cell 1 | Row 14 Cell 2 |
Row 15 Cell 1 | Row 15 Cell 2 |
Row 16 Cell 1 | Row 16 Cell 2 |
Row 17 Cell 1 | Row 17 Cell 2 |
Row 18 Cell 1 | Row 18 Cell 2 |
Row 19 Cell 1 | Row 19 Cell 2 |
Row 20 Cell 1 | Row 20 Cell 2 |
Content |