# Canvas

> A plane that pans and zooms, on which things are placed, selected, moved and resized by hand.

A canvas is a plane, larger than the screen, on which things are placed and then
arranged by hand: selected, moved, resized, lined up. It is the ground that
drawing tools, layout tools, diagrams and node editors stand on.

## When to use

Use a canvas when where a thing is, and how large, is itself what people are
deciding. When things have an order but no position, a
[listbox](https://ui.publictheta.com/components/listbox.md) or a [data grid](https://ui.publictheta.com/components/data-grid.md) says so
more plainly, and is far easier to use without a pointer.

## Best practices

**Move the view as paper under the hand.** Scrolling moves the view; a pinch,
or the wheel with the command key, zooms about the point under the pointer; a
drag with Space held, or with the middle button, pulls the plane about. Offer
"fit everything", "fit the selection" and "actual size" by name. See
[Pan and zoom](https://ui.publictheta.com/foundations/viewport.md).

**Select as collections do, and by area.** A click selects one thing; with
Shift or the command key it adds a thing or takes it out; a click on empty
space clears. A drag from empty space draws a marquee that selects what it
touches — with Alt, only what lies wholly inside it; with Shift, in addition to
what was selected. A press on one of several selected things keeps them all, so
that a drag can begin from it. See [Selection](https://ui.publictheta.com/foundations/selection.md).

**Move everything selected together.** Dragging a selected thing moves every
selected thing by the same distance. A press on a thing that is not selected
selects it first, and the drag moves it alone.

**Help things into line, visibly, and offer a way out.** What is moved or
resized comes to rest in line with the edges and middles of what is around it,
and shows the line it found. Holding Control or the command key moves freely;
holding Shift keeps a move to one direction. See [Snapping](https://ui.publictheta.com/foundations/snap.md).

**Resize by handles.** One selected thing shows handles at its corners and
sides; several show one frame around them all. See
[Resizing](https://ui.publictheta.com/foundations/resize.md).

**Let the application say where things may go.** A frame things must stay
within, lanes, a minimum size: apply the rule to every place a thing is shown
at while it is dragged, not only to where it is dropped, so that what people
see is what they will get.

**Lock what should stay put.** A locked thing is not moved, resized, or caught
by a marquee, and a press on it is a press on the plane beneath — a locked
background does not get in the way of a marquee drawn over it. It can still be
reached from the keyboard, and says that it is locked.

**Make one gesture one change.** A drag is reported once, when it ends, as the
places of every thing it changed before and after, so that one undo takes back
the whole of it. Each press of an arrow key is likewise one change. Escape in
the middle of a drag puts everything back, and nothing is reported. See
[Undo and redo](https://ui.publictheta.com/foundations/history.md).

**Carry the view along.** A drag held near the edge of the view — of a thing,
a handle, a marquee — moves the view that way, faster the further it goes, and
what is dragged stays under the pointer. An edge pulls only a drag that has
travelled toward it, so that picking up something beside an edge moves nothing.
Escape puts the view back with everything else.

**Copy by dragging with Alt.** A drag with Alt held leaves the originals where
they were and makes copies where the drag ends. Mark the originals' places
while it lasts.

**Leave the content of a thing to itself.** A field inside a thing is typed in
as anywhere, and a press on it does not drag the thing. Where a thing has a
part made to be dragged by — a title bar — only that part drags it, and a press
elsewhere on it selects.

**Give what is drawn between things a layer of the plane.** The lines of a
diagram, a grid, a ruler: drawn on the plane itself, beneath the things or over
them, so that they move and scale with it and need no moving of their own.

**Stay immediate among thousands.** Draw only what is in and around the view;
move the plane, not each thing on it, when the view moves; find what a marquee
touches, and what a drag may align with, by looking near it rather than at
everything.

**Hold together far from zero.** A plane has no edges. Place what is drawn
relative to somewhere near the view, so that things a hundred million units
away are drawn as exactly as those at the origin.

## Conventions

| Intent                 | Pointer                                  | Keyboard                             | Touch                                   |
| ---------------------- | ---------------------------------------- | ------------------------------------ | --------------------------------------- |
| Move between things    | —                                        | Tab, Shift-Tab; Home, End            | —                                       |
| Move to a thing nearby | —                                        | Alt with an arrow key                | —                                       |
| Select one thing       | Click                                    | Space on the focused thing           | Tap                                     |
| Add or remove a thing  | Shift-click, Command-click               | Space on the focused thing           | Tap                                     |
| Select by area         | Drag from empty space                    | —                                    | Hold, then drag, from empty space       |
| Select all; clear      | Click empty space to clear               | Command-A; Escape                    | Tap empty space to clear                |
| Move the selection     | Drag a selected thing                    | Arrow keys; with Shift, by ten       | Drag a thing                            |
| Resize the selection   | Drag a handle                            | Command with the arrow keys          | Drag a handle                           |
| Move freely; one axis  | Hold Control or Command; hold Shift      | —                                    | —                                       |
| Copy                   | Drag with Alt                            | —                                    | —                                       |
| Pan                    | Scroll; drag with Space or middle button | Arrow keys, when nothing is selected | Drag empty space; drag with two fingers |
| Zoom                   | Pinch; wheel with Command or Control     | Command-Plus, Command-Minus          | Pinch                                   |
| Fit; actual size       | —                                        | Shift-1, Shift-2; Command-0          | —                                       |
| Act on a thing         | Double click                             | Return                               | —                                       |
| Cancel a drag          | —                                        | Escape                               | —                                       |

Command is ⌘ on Apple platforms and Ctrl elsewhere.

## Platform considerations

**Keyboard.** Everything can be done without a pointer. Tab enters the canvas
on one thing — the one last focused, else the first selected, else the first in
reading order — and from there Tab and Shift-Tab go through the things in
reading order: in rows from the top, and along each row from the side reading
starts at. Past the last thing, and before the first, Tab leaves the canvas, so
that it is never a trap. Alt with an arrow key goes to the nearest thing in
that direction — the nearest within 45° of it, or failing that the nearest that
way at all — as it moves between panes elsewhere; where nothing lies that way
focus stays, and the key is still the canvas's, not the browser's to go back
with. Moving focus does not change the selection; Space does. The arrow keys move what is selected by one unit, exactly, without
snapping — and move the view when nothing is selected. A thing that focus
reaches, or that the keyboard moves out of view, is brought into view.

**Pointer.** A secondary press selects the thing under it unless that thing is
already selected, so that a menu opened there acts on what it appears over.

**Touch.** A tap adds a thing to the selection or takes it out, since a finger
has no modifier keys. One finger dragged from a thing moves it; from empty
space it moves the view; held still for half a second first, it draws a
marquee. Two fingers always move and zoom the view, about the point between
them, and a finger added to a drag already under way does not take it over. A
handle's target is at least 44 pixels across.

**Pen.** A pen selects as a finger does, on a tap, and drags as a mouse does:
from empty space it draws a marquee.

**Right to left.** The plane does not mirror: its coordinates are geometry, and
an arrow key moves a thing the way the arrow points. What follows the writing
direction is the order in which Tab goes through the things.

**Motion.** Zooming to a named scale and fitting are immediate. Nothing moves
that the person did not move.

**Forced colours.** The frame of a selected thing, the handles, the marquee,
the guides and the focus ring are drawn in the system's own highlight and text
colours, so that they remain visible when the system replaces the page's.

**Assistive technology.** The canvas is exposed as an application, because its
keys are its own: it has a name, and describes its keys. Each thing is a named
group that says when it is selected and when it is locked, and holds focus
itself. What cannot be seen happening is said: how many things are selected
after the keyboard changed the selection; where a thing is after a move, and
how large after a resize.

## 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.

### Semantics

- The canvas is an application with a name, and says how its keys work.
- Each item is a group with its name.
- An item says when it is selected, and when it is locked.
- It has no accessibility violations, with items selected and locked.
- Where the system forces its colours, the selection, its handles and the marquee take the system's highlight.

### The view

- The wheel scrolls the view, and with Shift scrolls it sideways. *(Chromium, Firefox, WebKit)*
- The wheel with Control or Command zooms about the pointer: what is under it stays under it. *(Chromium, Firefox, WebKit)*
- A wheel over the canvas does not scroll or zoom the page. *(Chromium, Firefox, WebKit)*
- A trackpad's pinch, where it is reported as a gesture of its own, zooms about the pointer.
- Zoom stops at its limits, and the view does not creep there.
- Dragging with Space held moves the view by as far as the pointer, and selects nothing.
- While Space is held the canvas shows that it can be grabbed, and while it is dragged, that it is.
- Dragging with the middle button moves the view.
- Escape during a drag of the view puts the view back.
- Two fingers move the view with the point between them, and zoom it as they part.
- A pinch on a touchscreen zooms about the point between the fingers. *(Chromium (touch))*
- Command with Plus and Minus step through the named scales, about the middle of the view.
- Command-0 returns to actual size.
- Shift-1 fits everything in the view, and Shift-2 fits the selection.
- Zooming and fitting are immediate: nothing animates.
- With nothing selected, the arrow keys move the view; with Shift, ten times as far.
- The plane is one element: moving the view moves it, and places no item anew.

#### Among ten thousand items

- Only the items in and around the view are drawn.
- Moving the view draws only the items that come into it.
- A marquee selects exactly what it touches.
- An item out of view, and so not drawn, is drawn, focused and brought into view when the keyboard reaches it.
- Dragging an item takes its lines from what is near the view, not from all ten thousand.

### Selection

- A click selects only that item.
- Shift-click and Command-click add an item to the selection, or take it out.
- A click on empty space clears the selection; with Shift it is kept.
- A press on one of several selected items keeps them all until it ends as a click on that one.
- A secondary press selects the item it lands on only if that is outside the selection. *(Chromium, Firefox, WebKit)*
- Command-A selects every item that is not locked.
- An item activated by assistive technology, which presses nothing, is selected or taken out.
- Escape clears the selection.

#### Marquee

- A drag from empty space draws a marquee, which selects what it touches.
- What a marquee no longer touches is no longer selected.
- With Alt held, a marquee selects only what lies wholly within it.
- With Shift held, a marquee adds to what was selected.
- Escape during a marquee puts the selection back as it was.

#### Locked items

- A locked item does not answer the pointer: a click on it clears the selection, as on empty space.
- A drag from a locked item draws a marquee, which does not catch it.
- A locked item can be focused, and selected from the keyboard.
- A locked item among the selected is not moved, and not resized.
- A locked item shows no handles.

#### Touch

- A tap adds an item to the selection or takes it out, since a finger has no modifier keys. *(Chromium (touch), WebKit (touch))*
- A tap on empty space clears the selection. *(Chromium (touch), WebKit (touch))*
- One finger dragged over empty space moves the view.
- A finger held still on empty space, then dragged, draws a marquee.
- A finger's hold does not open the system's menu, and is not ended by it.
- A mouse's secondary press still opens its menu.
- A pen dragged from empty space draws a marquee, as a mouse does.
- A finger held and lifted without moving draws nothing.
- A finger dragged from an item moves that item, selecting it if it was not.
- A second finger does not take over a drag already under way.

### Moving

- Dragging an item moves it by as far as the pointer goes.
- Zoomed in, an item still moves as far on the screen as the pointer does.
- A press on an unselected item selects it, and the drag moves it alone.
- Dragging one of several selected items moves them all together, and keeps them selected.
- A press too short to be a drag moves nothing.
- Escape during a drag puts everything back, and no change is reported.

#### Snapping

- What is moved comes to rest in line with a neighbour, and the line is shown for as long as it holds.
- Each direction snaps by itself, to a different neighbour.
- The reach of a snap is measured on the screen: zoomed in, a thing rests a hair off the line.
- With Control or Command held, it moves freely; let go, it snaps again.
- With Shift held, it keeps to the direction it has moved farther in.
- Where there is a grid and no neighbour nearer, a corner comes to rest on it.
- Snapping can be turned off.
- What is moved is not drawn back to where it was.
- A grid holds where snapping to neighbours is turned off, and Control moves free of it too.

#### By the keyboard

- The arrow keys move the selection by one unit, and by ten with Shift, never snapping.
- Every selected item moves, and each key is one change.
- A move is announced with where the selection now is.
- What the keyboard moves out of view is brought back into it.

#### Parts of an item

- An item that names a part to be dragged by is dragged only by it; a press elsewhere on it still selects.
- A field inside an item is typed in as anywhere, and a drag begun in it moves nothing.
- Tab goes through what an item holds before going on to the next item.
- A drag with Alt held leaves the original where it was, and asks for a copy where the drag ended.

#### At the edge of the view

- A drag held near the edge of the view moves the view along, and what is dragged stays under the pointer.
- However late a frame comes, what is dragged is drawn under the pointer in the frame the view moves.
- A drag begun beside an edge does not move the view until it heads for that edge.
- A marquee drawn to the edge moves the view along, and goes on growing over what comes into view.
- Escape during a drag that moved the view along puts the view back too.
- Dragging the view itself to an edge moves it no further than the pointer went.

### Resizing

- A selected item shows a handle at each corner and in the middle of each side.
- Handles are sized on the screen: the same at any zoom.
- A side too short on the screen to carry a handle clear of its corners has none.
- Under a finger a handle's target is 44 pixels across, and looks no larger. *(Chromium (touch), WebKit (touch))*
- A target reaches no more than a quarter of the way into a small item, which can still be taken by its middle. *(Chromium (touch), WebKit (touch))*
- Dragging a handle moves the edges it sits on, and leaves the opposite ones.
- With Alt held, it resizes about its centre.
- With Shift held, it keeps its proportion.
- An edge dragged past the one opposite stops at the least size: the item does not turn inside out.
- A resized edge comes to rest on a neighbour's line, and the line is shown.
- Escape during a resize puts the size back.
- Several selected items show one frame, and resize in proportion within it.
- No item of several goes below the least size: the frame stops where the smallest would.
- Command with the arrow keys resizes the selection from its top-left corner, by one unit or ten with Shift.
- A resize by the pointer is announced with the new size.

### Constraints

- An item dragged past a bound stops at it: every place it is shown at has passed the constraint.
- A resize is held by the constraint too, and told that it is a resize.
- The keyboard is held by the same constraint, and a key that changes nothing reports nothing.
- A guide is shown only where the item, as the constraint left it, lies on the line.

### Keyboard and focus

- Tab into the canvas lands on one item: the first in reading order, wherever it is among the items.
- Tab and Shift-Tab move through the items in reading order, and past either end leave the canvas.
- Moving focus does not change the selection.
- Home and End go to the first and the last item.
- Space selects the focused item or takes it out of the selection, and says how many are selected.
- The keyboard alone moves an item: Tab to it, Space, then the arrows.
- An item reached by the keyboard is brought into view, by the least movement.
- An item taken by the pointer is not moved under it by being focused.
- Once the press is over, an item given focus by the application is brought into view.
- Focus returns to the item it was last on.
- Right to left, reading order starts from the right; the plane and the arrow keys do not mirror.
- When the item that has focus is taken away, focus stays in the canvas.
- A canvas with nothing on it takes focus itself.
- Alt with an arrow key moves focus to the nearest item in that direction, and changes nothing else.
- Where nothing lies that way focus stays, and the key is still the canvas's: the browser does not go back.
- Alt with an arrow key in a field inside an item is the field's.

### Layers

- What is drawn in a layer moves and scales with the plane: beneath the items, or over them.
- A layer is told where what is being dragged is shown, for as long as the drag lasts.
- A hundred million units from zero, a layer draws from a point near the view, in small numbers.

### Robustness

- An item a hundred million units from zero is drawn where it should be.
- An item taken away in the middle of a drag is not among the changes.
- When its owner turns a change down, the item is shown where its owner says it is.
- A canvas with no size draws its items, and its keys do no harm.
- Unmounting in the middle of a drag leaves no listener behind.
- Unmounting with fingers down leaves no listener behind.

## Reference implementation

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