Root, Track, Range, Thumb

Компонент Slider библиотеки Radix UI построен по композиционной архитектуре. Вместо одного монолитного компонента используются несколько низкоуровневых примитивов, каждый из которых отвечает за отдельную часть интерфейса и поведения.

Базовыми элементами структуры являются:

  • Root — корневой контейнер и управляющая логика
  • Track — трек, по которому перемещается ползунок
  • Range — выделенный диапазон между значениями
  • Thumb — интерактивный ползунок

Такая архитектура обеспечивает:

  • полный контроль над разметкой
  • гибкость стилизации
  • возможность создания нестандартных интерфейсов
  • доступность (ARIA-совместимость)
  • поддержку клавиатуры и указателей

Типичная структура выглядит следующим образом:

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

<Slider.Root defaultValue={[50]} max={100} step={1}>
  <Slider.Track>
    <Slider.Range />
  </Slider.Track>
  <Slider.Thumb />
</Slider.Root>

Каждый примитив играет собственную роль в построении интерфейса.


Root

Назначение

Root — основной контейнер компонента слайдера. В нем сосредоточена вся логика управления значением, обработка пользовательских событий, а также взаимодействие между внутренними элементами.

Root:

  • хранит текущее значение
  • управляет несколькими ползунками
  • обрабатывает ввод мыши, касания и клавиатуры
  • обеспечивает доступность
  • синхронизирует состояние дочерних компонентов

Фактически Root выступает контроллером всей системы Slider.


Базовое использование

<Slider.Root defaultValue={[30]} max={100} step={1}>
  <Slider.Track>
    <Slider.Range />
  </Slider.Track>
  <Slider.Thumb />
</Slider.Root>

Root принимает массив значений, поскольку компонент поддерживает несколько ползунков.

Пример диапазонного слайдера:

<Slider.Root defaultValue={[20, 80]} max={100}>
  <Slider.Track>
    <Slider.Range />
  </Slider.Track>
  <Slider.Thumb />
  <Slider.Thumb />
</Slider.Root>

Основные свойства Root

defaultValue

Начальное значение слайдера.

defaultValue={[50]}

Для диапазонного слайдера:

defaultValue={[25, 75]}

Это неконтролируемое состояние.


value

Контролируемое значение.

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

<Slider.Root value={value} onValueCha nge={setValue}>

Теперь управление полностью осуществляется через состояние React.


min

Минимальное значение шкалы.

min={0}

max

Максимальное значение шкалы.

max={100}

step

Шаг изменения значения.

step={5}

Это означает:

0 → 5 → 10 → 15 → 20

orientation

Ориентация слайдера.

orientation="horizontal"

или

orientation="vertical"

Вертикальный вариант часто используется для:

  • регулировки громкости
  • настройки параметров
  • панели инструментов

disabled

Отключает взаимодействие.

disabled

onValueChange

Срабатывает при каждом изменении значения.

onValueCha nge={(value) => console.log(value)}

onValueCommit

Вызывается после завершения взаимодействия (например, после отпускания мыши).

onValueCom mit={(value) => save(value)}

Это удобно для:

  • отправки данных на сервер
  • сохранения настроек
  • тяжелых вычислений

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

Root автоматически обеспечивает управление клавиатурой:

Клавиша Действие
ArrowRight / ArrowUp увеличить значение
ArrowLeft / ArrowDown уменьшить
PageUp большой шаг вверх
PageDown большой шаг вниз
Home минимальное значение
End максимальное значение

Это важная часть доступности интерфейса.


Track

Назначение

Track представляет собой визуальную шкалу, по которой перемещается ползунок.

Он выполняет роль:

  • фоновой линии
  • контейнера диапазона
  • области перемещения

Track не управляет логикой, а лишь отображает структуру.


Базовая структура

<Slider.Track>
  <Slider.Range />
</Slider.Track>

Track всегда содержит Range.


Пример стилизации

.sliderTrack {
  position: relative;
  height: 4px;
  background: #ddd;
  border-radius: 2px;
}

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

<Slider.Track className="sliderTrack">
  <Slider.Range />
</Slider.Track>

Вертикальный трек

.sliderTrackVertical {
  width: 4px;
  height: 200px;
}

Track автоматически меняет направление в зависимости от orientation.


Взаимодействие с указателем

Track реагирует на клик.

Когда пользователь кликает на трек:

  1. вычисляется позиция клика
  2. переводится в значение
  3. ближайший Thumb перемещается

Это поведение реализовано внутри Root.


Range

Назначение

Range отображает активную часть шкалы.

В одноползунковом слайдере Range показывает участок:

[начало шкалы → значение]

В диапазонном:

[value1 → value2]

Структура

Range всегда располагается внутри Track.

<Slider.Track>
  <Slider.Range />
</Slider.Track>

Пример стилизации

.sliderRange {
  position: absolute;
  height: 100%;
  background: #3b82f6;
  border-radius: 999px;
}

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

<Slider.Range className="sliderRange" />

Автоматическое позиционирование

Range не требует ручного управления стилями left/right.

Radix автоматически вычисляет:

  • начало диапазона
  • ширину диапазона

На основе:

  • текущих значений
  • min
  • max
  • orientation

Range при нескольких Thumb

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

Thumb 1 -------- Thumb 2

Range будет отображать участок между ними.

Это удобно для:

  • выбора диапазона цен
  • фильтров поиска
  • временных интервалов

Thumb

Назначение

Thumb — интерактивный элемент, который пользователь перемещает для изменения значения.

Он отвечает за:

  • перетаскивание
  • фокус
  • управление клавиатурой
  • отображение текущей позиции

Базовое использование

<Slider.Thumb />

В диапазонном слайдере:

<Slider.Thumb />
<Slider.Thumb />

Количество Thumb должно соответствовать количеству значений.


Стилизация Thumb

Пример:

.sliderThumb {
  width: 20px;
  height: 20px;
  background: white;
  border: 2px solid #3b82f6;
  border-radius: 50%;
}

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

<Slider.Thumb className="sliderThumb" />

Состояния Thumb

Radix добавляет состояния через атрибуты:

[data-state]

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

  • active
  • inactive

Также используется:

:focus-visible

Пример:

.sliderThumb:focus-visible {
  outline: 3px solid #93c5fd;
}

Обработка drag-событий

Thumb реагирует на:

  • mouse
  • touch
  • pointer events

Radix автоматически:

  • вычисляет позицию
  • ограничивает движение
  • синхронизирует значение

Ограничение пересечения

Для диапазонных слайдеров существует правило:

Thumb1 ≤ Thumb2

Radix предотвращает пересечение ползунков.

Это особенно важно для:

  • фильтров цен
  • диапазонов времени
  • параметров поиска

Пример полноценного Slider

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

export default function PriceSlider() {
  return (
    <Slider.Root
      className="sliderRoot"
      defaultValue={[20, 80]}
      min={0}
      max={100}
      step={1}
    >
      <Slider.Track className="sliderTrack">
        <Slider.Range className="sliderRange" />
      </Slider.Track>

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

Пример CSS

.sliderRoot {
  position: relative;
  display: flex;
  align-items: center;
  width: 300px;
}

.sliderTrack {
  position: relative;
  flex-grow: 1;
  height: 4px;
  background: #e5e7eb;
}

.sliderRange {
  position: absolute;
  height: 100%;
  background: #2563eb;
}

.sliderThumb {
  width: 18px;
  height: 18px;
  background: white;
  border: 2px solid #2563eb;
  border-radius: 50%;
}

Взаимодействие компонентов

Работа компонентов Slider строится на внутреннем контексте.

Связь выглядит следующим образом:

Root
 ├── Track
 │    └── Range
 └── Thumb

Root передает:

  • текущее значение
  • координаты
  • обработчики событий

Track и Range используют данные для отображения, а Thumb — для взаимодействия.


Расширенные возможности

Минимальное расстояние между Thumb

Для диапазонных слайдеров можно задать:

minStepsBetweenThumbs
<Slider.Root
  defaultValue={[20, 40]}
  minStepsBetweenThumbs={5}
>

Это предотвращает слишком близкое расположение ползунков.


Вертикальный слайдер

<Slider.Root orientation="vertical">
  <Slider.Track>
    <Slider.Range />
  </Slider.Track>

  <Slider.Thumb />
</Slider.Root>

CSS:

.sliderRoot {
  height: 200px;
  width: 20px;
}

Интеграция с формами

Slider можно связать с формами:

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

<input type="hidden" value={value[0]} name="volume" />

Это позволяет отправлять данные через HTML-формы.


Доступность (Accessibility)

Компонент Slider в Radix UI соответствует стандартам ARIA.

Thumb автоматически получает:

role="slider"

Также устанавливаются:

aria-valuemin
aria-valuemax
aria-valuenow
aria-orientation

Это обеспечивает корректную работу:

  • screen readers
  • клавиатурной навигации
  • assistive технологий

Основные преимущества архитектуры

Использование примитивов Root, Track, Range и Thumb обеспечивает:

Гибкость

Можно построить любой дизайн.

Контроль

Каждый элемент полностью управляется разработчиком.

Доступность

ARIA реализована по умолчанию.

Масштабируемость

Поддержка:

  • нескольких ползунков
  • диапазонов
  • вертикальных интерфейсов
  • сложных UI компонентов.

Такой подход делает Slider одним из самых гибких компонентов в экосистеме Radix UI.