DataTable
DataTable is the basic tabular-data widget in the authoring set.
Use it when users need to scan rows against shared columns: files, users, invoices, runs, and similar structured records. A table solves a different problem than a list or card grid. It trades visual warmth for fast comparison across fields.
Example
use fission::prelude::*;
use std::sync::Arc;
let node = DataTable {
id: WidgetNodeId::explicit("build_runs_table"),
columns: vec![
TableColumn {
id: "status".into(),
title: "Status".into(),
width: 120.0,
sortable: false,
},
TableColumn {
id: "branch".into(),
title: "Branch".into(),
width: 180.0,
sortable: true,
},
],
rows: vec![
TableRow {
id: "run_42".into(),
cells: vec!["Passed".into(), "main".into()],
},
],
selected_ids: view.state.selected_run_ids.clone(),
on_selection_change: Some(Arc::new(move |row_id| ActionEnvelope {
id: toggle_row_selection_id,
payload: serde_json::to_vec(&ToggleRowSelection(row_id)).unwrap(),
})),
}
.build(ctx, view);
Here the table is responsible for presentation. The reducer is responsible for which rows are selected and what selection means.
Field table
| Field | Type | Meaning | Notes / default behavior |
|---|---|---|---|
id | WidgetNodeId | Stable identity for the table instance. | Present in the public struct, but the checked-in renderer does not currently consume it internally. |
columns | Vec<TableColumn> | Column definitions in display order. | Required. Width comes from the column records. |
rows | Vec<TableRow> | Row data in display order. | Required. Each row's cells are matched to columns by index. |
selected_ids | Vec<String> | Currently selected row ids. | Controlled by app state. |
on_selection_change | Option<Arc<dyn Fn(String) -> ActionEnvelope + Send + Sync>> | Closure that builds the action for row or checkbox selection. | Called with the row id. |
How to think about tabular data here
A table works when every row shares the same shape and when columns matter more than custom per-row layout. The checked-in DataTable is intentionally simple: cells are plain strings, not arbitrary widgets. That keeps comparison easy, but it also means complex media cells, nested controls, or heavily formatted content usually want a custom table layout instead.
Selection is explicit. The widget highlights rows whose ids appear in selected_ids, and it uses the same selection callback for row presses and row checkboxes.
Current behavior and limits
Two implementation details matter today. First, the header's select-all checkbox is currently visual only. Second, TableColumn.sortable currently adds a sort indicator but no built-in sorting callback. In other words, the widget presents table affordances, but your app still owns all real sorting and bulk-selection behavior.
Specific advice
Keep column counts modest on narrow screens. If comparison is still important on mobile, consider a smaller table with fewer columns plus a drill-in detail view instead of forcing a huge horizontal matrix.
Related
TableColumn, TableRow, Pagination, and Scroll.