Input Number
Input Number хранит number | null, использует нативный spinbox и дублирует ArrowUp/ArrowDown явными кнопками шага. Числовые границы не превращаются в строковый формат.
Статус: experimental · в системе с 2026-07 · интерактивность: always (всегда)
Когда использовать
- Значение участвует в арифметике и должно оставаться числом.
- Пользователю полезно менять значение на предсказуемый step.
- Нужны нативные min/max/required-ограничения spinbox.
Не использовать:
- Цифры являются идентификатором, телефоном, индексом или кодом — используй Input.
- Точное число вводить не нужно, важнее положение в диапазоне — используй Slider.
- Значение выбирается из справочника — используй Select или Combobox.
Альтернативы:
input— строковое значение, даже если оно визуально состоит из цифр
Базовый
Число, пустота и явные действия шага.
<!--
🟢
Базовый пример Input Number сравнивает заполненное число и null. Кнопки
шага и стрелки клавиатуры изменяют одну числовую модель.
-->
<script>
import { t } from "$lib/spec/demo-lang.svelte.js";
import InputNumber from "$lib/ui/InputNumber.svelte";
let quantity = $state(3);
let optional = $state(null);
</script>
<div style="display: grid; gap: var(--sp-3); width: var(--control-field-min);">
<InputNumber label={t("Количество")} bind:value={quantity} />
<InputNumber
label={t("Необязательное число")}
placeholder={t("Введите значение")}
bind:value={optional}
/>
</div>
Границы и шаг
Min, max и дробный step остаются нативным контрактом spinbox.
%
<!--
🟢
Пример границ показывает целый и дробный шаг Input Number. Min и max
остаются нативными ограничениями spinbox, а не форматированием строки.
-->
<script>
import { t } from "$lib/spec/demo-lang.svelte.js";
import InputNumber from "$lib/ui/InputNumber.svelte";
let percent = $state(50);
let coefficient = $state(1.25);
</script>
<div style="display: grid; gap: var(--sp-3); width: var(--control-field-min);">
<InputNumber
label={t("Доля")}
suffix="%"
min={0}
max={100}
step={5}
bind:value={percent}
/>
<InputNumber
label={t("Коэффициент")}
min={0}
max={2}
step={0.25}
bind:value={coefficient}
/>
</div>
Поле
Аффиксы, обязательность, описание, ошибка и readonly.
₽
₽
%
<!--
🟢
Пример поля Input Number собирает аффиксы, сообщения и режим только чтение.
Ошибка относится к числу целиком, а не к отдельной кнопке шага.
-->
<script>
import { t } from "$lib/spec/demo-lang.svelte.js";
import InputNumber from "$lib/ui/InputNumber.svelte";
let budget = $state(50000);
let invalidBid = $state(null);
</script>
<div style="display: grid; gap: var(--sp-3); width: var(--control-field-min);">
<InputNumber
label={t("Дневной бюджет")}
suffix="₽"
hint={t("Сумма на один день")}
description={t("Значение можно менять с шагом 1000.")}
name="budget"
required
step={1000}
bind:value={budget}
/>
<InputNumber
label={t("Ставка")}
suffix="₽"
error={t("Введите ставку.")}
bind:value={invalidBid}
/>
<InputNumber label={t("Лимит")} value={100} suffix="%" readonly />
</div>