# Connecting

> Joining one port to another by a drag, by two presses or by keys, with the answer shown before the hand lets go.

Connecting is joining one thing to another by hand: a line pulled from a port
on one node to a port on another, a wire from a pin to a socket. It is a drag
with a question in it — may it end here? — and the answer should be visible
before the hand lets go.

## Best practices

**Show where it may end as soon as it begins.** The moment a connection is
begun, every port that can take it says so, and the rest draw back. People
should not have to try a port to find out.

**Draw the line as it goes.** From the port it began at to the pointer; and
once the pointer is within reach of a port that can take it, to that port, so
that what will happen on release is what is already shown.

**Be generous about where it ends.** A release ends on the nearest port that
can take it within reach, not only on one the pointer is exactly over. A hand
aims at a small thing from a distance; reach further for a finger than for a
mouse. Only ports that can take the connection draw it in: a port that cannot
does not catch a line meant for its neighbour.

**Refuse in the open.** A pointer on a port that cannot take the connection
shows the refusal there, on the port and on the line, while there is still time
to go elsewhere. A release there joins nothing and says why.

**Do not require a held button.** A click or a tap on a port begins a
connection, and a second on another port ends it. Holding a small thing down
while crossing a screen is hard for many hands and impossible for some.

**Give the keyboard the same thing.** Enter on a port begins a connection, and
focus goes to the nearest port that can take it. The arrow keys move among
those ports by direction, since they are scattered on a plane; Tab goes through
them in order. Enter joins; Escape gives it up and returns to where it began.
Say what is happening: where the connection is from, and how many ports can
take it.

**Let people change their mind.** Escape abandons a connection at any moment,
however it was begun, and is not also taken by whatever is around it. A release
over nothing joins nothing.

**Move an end, do not make people begin again.** The end of a line already
drawn can be taken hold of and carried to another port. The line it was is not
counted against it — it may return to the port it left — and until it is let go
on a port that takes it, nothing has changed.

**Carry the view along.** A line drawn toward the edge of the view moves the
view, so that a port out of sight can be reached; when a port that can take the
line comes under the pointer, the view stops there.

## Conventions

| Intent       | Pointer                            | Keyboard                           | Touch                           |
| ------------ | ---------------------------------- | ---------------------------------- | ------------------------------- |
| Begin        | Press a port and drag; or click    | Enter or Space on a port           | Drag from a port; or tap it     |
| Choose where | Move toward a port                 | Arrow keys; Tab, Shift-Tab         | Move toward a port              |
| Join         | Release within reach; or click     | Enter                              | Lift within reach; or tap       |
| Give up      | Escape; release or press elsewhere | Escape                             | Lift or tap elsewhere           |
| Move an end  | Drag the end of a selected line    | Enter on the connection, in a list | Drag the end of a selected line |

A release is within reach of a port at 12 pixels for a mouse, 16 for a pen and
28 for a finger.

See also [Dragging](https://ui.publictheta.com/foundations/drag.md), [Graphs](https://ui.publictheta.com/foundations/graph.md) and
[Diagram](https://ui.publictheta.com/components/diagram.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.

### Reach

- A release ends on the nearest port within reach; a point inside a port is no distance from it.
- Only the ports it may end on are in reach.
- What is found is within reach, and nothing allowed is nearer.
- A finger reaches further than a pen, and a pen than a mouse: 28 pixels, 16 and 12.

### By a drag

- A press on a port, dragged to another and released there, joins them.
- While it lasts every port says what it is to it: where it began, where it may end, where it would end now, and the rest.
- A release near a port it may end on ends on it: within twelve pixels for a mouse, and no further.
- A release on a port it may not end on is refused, and says which; nothing is joined.
- Being near a port it may not end on says nothing: only the pointer on it does.
- A release on no port joins nothing, and says where it was.
- Escape during the drag takes it back: nothing is joined, and the release that follows does nothing.
- A drag from something that stands for a port — the end of a line — begins from that port, and brings back what it was given.
- Its beginning is told, with the ports it may end on.
- Each move of a drag is told, with the port it would end on, and its end: for a view to be moved along under it.
- A finger's drag ends on a port within its wider reach. *(Chromium (touch), WebKit (touch))*

### By two presses

- A click on a port begins from it, and a click on another ends there: nothing need be held down.
- A tap on a port, then a tap on another, joins them. *(Chromium (touch), WebKit (touch))*
- A finger that rests on a port before lifting has pressed it all the same, and once. *(Chromium (touch), WebKit (touch))*
- A click on a port it may not end on is refused, and it is still being made.
- A press anywhere else gives it up, and so does a second click on the port it began from.
- Escape gives it up, wherever focus is.
- The port under the mouse is where it would end, if it may end there. *(Chromium, Firefox, WebKit)*

### By the keyboard

- Enter on a port begins from it, and focus goes to the nearest port it may end on.
- The arrow keys move among the ports it may end on, by direction, and stay where nothing lies that way.
- Tab and Shift-Tab go through the ports it may end on, in order, round and round: Tab does not leave.
- Enter on a port it may end on joins it, and focus stays there.
- Escape gives it up and returns focus to the port it began from, and is not heard by what is around.
- From a port with nowhere to go, Enter begins nothing, and says so.
- Before a connection is begun, the arrow keys and Tab are not the ports'.

## Reference implementation

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