Skip to the page
TACTILE UI

Kit part · Forms · Steppers

Stepper

A small integer with − and + keys either side, in one well.

Element
<input type="number">
Needs
kit.css
Rules
field.rules.md · 5
Finishes
Aluminium · Graphite · Porcelain · Black
Volumes
Tactile · Quiet
On this page
  1. Variants
  2. Every state, at once
  3. API
  4. Markup
  5. Accessibility
  6. How it’s built
  7. Rules
  8. Related parts
01

Variants

Copies
In a settings row
02

Every state, at once

Both finishes, side by side. Hover, pressed and focus are forced with .is-hover, .is-down and .is-focus; checked and disabled are real.

Aluminium

PartRestPressing +Focus
Stepper

Graphite

PartRestPressing +Focus
Stepper
03

API

NameKindValuesWhat it does
.tui-stepperclass—One well, 3px inside: key, number, key.
input[type=number]elementmin · max · stepNative: 5ch wide, centred, tabular, spinner hidden.
.tui-keyclassinside28px square keys with a 1.5px skirt.
data-stepattribute-1 · 1Read by the few lines of script above; the kit does not wire the keys itself.
changeevent—Native from typing; dispatch it yourself from the keys.
Arrowskeyboard—Native number input: Up and Down step it.
04

Markup

<div class="tui-field">
  <span class="tui-label" id="take-l">Take</span>
  <div class="tui-stepper">
    <button class="tui-key" aria-label="Fewer takes" data-step="-1">−</button>
    <input type="number" value="12" min="1" max="99" aria-labelledby="take-l">
    <button class="tui-key" aria-label="More takes" data-step="1">+</button>
  </div>
</div>
// kit.css draws the stepper; the two keys need these lines.
for (const key of document.querySelectorAll('.tui-stepper [data-step]')) {
  key.addEventListener('click', () => {
    const input = key.parentElement.querySelector('input');
    key.dataset.step > 0 ? input.stepUp() : input.stepDown();
    input.dispatchEvent(new Event('change', { bubbles: true }));
  });
}

Needs kit.css only, no script. How to install the kit.

05

Accessibility

  • Give each key an aria-label that says what it does: “More takes”, not “+”.
  • Name the number with aria-labelledby pointing at the printed label.
  • Set min and max, so the keys and the arrows stop where the value does.
06

How it’s built

A native number input between two kit keys, in one recess. The spinner is hidden and the focus ring moved to the whole well with :has(). The kit does not ship script for the keys: they are eight lines, shown above, using the input’s own stepUp() and stepDown().

07

Rules

field.rules.mdIn the brain

Steppers are for small integers only.

5 rules in this file, with the foundations they rest on and the anti-patterns that break them. Full rules ship in the brain with the Pass.

08

Field

Text entry in a recess, the label printed above it, and a hint that says how to fix an error.

Combo

One field with its one action in a shared well: subscribe, search, add.

Fader

A continuous value along a line: a native range whose cap rides in a slot cut into the plate, with a printed scale.

Docs
Finish
Volume