Skip to content

Selection Plugin

The Selection plugin adds cell, row, and range selection capabilities to the grid with full keyboard support. Whether you need simple cell highlighting or complex multi-range selections, this plugin has you covered.

The Selection plugin exists to maintain a selection state — a set of cells, rows, or ranges — that other plugins can act on. It is the prerequisite for things like:

  • ClipboardPlugin — copy/paste the current selection
  • ExportPlugin — when onlySelected: true, export only the rows the user has selected (without it, all rows are exported)
  • ContextMenuPlugin — when present, the context menu will operate on the multi-row selection instead of just the right-clicked row (the menu itself works fine without it)
  • Any custom logic that needs to know “which rows/cells did the user pick?”

If all you want is to visually highlight the row the user has navigated to (the focused row), you do not need this plugin. The grid core already tracks keyboard focus on the active cell via the .cell-focus class — you can style the surrounding row with a small CSS snippet:

/* Highlight the row containing the focused cell, no plugin required */
tbw-grid .data-grid-row:has(.cell-focus) {
background-color: var(--tbw-focus-background, rgba(from var(--tbw-color-accent) r g b / 12%));
}
/* Optional: paint the focus tint over sticky/pinned cells too,
which otherwise have an opaque background to mask scrolling content */
tbw-grid .data-grid-row:has(.cell-focus) > .cell.sticky-left,
tbw-grid .data-grid-row:has(.cell-focus) > .cell.sticky-right {
background:
linear-gradient(var(--tbw-focus-background, rgba(from var(--tbw-color-accent) r g b / 12%)) 0 0),
var(--tbw-color-panel-bg);
}
/* Optional: suppress the per-cell focus outline if you want a row-only
indicator. The grid core paints `outline: var(--tbw-focus-outline)` on
`.cell-focus` while the grid has focus; leaving it ON makes it easier
for keyboard users to see which cell they're on inside the highlighted
row. Only add this rule if you specifically want the row to be the sole
focus indicator (mimicking the Selection plugin's row mode).
The grid core sets the `data-has-focus` attribute on the host element
whenever focus is inside the grid (managed by the focus controller),
and removes it on blur — so this rule only suppresses the cell outline
while the grid is actively focused. */
tbw-grid[data-has-focus] .cell-focus {
outline: none;
}

This mirrors what the Selection plugin does for row mode focus — without shipping the plugin’s selection-state machinery, keyboard range extension, or click handlers. Reach for the plugin only when something downstream needs to read or react to a selection.

import '@toolbox-web/grid/features/selection';
import { queryGrid } from '@toolbox-web/grid';
import '@toolbox-web/grid/features/selection';
const grid = queryGrid('tbw-grid');
grid.gridConfig = {
columns: [
{ field: 'id', header: 'ID' },
{ field: 'name', header: 'Name' },
{ field: 'email', header: 'Email' },
],
features: {
selection: 'row',
},
};
grid.rows = data;

Switch between selection modes to see how each one behaves. The state panel below the grid shows the current selection in real time.

  • Cell mode: Click cells to select them individually
  • Row mode: Click anywhere in a row to select the entire row. Ctrl+Click to toggle, Shift+Click for range
  • Range mode: Click and drag to select rectangular ranges. Ctrl+drag for multiple ranges
Mode Selection mode determines what gets selected on click
Interact with the grid to see state updates...

Add checkbox: true to show a selection checkbox column with a “select all” header. Works exclusively in row mode.

features: { selection: { mode: 'row', checkbox: true } }

You can disable selection grid-wide using gridConfig.selectable:

grid.gridConfig = {
selectable: false, // Disables ALL selection
features: { selection: 'range' },
};

See SelectionConfig for the full list of options and defaults.

In data-entry grids, you may want single-click to only focus the row/cell for keyboard navigation, while double-click changes the selection state.

features: {
selection: {
mode: 'row',
triggerOn: 'dblclick', // Single-click focuses, double-click selects
},
}

Use the isSelectable callback to prevent selection of specific rows or cells:

features: {
selection: {
mode: 'row',
isSelectable: (row) => row.status !== 'locked',
},
}

Behavior of non-selectable rows/cells:

AspectBehavior
ClickIgnored (no selection change)
KeyboardSkipped with Shift+Arrow
Select AllExcluded
VisualMuted via [data-selectable="false"] attribute
FocusStill navigable

Rows with status "locked" cannot be selected. Try clicking or using Shift+Click — locked rows are skipped.

ShortcutAction
Arrow KeysMove focus
Shift + ArrowExtend selection (row and range modes)
Shift + Page Up/DownExtend selection by page (row and range modes)
Shift + Ctrl/⌘ + Home/EndExtend selection to first/last row (row and range modes)
Ctrl/⌘ + ClickToggle row/cell (multi-select)
Shift + ClickExtend selection from anchor
Ctrl/⌘ + ASelect all (row and range modes)
EscapeClear selection
const plugin = grid.getPluginByName('selection');
// Query
const selection = plugin.getSelection();
plugin.isCellSelected(2, 1);
// Row mode
plugin.selectRows([0, 2, 4]);
const rows = plugin.getSelectedRows<Employee>();
// Range mode
plugin.setRanges([{ from: { row: 0, col: 0 }, to: { row: 5, col: 3 } }]);
// Actions
plugin.selectAll();
plugin.clearSelection();
EventDescription
selection-changeFired when the selection is modified
Event Log

See SelectionChangeDetail and CellRange for the full event payload types.

PropertyDefaultDescription
--tbw-focus-backgroundrgba(accent, 12%)Focused row background
--tbw-range-selection-bgrgba(accent, 12%)Range selection fill
--tbw-range-border-colorvar(--tbw-color-accent)Range selection border
--tbw-color-accent#3b82f6Primary accent color
tbw-grid {
--tbw-range-selection-bg: rgba(76, 175, 80, 0.15);
--tbw-range-border-color: #4caf50;
--tbw-focus-background: rgba(76, 175, 80, 0.1);
}
ClassElement
.selectingGrid during range drag
.row-focusFocused row (row mode)
.cell-focusFocused cell (cell mode)
.selectedSelected cell in range
.selected.top / .bottom / .first / .lastRange boundary edges
PluginIntegration
EditingPluginClick-to-select + double-click-to-edit
ClipboardPluginCopy/paste selected cells (requires SelectionPlugin)
FilteringPluginFilter data, then select from results
ContextMenuPluginRight-click selected rows for actions
AI assistants: For complete API documentation, implementation guides, and code examples for this library, see https://raw.githubusercontent.com/OysteinAmundsen/toolbox/main/llms-full.txt