# Selection

> Identifying the items an action applies to: one, several, or a range.

Selection identifies the items an action will apply to. It is distinct from
focus, which identifies the one item that keyboard input goes to. The two often
coincide, but a collection that supports multiple selection must let them part.

## Best practices

**Make the selection unmistakable.** A selected item should stand apart from its
neighbours at a glance. When the collection loses focus, keep the selection
visible in a subdued form, so people can still tell what an action will affect.

**Keep focus legible on selected and unselected items alike.** In a multiple
selection, people move between items without changing what is selected; the
focus indicator must remain distinct against both appearances.

**Keep several selected items through a press.** A press on one of several
selected items leaves them all selected until it ends as a click on that one, so
that a drag can begin from it with all of them.

**Let a drag draw a range.** A press on an item that is not selected, dragged,
selects from that item to wherever the pointer is, and follows the pointer back
as it returns. With Command held the range adds to what was selected. A drag
from a selected item draws no range: it is the selection's, to be carried. Keep
the drag when the pointer leaves the collection, and scroll while it is held
past an edge — at a walk just outside, faster the further out, up to a speed the
eye can follow.

**Give back what a cancelled gesture took.** When the platform takes a gesture
back — to scroll, or for a gesture of its own — the selection returns to what it
was before the press.

**Let a secondary press select what it lands on.** A secondary press on an item
outside the selection selects it; on an item within the selection it changes
nothing, so that a menu opened there acts on the whole selection.

**Extend from where focus is.** When a selection was not made by a gesture —
restored, or given by the application — Shift with an arrow extends it from the
focused item.

**Change the selection only in response to a selection gesture.** Scrolling,
resizing, filtering the view or switching away should leave the selection as it
was.

**Apply an action to the whole selection.** Commands such as move, share or
delete act on every selected item. When the number is not evident, state it in
the command or its confirmation.

**Offer multiple selection where acting on several items is a real task.**
Managing files and messages benefits from it; choosing a single setting does
not. Each additional gesture is something people must learn.

## Conventions

| Intent                 | Pointer                                      | Keyboard                                               | Touch                                 |
| ---------------------- | -------------------------------------------- | ------------------------------------------------------ | ------------------------------------- |
| Select one item        | Click                                        | Arrow keys                                             | Tap                                   |
| Add or remove one item | Command-click                                | Command with arrow keys to move, then Space            | Tap, in a multiple selection          |
| Select a range         | Shift-click, or drag from an unselected item | Shift with arrow keys, Page Up, Page Down, Home or End | Long press, then move without lifting |
| Begin a selection      | —                                            | —                                                      | Long press, in a multiple selection   |
| Select all             | —                                            | Command-A                                              | —                                     |
| Ask for a menu         | Secondary click                              | The platform's menu key                                | Long press, in a single selection     |

Shift with Home or End extends to that end whether or not Command is held.

Command is ⌘ on Apple platforms and Ctrl elsewhere. On a Mac, Control-click
opens a contextual menu and is never a selection gesture.

### The anchor

A range extends from the _anchor_ — the item most recently selected by a click or
Command-click — to the item indicated. Extending again redraws the range from the
same anchor rather than adding a second range, so people can adjust a range
until it is right. A range adds to whatever was selected before it began, which
is what lets Command-click and Shift-click combine.

### Touch

A finger has no modifier keys, no secondary button and no double click, so the
same intents take other forms.

A **long press** — about half a second without moving — is heard as the
platform's request for a contextual menu, and is raised by the collection itself
on platforms that raise none. In a single selection it does what a secondary
press does: selects the item if it was not selected, and leaves a menu to open on
it. In a multiple selection it begins selecting: the item is added, the rest are
kept, and while the finger stays down the range from that item follows it, the
collection holding still beneath. A long press on an item already selected
changes nothing. The tap that would follow a long press is not heard as a tap.

A finger that moves before its press is long is scrolling, and selects nothing.

A **tap** selects; where selecting would change nothing and items have an
action, it performs the action: on the selected item of a single selection, and
in a multiple selection that replaces while nothing is selected.

### Disabled items

An item that cannot be selected is never selected indirectly: a range passes
over it, and Select All leaves it out.

## Selection behaviours

**Replace.** A selection gesture replaces the selection; modifier keys add to it,
and selection follows keyboard focus. This is the convention of file browsers and
most collections people act on.

**Toggle.** Every selection gesture adds or removes one item, in the manner of
checkboxes, and focus moves independently. It suits collections where choosing
several items is the common case, such as a set of filters.

## Behaviour

Each statement is verified by a test in Chromium, Chromium (touch), Firefox, WebKit, WebKit (touch), unless it names the environments it applies to or is marked open.

### Single

- Every intent selects only the key.
- Toggling the selected key clears the selection.
- `disallowEmpty` keeps the selected key when it is toggled.

### Multiple

- `replace` selects only the key and makes it the anchor.
- `toggle` adds or removes the key and keeps the rest.
- `extend` selects every key between the anchor and the key, in either direction.
- Extending again redraws the range from the same anchor.
- A range adds to what was selected before it.
- `extend` with no anchor selects only the key.
- `disallowEmpty` keeps the last selected key when it is toggled.
- `selectAll` selects every key and keeps the anchor.
- A key outside the order is ignored.
- A range never includes a key outside the order, such as a disabled one.

### Pointer gestures

- A plain click replaces; Shift extends; the command key toggles.
- Toggle behaviour toggles on a plain click.
- A touch toggles, since it has no modifier keys.
- In a single selection, only the command key toggles.

### Taps

- In a single selection, a tap acts on the selected item and selects any other.
- In a multiple selection that replaces, a tap acts only while nothing is selected.
- In a multiple selection that toggles, a tap never acts.

### Drags

- The item at a position is the one that holds it.
- A position between two items is the nearer one's.
- A position past either end is the item's at that end.
- Where there are no items there is none to find.
- A drag is a range redrawn from where it began, so it follows the pointer back.
- Among ten thousand items, finding the one at a position measures at most sixteen.
- Held past an edge, a drag scrolls faster the further out it is, up to a limit.

## Reference implementation

React: `npx shadcn@latest add https://ui.publictheta.com/r/selection.json`
