React Aria предоставляет мощный набор хуков и утилит для создания доступных пользовательских интерфейсов. Одной из ключевых задач в интерактивных приложениях является выделение диапазонов элементов, например, дат в календаре, строк в таблице или диапазонов значений в слайдере. Использование React Aria позволяет реализовать это с соблюдением стандартов доступности, включая поддержку клавиатуры и экранных читалок.
useRangeSelectionЭтот хук предназначен для управления состоянием выделения диапазонов. Он предоставляет следующие возможности:
selectedKeys и
setSelectedKeys.single) или
множественное (multiple).Пример использования:
import {useRangeSelection} from '@react-aria/selection';
import {useState} from 'react';
function DateRangeSelector({items}) {
const [selectedKeys, setSelectedKeys] = useState(new Set());
const {selectionProps} = useRangeSelection({
selectedKeys,
onSelectionChange: setSelectedKeys,
selectionMode: 'multiple'
});
return (
<ul {...selectionProps}>
{items.map(item => (
<li key={item.key} id={item.key}>
{item.label}
</li>
))}
</ul>
);
}
В этом примере selectionProps автоматически добавляет
необходимые атрибуты ARIA и обработчики событий, позволяя пользователю
выделять элементы с клавиатуры и мышью.
React Aria поддерживает несколько режимов выделения:
single) – можно выбрать
только один элемент в списке.multiple) –
пользователь может выделять несколько несвязанных элементов.range) – выделение
непрерывного диапазона элементов с помощью Shift-клавиши или жестов
мыши.Для работы с диапазоном особенно важна корректная обработка клавиатуры:
ArrowUp / ArrowDown – перемещение фокуса
между элементами.Shift + Arrow – расширение текущего диапазона
выделения.Ctrl + Click / Cmd + Click – добавление
или снятие отдельных элементов при множественном выделении.Для реализации визуального выделения важно синхронизировать состояние
selectedKeys с компонентами интерфейса. Например:
<ul {...selectionProps}>
{items.map(item => {
const isSelected = selectedKeys.has(item.key);
return (
<li
key={item.key}
id={item.key}
style={{
background: isSelected ? 'lightblue' : 'transparent'
}}
>
{item.label}
</li>
);
})}
</ul>
Здесь выделенные элементы получают визуальный фон, а React Aria обеспечивает корректное поведение для доступности.
useSelectableCollection для сложных структурКогда элементы находятся в сложной иерархии или требуется
динамическая коллекция, рекомендуется комбинировать
useRangeSelection с useSelectableCollection.
Это позволяет:
aria-selected,
aria-multiselectable,
aria-activedescendant.Пример:
import {useSelectableCollection} from '@react-aria/selection';
function NestedList({sections}) {
const [selectedKeys, setSelectedKeys] = useState(new Set());
const {collectionProps} = useSelectableCollection({
items: sections.flatMap(section => section.items),
selectionMode: 'multiple',
selectedKeys,
onSelectionChange: setSelectedKeys
});
return (
<div {...collectionProps}>
{sections.map(section => (
<div key={section.id}>
<h3>{section.title}</h3>
<ul>
{section.items.map(item => (
<li
key={item.key}
style={{
background: selectedKeys.has(item.key) ? 'lightgreen' : 'transparent'
}}
>
{item.label}
</li>
))}
</ul>
</div>
))}
</div>
);
}
React Aria обеспечивает соответствие WCAG следующим образом:
aria-selected.aria-activedescendant, что позволяет навигацию без потери
контекста.React Aria позволяет настраивать поведение выделения через параметры хука:
disallowEmptySelection – запрещает снятие всех
выделений.defaultSelectedKeys – начальная конфигурация выбранных
элементов.selectionBehavior – определяет, расширяется ли
выделение при Shift или перезаписывается.Пример использования:
const {selectionProps} = useRangeSelection({
selectedKeys,
onSelectionChange: setSelectedKeys,
selectionMode: 'range',
disallowEmptySelection: true
});
Для сложных компонентов, например календарей с выбором диапазона дат, рекомендуется использовать комбинацию:
useRangeSelection – управление состоянием
выделения.useSelectableCollection – поддержка вложенных или
динамических списков.aria-selected, aria-multiselectable).Такое сочетание обеспечивает:
Это позволяет создавать сложные интерактивные элементы интерфейса, которые остаются удобными для всех пользователей и соответствуют современным стандартам доступности.