Шаг и границы

Во многих интерфейсных элементах требуется контролировать диапазон допустимых значений и точность их изменения. В компонентах библиотеки Radix UI это достигается за счёт параметров шага (step) и границ значений (min / max). Эти параметры применяются в элементах, которые работают с числовыми данными и позволяют пользователю изменять их постепенно.

К таким компонентам относятся:

  • Slider
  • Number Field (через кастомную реализацию)
  • Progress с вычисляемыми значениями
  • Range-подобные интерфейсы

Основная задача шага и границ — обеспечить контролируемое изменение состояния, исключить недопустимые значения и упростить взаимодействие пользователя с элементом.


Понятие шага (Step)

Шаг определяет величину изменения значения при одном действии пользователя.

Изменение может происходить:

  • при перемещении ползунка
  • при нажатии клавиш управления
  • при программном изменении состояния
  • при использовании кнопок увеличения/уменьшения

Если шаг равен 1, значение изменяется на единицу. Если шаг равен 10, значение изменяется десятками.

Базовый пример Slider с шагом

import * as Slider from "@radix-ui/react-slider";

function VolumeSlider() {
  return (
    <Slider.Root
      defaultValue={[50]}
      max={100}
      step={5}
      className="SliderRoot"
    >
      <Slider.Track className="SliderTrack">
        <Slider.Range className="SliderRange" />
      </Slider.Track>

      <Slider.Thumb className="SliderThumb" />
    </Slider.Root>
  );
}

Параметр:

step={5}

означает, что значения могут быть:

0, 5, 10, 15, 20 ... 100

Любое промежуточное значение автоматически округляется.


Минимальная граница (min)

Минимальная граница задаёт нижний предел допустимого значения.

В Slider она определяется свойством:

min={0}

Если пользователь пытается уменьшить значение ниже минимального, библиотека блокирует изменение.

Пример

<Slider.Root
  min={10}
  max={50}
  step={5}
  defaultValue={[20]}
/>

Допустимые значения:

10, 15, 20, 25, 30, 35, 40, 45, 50

Значение никогда не станет меньше 10, даже при попытке программной установки.


Максимальная граница (max)

Максимальная граница определяет верхний предел диапазона.

max={100}

Если пользователь пытается увеличить значение за пределы диапазона, оно фиксируется на максимальном значении.

Пример диапазона

<Slider.Root
  min={0}
  max={200}
  step={20}
  defaultValue={[100]}
/>

Допустимые значения:

0, 20, 40, 60, 80, 100, 120, 140, 160, 180, 200

Связь шага и диапазона

Правильная настройка шага зависит от размера диапазона.

Формула количества возможных значений:

(max - min) / step

Пример

min = 0
max = 100
step = 5

Количество шагов:

(100 - 0) / 5 = 20

Итого доступно 21 значение, включая ноль.


Множественные значения (Range Slider)

Radix UI поддерживает несколько ползунков, что позволяет задавать диапазон.

Пример диапазона цен

function PriceRange() {
  return (
    <Slider.Root
      min={0}
      max={1000}
      step={50}
      defaultValue={[200, 700]}
    >
      <Slider.Track>
        <Slider.Range />
      </Slider.Track>

      <Slider.Thumb />
      <Slider.Thumb />
    </Slider.Root>
  );
}

Здесь используется два значения:

[200, 700]

Первый ползунок — нижняя граница, второй — верхняя.


Ограничение пересечения ползунков

При использовании нескольких ползунков важно контролировать минимальное расстояние между ними.

Radix UI предоставляет свойство:

minStepsBetweenThumbs

Пример

<Slider.Root
  min={0}
  max={100}
  step={5}
  minStepsBetweenThumbs={2}
  defaultValue={[20, 80]}
/>

Если шаг равен 5, то расстояние между ползунками:

2 * 5 = 10

Минимальный интервал:

10 единиц

Это предотвращает наложение элементов.


Программное управление значениями

Значение Slider обычно хранится в состоянии React.

Пример

import { useState } from "react";
import * as Slider from "@radix-ui/react-slider";

function ControlledSlider() {
  const [value, setValue] = useState([30]);

  return (
    <Slider.Root
      min={0}
      max={100}
      step={10}
      value={value}
      onValueCha nge={setValue}
    >
      <Slider.Track>
        <Slider.Range />
      </Slider.Track>

      <Slider.Thumb />
    </Slider.Root>
  );
}

Radix автоматически гарантирует, что:

  • значение не выйдет за min
  • значение не превысит max
  • значение соответствует step

Поведение клавиатуры

Radix UI реализует доступность по стандарту WAI-ARIA. Ползунок реагирует на клавиатуру.

Клавиши управления:

Клавиша Действие
ArrowRight +1 шаг
ArrowUp +1 шаг
ArrowLeft -1 шаг
ArrowDown -1 шаг
PageUp +10 шагов
PageDown -10 шагов
Home минимальное значение
End максимальное значение

Шаг учитывается автоматически.

Если step = 5, нажатие стрелки увеличит значение на 5.


Нелинейные диапазоны

Иногда требуется имитировать нелинейную шкалу.

Пример: регулировка экспозиции, громкости или скорости.

Radix Slider остаётся линейным, но можно преобразовать значение.

Пример логарифмической шкалы

function logTransform(value) {
  return Math.pow(10, value);
}

Использование:

const [value, setValue] = useState([1]);

const actualValue = logTransform(value[0]);

Пользователь двигает линейный слайдер, но фактическое значение изменяется по логарифму.


Привязка значений к данным

Slider часто используется для управления:

  • громкостью
  • яркостью
  • фильтрами
  • диапазонами цен
  • процентами
  • масштабом

Пример управления прозрачностью:

const [opacity, setOpacity] = useState([0.5]);

<Slider.Root
  min={0}
  max={1}
  step={0.05}
  value={opacity}
  onValueCha nge={setOpacity}
/>

Шаг 0.05 позволяет точно управлять значением.


Округление значений

Radix автоматически округляет значение до ближайшего шага.

Например:

min = 0
step = 10

Попытка установить:

23

Результат:

20

Или:

30

в зависимости от ближайшего шага.


Работа с дробными шагами

Шаг может быть дробным числом.

Пример

<Slider.Root
  min={0}
  max={1}
  step={0.01}
  defaultValue={[0.5]}
/>

Диапазон:

0.00
0.01
0.02
...
1.00

Это полезно для:

  • прозрачности
  • масштабирования
  • коэффициентов

Ограничение пользовательского ввода

При использовании Radix Slider вместе с числовыми полями необходимо синхронизировать границы.

Пример:

<input
  type="number"
  min={0}
  max={100}
  step={5}
/>

И Slider:

<Slider.Root
  min={0}
  max={100}
  step={5}
/>

Совпадение параметров предотвращает рассинхронизацию значений.


Производительность при большом диапазоне

Большие диапазоны могут влиять на производительность.

Например:

min = 0
max = 1 000 000
step = 1

Количество возможных значений:

1 000 000

В таких случаях рекомендуется:

  • увеличить шаг
  • использовать масштабирование
  • преобразовывать значения программно

Типичные ошибки

Неправильный шаг

min = 0
max = 100
step = 30

Значения:

0
30
60
90

Число 100 никогда не будет достигнуто.


Несоответствие диапазона и шага

min = 0
max = 1
step = 0.3

Возможные значения:

0
0.3
0.6
0.9

Значение 1.0 недостижимо.


Неверная инициализация диапазона

defaultValue={[120]}

при

max = 100

Radix автоматически исправит значение, но подобные ситуации следует избегать.


Практический пример: фильтр цены

function PriceFilter() {
  const [value, setValue] = useState([100, 500]);

  return (
    <Slider.Root
      min={0}
      max={1000}
      step={50}
      value={value}
      onValueCha nge={setValue}
    >
      <Slider.Track>
        <Slider.Range />
      </Slider.Track>

      <Slider.Thumb />
      <Slider.Thumb />
    </Slider.Root>
  );
}

Особенности:

  • диапазон цен
  • шаг 50
  • два ползунка
  • контролируемое состояние

Практический пример: регулировка громкости

function VolumeControl() {
  const [volume, setVolume] = useState([70]);

  return (
    <Slider.Root
      min={0}
      max={100}
      step={1}
      value={volume}
      onValueCha nge={setVolume}
    >
      <Slider.Track>
        <Slider.Range />
      </Slider.Track>

      <Slider.Thumb />
    </Slider.Root>
  );
}

Малый шаг обеспечивает плавное управление громкостью.


Рекомендации по выбору шага

Оптимальный шаг зависит от задачи.

Сценарий Рекомендуемый шаг
громкость 1
цена 10 / 50
проценты 1
прозрачность 0.01
масштаб 0.1

Правильный шаг улучшает точность управления и удобство интерфейса.


Архитектурная роль границ

Границы выполняют несколько функций:

  1. валидация данных
  2. защита состояния
  3. контроль пользовательского ввода
  4. оптимизация интерфейса
  5. предсказуемость поведения компонентов

В библиотеке Radix UI эти механизмы реализованы на уровне компонента, что избавляет от необходимости самостоятельно писать проверки диапазона.