Skip to content

Commit 69cf00a

Browse files
authored
Add docs for highlight selection (#2579)
1 parent 896eabe commit 69cf00a

File tree

2 files changed

+63
-8
lines changed

2 files changed

+63
-8
lines changed

packages/@react-aria/table/docs/useTable.mdx

Lines changed: 41 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,9 @@ HTML tables are meant for static content, rather than tables with rich interacti
6464
* Single, multiple, or no row selection via mouse, touch, or keyboard interactions
6565
* Support for disabled rows, which cannot be selected
6666
* Optional support for checkboxes in each row for selection, as well as in the header to select all rows
67+
* Support for both `toggle` and `replace` selection behaviors
68+
* Support for row actions via double click, <kbd>Enter</kbd> key, or tapping
69+
* Long press to enter selection mode on touch when there is both selection and row actions
6770
* Column sorting support
6871
* Async loading, infinite scrolling, filtering, and sorting support
6972
* Support for column groups via nested columns
@@ -132,7 +135,12 @@ import {useRef} from 'react';
132135
import {useFocusRing} from '@react-aria/focus';
133136

134137
function Table(props) {
135-
let state = useTableState({...props, showSelectionCheckboxes: props.selectionMode === 'multiple'});
138+
let {selectionMode, selectionBehavior, onAction} = props;
139+
let state = useTableState({
140+
...props,
141+
showSelectionCheckboxes: selectionMode === 'multiple' && selectionBehavior !== 'replace'
142+
});
143+
136144
let ref = useRef();
137145
let {collection} = state;
138146
let {gridProps} = useTable(props, state, ref);
@@ -152,7 +160,7 @@ function Table(props) {
152160
</TableRowGroup>
153161
<TableRowGroup type="tbody">
154162
{[...collection.body.childNodes].map(row => (
155-
<TableRow key={row.key} item={row} state={state}>
163+
<TableRow key={row.key} item={row} state={state} onAction={onAction}>
156164
{[...row.childNodes].map(cell =>
157165
cell.props.isSelectionCell
158166
? <TableCheckboxCell key={cell.key} cell={cell} state={state} />
@@ -251,27 +259,32 @@ Now that we've covered the table header, let's move on to the body. We'll use
251259
the <TypeLink links={docs.links} type={docs.exports.useTableRow} /> hook to render each row in the table.
252260
Table rows can be focused and navigated to using the keyboard via the arrow keys. In addition, table rows
253261
can optionally support selection via mouse, touch, or keyboard. Clicking, tapping, or pressing the <kbd>Space</kbd>
254-
key anywhere in the row selects it.
262+
key anywhere in the row selects it. Row actions are also supported via the provided `onAction` prop. See [below](#row-and-cell-actions) for details.
255263

256264
We'll use the <TypeLink links={selectionDocs.links} type={selectionDocs.exports.SelectionManager} /> object exposed
257265
by the `state` to determine if a row is selected, and render a pink background if so. We'll also use the <TypeLink links={focusDocs.links} type={focusDocs.exports.useFocusRing} />
258266
hook to render a focus ring when the user navigates to the row with the keyboard.
259267

260268
```tsx example export=true render=false
261-
function TableRow({item, children, state}) {
269+
function TableRow({item, children, state, onAction}) {
262270
let ref = useRef();
263271
let isSelected = state.selectionManager.isSelected(item.key);
264-
let {rowProps} = useTableRow({node: item}, state, ref);
272+
let {rowProps, isPressed} = useTableRow({
273+
node: item,
274+
onAction: onAction && (() => onAction(item.key))
275+
}, state, ref);
265276
let {isFocusVisible, focusProps} = useFocusRing();
266277

267278
return (
268279
<tr
269280
style={{
270281
background: isSelected
271282
? 'blueviolet'
272-
: item.index % 2
273-
? 'var(--spectrum-alias-highlight-hover)'
274-
: 'none',
283+
: isPressed
284+
? 'var(--spectrum-global-color-gray-400)'
285+
: item.index % 2
286+
? 'var(--spectrum-alias-highlight-hover)'
287+
: 'none',
275288
color: isSelected ? 'white' : null,
276289
outline: isFocusVisible ? '2px solid orange' : 'none'
277290
}}
@@ -584,6 +597,26 @@ Note that you are responsible for the styling of disabled rows, however, the sel
584597
<PokemonTable selectionMode="multiple" disabledKeys={[3]} />
585598
```
586599

600+
### Selection behavior
601+
602+
By default, `useTable` uses the `"toggle"` selection behavior, which behaves like a checkbox group: clicking, tapping, or pressing the <kbd>Space</kbd> or <kbd>Enter</kbd> keys toggles selection for the focused row. Using the arrow keys moves focus but does not change selection. The `"toggle"` selection mode is often paired with a column of checkboxes in each row as an explicit affordance for selection.
603+
604+
When the `selectionBehavior` prop is set to `"replace"`, clicking a row with the mouse _replaces_ the selection with only that row. Using the arrow keys moves both focus and selection. To select multiple rows, modifier keys such as <kbd>Ctrl</kbd>, <kbd>Cmd</kbd>, and <kbd>Shift</kbd> can be used. To move focus without moving selection, the <kbd>Ctrl</kbd> key on Windows or the <kbd>Option</kbd> key on macOS can be held while pressing the arrow keys. Holding this modifier while pressing the <kbd>Space</kbd> key toggles selection for the focused row, which allows multiple selection of non-contiguous items. On touch screen devices, selection always behaves as toggle since modifier keys may not be available. This behavior emulates native platforms such as macOS and Windows, and is often used when checkboxes in each row are not desired.
605+
606+
```tsx example
607+
<PokemonTable selectionMode="multiple" selectionBehavior="replace" />
608+
```
609+
610+
### Row and cell actions
611+
612+
`useTable` may be used in use cases where users can perform actions on rows or cells, such as navigating into items to open them or get more details. In the default `"toggle"` selection behavior, it is recommended to use a link in the first column for navigation.
613+
614+
In the `"replace"` selection behavior, the `onAction` prop can be used to enable row and cell actions, which differ depending on the interaction method. When provided to `useTableRow` or `useTableCell`, double clicking with a mouse or pressing the <kbd>Enter</kbd> key triggers `onAction`, while single click and the <kbd>Space</kbd> key are reserved for selection. On touch devices, `onAction` becomes the primary tap interaction, and a long press enters into selection mode, which temporarily swaps the selection behavior to `"toggle"` to perform selection (you may wish to display checkboxes when this happens). Deselecting all items exits selection mode and reverts the selection behavior back to `"replace"`. Double clicking matches the behavior of desktop platforms like macOS and Windows, and a separate selection mode matches mobile platforms like iOS and Android.
615+
616+
```tsx example
617+
<PokemonTable selectionMode="multiple" selectionBehavior="replace" onAction={key => alert(`Opening item ${key}...`)} />
618+
```
619+
587620
### Sorting
588621

589622
Table supports sorting its data when a column header is pressed. To designate that a Column should support sorting, provide it with

packages/@react-spectrum/table/docs/TableView.mdx

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -465,6 +465,28 @@ You can disable specific rows by providing an array of keys to TableView via the
465465
<PokemonTable selectionMode="multiple" disabledKeys={[3]} />
466466
```
467467

468+
### Highlight selection
469+
470+
By default, TableView uses the checkbox selection style, which includes a column of checkboxes in each row for selection. When the `selectionStyle` prop is set to `"highlight"`, the checkboxes are hidden, and the selected rows are displayed with a highlighted background instead.
471+
472+
In addition to changing the appearance, the selection behavior also changes depending on the `selectionStyle` prop. In the default checkbox selection style, clicking, tapping, or pressing the <kbd>Space</kbd> or <kbd>Enter</kbd> keys toggles selection for the focused row. Using the arrow keys moves focus but does not change selection.
473+
474+
In the highlight selection style, however, clicking a row with the mouse _replaces_ the selection with only that row. Using the arrow keys moves both focus and selection. To select multiple rows, modifier keys such as <kbd>Ctrl</kbd>, <kbd>Cmd</kbd>, and <kbd>Shift</kbd> can be used. To move focus without moving selection, the <kbd>Ctrl</kbd> key on Windows or the <kbd>Option</kbd> key on macOS can be held while pressing the arrow keys. Holding this modifier while pressing the <kbd>Space</kbd> key toggles selection for the focused row, which allows multiple selection of non-contiguous items. On touch screen devices, selection always behaves as toggle since modifier keys may not be available. This behavior emulates native platforms such as macOS and Windows.
475+
476+
```tsx example
477+
<PokemonTable selectionMode="multiple" selectionStyle="highlight" />
478+
```
479+
480+
### Row actions
481+
482+
TableView may be used in use cases where users can perform actions on rows, such as navigating into items to open them or get more details. In the default checkbox selection style, it is recommended to use a [Link](Link.html) component in the first column for navigation.
483+
484+
In the highlight selection style, the `onAction` prop can be used to enable row actions, which differ depending on the interaction method. When provided, double clicking with a mouse or pressing the <kbd>Enter</kbd> key triggers `onAction`, while single click and the <kbd>Space</kbd> key are reserved for selection. On touch devices, `onAction` becomes the primary tap interaction, and a long press enters into selection mode, which displays checkboxes to perform selection. Deselecting all items exits selection mode and hides the checkboxes. Double clicking matches the behavior of desktop platforms like macOS and Windows, and a separate selection mode matches mobile platforms like iOS and Android.
485+
486+
```tsx example
487+
<PokemonTable selectionMode="multiple" selectionStyle="highlight" onAction={key => alert(`Opening item ${key}...`)} />
488+
```
489+
468490
## Sorting
469491

470492
TableView supports sorting its data when a column header is pressed. To designate that a Column should support sorting, provide it with

0 commit comments

Comments
 (0)