В React Aria управление фокусом реализуется через специализированные хуки, которые обеспечивают доступность интерфейса и корректное взаимодействие с клавиатурой и вспомогательными технологиями. Главная цель — гарантировать, что элементы интерфейса получают фокус в правильном порядке, и пользователь всегда понимает, где находится активный элемент.
useFocususeFocus предназначен для отслеживания состояния фокуса
на элементе. Он возвращает объект с ключевыми свойствами и
обработчиками:
import {useFocus} from '@react-aria/interactions';
import {useRef} from 'react';
function FocusableButton() {
const ref = useRef();
const {isFocused, focusProps} = useFocus({});
return (
<button {...focusProps} ref={ref}>
{isFocused ? 'В фокусе' : 'Не в фокусе'}
</button>
);
}
Основные моменты:
focusProps содержит стандартные обработчики событий
onFocus и onBlur, а также дополнительную
логику для корректного взаимодействия с клавиатурой и вспомогательными
технологиями.isFocused позволяет динамически изменять визуальное
представление элемента при получении фокуса.useFocusRingДля визуальной индикации фокуса используется хук
useFocusRing:
import {useFocusRing} from '@react-aria/focus';
import {useRef} from 'react';
function StyledButton() {
const ref = useRef();
const {isFocusVisible, focusProps} = useFocusRing();
return (
<button {...focusProps} ref={ref} className={isFocusVisible ? 'focus-ring' : ''}>
Кнопка
</button>
);
}
Ключевые моменты:
isFocusVisible определяет, должен ли быть показан
визуальный индикатор фокуса. React Aria учитывает, был ли фокус
установлен с клавиатуры или мыши.React Aria предоставляет удобные инструменты для управления
фокусируемыми элементами и их порядком в интерфейсе. Для сложных
компонентов, таких как модальные окна,
меню или таблицы, используется
useTabList и useTabPanel:
import {useTabList, useTab, useTabPanel} from '@react-aria/tabs';
import {useState} from 'react';
function TabsExample() {
const [selectedKey, setSelectedKey] = useState('tab1');
const {tabListProps} = useTabList({selectedKey, onSelectionChange: setSelectedKey});
return (
<div {...tabListProps}>
<Tab id="tab1" label="Вкладка 1" />
<Tab id="tab2" label="Вкладка 2" />
</div>
);
}
function Tab({id, label}) {
const {tabProps} = useTab({id, key: id});
return <button {...tabProps}>{label}</button>;
}
Особенности:
tabIndex —
React Aria делает это автоматически.Для модальных диалогов или всплывающих меню важно
зафиксировать фокус внутри контейнера. Используется хук
useOverlay:
import {useOverlay} from '@react-aria/overlays';
import {useRef} from 'react';
function Modal({isOpen, onClose}) {
const ref = useRef();
const {overlayProps} = useOverlay({isOpen, onClose}, ref);
if (!isOpen) return null;
return (
<div {...overlayProps} ref={ref} className="modal">
Контент модального окна
</div>
);
}
Принципы работы:
React Aria учитывает все стандартные паттерны взаимодействия с клавиатурой:
ArrowUp, ArrowDown,
ArrowLeft, ArrowRight) для перемещения между
элементами в списках, вкладках или меню.Tab и Shift+Tab для циклической навигации
внутри контейнеров.Home, End,
PageUp, PageDown в сложных списках или
таблицах.Пример управления фокусом в списке:
import {useListBox, useOption} from '@react-aria/listbox';
import {useState, useRef} from 'react';
function ListBoxExample({items}) {
const [selectedKey, setSelectedKey] = useState(null);
const ref = useRef();
const {listBoxProps} = useListBox({items, selectedKey, onSelectionChange: setSelectedKey}, ref);
return (
<ul {...listBoxProps} ref={ref}>
{items.map(item => <Option key={item.key} item={item} />)}
</ul>
);
}
function Option({item}) {
const ref = useRef();
const {optionProps, isSelected, isFocused} = useOption({key: item.key}, {key: item.key}, ref);
return (
<li {...optionProps} ref={ref} className={isFocused ? 'focused' : ''}>
{item.name}
</li>
);
}
Для элементов, которые должны быть доступны для клавиатуры,
но невидимы визуально, React Aria предоставляет поддержку через
focusProps и атрибуты ARIA. Это позволяет создавать
кастомные компоненты, где фокус управляется программно, сохраняя полную
доступность.
ref.focus().isFocused или isFocusVisible для классов
CSS.Эти принципы обеспечивают соблюдение стандартов ARIA и делают интерфейсы React Aria полностью доступными.