Focus Lock

Focus Lock — это механизм управления фокусом внутри интерактивных компонентов, который предотвращает случайное выход за пределы определённой области интерфейса. В Chakra UI он реализован через компонент FocusLock и тесно интегрирован с модальными окнами, выпадающими меню и тултипами. Основная цель — обеспечить доступность и корректное взаимодействие с клавиатурой, особенно для пользователей, полагающихся на навигацию с помощью клавиш Tab и Shift+Tab.


Подключение и базовое использование

Chakra UI предоставляет FocusLock через пакет @chakra-ui/react. Для использования необходимо обернуть интерактивный компонент в <FocusLock>:

import { Button, Box } from "@chakra-ui/react";
import FocusLock from "react-focus-lock";

function Example() {
  return (
    <FocusLock>
      <Box p={4} border="1px solid gray">
        <Button colorScheme="blue" mr={2}>Кнопка 1</Button>
        <Button colorScheme="green">Кнопка 2</Button>
      </Box>
    </FocusLock>
  );
}

В этом примере фокус остаётся внутри контейнера, и пользователь не сможет переключиться на элементы за пределами Box с помощью клавиши Tab.


Основные свойства FocusLock

  1. disabled — отключает блокировку фокуса. Полезно, если блокировка должна активироваться динамически.
<FocusLock disabled={true}>
  {/* Содержимое */}
</FocusLock>
  1. returnFocus — автоматически возвращает фокус к элементу, который был активен до активации FocusLock, при его размонтировании. По умолчанию включено (true).
<FocusLock returnFocus={false}>
  {/* Содержимое */}
</FocusLock>
  1. persistentFocus — заставляет фокус оставаться внутри контейнера даже при кликах вне его. Используется в сложных модальных интерфейсах.
<FocusLock persistentFocus={true}>
  {/* Содержимое */}
</FocusLock>
  1. autoFocus — автоматически фокусирует первый доступный интерактивный элемент при монтировании. Полезно для модальных окон.
<FocusLock autoFocus={true}>
  <Button>Первая кнопка</Button>
</FocusLock>

Интеграция с модальными компонентами

Модальные окна Chakra UI (Modal) уже используют FocusLock под капотом через ModalContent. Это обеспечивает доступность и корректное управление клавиатурой без дополнительной конфигурации. Пример модального окна:

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

function ModalExample() {
  const { isOpen, onOpen, onClose } = useDisclosure();

  return (
    <>
      <Button onCl ick={onOpen}>Открыть модальное окно</Button>
      <Modal isOpen={isOpen} onCl ose={onClose}>
        <ModalOverlay />
        <ModalContent>
          <ModalHeader>Заголовок</ModalHeader>
          <ModalCloseButton />
          <ModalBody>
            <Button colorScheme="blue" mr={2}>Кнопка 1</Button>
            <Button colorScheme="green">Кнопка 2</Button>
          </ModalBody>
          <ModalFooter>
            <Button onCl ick={onClose}>Закрыть</Button>
          </ModalFooter>
        </ModalContent>
      </Modal>
    </>
  );
}

Фокус при открытии автоматически переходит на первый интерактивный элемент (Button) внутри модального окна, а при закрытии возвращается к кнопке, которая его открывала.


Фокус и доступность

Использование FocusLock критически важно для доступности (a11y):

  • TabIndex: элементы внутри FocusLock получают естественный порядок фокусировки.
  • Screen readers: фокусирование ограничено контейнером, что предотвращает случайное смещение курсора на скрытые элементы.
  • Keyboard navigation: пользователи, работающие только с клавиатурой, получают предсказуемый и логичный порядок взаимодействия.

Советы по использованию

  • Для сложных интерфейсов с множественными модальными окнами или дропдаунами рекомендуется всегда проверять, что FocusLock не конфликтует с внешними событиями клика.
  • В случае динамического отображения элементов внутри FocusLock (render conditional) важно использовать autoFocus и returnFocus, чтобы не терять управление фокусом.
  • FocusLock можно комбинировать с компонентами Portal и Drawer, чтобы обеспечить корректное управление фокусом даже при рендеринге элементов вне обычного DOM-потока.

Расширенные возможности

  1. Nested FocusLock: разрешено вложенное использование для случаев, когда внутри модального окна есть ещё один интерактивный блок с отдельной фокусировкой.
  2. Custom focus trap: можно интегрировать с внешними библиотеками управления фокусом, если требуется специфическая логика (например, циклическая фокусировка через определённые элементы формы).

Использование Focus Lock в Chakra UI позволяет создавать доступные, предсказуемые и управляемые интерфейсы, где фокус всегда остаётся в пределах интерактивного блока. Это особенно важно для модальных окон, дропдаунов и других всплывающих компонентов, где нарушение порядка фокуса может приводить к проблемам с навигацией и доступностью.