Row Selection
Checkbox selection for one row or many, with a select-all across every filtered page. The table owns the selected set until you pass selectedIds.
Selection Modes
selectionMode switches on a checkbox column. "multi" lets the user mark any number of rows and adds
a select-all checkbox to the header; "single" keeps one row
at a time — selecting a row clears the one before.
Select-all covers every row that matches the current search and filters, on every page — not just the rows on screen. While only part of that set is selected, the checkbox shows as indeterminate.
The selection is a set of ids, keyed by item.id with
the row's position as fallback. Sorting, paging and filtering change what is on screen, not
the set — a selected row that moves to another page stays selected. onSelectionChange reports the selected items — the rows themselves,
not their ids.
Live — select-all spans both pages
Name | Role | Department | Location | |
|---|---|---|---|---|
Emma Wilson | Staff Engineer | Platform | Berlin | |
Liam Chen | Product Designer | Design | Hamburg | |
Sofia Martinez | Engineering Manager | Platform | Munich | |
James Park | Frontend Developer | Product | Remote |
0 selected
<script>
let selected = $state([]);
</script>
<Table
{items}
{columns}
selectionMode="multi"
onSelectionChange={(items) => (selected = items)}
/>
<p>{selected.length} selected</p>A row you only show somewhere else — the master/detail pattern — is not a selection. activeRowId highlights it without bringing the checkbox column
along.
Selecting by Row Click
In "single" mode a click anywhere on the row selects it
— the checkbox is not the only target. With onRowClick or expandable rows a click already means
something else, so only the checkbox selects. rowClickSelects decides explicitly, in either mode.
Single select — click the row
Name | Role | Department | Location | |
|---|---|---|---|---|
Emma Wilson | Staff Engineer | Platform | Berlin | |
Liam Chen | Product Designer | Design | Hamburg | |
Sofia Martinez | Engineering Manager | Platform | Munich | |
James Park | Frontend Developer | Product | Remote |
<Table
{items}
{columns}
selectionMode="single"
onSelectionChange={(items) => handleSelect(items[0])}
/>Controlled Selection
The table owns the selection until you pass selectedIds — then your code does. Take it over when
the set has a life outside the table: preselected from the URL, cleared after a bulk action,
shared with another view. If all you need is a starting value, initialSelectedIds seeds the table-owned selection once;
later changes to the prop are ignored.
selectedIds drives the table; clicks keep arriving
through onSelectionChange as items, and the write-back
maps them to ids. An empty array is a valid value — nothing selected; undefined hands the selection back to the table. A
controlled selection is never written to storage — prefs.persistSelection restores only a table-owned one.
Controlled — buttons and checkboxes write the same set
Name | Role | Department | Location | |
|---|---|---|---|---|
Emma Wilson | Staff Engineer | Platform | Berlin | |
Liam Chen | Product Designer | Design | Hamburg | |
Sofia Martinez | Engineering Manager | Platform | Munich | |
James Park | Frontend Developer | Product | Remote | |
Aisha Patel | Data Scientist | Data | Berlin | |
Noah Kim | DevOps Engineer | Platform | Hamburg |
<script>
let selectedIds = $state<Array<string | number>>([]);
</script>
<Table
{items}
{columns}
selectionMode="multi"
{selectedIds}
onSelectionChange={(items) => (selectedIds = items.map((item) => item.id))}
/>
<Button onclick={() => (selectedIds = [])}>Clear selection</Button>Write every change back
WhenonSelectionChange does not feed selectedIds, clicks still change the screen, nothing warns — and the next
change to the prop throws the user's clicks away.