Управление фокусом в оверлеях

В Chakra UI управление фокусом реализуется через механизмы FocusLock и встроенные свойства компонентов оверлеев, таких как Modal, Drawer, Popover и AlertDialog. Основная цель — предотвратить потерю фокуса пользователем при взаимодействии с модальными окнами и обеспечить корректную навигацию с клавиатуры.


Автоматическая установка фокуса

Компоненты оверлеев в Chakra UI автоматически устанавливают фокус на первый интерактивный элемент внутри при открытии. Для Modal это свойство initialFocusRef:

import { useRef } from "react";
import { Modal, ModalOverlay, ModalContent, ModalHeader, ModalBody, ModalCloseButton, Button } from "@chakra-ui/react";

function ExampleModal({ isOpen, onClose }) {
  const initialRef = useRef();

  return (
    <Modal isOpen={isOpen} onCl ose={onClose} initialFocusRef={initialRef}>
      <ModalOverlay />
      <ModalContent>
        <ModalHeader>Пример модального окна</ModalHeader>
        <ModalCloseButton />
        <ModalBody>
          <input ref={initialRef} placeholder="Фокус сюда при открытии" />
          <Button mt={4}>Подтвердить</Button>
        </ModalBody>
      </ModalContent>
    </Modal>
  );
}

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

  • initialFocusRef позволяет точно указать элемент, который получит фокус при открытии.
  • Если initialFocusRef не задан, Chakra UI установит фокус на первый доступный интерактивный элемент внутри оверлея.

Управление возвратом фокуса

После закрытия модального окна полезно вернуть фокус к элементу, который его инициировал. Для этого используется свойство finalFocusRef:

const btnRef = useRef();

<Button ref={btnRef} onCl ick={onOpen}>Открыть модал</Button>

<Modal
  isOpen={isOpen}
  onCl ose={onClose}
  initialFocusRef={initialRef}
  finalFocusRef={btnRef}
>
  {/* Содержимое модала */}
</Modal>

Принцип работы: Chakra UI автоматически переносит фокус обратно к finalFocusRef после закрытия оверлея, что повышает удобство навигации для пользователей клавиатуры.


Фокус-замок внутри оверлея

Chakra UI использует библиотеку react-focus-lock, чтобы запирать фокус внутри модального окна. Это предотвращает выход фокуса наружу и улучшает доступность.

Особенности работы FocusLock:

  • Фокус циклично перемещается между интерактивными элементами внутри оверлея при нажатии клавиши Tab и Shift+Tab.
  • Пользователь не сможет случайно взаимодействовать с элементами под модальным окном, пока оно активно.
  • Для компонентов Popover и Drawer этот механизм также активен по умолчанию.

Управление фокусом в сложных оверлеях

Иногда требуется переназначить фокус динамически, например, при условных рендерах или асинхронной загрузке контента. Для этого можно использовать эффект useEffect:

import { useEffect, useRef } from "react";

const dynamicRef = useRef();

useEffect(() => {
  if (isOpen && dynamicRef.current) {
    dynamicRef.current.focus();
  }
}, [isOpen]);

Рекомендации:

  • Всегда проверять наличие элемента через ref.current перед установкой фокуса.
  • Использовать tabIndex={-1} для элементов, которые должны получать фокус программно, но не участвуют в обычной таб-навигации.

Доступность и клавиатурная навигация

Chakra UI следует стандартам WAI-ARIA. Для модальных оверлеев:

  • Добавляется aria-modal="true".
  • Обеспечивается скрытие контента под оверлеем для скринридеров.
  • Фокус всегда перемещается в оверлей при его открытии.

Для Popover и Menu также поддерживается автоматическая фокусировка и правильный порядок табуляции:

<Menu>
  <MenuButton as={Button}>Открыть меню</MenuButton>
  <MenuList>
    <MenuItem>Пункт 1</MenuItem>
    <MenuItem>Пункт 2</MenuItem>
  </MenuList>
</Menu>

Пользователь может перемещаться между пунктами меню с помощью стрелок, а фокус остается внутри компонента до его закрытия.


Настройка исключений фокуса

Иногда требуется разрешить взаимодействие с элементами вне оверлея, например, с уведомлениями. Для этого можно отключить фокус-замок через trapFocus={false}:

<Drawer isOpen={isOpen} onCl ose={onClose} trapFocus={false}>
  {/* Контент */}
</Drawer>

Использование этой опции должно быть обоснованным, так как нарушение фокус-замка может ухудшить доступность.


Практические советы

  1. Всегда использовать initialFocusRef и finalFocusRef, чтобы управление фокусом было предсказуемым.
  2. Использовать ref для динамических элементов, чтобы гарантировать правильное перемещение фокуса.
  3. Проверять таб-индексы и порядок элементов, особенно если внутри оверлея несколько интерактивных компонентов.
  4. Не отключать фокус-замок без веской причины, чтобы сохранять доступность для пользователей клавиатуры.

Управление фокусом в Chakra UI обеспечивает безопасное и удобное взаимодействие с оверлеями, минимизируя ошибки навигации и повышая доступность интерфейсов.