gridcn1.3.0

Selection & keyboard

Range selection, mouse gestures, and the full keyboard shortcut reference.

Selection model

A selection has an anchor cell (the active cell, Excel's white cell) and a rectangular range around it. With multi-range enabled, it also has a stack of additional ctrl-clicked ranges. Rows and columns also have their own whole-row and whole-column selection channels, through marker-column checkbox clicks and header clicks, independent of the range.

Checked rows follow their records when a sort, filter, or new data array rebuilds the view. When a row leaves the view, the grid unchecks it. Row ids must be unique: when two rows share an id, the check follows the first row with that id. The active cell follows its record and its column when the view rebuilds and when columns move, hide, or pin. When its row or its column leaves the view, the active cell keeps its view position, clamped into the view. When a rebuild puts other records or other columns under the range, the grid collapses the range onto the active cell. A clamp that moves the active cell also collapses the selection onto it. A clamp that keeps the active cell in place drops the range. A row operation never reaches a record that you did not select. Without checked rows or a range, a row operation acts on the active cell's row. Selected columns follow their column when columns move, hide, or pin, and a column that leaves the view leaves the selection.

Selection overlays are placed on grid lines and render with zero cell re-renders. Dragging a selection never re-renders a single cell.

Mouse gestures

  • Plain left-button press and drag from any cell, active or not, live-paints a rectangular range from the press origin to the hovered cell, in any direction.
  • Shift+click extends the range from the current anchor to the clicked cell.
  • Header press and drag selects a contiguous multi-column range. A plain header click selects the whole column, or sorts it if headerClickBehavior="sort".
  • Marker press and drag, with rowMarkers enabled, selects multiple rows. The range follows the pointer from the press row, so dragging back over selected rows de-selects them again. In the reorder-family marker modes only a drag that starts on the drag handle zone reorders the row, and it leaves the selection as it was. Drags from the number or checkbox glyph still select.
  • Shift+click on a row marker, on its number or on its checkbox, checks the rows from the anchor row to this row. See Checking a range of rows.
  • Ctrl/Cmd-click adds a new range to the stack (enableMultiRange, on by default).

The grid body suppresses native browser text selection during these gestures. Editors remain normally text-selectable.

Name
Email
Age
Active
Role
Joined
Score
Silent Tiger
user0@example.com
63
Viewer
Jul 5, 2023
4
Quick Lion
user1@example.com
67
Viewer
Apr 3, 2021
89
Swift Wolf
user2@example.com
40
Manager
Oct 27, 2020
80
Eager Lion
user3@example.com
50
User
Oct 8, 2022
51
Eager Tiger
user4@example.com
45
Viewer
Oct 7, 2024
83
Silent Wolf
user5@example.com
24
User
Jun 1, 2020
15
Swift Lion
user6@example.com
34
Viewer
Oct 18, 2022
62
Eager Lion
user7@example.com
21
Manager
Oct 7, 2021
42
Eager Eagle
user8@example.com
25
Editor
Jun 11, 2024
35
Bold Tiger
user9@example.com
19
Editor
Mar 20, 2024
52
Bold Bear
user10@example.com
42
User
Apr 16, 2020
28
Swift Wolf
user11@example.com
47
Manager
Aug 4, 2022
9

Checking a range of rows

The row that you checked or unchecked last is the anchor. A Shift step checks the rows from the anchor to the target row. Each Shift step replaces the previous Shift step, so the range grows and shrinks. Rows outside the range keep their state, and checked rows that a filter hides stay checked.

GestureResult
Click a checkboxToggles the row. The row becomes the anchor.
Click a numberChecks only this row. The row becomes the anchor.
Ctrl/Cmd+clickToggles the row and keeps the other checked rows. The row becomes the anchor.
Shift+clickChecks the rows from the anchor to the clicked row. If the anchor row is unchecked, the range unchecks its rows.
Ctrl/Cmd+Shift+clickKeeps the current range and adds the rows from the anchor to the clicked row. The next Shift step replaces only the new range.
Press a number or a checkbox and dragMoves the end of the range with the pointer. A drag that starts on a checked checkbox unchecks the rows.
Shift+press and dragMoves the end of the range from the anchor row.
Shift+click without an anchorStarts at the active row. Without an active row, it checks only the clicked row.

A sort or a filter ends the range. The next Shift+click then starts from the anchor row. The header checkbox and Escape clear the anchor, so the next Shift+click starts at the active row.

For example, click row 1, Shift+click row 5, and Shift+click row 3. Rows 1 to 3 are checked.

Touch gestures

A touch screen scrolls the grid natively. The grid reads the input type of each press, so a laptop with a touch screen and a trackpad gets touch gestures from the screen and mouse gestures from the trackpad.

GestureResult
Tap a cellSelects the cell. A scroll or a pan selects nothing.
Double-tap a cellStarts editing, or toggles a checkbox cell. A read-only grid does not edit.
Tap a headerSelects the column, or sorts it with headerClickBehavior="sort".
Tap a row markerSelects the row.
Long-press (hold for 500 ms)Opens the context menu on the cell or the header.
Drag a selection handleExtends the range from the opposite corner. The grid scrolls at the edges.

After a touch selection, two selection handles appear at the top-start and bottom-end corners of the range. Any key press hides them. A press must stay within 10 px to count as a tap or a long-press.

The grid sets touch-action: manipulation. A double-tap does not zoom the page, and pinch zoom stays available. Use density="comfortable" for rows that are easier to hit with a finger.

The demo has the fill and context menu add-ons:

Use a touch device or browser device mode. Drag a handle to select several cells, then press and hold to open the context menu. Fill down and Fill right appear for a touch selection.

Name
Role
Age
Score
Silent Tiger
Viewer
63
4
Quick Lion
Viewer
67
89
Swift Wolf
Manager
40
80
Eager Lion
User
50
51
Eager Tiger
Viewer
45
83
Silent Wolf
User
24
15
Swift Lion
Viewer
34
62
Eager Lion
Manager
21
42
Eager Eagle
Editor
25
35
Bold Tiger
Editor
19
52
Bold Bear
User
42
28
Swift Wolf
Manager
47
9
Swift Bear
Viewer
41
45
Eager Wolf
Editor
35
44
Swift Eagle
Viewer
65
51
Quick Lion
Manager
22
28
Bold Wolf
Editor
30
76
Swift Eagle
Admin
19
26
Eager Eagle
Manager
35
70
Eager Bear
Editor
33
67
Silent Lion
Manager
48
89
Silent Tiger
Manager
62
40
Eager Tiger
Manager
51
82
Silent Lion
Admin
26
16
Bold Eagle
Admin
26
38
Bold Lion
Viewer
49
3
Quick Tiger
Viewer
26
41
Bold Eagle
Editor
50
10
Swift Tiger
Editor
55
6
Silent Lion
Viewer
35
42

Configurability

You can disable each selection channel independently through DataGridProvider props. All default to true:

<DataGridProvider
  enableRowSelection={true}
  enableColumnSelection={true}
  enableRangeSelection={true}
  enableMultiRange={true}
  {...grid}
  columns={columns}
>

Disabling a channel removes its state, not just its gestures

enableColumnSelection={false} makes header clicks do nothing, rather than only hiding a highlight. The column selection channel itself is gone.

Checked rows

A checked row is a row whose marker checkbox is on. A click outside the grid, or in the empty space of the grid, clears the cell range and the column selection. It never clears checked rows. A toolbar button outside the grid reads the checked rows after it is clicked.

Selecting a cell clears the checked rows. Set keepCheckedRows to keep them:

<DataGridProvider keepCheckedRows {...grid} columns={columns}>

With keepCheckedRows, a cell click, an arrow key, and a Shift or Ctrl click leave the checked rows as they are. Escape, the marker checkboxes, the header checkbox, clearSelection(), and deleting a row change them.

While at least one row is checked, row operations act only on the checked rows, never on the range. This covers Delete rows, Duplicate row, Move rows, and the row items of the cell context menu. Cell operations such as copy, cut, fill, and Delete stay on the cell range. With no checked row, row operations use the range.

A filter removes the checked rows it hides. Set keepHiddenCheckedRows to remember them:

<DataGridProvider keepCheckedRows keepHiddenCheckedRows {...grid} columns={columns}>

A hidden checked row is a checked row that the current filter hides. The grid checks it again when the filter lets it back in. A sort keeps both the visible and the hidden checks.

The demo sets both props:

Check a few rows, then open the Role filter and keep one role. The status bar counts the checked rows the filter hides. Clear the filter and the checks come back.

Row markers
Name
Role
Score
Silent Tiger
Viewer
4
Quick Lion
Viewer
89
Swift Wolf
Manager
80
Eager Lion
User
51
Eager Tiger
Viewer
83
Silent Wolf
User
15
Swift Lion
Viewer
62
Eager Lion
Manager
42
Eager Eagle
Editor
35
Bold Tiger
Editor
52
Bold Bear
User
28
Swift Wolf
Manager
9
Swift Bear
Viewer
45
Eager Wolf
Editor
44
Swift Eagle
Viewer
51
Quick Lion
Manager
28
Bold Wolf
Editor
76
Swift Eagle
Admin
26
Eager Eagle
Manager
70
Eager Bear
Editor
67
Silent Lion
Manager
89
Silent Tiger
Manager
40
Eager Tiger
Manager
82
Silent Lion
Admin
16
Bold Eagle
Admin
38
Bold Lion
Viewer
3
Quick Tiger
Viewer
41
Bold Eagle
Editor
10
Swift Tiger
Editor
6
Silent Lion
Viewer
42

While every checked row is hidden, Delete rows, Duplicate row, and Move rows do nothing, and their context menu items are disabled. Row operations never touch a hidden checked row. Delete rows, Duplicate row, Move rows, the context menu, the export scope 'selection', and the clipboard read only the checked rows you can see. Select all checks the rows of the view and adds no hidden row. Escape, clearSelection(), setSelection(null), an empty controlled selection, and the header checkbox set to off clear the hidden checks too.

The controlled selection prop and onSelectionChange carry the visible rows only. useDataGridHiddenCheckedCount() returns the number of hidden checked rows. DataGridStatusBar shows it as (+3 hidden) beside the selection stats. With fewer than two cells selected, it shows 3 hidden checked rows. The labels are labels.statusBar.hiddenChecked and labels.statusBar.hiddenCheckedOnly.

The grid remembers at most 100,000 hidden checked rows. A server-sorted grid ignores the option. A grid with unloaded rows (a lazy source) ignores it while its data holds them. Both warn once in development. Switching to sortMode="server" clears the hidden checks.

setSelection with a non-empty value and a non-empty controlled selection change the visible checks and keep the hidden ones.

PropTypeDefault
keepCheckedRowsbooleanfalse
keepHiddenCheckedRowsbooleanfalse
announceResults Newbooleanfalse
onBeforeDeleteRows(ctx: { rowIds: readonly string[]; hiddenCount: number }) => boolean | Promise<boolean>none

keepHiddenCheckedRows takes effect only with keepCheckedRows. announceResults reads the row count of the view after a filter or sort change; see Accessibility. onBeforeDeleteRows is described in Row operations.

Header click behavior

headerClickBehavior on DataGridProvider picks what a plain header click does. Header press and drag always multi-selects columns, regardless of this setting.

ValueA plain header click...
"select" (default)Selects the whole column, through the column selection channel.
"sort"Cycles that column's sort between ascending, descending, and clear, instead of selecting. See Sorting, filtering & search.
"none"Does nothing. Use this when you drive sort exclusively through data-grid-sort-list or your own UI, and you do not want header clicks to also select or sort.
<DataGridProvider headerClickBehavior="none" {...grid} columns={columns}>

Try all three values live in the playground.

Per-column sortable: false still removes that one column from the click-to-sort gesture, even under headerClickBehavior="sort". You can still sort it programmatically through useDataGridActions().setSorts().

Keyboard map

The keymap is a plain data table, the keymap prop, merged over DEFAULT_KEYMAP. You can remap or extend any binding without touching the engine. The remapping surface and the in-app shortcuts dialog are on the Keybindings page. The table below is generated from the shipped defaults.

Navigation

Move up
↑
Move down
↓
Move left
←
Move right
→
Move up (keep selection)
Alt↑
Move down (keep selection)
Alt↓
Move left (keep selection)
Alt←
Move right (keep selection)
Alt→
Scroll active cell into view
CtrlEnter
Move to row start
Home
Move to row end
End
Jump to edge (up)
Ctrl↑
Jump to edge (down)
Ctrl↓
Jump to edge (left)
Ctrl←
Jump to edge (right)
Ctrl→
Move to first cell
CtrlHome
Move to last cell
CtrlEnd
Page up
PageUp
Page down
PageDown

Selection

Extend selection up
Shift↑
Extend selection down
Shift↓
Extend selection left
Shift←
Extend selection right
Shift→
Extend selection to edge (up)
CtrlShift↑
Extend selection to edge (down)
CtrlShift↓
Extend selection to edge (left)
CtrlShift←
Extend selection to edge (right)
CtrlShift→
Extend selection to first cell
CtrlShiftHome
Extend selection to last cell
CtrlShiftEnd
Check rows up to the first row
ShiftHome
Check rows down to the last row
ShiftEnd
Check rows up one page
ShiftPageUp
Check rows down one page
ShiftPageDown
Select row
ShiftSpace
Select column
CtrlSpace
Select all
CtrlA
Check or uncheck row
CtrlShiftSpace
Check or uncheck all rows
CtrlShiftE
Open column menu
ShiftAlt↓
Open column filter
ShiftAlt↑

Editing

Edit cell
EnterF2Space
Commit and move down (editor)
Enter
Commit and move up (editor)
ShiftEnter
Leave the grid forward (Tab)
Tab
Leave the grid backward (Shift+Tab)
ShiftTab
Cancel edit
Escape
Delete contents
DeleteBackspace
Insert row below
CtrlShiftF
Duplicate row
CtrlShiftX
Insert row above
CtrlShiftU
Delete row(s)
CtrlShiftBackspace
Move rows up
ShiftAltPageUp
Move rows down
ShiftAltPageDown
Open link
AltEnter

Clipboard & Fill

Fill down
CtrlD
Fill right
CtrlR
Copy
CtrlC
Cut
CtrlX
Paste
CtrlV

History

Undo
CtrlZ
Redo
CtrlYCtrlShiftZ

mod resolves to Cmd on macOS and Ctrl elsewhere. Copy, Cut, and Paste (Ctrl/Cmd+C/X/V) are native browser clipboard events, not part of the keymap, but the list above includes them because the shortcuts dialog shows them together.

Escape outside edit mode clears the whole selection

The Esc row is labeled "Cancel edit", but with no editor open the cancel action clears the entire selection: the cell range and its stack, plus any whole-row and whole-column selection. To keep a selection across an Escape, remap or drop the cancel binding through the keymap prop.

Undo and redo outside the grid

The in-grid undo and redo bindings above work only while focus is inside the grid. Global shortcuts extends them to a custom toolbar or anywhere else on the page: mount DataGridGlobalShortcuts inside DataGridRoot and the same bindings reach the grid while focus is outside.

Checking rows by keyboard

The marker checkboxes are not tab stops, so the keyboard has its own actions:

  • Ctrl+Shift+Space (toggleRow) checks or unchecks the active row. The other checked rows stay checked.
  • Mod+Shift+E (toggleAllRows) checks every row, or unchecks them when every row is checked. It does what the header checkbox does.
  • Shift+Space (selectRow) replaces the selection with the active row.
  • After selectRow or toggleRow, Shift+ArrowUp and Shift+ArrowDown (extendUp, extendDown) move the end of the range and the active row, and check the rows from the anchor to the new end. They shrink the range when you reverse. After a click on a cell, the same keys extend the cell range.
  • In the same state, Shift+Home (extendRowsToStart), Shift+End (extendRowsToEnd), Shift+PageUp (extendRowsPageUp), and Shift+PageDown (extendRowsPageDown) move the end of the range to the first row, the last row, or one page away. Without a row check, these keys do nothing, and the browser keeps them.

To check rows that are not next to each other, move with Alt+Arrow, which keeps the selection, and press toggleRow on each row. Ctrl/Cmd+A (selectAll) selects cells, not checked rows.

A check or uncheck New by toggleRow, toggleAllRows, the Shift+Arrow range keys, a marker checkbox, a marker range drag, or the header checkbox reads the number of checked rows in the grid's live region, for example "3 rows checked" (labels.grid.rowsChecked). Escape reads the drop too. The count includes the hidden checked rows that keepHiddenCheckedRows holds.

Moving rows

Shift+Alt+PageUp (moveRowsUp) and Shift+Alt+PageDown (moveRowsDown) move the checked rows one place. When no row is checked, they move the rows of the selected range, or the active row. They need a reorder-family rowMarkers mode. See Row operations.

Opening the column filter

Shift+Alt+ArrowUp (openColumnFilter) opens the header filter of the active cell's column. It does nothing unless the root has a renderHeaderFilter slot and the column offers a set filter. The Shift+Alt+ArrowDown chord opens the column menu.

Two-stage Ctrl+A

Two-stage select-all

The first Ctrl/Cmd+A selects the current data region. Press it again to select the whole grid.

Accessibility

The full aria model, the conformance target, and the honest test status matrix are on the Accessibility page.

On this page