В интерфейсах веб-приложений правильное управление фокусом играет ключевую роль для доступности и удобства пользователя. React Aria предоставляет набор инструментов для контроля фокуса, предотвращения его потери и решения конфликтов, возникающих при взаимодействии с несколькими компонентами.
Конфликты фокуса возникают, когда несколько элементов одновременно претендуют на получение фокуса, либо когда фокус неожиданно покидает текущий компонент. Основные причины:
autoFocus, могут конкурировать за
фокус.React Aria предлагает инструменты для точного контроля этих ситуаций, включая hooks для фокуса, состояния управления клавиатурой и контексты блокировки фокуса.
useFocusScope для ограничения фокусаuseFocusScope позволяет создать
область, внутри которой фокус не покидает компоненты. Это особенно важно
для модальных окон, всплывающих списков и кастомных диалогов.
import { useFocusScope } from "@react-aria/focus";
import { useRef } from "react";
function Modal({ isOpen }) {
let ref = useRef();
useFocusScope(ref, { restoreFocus: true });
if (!isOpen) return null;
return (
<div ref={ref} role="dialog" aria-modal="true">
<button>Закрыть</button>
<input type="text" placeholder="Введите текст"/>
</div>
);
}
Ключевые моменты:
restoreFocus: true возвращает фокус на элемент, который
был активен до открытия модального окна.ref защищает внутренние элементы от случайного
ухода фокуса на другие части интерфейса.useFocusRing и useFocususeFocus предоставляет низкоуровневый
контроль над событиями фокуса и blur. Используется для создания
собственных компонентов с управляемым поведением при фокусе.
import { useFocus } from "@react-aria/focus";
function CustomButton(props) {
let { focusProps, isFocused } = useFocus(props);
return (
<button {...focusProps} style={{ border: isFocused ? "2px solid blue" : "none" }}>
{props.children}
</button>
);
}
focusProps содержит все необходимые обработчики
(onFocus, onBlur) для корректного
управления.isFocused позволяет визуализировать состояние фокуса,
повышая доступность.useFocusRing строит поверх
useFocus, предоставляя визуальные индикаторы
фокуса, автоматически учитывая клавиатурные и мышиные
события.
FocusScope и FocusManagerДля сложных интерфейсов с динамическими элементами полезно использовать контекст фокуса, предоставляемый React Aria.
import { FocusScope } from "@react-aria/focus";
function Dialog({ isOpen }) {
return (
<FocusScope contain restoreFocus autoFocus>
<div role="dialog">
<input placeholder="Имя"/>
<button>Сохранить</button>
</div>
</FocusScope>
);
}
contain предотвращает уход фокуса за пределы
области.autoFocus автоматически ставит фокус на первый
интерактивный элемент внутри.restoreFocus возвращает фокус на элемент, который был
активен до открытия области.Для динамических списков и вкладок FocusManager
позволяет программно управлять порядком фокуса и корректно обрабатывать
удаление или добавление элементов.
Конфликты часто возникают при навигации клавишами Tab и
Shift+Tab. React Aria обеспечивает корректное поведение
через:
useTabList и useTabPanel – автоматически
управляют фокусом внутри вкладок.useGrid и useList – обеспечивают навигацию
стрелками и управление фокусом на динамических элементах.focusManager.focusNext() и
focusManager.focusPrevious() – программное управление
фокусом для сложных кейсов.import { focusManager } from "@react-aria/focus";
function handleKeyDown(event) {
if (event.key === "ArrowDown") {
focusManager.focusNext();
} else if (event.key === "ArrowUp") {
focusManager.focusPrevious();
}
}
Такой подход предотвращает потерю фокуса при ререндере элементов и обеспечивает предсказуемое поведение.
FocusScope для модальных
окон – это предотвращает утечку фокуса на фоновый
интерфейс.autoFocus в нескольких
компонентах одновременно – конфликт будет непредсказуем.focusManager для динамических
списков и таблиц – гарантирует корректную навигацию.useFocusRing – повышает доступность интерфейса для
пользователей клавиатуры.Эти механизмы позволяют создавать интерфейсы с корректным управлением фокусом, предотвращая конфликты и обеспечивая плавное, предсказуемое взаимодействие пользователя с любым количеством динамических компонентов.