Basic usage
Table is a set of building blocks that render a native <table>. Import the Table namespace and
compose its parts: Table.Table, Table.Head, Table.HeaderRow, Table.HeaderCell, Table.Body,
Table.Row and Table.Cell.
caption is required and describes the table content. It isn't displayed. Every Table.HeaderCell
needs a scope so screen readers can tie it to its data cells.
import {Table} from '@pleo-io/telescope'
const Heroes = () => (
<Table.Table caption="Super heroes and their real names">
<Table.Head>
<Table.HeaderRow>
<Table.HeaderCell scope="col">Super hero</Table.HeaderCell>
<Table.HeaderCell scope="col">Real name</Table.HeaderCell>
</Table.HeaderRow>
</Table.Head>
<Table.Body>
<Table.Row>
<Table.Cell>Iron Man</Table.Cell>
<Table.Cell>Tony Stark</Table.Cell>
</Table.Row>
<Table.Row>
<Table.Cell>Batman</Table.Cell>
<Table.Cell>Bruce Wayne</Table.Cell>
</Table.Row>
</Table.Body>
</Table.Table>
)Alignment
Right-align numeric columns with $textAlign on both the header and the data cells.
<Table.HeaderCell scope="col" $textAlign="right">
Amount
</Table.HeaderCell>
...
<Table.Cell $textAlign="right">1,000.00</Table.Cell>Clickable and active rows
$isClickable adds a hover state and pointer cursor. Make the row keyboard reachable with
tabIndex={0} and handle both click and Enter. $isActive outlines the row, for example
to mark the row whose details are open in a drawer.
<Table.Row
$isClickable
$isActive={selectedId === expense.id}
tabIndex={0}
onClick={() => open(expense.id)}
onKeyDown={(event) => event.key === 'Enter' && open(expense.id)}
>
<Table.Cell>{expense.merchant}</Table.Cell>
</Table.Row>Cell content with subtext
Use Table.CellContent to show a quieter second line, e.g. an email under a name. Both lines
truncate rather than wrap, so rows keep the same height with or without subtext.
<Table.Cell>
<Table.CellContent subtext="tony@stark.com">Tony Stark</Table.CellContent>
</Table.Cell>Links and actions in cells
Table.CellLink and Table.CellAction are styled for use inside a cell.
<Table.Cell>
<Table.CellLink href={`/people/${person.id}`}>{person.name}</Table.CellLink>
</Table.Cell>
<Table.Cell>
<Table.CellAction onClick={() => edit(person.id)}>Edit</Table.CellAction>
</Table.Cell>Group summary rows
Table.GroupSummaryRow renders a summary row, e.g. totals for a group. $isHighlighted gives it a
louder background.
<Table.GroupSummaryRow $isHighlighted>
<Table.Cell>3 expenses</Table.Cell>
<Table.Cell $textAlign="right">1,200.00</Table.Cell>
</Table.GroupSummaryRow>Scrolling and sticky header
Wrap the table in Table.ScrollableWrapper to scroll it within a constrained area. Pass
$stickyHeader to keep the header visible while the body scrolls.
<Table.ScrollableWrapper $stickyHeader style={{height: 400}}>
<Table.Table caption="Expenses">...</Table.Table>
</Table.ScrollableWrapper>Virtualization
When only a window of rows is rendered, pass the data index of the first rendered row as
virtualStartIndex so the zebra striping doesn't flicker while scrolling.
<Table.Table caption="Expenses" virtualStartIndex={virtualRows[0]?.index ?? 0}>
...
</Table.Table>API reference
Table.Table
| Prop | Type | Default |
|---|---|---|
caption (required)Description of the table content. Required for accessibility, but not displayed. | string | |
virtualStartIndexWhen the table is virtualized, the data index of the first rendered row. Keeps the zebra striping stable while scrolling. | enumnumber | undefined | 0 |
Table.HeaderCell
| Prop | Type | Default |
|---|---|---|
$textAlignHorizontal alignment of the cell content | enum"center" | "left" | "right" | undefined | 'left' |
$withBorderAdds a border on the right side of the cell | boolean | |
scope (required)The cells the header applies to. Required so screen readers can associate it with its data. | enum"col" | "colgroup" | "row" | "rowgroup" |
Table.Row
| Prop | Type | Default |
|---|---|---|
$isActiveOutlines the row, e.g. to mark the row whose details are open | boolean | |
$isClickableAdds a hover background and pointer cursor. Pair with | boolean |
Table.Cell
| Prop | Type | Default |
|---|---|---|
$textAlignHorizontal alignment of the cell content | enum"center" | "left" | "right" | undefined | 'left' |
$withBorderAdds a border on the right side of the cell | boolean |
Table.CellContent
| Prop | Type | Default |
|---|---|---|
subtextQuieter second line under the main content, e.g. an email under a person's name | enumnull, string, number, bigint, false, true, ReactElement<unknown, string | JSXElementConstructor<any>>, Iterable<ReactNode>, ReactPortal, Promise<AwaitedReactNode> |
Table.GroupSummaryRow
| Prop | Type | Default |
|---|---|---|
$isHighlightedGives the row a louder background, overriding the zebra striping | boolean |
Table.ScrollableWrapper
| Prop | Type | Default |
|---|---|---|
$stickyHeaderKeeps the table header visible while the body scrolls | boolean |