Capítulo 31 de 51

Chapter 31: Number Field

Core Idea

A numeric input with increment/decrement buttons and an optional drag-to-scrub area — locale-aware formatting/parsing, configurable step sizes (including modifier-key small/large steps), and a scrub gesture (click-drag to change value, like a video editor's numeric field) baked in.

Key Concepts

  • Anatomy: RootScrubAreaScrubAreaCursor; GroupDecrement, Input, Increment.
  • Scrubbing: ScrubArea (typically a label or icon next to the input) lets users click-drag horizontally/vertically to change the value; direction sets the drag axis, pixelSensitivity sets drag-distance-per-unit, teleportDistance controls cursor-wrap behavior at screen edges. allowWheelScrub extends the same idea to mouse-wheel-over-input. ScrubAreaCursor renders a custom cursor during the drag; data-scrubbing marks every part while a scrub is active.
  • Stepping: step (default increment), smallStep/largeStep (modifier-key-adjusted increments, typically Shift/Alt), snapOnStep (whether values snap to the step grid).
  • Formatting: format (an Intl.NumberFormat-style options object) + locale control both display formatting and parsing of typed input — critical for non-US decimal/thousands separators (v1.5.0 added Persian digit support here).
  • Range: min/max; allowOutOfRange permits typing a value outside that range before it's clamped/rejected (vs. hard-clamping as you type).
  • onValueCommitted vs. onValueChange: onValueChange fires per keystroke/scrub-tick, onValueCommitted fires once the value is finalized (blur, Enter, scrub release) — use committed for anything expensive (server sync, heavy re-render).

Reference Tables

PartNotable propsNotable data attributes
Rootvalue/onValueChange/onValueCommitted, min/max, step/smallStep/largeStep, snapOnStep, format, locale, allowOutOfRange, allowWheelScrubdata-scrubbing, plus shared field-state attributes
ScrubAreadirection, pixelSensitivity, teleportDistancedata-scrubbing
Decrement/IncrementnativeButtonshared field-state attributes

Key Takeaways

  1. Always set locale (or rely on the app's global locale context if the library reads one) — number parsing bugs from unhandled decimal-separator differences are the most common Number Field integration mistake.
  2. Use onValueCommitted, not onValueChange, for expensive side effects — onValueChange fires continuously during a scrub gesture.
  3. Reserve ScrubArea for contexts where a mouse/trackpad drag gesture makes sense (design tools, dashboards) — it adds no value on touch-primary interfaces and should be paired with the normal Increment/Decrement buttons regardless.

Connects To

  • ch009 (Forms) / ch023 (Field): standard labeling/validation wrapper, same as every form control.
  • ch026 (Input): plain-text sibling when numeric formatting/stepping isn't needed.