Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Table

The Table widget displays tabular data with columns, headers, and row selection.

Creating a Table

import { Table } from "perry/ui";

const table = Table(10, 3, (row, col) => {
  return `Row ${row}, Col ${col}`;
});

Table(rowCount, colCount, renderCell) creates a table. The render function is called for each cell and should return the text content.

Column Headers

const table = Table(100, 3, (row, col) => {
  const data = [
    ["Alice", "alice@example.com", "Admin"],
    ["Bob", "bob@example.com", "User"],
    // ...
  ];
  return data[row]?.[col] ?? "";
});

table.setColumnHeader(0, "Name");
table.setColumnHeader(1, "Email");
table.setColumnHeader(2, "Role");

Column Widths

table.setColumnWidth(0, 150);  // Name column
table.setColumnWidth(1, 250);  // Email column
table.setColumnWidth(2, 100);  // Role column

Row Selection

table.setOnRowSelect((row) => {
  console.log(`Selected row: ${row}`);
});

// Get the currently selected row
const selected = table.getSelectedRow();

Dynamic Row Count

Update the number of rows after creation:

table.updateRowCount(newCount);

Platform Notes

PlatformImplementation
macOSNSTableView + NSScrollView
WebHTML <table>
iOS/Android/Linux/WindowsStubs (pending native implementation)

Complete Example

import { App, Table, Text, VStack, State } from "perry/ui";

const selectedName = State("None");

const users = [
  { name: "Alice", email: "alice@example.com", role: "Admin" },
  { name: "Bob", email: "bob@example.com", role: "Editor" },
  { name: "Charlie", email: "charlie@example.com", role: "Viewer" },
  { name: "Diana", email: "diana@example.com", role: "Admin" },
  { name: "Eve", email: "eve@example.com", role: "Editor" },
];

App("Table Demo", () =>
  VStack([
    (() => {
      const table = Table(users.length, 3, (row, col) => {
        const user = users[row];
        if (col === 0) return user.name;
        if (col === 1) return user.email;
        return user.role;
      });

      table.setColumnHeader(0, "Name");
      table.setColumnHeader(1, "Email");
      table.setColumnHeader(2, "Role");
      table.setColumnWidth(0, 150);
      table.setColumnWidth(1, 250);
      table.setColumnWidth(2, 100);

      table.setOnRowSelect((row) => {
        selectedName.set(users[row].name);
      });

      return table;
    })(),

    Text(`Selected: ${selectedName.get()}`),
  ])
);

Next Steps