Перейти до вмісту
tatetUI

NumberInput

Числове поле зі степерами, групуванням тисяч і повною клавіатурою — без нативного type=number.

Кількість, ціна, знижка, вага — усе, де число вводять руками, а помилка на порядок коштує грошей.

Стрілки ↑/↓ змінюють на 1, PageUp/PageDown — на 10

Разом: 12 шт., знижка 15 %

Чому не type="number"

Нативне числове поле здається очевидним вибором і не годиться відразу з трьох причин:

  1. Воно не приймає згрупований рядок. «14 762,50» для нього невалідне значення, тобто групування тисяч вимкнене назавжди.
  2. Воно малює власні стрілки — поруч із нашими кнопками «−»/«+».
  3. Для невалідного вводу воно повертає порожній рядок — рівно те саме, що й для порожнього поля. Відрізнити «користувач нічого не ввів» від «користувач ввів казна-що» неможливо.

Тому тут type="text" плюс inputmode="decimal" (числова клавіатура на телефоні) плюс role="spinbutton" з aria-valuenow/min/max. Роль обов'язкова: без неї скрінрідер оголошує звичайне текстове поле, і робота стрілок виглядає як поламка.

Розбір значення розуміє український запис: кому як десятковий роздільник і нерозривний пробіл як роздільник тисяч. Number.parseFloat на «1 234,5» повернув би 1.

Видимий рядок — не модель

Клацніть у поле — групування зникне на час редагування

У фокусі поле показує сире число, поза фокусом — згруповане. Це вимагає тримати видимий рядок окремо від моделі й синхронізувати його з неї лише поки поле не у фокусі.

Інакше відбувається таке: користувач набирає «1,», батько отримує 1, повертає його назад у поле, рядок перетворюється на «1», а каретка стрибає в кінець. Проміжні стани — «1,», «-», «0,00» — парсяться в число, але переписувати рядок на них не можна.

Клавіші ArrowUp/ArrowDown, PageUp/PageDown і Home/End одразу оновлюють і модель, і видимий сирий рядок; після blur рядок знову локалізується.

API

Props

НазваТипТиповоОпис
modelValuenumbernullЗначення. Порожнє поле — `null`, ніколи не `NaN`. Через `v-model`.
sizeFieldSize"md"Висота поля. На мобільному кожен розмір вищий за десктопний.
stepnumber1Крок стрілок і кнопок «−»/«+».
precisionnumber0Скільки знаків після коми лишати. Округлення відбувається на blur.
namestring
labelstring
placeholderstring
errorstringТекст помилки. Стан помилки вмикає САМА наявність тексту.
hintstringПідказка під полем. Ховається, коли показано помилку.
idstring
minnumberНайменше допустиме значення.
maxnumberНайбільше допустиме значення.
stepFastnumberКрок PageUp/PageDown. Типово — `step` × 10.
unitstringСуфікс одиниці: %, грн, шт. Потрапляє і в `aria-valuetext`.
formatOnBlurbooleantrueГрупувати тисячі, поки поле поза фокусом. У фокусі показується сире число: редагувати рядок із нерозривними пробілами неможливо.
steppersbooleantrueКнопки «−» і «+». Без них лишається чистий числовий ввід.
requiredboolean
disabledboolean
readonlyboolean

Події

НазваPayloadОпис
update:modelValue[value: number]Нове значення або `null`, якщо поле порожнє. Використовуйте через `v-model`.
change[value: number]Значення, зафіксоване після втрати фокуса або натискання степерів.

Доступно через ref

НазваТипОпис
focus() => voidСтавить фокус на поле.
select() => voidВиділяє весь текст у полі.

Коли використовувати

  • Кількість, ціна, відсоток, вага — будь-яке число з відомим кроком.
  • Поля, де стрілки з клавіатури природні: коригування на одиницю.
  • Значення з межами, які треба показати користувачу.

Коли НЕ використовувати

  • Для номера телефону, картки, рахунку: це не числа, а рядки цифр, і крок для них не має сенсу. Беріть UiInput.
  • Для коду підтвердження — UiInputOtp.
  • Для вибору з діапазону, де точне значення не важливе — UiSlider.

Доступність

role="spinbutton" з aria-valuenow, aria-valuemin, aria-valuemax. Коли задано unit, значення дублюється в aria-valuetext разом з одиницею — інакше «15» звучить без «відсотків».

Кнопки «−»/«+» мають tabindex="-1": та сама дія вже доступна стрілками, і дві зайві зупинки табуляції на кожному числовому полі форми — це дорого. Розмір кнопок — 44px на мобільному, 36px на десктопі.

Утримання кнопки повторює крок. Таймери знімаються на pointerup, pointercancel, pointerleave і на приховуванні вкладки: пропустити хоч один шлях — і значення продовжує рости у фоновій вкладці.