# Cell selection

> Selecting the cells of a grid in rectangles, with one active cell among them.

In a grid, people select cells in rectangles: one cell, a block, a whole row or
column, or several of these at once. One cell among them is the active cell,
where typing goes.

## Best practices

**Keep one active cell.** Whatever is selected, exactly one cell is active: it
takes what is typed, and it is where a range is measured from. Show it apart
from the rest of the selection.

**Extend from the active cell.** Shift with an arrow key, or Shift-click, draws a
rectangle from the active cell to the cell indicated. The active cell does not
move; the far corner does. Extending again redraws the rectangle rather than
adding to it.

**Let a drag draw the rectangle.** Pressing a cell and dragging to another
selects the block between them.

**Give a finger two handles.** A finger has no Shift, and its drag scrolls. Under
touch the selection carries a handle at its start corner and one at its end,
each large enough to press. Dragging a handle takes its corner with it; the
opposite corner stays where it is and is the active cell, since that is what a
range is measured from. A corner dragged past the one that stays turns the
rectangle over.

**Add with the command key.** Command-click adds a cell to the selection and
makes it the active cell; extending then extends only that addition.

**Select whole rows and columns.** A press on a column's header selects the
column, however long it is; with Shift, the columns from the active cell's to
it. From the keyboard, Shift with Space selects the active cell's row and
Control with Space its column; a press on a row's header selects the row too.
The active cell stays where it was, and Shift with an arrow along whole rows or
columns takes in the next whole one.

**Select all without losing place.** Selecting everything leaves the active cell
where it was.

**Act on the whole selection.** Clearing applies to every selected cell. Copying,
cutting and pasting apply to the selection when it is one rectangle, and to the
active range when it is several apart — so that what a cut clears is exactly
what it copied.

**Keep the selection under a secondary press.** A secondary press on a selected
cell leaves the selection as it is; on any other cell it selects that cell.

**Dim the selection when focus is elsewhere.** A selection in a grid that does
not have focus stays visible, in a subdued form.

**Hold the selection through scrolling.** Cells that scroll out of view remain
selected, and the selection is still there when they return.

## Conventions

| Intent             | Pointer              | Keyboard              | Touch          |
| ------------------ | -------------------- | --------------------- | -------------- |
| Make a cell active | Click                | Arrow keys            | Tap            |
| Select a block     | Drag, or Shift-click | Shift with arrow keys | Drag a handle  |
| Add a cell         | Command-click        | —                     | —              |
| Select a column    | Press its header     | Control-Space         | Tap its header |
| Select a row       | Press its header     | Shift-Space           | Tap its header |
| Select everything  | —                    | Command-A             | —              |
| Return to one cell | Click a cell         | Escape                | Tap a cell     |

Command is ⌘ on Apple platforms and Ctrl elsewhere.

See also [Selection](https://ui.publictheta.com/foundations/selection.md) and [Grid navigation](https://ui.publictheta.com/foundations/grid-navigation.md).

## 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.
- Selecting a cell selects it alone, and makes it the active cell.
- Extending selects the rectangle between the active cell and the cell, in any direction.
- Extending leaves the active cell where it was, and moves the far corner.
- Extending again redraws the range from the same active cell.
- Extending to where the range already ends returns the same selection.
- Adding a cell keeps what was selected, and the added cell becomes active.
- Extending after adding extends only the added range.
- Whole rows and whole columns are single ranges, however long.
- Selecting all selects every cell and leaves the active cell where it was.
- When the grid shrinks, the selection is held inside it.
- What is copied is the whole selection when it is one rectangle, and the active range when it is not.
- A rectangle held by a corner is redrawn from the opposite corner, which stays and is the active cell.
- A corner taken past the one that stays turns the rectangle over.
- A row's spans say of every column what the selection says of that cell.
- Rows with the same stake in a selection have the same spans, so they need not be drawn again.

## Reference implementation

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