---
title: Table
url: "https://native-sdk.dev/docs/components/table"
docs_index: /llms.txt
lastUpdated: 2026-10-16
---

> For an index of all documentation, see [/llms.txt](/llms.txt).

Use `table` for aligned columns of text. It contains `table-row` elements, each containing `table-cell` leaves; the validator checks this nesting. Give corresponding cells matching `grow` factors to align columns.

Rows have separators and a hover highlight. Bind `selected` to highlight a row, `text-alignment="end"` to right-align numeric cells, and `on-press` to handle cell activation.

## Markup

```html
<table width="420">
  <table-row>
    <table-cell grow="1" size="sm" foreground="text_muted">Invoice</table-cell>
    <table-cell grow="1" size="sm" foreground="text_muted">Status</table-cell>
    <table-cell grow="1" size="sm" foreground="text_muted" text-alignment="end">Amount</table-cell>
  </table-row>
  <for each="invoices" as="invoice" key="id">
    <table-row selected="{invoice.id == selected_invoice}">
      <table-cell grow="1" on-press="open_invoice:{invoice.id}">{invoice.number}</table-cell>
      <table-cell grow="1">{invoice.status}</table-cell>
      <table-cell grow="1" text-alignment="end">{invoice.amount}</table-cell>
    </table-row>
  </for>
</table>
```

## Programmatic construction (Zig)

In a Zig view, the `canvas.Ui` builder constructs the same tree programmatically. The builder names differ from the markup: rows are `.data_row` and cells are `.data_cell` (the underlying widget kinds).

```zig
ui.el(.table, .{ .width = 420 }, .{
    ui.el(.data_row, .{}, .{
        ui.el(.data_cell, .{ .text = "Invoice", .grow = 1, .size = .sm, .style_tokens = .{ .foreground = .text_muted } }, .{}),
        ui.el(.data_cell, .{ .text = "Status", .grow = 1, .size = .sm, .style_tokens = .{ .foreground = .text_muted } }, .{}),
        ui.el(.data_cell, .{ .text = "Amount", .grow = 1, .size = .sm, .text_alignment = .end, .style_tokens = .{ .foreground = .text_muted } }, .{}),
    }),
    ui.el(.data_row, .{}, .{
        ui.el(.data_cell, .{ .text = "INV-001", .grow = 1, .on_press = .{ .open_invoice = 1 } }, .{}),
        ui.el(.data_cell, .{ .text = "Paid", .grow = 1 }, .{}),
        ui.el(.data_cell, .{ .text = "$250.00", .grow = 1, .text_alignment = .end }, .{}),
    }),
    ui.el(.data_row, .{ .selected = true }, .{
        ui.el(.data_cell, .{ .text = "INV-002", .grow = 1, .on_press = .{ .open_invoice = 2 } }, .{}),
        ui.el(.data_cell, .{ .text = "Pending", .grow = 1 }, .{}),
        ui.el(.data_cell, .{ .text = "$150.00", .grow = 1, .text_alignment = .end }, .{}),
    }),
})
```

Use [list](/docs/components/list) for icon rows or a single column; use a table when columns need to align.

## Attributes

| Attribute        | Description                                                                                                                                                                                                                                                                                   |
| ---------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `grow`           | Flex grow factor; give spacer one.                                                                                                                                                                                                                                                            |
| `selected`       | Selected state; often a \{a == b} equality.                                                                                                                                                                                                                                                   |
| `text-alignment` | Horizontal alignment of text content: start\|center\|end. Consumed by text (plain and wrapped), status-bar, and surface titles; controls that own their label placement (button, badge) ignore it. On a bubble's reactions child it names the pill's dock (end is the default trailing dock). |
| `on-press`       | Dispatch a Msg on press: tag or tag:\{payload}. Legal on any element — a bound press handler makes it pressable, and presses on plain text/icons inside it fall through to it (dragging still selects text).                                                                                  |

---

For a semantic overview of all documentation, see [/sitemap.md](/sitemap.md)

For an index of all available documentation, see [/llms.txt](/llms.txt)

For agent-facing discovery, including API and MCP surfaces, see [/agents.md](/agents.md)