Selection

Many collection components support selecting items by clicking or tapping them, or by using the keyboard. This page discusses how to handle selection events, how to control selection programmatically, and the data structures used to represent a selection.

Multiple selection

Most collection components support item selection, which is handled by the onSelectionChange event. Use the selectedKeys prop to control the selected items programmatically, or defaultSelectedKeys for uncontrolled behavior.

Selection is represented by a Set containing the id of each selected item. You can also pass any iterable collection (e.g. an array) to the selectedKeys and defaultSelectedKeys props, but the onSelectionChange event will always pass back a Set.

Lettuce
Tomato
Cheese
Tuna Salad
Egg Salad
Ham

selectedKeys: cheese

import {ListBox, ListBoxItem, type Selection} from 'react-aria-components';
import {useState} from 'react';

function Example() {
  let [selectedKeys, setSelectedKeys] = useState<Selection>(new Set(['cheese']));

  return (
    <div>
      <ListBox
        aria-label="Sandwich contents"
        selectionMode="multiple"
        selectedKeys={selectedKeys}
        onSelectionChange={setSelectedKeys}
      >
        <ListBoxItem id="lettuce">Lettuce</ListBoxItem>
        <ListBoxItem id="tomato">Tomato</ListBoxItem>
        <ListBoxItem id="cheese">Cheese</ListBoxItem>
        <ListBoxItem id="tuna">Tuna Salad</ListBoxItem>
        <ListBoxItem id="egg">Egg Salad</ListBoxItem>
        <ListBoxItem id="ham">Ham</ListBoxItem>
      </ListBox>
      <p>selectedKeys: {selectedKeys === 'all' ? 'all' : [...selectedKeys].join(', ')}</p>
    </div>
  );
}

Select all

Some components support a checkbox to select all items in the collection, or a keyboard shortcut like ⌘ Cmd + A. This represents a selection of all items in the collection, regardless of whether or not all items have been loaded from the network. For example, when using a component with infinite scrolling support, the user will be unaware that all items are not yet loaded. For this reason, it makes sense for select all to represent all items, not just the loaded ones.

When a select all event occurs, onSelectionChange is called with the string "all" rather than a set of selected keys. selectedKeys and defaultSelectedKeys can also be set to "all" to programmatically select all items. The application must adjust its handling of bulk actions in this case to apply to the entire collection rather than only the keys available to it locally.

NameTypeDate Modified
GamesFile folder6/7/2020
Program FilesFile folder4/7/2021
bootmgrSystem file11/20/2010
log.txtText Document1/18/2016

selectedKeys:

import {Table, TableHeader, Column, TableBody, Row, Cell} from 'react-aria-components';
import {Checkbox} from './Checkbox';
import {useState} from 'react';

function Example() {
let [selectedKeys, setSelectedKeys] = useState(new Set()); function performBulkAction() { if (selectedKeys === 'all') { // perform action on all items } else { // perform action on selected items in selectedKeys } }
}

Selection behavior

By default, React Aria uses the "toggle" selection behavior, which behaves like a checkbox group: clicking, tapping, or pressing the Space or Enter 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.

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 Ctrl, Cmd, and Shift can be used. 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.

To move focus without moving selection, the Ctrl key on Windows or the Option key on macOS can be held while pressing the arrow keys. Holding this modifier while pressing the Space key toggles selection for the focused row, which allows multiple selection of non-contiguous items.

These selection styles implement the behaviors defined in Aria Practices.

One
Two
Three
selectionBehavior 
import {ListBox, ListBoxItem} from 'react-aria-components';
import {useState} from 'react';

function Example(props) {
  let [selectedKeys, setSelectedKeys] = useState(new Set());

  return (
    <ListBox
      {...props}
      aria-label="ListBox"
      selectionMode="multiple"
      selectedKeys={selectedKeys}
      onSelectionChange={setSelectedKeys}>
      <ListBoxItem id="one">One</ListBoxItem>
      <ListBoxItem id="two">Two</ListBoxItem>
      <ListBoxItem id="three">Three</ListBoxItem>
    </ListBox>
  );
}

Single selection

In some components, like a Select or ComboBox, only single selection is supported. In this case, the singular selectedKey and defaultSelectedKey props are available instead of their plural variants. These accept a single id instead of a Set as their value.

selectedKey: null

import type {Key} from 'react-aria-components';
import {ComboBox, ComboBoxItem} from './ComboBox';
import {useState} from 'react';

function Example() {
  let [selectedKey, setSelectedKey] = useState<Key | null>(null);

  return (
    <div>
      <ComboBox
        label="ComboBox"
        selectedKey={selectedKey}
        onSelectionChange={setSelectedKey}>
        <ComboBoxItem id="one">One</ComboBoxItem>
        <ComboBoxItem id="two">Two</ComboBoxItem>
        <ComboBoxItem id="three">Three</ComboBoxItem>
      </ComboBox>
      <p>selectedKey: {String(selectedKey)}</p>
    </div>
  );
}

In components which support multiple selection, you can limit the selection to a single item using the selectionMode prop. This continues to accept selectedKeys and defaultSelectedKeys as a Set, but it will only contain a single id at a time.

Item actions

In addition to selection, collection items support actions via the onAction prop, which is useful for functionality such as navigation. In the default "toggle" selection behavior, when nothing is selected, clicking, tapping, or pressing the Enter key triggers the item action. Items may be selected using the checkbox, or by pressing the Space key. When at least one item is selected, clicking or tapping a row toggles the selection.

In the "replace" selection behavior, selection is the primary interaction. Clicking an item with a mouse selects it, and double clicking performs the action. On touch devices, actions remain the primary tap interaction. Long pressing enters selection mode, which temporarily swaps the selection behavior to "toggle". Deselecting all items exits selection mode and reverts the selection behavior back to "replace". Keyboard behaviors are unaffected.

Games
Documents
Photos
selectionBehavior 
import {GridList, GridListItem} from './GridList';

<GridList
  aria-label="Files"
  selectionMode="multiple">
  <GridListItem onAction={() => alert('Opening Games')}>
    Games
  </GridListItem>
  <GridListItem onAction={() => alert('Opening Documents')}>
    Documents
  </GridListItem>
  <GridListItem onAction={() => alert('Opening Photos')}>
    Photos
  </GridListItem>
</GridList>

In dynamic collections, it may be more convenient to use the onAction prop at the collection level instead of on individual items. This receives the id of the pressed item.

Games
Documents
Photos
selectionBehavior 
import {GridList, GridListItem} from './GridList';

<GridList
aria-label="Files" selectionMode="multiple" items={files} onAction={id => alert(`Opening ${id}`)}> {item => <GridListItem>{item.name}</GridListItem>} </GridList>

Disabled items

An item can be disabled with the isDisabled prop. By default, disabled items are not focusable, selectable, or actionable. When disabledBehavior="selection", only selection is disabled.

Charizard
Blastoise
Venusaur
Pikachu
disabledBehavior 
import {GridList, GridListItem} from './GridList';

<GridList
  aria-label="Pokemon"
  selectionMode="multiple">
  <GridListItem>Charizard</GridListItem>
  <GridListItem>Blastoise</GridListItem>
  <GridListItem isDisabled>Venusaur</GridListItem>
  <GridListItem>Pikachu</GridListItem>
</GridList>

In dynamic collections, it may be more convenient to use the disabledKeys prop at the GridList level instead of isDisabled on individual items. This accepts a list of item ids that are disabled. An item is considered disabled if its key exists in disabledKeys or if it has isDisabled.

Charizard
Blastoise
Venusaur
Pikachu
disabledBehavior 
import {GridList, GridListItem} from './GridList';

<GridList aria-label="Pokemon" selectionMode="multiple" disabledKeys={[3]} items={items}> {item => <GridListItem>{item.name}</GridListItem>} </GridList>