Skip to content
Glint UI

Table

A static table whose columns carry the geometry every row obeys, and whose cells can hold a widget rather than only a string.

Usage

import { Table } from "@glint/components/table.slint";
import { TableAlign } from "@glint/components/table-cell.slint";
import { Tokens } from "@glint/theme/tokens.slint";
export component AppWindow inherits Window {
width: 520px;
height: 240px;
background: Tokens.color-background;
VerticalLayout {
padding: 24px;
alignment: start;
Table {
accessible-label: "Team seats";
columns: [
{ title: "Member" },
{ title: "Seats", align: TableAlign.end, width: 80px },
];
rows: [
{ cells: [{ text: "Engineering" }, { text: "24" }] },
{ cells: [{ text: "Design" }, { text: "6" }] },
];
}
}
}

columns carries the headings and the geometry every row obeys; each row’s cells line up with them by position. Naming the table is the call site’s job — accessible-label is what a screen reader announces before the rows — and caption is a descriptive title drawn under the table and announced as its description.

TableRow describes this component’s rows. TableColumn, TableCell, TableAlign and TableCellKind are shared with DataTable, while DataTable uses its own DataTableRow because its rows also carry selection state:

TypeFields
TableColumntitle, width (leave it out to share the free space), align, hidden
TableRowcells, label (what a screen reader calls the row; falls back to the first cell)
TableCellkind, text, icon, badge-variant, checked, actions

TableCellKind is what a cell draws: text (the default), badge, icon, checkbox and actions. Every kind reads text — it is the value a text cell shows, the label a badge carries, the name an icon is announced by, the label beside a checkbox and the name of an action menu’s button. A kind ignores the fields it has no use for (ADR-0026).

Rows carry no pointer handling of their own and no hover tint, on purpose: a row that lights up under the pointer is promising an interaction this table does not have. Reach for DataTable when the rows themselves must sort, paginate or act.

Examples

Column widths and alignment

A column with a width keeps it; one without shares the free space equally with the other unsized columns. align decides where the cells sit inside that width — numbers read right, labels read left, and a lone control reads centered.

Widget cells

A cell is a TableCell rather than a string, so a status badge, an icon, a checkbox or a per-row action menu can stand in one (ADR-0028). A checkbox cell settles its own state in rows before cell-toggled fires, and an action cell reports through cell-action with the entry that was taken.

A totals line

footer draws a row of cells under the body, in the body’s own columns. A footer shorter than the columns leaves the rest blank rather than reading past its own end, so { } is how a column is skipped. Its cells report as row -1.

A hidden column

hidden keeps a column off screen without reshaping a single row: the cells stay where they are and the column they belong to collapses to nothing. Nothing is left in the accessibility tree either — a hidden column draws no node at all.

API Reference

Properties

PropertyTypeDefaultDescription
columnsin [TableColumn]no defaultColumns, left-to-right: their headings, widths and alignment.
rowsin-out [TableRow]no defaultRow data; each row's cells line up with columns by position. in-out because a checkbox cell settles its own state here before cell-toggled fires — the model is the state, as it is for a menu row.
footerin-out [TableCell]no defaultTotals line under the body, in the body's own columns. Empty leaves it off. Its cells report as row -1.
captionin stringno defaultDescriptive title for the table, drawn under it and announced as its description.
actions-labelin string@tr("Row actions")Name an action cell's button falls back to when its cell carries no text of its own.

Callbacks

CallbackDescription
cell-toggled(int, int, bool)A checkbox cell was flipped: its row (-1 in the footer), its column and the state it now holds.
cell-action(int, int, int, int)An action cell fired: its row (-1 in the footer), its column, the entry's index and the submenu leaf's index, or -1 when the entry itself was taken.

TableRow, TableColumn, TableCell and the TableAlign / TableCellKind enums are data types rather than components; their fields are in Usage above, and the primitives every table draws them with are on DataTable’s page.

Accessibility

  • Table role. The root carries accessible-role: table and publishes accessible-item-count as the number of rows. Naming it is the call site’s — set accessible-label. caption becomes the table’s accessible-description, and the caption text under the table is silenced as a node of its own so a screen reader hears it once.
  • Rows. Slint 1.17 has a table role but no row, cell or column-header member, so each row wears list-item with its index. A row is announced by its label, which falls back to the first cell — the column a table is usually read by.
  • Cells. A cell that draws no control is a text node announced as its column then its value (“Status: Paid”), carrying the column’s position so assistive technology can navigate across a row as well as down a column. That pairing is as close to header association as the platform gets.
  • Widget cells speak for themselves. A checkbox cell announces itself a checkbox and an action cell a button, each carrying the column’s position the same way. A box with nothing written beside it is named by its column; actions-label names an action button whose cell carries no text.
  • Hidden columns leave no trace. A hidden column draws nothing at all rather than a collapsed node assistive technology would still find.
  • No row affordance. Rows take no pointer events and draw no hover tint, so nothing invites a click the table does not answer. Only a widget cell takes the pointer, and it takes it the way any control does.