# Number field

> A single numeric value, typed with arithmetic and units or stepped with the keys, committed when people are done.

A number field takes a single numeric value, typed, stepped or dragged. It is
the workhorse of inspectors, forms and settings, and it should feel like nothing
at all: whatever people type, paste, step or drag should simply become the value
they meant.

## When to use

Use a number field when the value is exact and people know it, or work it out.
When the value is approximate and its position within a range matters more than
its exact figure, a slider shows that directly; many interfaces pair the two.

## Best practices

**Edit as every typed field does.** Typing is left alone, the value is read at
commit, Escape takes an edit back, and an input method is allowed to finish; see
[Editing values](https://ui.publictheta.com/foundations/use-field.md).

**Show the unit, and label the field.** A field without a unit leaves people to
guess what it measures; a field without a label leaves assistive technology
nothing to announce.

**Tell a change from its end.** While an arrow key is held, a label is dragged
or a button is held down, the value passes through many values: show each as it
is reached, so that what the number controls follows. Report the whole as one
change when it ends — the key let go, the pointer released — so that it is one
entry to undo and expensive work runs once. A commit of what was typed is a
change and its end at once. Nothing ends that left the value where it was.

**Let the label be dragged, where values are set by eye.** In an inspector,
dragging sideways across a field's label — or a letter or icon at the start of
the field — changes the value a step at a time, as the arrow keys would; see
[Scrubbing](https://ui.publictheta.com/foundations/scrub.md). A click on the label still gives the field
focus. In a form, where a value is known and typed once, leave the label alone.

**Let a cycle go round.** An angle or an hour has no ends: a step past the
maximum arrives from the minimum, and a typed value beyond the range is read
round it — 370° is 10°. The maximum is the minimum again and is shown as the
minimum: 360° is 0°. Nothing was limited, so nothing is said or marked. A range
is a cycle only when it has both ends.

**Say in words what the field shows by a mark.** When a typed value was held
within the range, say so, with the limit as the field shows it: "Limited to 100
mm." When text could not be read, say why, and make that the field's description
for as long as it is invalid. Say nothing while people type, and nothing about a
value that was only rounded or stepped to the end of its range. Where whatever
contains the field already marks it invalid and gives the reason, the field
leaves the words to it.

## Platform considerations

**Keyboard.** Up and Down Arrow step; Shift makes a step ten times larger and
Option or Alt ten times smaller; Page Up and Page Down step by ten. A key held
down repeats.

**Pointer.** A press that brings focus selects the value, so that typing
replaces it. A label or handle that can be dragged shows a sideways resize
cursor.

**Touch.** The field is at least 44 CSS pixels tall. It offers a number pad only
where a plain number of zero or more is all there is to type — with a decimal
point unless the value is whole. A phone's number pads have no minus sign, no
letters and no percent sign, so a field that takes a negative number, a unit or
a percentage offers the full keyboard, which has them. A number pad may have no
key to finish with either: leaving the field commits, as it does everywhere.

A phone has no arrow keys. Where stepping matters, offer a button on either side
of the field to decrease and increase, each at least 44 CSS pixels square. A
press steps once; held down, a button steps again after a moment and then faster
and faster, until it is let go, the finger slides off it, or the value reaches
the end of its range — where that button is no longer offered. A press on a
button leaves focus where it was, so no keyboard appears or disappears. With a
mouse and a keyboard at hand the buttons are clutter: show them there only where
they are the point, as in a quantity.

A label is dragged with a finger as with a mouse, and only sideways: a drag up
or down that begins on it still scrolls the page.

**Assistive technology.** The field is a spin button with its value, its range,
and the value with its unit as read aloud — while the text is that value. While
another is being typed, the field states none. The buttons that step are named
— "Decrease", "Increase", in the language of the interface — say which field
they control, and are left out of the Tab order, since the field's own arrow
keys step; activated without a pointer, each steps once. A handle inside the
field is decoration: the field keeps its one name. What the field says in words
is said politely, once, when it becomes true.

See also [Numbers](https://ui.publictheta.com/foundations/number-type.md) and
[Scrubbing](https://ui.publictheta.com/foundations/scrub.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.

### Semantics

- Is a spin button with its value, range, and the value as read aloud.
- While another value is being typed, the field does not state the one it holds.
- Has no accessibility violations, valid or invalid.
- Has no accessibility violations with a label that scrubs, a handle, and buttons that step.

### Typing and committing

- What is typed is left as typed until it is committed.
- Enter commits, and the value is shown in the locale's format.
- Leaving the field commits.
- Arithmetic commits as its result.
- Text pasted from elsewhere — another locale, full-width digits — commits as a number.
- A value in another unit is converted to the field's.
- A value beyond the range commits as the nearest end of it.
- A value is rounded to the field's precision.
- Text that is not a number stays as typed, marked invalid, and the value is unchanged.
- A press that brings focus selects the value, so that typing replaces it. *(Chromium, Firefox, WebKit)*
- Escape abandons the edit and shows the last value again.
- With nothing to abandon, Escape is left for what contains the field.
- Clearing the field commits no value, unless a value is required.
- The field follows the document's language when given none.

### Stepping

- Up and Down Arrow add and subtract a step.
- With Shift a step is ten times larger, with Alt ten times smaller.
- Page Up and Page Down step ten at a time.
- Stepping starts from what is typed, when it is a number.
- Stepping stops at the ends of the range.
- In a range that is a cycle, a step past one end arrives from the other.
- A typed value beyond a cycle is read round it — the maximum is the minimum again — and nothing was limited.

### Scrubbing

- Dragging sideways across the field's label changes the value: a step for every two pixels.
- A click on the label still gives the field focus; the release of a scrub does not.
- With Shift a scrubbed step is ten times larger, with Alt ten times smaller.
- A scrub lands on multiples of the step, as stepping does.
- A scrub stops at the end of the range, and a drag back from beyond it moves the value at once.
- In a range that is a cycle, a scrub goes round it.
- In a field written right to left, a drag to the left raises the value.
- A scrub starts from what is typed, when it is a number.
- Escape during a scrub puts back the value it began from, and the rest of the drag changes nothing.
- A handle at the start of the field scrubs as the label does, and a click on it gives the field focus.
- What scrubs shows a sideways resize cursor and keeps a sideways drag for itself; the field, and the page, are as they were.
- A pen and a finger scrub the label as a mouse does.
- A finger dragged sideways across the label scrubs. *(Chromium, Chromium (touch))*
- A field that cannot be changed is not scrubbed, and its label does not offer to be.

### Buttons that step

- They are offered where the pointer is a finger — elsewhere only when asked for always.
- Each has a name, says which field it controls, and is outside the Tab order: the field's own keys step.
- A press steps once.
- A tap steps once, on a target at least 44 pixels square. *(Chromium (touch), WebKit (touch))*
- Held down, a button steps again after a moment and then faster and faster.
- A held button stops at the end of the range, where it is no longer offered.
- In a range that is a cycle, neither button reaches an end.
- The pointer leaving a held button ends the hold.
- A finger held on a button goes on stepping, until it slides off. *(Chromium, Chromium (touch))*
- A press the browser cancels, and the window losing focus, end the hold.
- A press on a button leaves focus where it was, and steps from what is typed.
- A button activated without a press, as assistive technology does, steps once.
- A field that cannot be changed offers neither button.

### Said in words

- A typed value that was held within the range is said to have been, with the limit as it is shown.
- A value that was only rounded, or stepped to the end of the range, is not said to have been limited.
- Why text could not be read is said, and is the field's description while it is invalid.
- An empty field that needs a value says so.
- Nothing is said while typing: not of what is being typed, nor again of what was typed before.

### Input methods

- A composition is neither read nor reformatted until it is confirmed and committed. *(Chromium, Chromium (touch))*
- A key that belongs to a composition does not commit the field.

### Touch

- Where only a number of zero or more can be typed, a touchscreen offers a number pad.
- Where a minus sign, a unit or a percent sign may be typed, it offers the full keyboard, which has them.
- On a touchscreen, the field is at least 44 pixels tall. *(Chromium (touch), WebKit (touch))*

## Reference implementation

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