useSlider для слайдеров

useSlider — это хук из библиотеки React Aria, предназначенный для создания доступных и настраиваемых слайдеров. Он обеспечивает управление состоянием, взаимодействие с клавиатурой и мышью, а также корректную поддержку технологий вспомогательного доступа (screen readers). Хук возвращает набор пропсов для контейнера слайдера, трека, ползунков и меток, которые интегрируются в JSX.

Импорт и базовое использование

import {useSlider} from '@react-aria/slider';
import {useSliderState} from '@react-stately/slider';
import {useRef} from 'react';

function SliderExample() {
  const state = useSliderState({
    minValue: 0,
    maxValue: 100,
    step: 1,
    defaultValue: [50],
  });

  const ref = useRef();
  const {sliderProps, trackProps, thumbProps} = useSlider({orientation: 'horizontal'}, state, ref);

  return (
    <div {...sliderProps} ref={ref} style={{width: 300, padding: 20}}>
      <div {...trackProps} style={{height: 4, background: '#ddd', position: 'relative'}}>
        <div {...thumbProps[0]} style={{position: 'absolute', left: `${state.value[0]}%`, width: 20, height: 20, background: '#007aff', borderRadius: '50%'}} />
      </div>
    </div>
  );
}

Ключевые моменты:

  • useSliderState управляет внутренним состоянием слайдера (значения, минимальные и максимальные границы, шаги).
  • useSlider генерирует пропсы для элементов слайдера и трека, обеспечивая доступность.
  • ref передается контейнеру слайдера, чтобы хук мог корректно вычислять позиции ползунков.
  • thumbProps представляет массив, так как слайдер может иметь несколько ползунков.

Настройка ориентации

Слайдер может быть горизонтальным или вертикальным через свойство orientation.

const {sliderProps, trackProps, thumbProps} = useSlider({orientation: 'vertical'}, state, ref);

При вертикальной ориентации ползунок перемещается по оси Y, при этом React Aria автоматически обновляет атрибуты ARIA и обработчики событий для клавиатуры и мыши.

Поддержка множественных ползунков

useSlider легко масштабируется для диапазонных слайдеров:

const state = useSliderState({
  minValue: 0,
  maxValue: 100,
  defaultValue: [20, 80],
});

const {thumbProps} = useSlider({}, state, ref);
  • thumbProps теперь содержит два объекта, по одному на каждый ползунок.
  • Состояние хранит массив значений, где каждый элемент соответствует отдельному ползунку.
  • Автоматически обрабатываются ограничения, чтобы ползунки не пересекались.

Настройка шагов и дискретных значений

Свойство step задаёт шаг изменения значения:

const state = useSliderState({
  minValue: 0,
  maxValue: 100,
  step: 5,
  defaultValue: [50],
});
  • Слайдер будет изменять значение только на кратные шагу.
  • Для дискретных шагов React Aria корректно устанавливает атрибут aria-valuetext, облегчая восприятие пользователям с экранными читалками.

Пользовательские метки и индикаторы

Для отображения меток или прогресса можно использовать state.value:

<div>
  {state.value[0]}
</div>

Для динамического отображения прогресса трека:

<div style={{position: 'absolute', height: '100%', background: '#007aff', width: `${state.value[0]}%`}} />
  • state.value обновляется автоматически при перемещении ползунка.
  • Это позволяет создавать визуальные индикаторы текущего значения, диапазона или прогресса.

Обработка событий клавиатуры и мыши

useSlider автоматически добавляет поддержку клавиш:

  • Стрелки — шаг вперед/назад.
  • PageUp/PageDown — увеличение/уменьшение на крупный шаг.
  • Home/End — переход к минимальному или максимальному значению.

Мышь и сенсорный ввод также полностью поддерживаются, включая drag & drop.

Доступность и ARIA атрибуты

Хук гарантирует корректную работу с технологиями вспомогательного доступа:

  • role="slider" для ползунков.
  • aria-valuemin, aria-valuemax, aria-valuenow и aria-valuetext обновляются автоматически.
  • Поддерживается фокусировка и взаимодействие через клавиатуру.

Продвинутые возможности

  • Динамические диапазоны: изменение minValue и maxValue в рантайме поддерживается.
  • Синхронизация нескольких слайдеров: состояние можно хранить в общем store или useSliderState.
  • Кастомные стили ползунков: любые CSS-свойства применимы через thumbProps и trackProps.

Пример с двумя ползунками и кастомными метками

const state = useSliderState({minValue: 0, maxValue: 100, defaultValue: [20, 80]});
const ref = useRef();
const {sliderProps, trackProps, thumbProps} = useSlider({}, state, ref);

return (
  <div {...sliderProps} ref={ref} style={{width: 300, padding: 20}}>
    <div {...trackProps} style={{height: 4, background: '#ddd', position: 'relative'}}>
      <div style={{position: 'absolute', height: '100%', background: '#007aff', left: `${state.value[0]}%`, width: `${state.value[1]-state.value[0]}%`}} />
      {thumbProps.map((thumb, i) => (
        <div key={i} {...thumb} style={{position: 'absolute', left: `${state.value[i]}%`, width: 20, height: 20, background: '#007aff', borderRadius: '50%'}} />
      ))}
    </div>
    <div style={{display: 'flex', justifyContent: 'space-between', marginTop: 10}}>
      <span>{state.value[0]}</span>
      <span>{state.value[1]}</span>
    </div>
  </div>
);
  • Ползунки и прогресс-бар обновляются синхронно.
  • Метки отражают текущие значения каждого ползунка.
  • Доступность обеспечена автоматически через React Aria.

Этот подход с useSlider позволяет создавать любые типы слайдеров: одиночные, диапазонные, вертикальные и горизонтальные, с полной поддержкой доступности и управлением состоянием без лишнего кода.