j3w1 / theme

j3w1 / theme4.0.0

j3w1 / command

  • SPEC Overview
  • SPEC Foundations
  • SPEC Components
  • SPEC Patterns
  • SPEC Tokens
  • SPEC Tools
  • SPEC Workbench
  • SPEC Form builder
  • SPEC Task kit
  • SPEC Recipes
  • SPEC Figma bridge
  • SPEC Report an issue
  • SPEC Implement
  • SPEC For agents
  • SPEC Ports
  • SPEC Releases
  • SPEC Specification
  • DEMO Vue application demo

Number field

The text-field box around a native number input with right-aligned tabular digits, an optional unit affix and two square stepper buttons that replace the host spinner.

stable · light DOM · 4.0.0. Visible native controls retain FormData, labels, constraints, disabled fieldsets and reset. No duplicate form-value mechanism is installed.

Live variants

default

Between 1 and 20.

✕ Between 1 and 20.

Markup
<j3w1-number-field id="example-number-field-default"><div class="number-field">
  <label class="number-field-label" for="example-number-field-default-nf-workspaces">Workspaces</label>
  <div class="number-field-root">
    <input class="number-field-input" id="example-number-field-default-nf-workspaces" type="number" value="10" min="1" max="20" step="1" aria-describedby="example-number-field-default-nf-workspaces-help example-number-field-default-nf-workspaces-message" name="example-number-field-default-nf-workspaces">
    <span class="number-field-stepper">
      <button class="number-field-action" type="button" aria-label="Increase workspaces">+</button>
      <button class="number-field-action" type="button" aria-label="Decrease workspaces">−</button>
    </span>
  </div>
  <p class="number-field-help" id="example-number-field-default-nf-workspaces-help">Between 1 and 20.</p>
  <p class="number-field-message" id="example-number-field-default-nf-workspaces-message">✕ Between 1 and 20.</p>
</div></j3w1-number-field>

with-unit

Between 0 and 64 pixels; Up and Down step by one.

✕ Between 0 and 64.

Markup
<j3w1-number-field id="example-number-field-with-unit"><div class="number-field">
  <label class="number-field-label" for="example-number-field-with-unit-nf-gap">Inner gap (px)</label>
  <div class="number-field-root">
    <input class="number-field-input" id="example-number-field-with-unit-nf-gap" type="number" value="14" min="0" max="64" step="1" aria-describedby="example-number-field-with-unit-nf-gap-help example-number-field-with-unit-nf-gap-message" name="example-number-field-with-unit-nf-gap">
    <span class="number-field-unit" aria-hidden="true">px</span>
    <span class="number-field-stepper">
      <button class="number-field-action" type="button" aria-label="Increase inner gap">+</button>
      <button class="number-field-action" type="button" aria-label="Decrease inner gap">−</button>
    </span>
  </div>
  <p class="number-field-help" id="example-number-field-with-unit-nf-gap-help">Between 0 and 64 pixels; Up and Down step by one.</p>
  <p class="number-field-message" id="example-number-field-with-unit-nf-gap-message">✕ Between 0 and 64.</p>
</div></j3w1-number-field>

Install and register

Use the exact version. If npm publication is pending, install the release tarball from the installation guide.

npm install --save-exact @j3w1/ui@4.0.0
import '@j3w1/ui/tokens.css';
import '@j3w1/ui/styles/number-field.css';
import '@j3w1/ui/register/number-field';

Insert the maintained markup above after loading these imports. Its native children provide accessible names and form behavior; the empty custom tag alone does not create a control.

Vue SFC, React, Astro and plain HTML integration →

Copy the complete implementation

npx --package=@j3w1/ui@4.0.0 j3w1-ui copy number-field --out ./vendor/j3w1/number-field

The CLI verifies every file before writing and refuses overwrites. Serve the output over HTTP and open index.html. Keep its modules, CSS, tokens and licence notices together.

Public API

attributes

NameType / signatureMeaning
disabledCustomEventDisable the native controls owned by this instance.
loadingCustomEventMark the primary control busy and prevent duplicate activation.
valueCustomEventForwards value to the primary native control.
requiredCustomEventForwards required to the primary native control.
readonlyCustomEventForwards readonly to the primary native control.
checkedCustomEventForwards checked to the primary native control.

properties

NameType / signatureMeaning
disabledbooleanDelegates disabled state to native children.
namestringNative control name; application form keys remain explicit.
valuestringPrimary native value; assignment does not fabricate user events.
checkedbooleanNative checkbox state.
requiredbooleanNative required constraint.
readOnlybooleanNative readonly property.
formHTMLFormElement | nullOwning native form. Read only.

methods

NameType / signatureMeaning
refresh(): voidReconnect behavior after replacing native child structure.
focus(options?: FocusOptions): voidFocus the first usable native control.
checkValidity(): booleanCheck owned native constraints.
reportValidity(): booleanReport the first invalid owned control.
clear(): voidClear an editable primary input and emit native input/change.
stepBy(amount: number): voidStep a number input by the supplied number of native steps.

events

NameType / signatureMeaning
j3w1-changeCustomEventNative change from an owned control, alongside the original native event.

Dependencies and verification

Registered components: none. Style dependencies: none.

Package presence establishes an available implementation. Actual passes depend on the tested artifact and environment. Read specification execution evidence; read packed-consumer evidence; inspect the complete state matrix.

Full implementation manifest, API and token dependency closure

Canonical specification

Number field number-field

  • Family: Basic forms
  • Maturity: stable
  • Priority: R1
  • Since: 0.1.0
  • Native control: native <input type="number"> with <label>; stepper buttons are separate <button>s — APG pattern
  • specified
  • demonstrated

The text-field box around a native number input with right-aligned tabular digits, an optional unit affix and two square stepper buttons that replace the host spinner.

Report an issue with this component

Tokens

Focus a role to inspect its values; follow its link for persistent usage and source details.

PartRoleValueUse
root.bgcolor.surface.inputapproveduse#000000Form-control fill.
root.bordercolor.border.controlapproveduse#c81a1aD-041 owner correction: red control and floating-frame borders, distinct from rose text.
root.bg-hovercolor.interaction.hover.bgapproveduse#1c1010D-041 interaction.hover.bg: color.primitive.modern.hover.
root.border-focuscolor.border.activeobserveduse#e53935Active or focused control border.
root.ringcolor.interaction.focus.ringobserveduse#e539351px dashed focus ring on controls and rows.
root.ring-invalidcolor.interaction.focus.ring-containerobserveduse#ffa2a7Focus colour for containers and explicitly mapped filled controls (D-015); component rules determine ring geometry.
root.border-invalidcolor.status.danger.borderobserveduse#e53935Danger border, 2px on invalid inputs.
root.border-disabledcolor.border.disabledapproveduse#482b2bD-041 border.disabled: color.primitive.modern.divider.
root.bg-disabledcolor.interaction.disabled.bgapproveduse#0d0707D-041 interaction.disabled.bg: color.primitive.modern.panel.
root.border-readonlycolor.border.dividerapproveduse#482b2bD-041 border.divider: color.primitive.modern.divider.
root.bg-readonlycolor.surface.canvasapproveduse#000000Page and terminal background.
input.textcolor.text.defaultapproveduse#e99499D-041 owner correction: rose is the default UI and reading foreground; near-white is reserved for document headings, highlights and contrast-critical fills.
input.text-disabledcolor.text.disabledapproveduse#a3676bD-041 owner correction: rose is the default UI and reading foreground; near-white is reserved for document headings, highlights and contrast-critical fills.
input.caretcolor.code.caretapproveduse#ffa2a7D-041 owner correction: rose is the default UI and reading foreground; near-white is reserved for document headings, highlights and contrast-critical fills.
unit.textcolor.text.mutedapproveduse#d4868bD-041 owner correction: rose is the default UI and reading foreground; near-white is reserved for document headings, highlights and contrast-critical fills.
unit.bordercolor.border.dividerapproveduse#482b2bD-041 border.divider: color.primitive.modern.divider.
action.textcolor.action.tertiary.textapproveduse#e99499D-041 owner correction: rose is the default UI and reading foreground; near-white is reserved for document headings, highlights and contrast-critical fills.
action.bg-hovercolor.action.tertiary.hover-bgobserveduse#1c0a09Ghost and icon button hover.
action.bordercolor.border.dividerapproveduse#482b2bD-041 border.divider: color.primitive.modern.divider.
label.textcolor.text.brightapproveduse#ffa2a7D-041 owner correction: rose is the default UI and reading foreground; near-white is reserved for document headings, highlights and contrast-critical fills.
help.textcolor.text.mutedapproveduse#d4868bD-041 owner correction: rose is the default UI and reading foreground; near-white is reserved for document headings, highlights and contrast-critical fills.
message.textcolor.status.danger.textobserveduse#f07178D-041 readable error text on neutral surfaces and native warning tints.

State matrix

Every declared state and combination, statically rendered; the default cell is live. Sizes: compact, comfortable (switch with the density control above).

StateDefaultWith unit
default

Between 1 and 20.

✕ Between 1 and 20.

Between 0 and 64 pixels; Up and Down step by one.

✕ Between 0 and 64.

hover
focus-visible
invalid
invalid+focus-visible
disabled
read-only

Purpose

Entering a bounded number: a gap in pixels, a timeout, a count. The host spinner, tiny and inconsistent, gives way to two square buttons that are real tab stops. Free-form numeric text (a version, an identifier) is a text-field with inputmode.

Anatomy

Parts as listed in the anatomy; each stepper button is at least 24px wide.

States

StateVisualNon-colour channel
default1px color.border.control on color.surface.input; digits color.text.default; unit color.text.muted; stepper glyphs color.action.tertiary.text—
hoverbackground → color.interaction.hover.bg; a hovered stepper button → color.action.tertiary.hover-bgcursor: text on the input, pointer on the buttons
focus-visibleborder → color.border.active; 1px dashed color.interaction.focus.ring at −2px on the box or the focused stepper buttonthe ring
invalid2px color.status.danger.border; message with the ✕ glyphborder 1 → 2px; glyph; aria-invalid
invalid+focus-visiblethe 2px danger border and the ring in color.interaction.focus.ring-container at −4pxdouble boundary
disabledtext, unit and glyphs color.text.disabled; border color.border.disabled; background color.interaction.disabled.bg; buttons disableddisabled; cursor: not-allowed
read-onlyno box: 1px dotted color.border.divider bottom edge on color.surface.canvas; stepper hiddenreadonly; dotted edge; no buttons

Precedence: disabled > invalid > hover; focus-visible is always drawn.

Keyboard

A value outside the range may be typed; it is reported invalid on blur or submit, never clamped silently.

Accessibility

A programmatic label is required. The aria-hidden unit is repeated in the label or help (“Inner gap (px)”). Help states min, max and step before the user types. aria-invalid only after interaction or submit. Text meets 4.5:1; borders 3:1.

Portability

The text-field box plus two buttons; the host spinner is hidden with the engine’s pseudo-elements and appearance: textfield. A host whose spin buttons cannot be replaced styles them square in the same colours and records it.

Non-examples

The host’s default spinner. Round or overlapping stepper buttons. A value clamped silently. Left-aligned digits. A unit typed into the value. A number field for phone numbers, postcodes or identifiers. Invalid by colour alone. Disabling by opacity.

Contrast report

22 declared pairs measured on resolved sRGB values with the WCAG 2.x formula; 0 waived (decorative only), 0 failing. A pass is a design target for the named role, not an application-wide conformance claim.

PairStateKindForegroundBackgroundRatioMinResult
number-field default textdefaulttextcolor.text.default #e99499color.surface.input #0000009.164.5pass
number-field default borderdefaultuicolor.border.control #c81a1acolor.surface.input #0000003.623pass
number-field hover texthovertextcolor.text.default #e99499color.interaction.hover.bg #1c10108.104.5pass
number-field hover borderhoveruicolor.border.control #c81a1acolor.interaction.hover.bg #1c10103.203pass
number-field focus-visible textfocus-visibletextcolor.text.default #e99499color.surface.input #0000009.164.5pass
number-field focus-visible borderfocus-visibleuicolor.border.active #e53935color.surface.input #0000004.973pass
number-field focus-visible outlinefocus-visibleuicolor.interaction.focus.ring #e53935color.surface.input #0000004.973pass
number-field invalid textinvalidtextcolor.text.default #e99499color.surface.input #0000009.164.5pass
number-field invalid borderinvaliduicolor.status.danger.border #e53935color.surface.input #0000004.973pass
number-field invalid+focus-visible textinvalid+focus-visibletextcolor.text.default #e99499color.surface.input #0000009.164.5pass
number-field invalid+focus-visible borderinvalid+focus-visibleuicolor.status.danger.border #e53935color.surface.input #0000004.973pass
number-field invalid+focus-visible outlineinvalid+focus-visibleuicolor.interaction.focus.ring-container #ffa2a7color.surface.input #00000010.983pass
number-field read-only textread-onlytextcolor.text.default #e99499color.surface.canvas #0000009.164.5pass
unit affix on the input surface—textcolor.text.muted #d4868bcolor.surface.input #0000007.584.5pass
stepper glyphs on the input surface—textcolor.action.tertiary.text #e99499color.surface.input #0000009.164.5pass
stepper glyphs on their hover fillhovertextcolor.action.tertiary.text #e99499color.action.tertiary.hover-bg #1c0a098.354.5pass
validation message on the panel surface—textcolor.status.danger.text #f07178color.surface.default #0d07076.984.5pass
help text on the panel surface—textcolor.text.muted #d4868bcolor.surface.default #0d07077.224.5pass
disabled text (exempt; house floor 3:1)disableduicolor.text.disabled #a3676bcolor.interaction.disabled.bg #0d07074.483pass
disabled border (exempt)disableduicolor.border.disabled #482b2bcolor.interaction.disabled.bg #0d07071.581pass
affix and stepper dividers (decorative)—uicolor.border.divider #482b2bcolor.surface.input #0000001.661pass
read-only bottom edge (decorative; the field has no box)read-onlyuicolor.border.divider #482b2bcolor.surface.canvas #0000001.661pass

Keys

KeyAction
Tab / Shift+TabInput, then the increase button, then the decrease button.
Up / DownSteps by the step attribute (native); Shift+Up / Shift+Down step by ten where the host binds it.
Page Up / Page DownSteps by ten times the step where the host binds it.
Home / EndJumps to min or max where the host binds it.

For agents

Component JSON ·Implementation brief ·Build a task kit ·

Related: text-field field range search-field

Stress fixtures: FX-LONG FX-320 FX-ZOOM-200 FX-I18N FX-RTL FX-RM FX-HC FX-TOUCH FX-DENSITY FX-STATE-MATRIX