Founding price: $35, then $99 after 23:59 UTC on 4 November, then $99
Get ProMulti-select state for rows or items with toggle, shift-click range selection, select all, and the all, some and none states a header checkbox needs.
This item has no props to tune. Use the lens above to change theme, density, direction and more.
Use it for tables, file lists and galleries where people tick rows, shift-click a range, and use a header checkbox to select all.
Do not use it for a plain set of tags (use useSet) or a single selected item (use useState).
import { useSelection } from "@/hooks/use-selection"const selection = useSelection(rows.map((row) => row.id))
<input type="checkbox" checked={selection.isSelected(id)} onClick={(e) => selection.handleClick(id, e)} onChange={() => {}} />useSelection<T>(ids: readonly T[]): Selection<T>
| Member | Description |
|---|---|
selected | ReadonlySet<T> of selected ids (only ids still in ids). |
isSelected(id) | Whether an id is selected. |
toggle(id) | Flip one id and remember it as the anchor for ranges. |
selectRange(id) | Select every id between the anchor and id. |
handleClick(id, event) | Calls selectRange when Shift is held, toggle otherwise. |
selectAll(), clear() | Select all of ids or none. |
toggleAll() | Select all unless all are selected, then clear. |
allSelected, someSelected | Booleans for a header checkbox (indeterminate when some but not all). |
Ids that disappear from ids (for example after filtering) are dropped from selected on the next render.
Use real checkboxes in a labelled column, set the header checkbox to indeterminate when some rows are selected, and announce the count ("3 selected") in a polite live region. Shift-click ranges also need a keyboard route: Shift+Space or Shift+arrow on rows.
The hook ships with renderHook tests (use-selection.test.ts) covering its behaviour, cleanup on unmount and server-safe defaults. It is safe to render on the server.