FloatingOverlay

FloatingOverlay — это компонент библиотеки Floating UI, предназначенный для управления модальными слоями поверх основного контента. Он обеспечивает корректное позиционирование всплывающих элементов, поддерживает управление фокусом, блокировку прокрутки и взаимодействие с клавиатурой, что делает его ключевым инструментом при реализации всплывающих окон, меню, тултипов и диалогов.


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

isOpen Определяет состояние видимости оверлея. При значении true элемент отображается, при false — скрывается. Это свойство связывается с состоянием компонента, чтобы динамически управлять появлением слоя.

onDismiss Функция обратного вызова, вызываемая при попытке закрыть оверлей (например, при клике вне области оверлея или нажатии клавиши Escape). Часто используется для синхронизации состояния видимости с родительским компонентом:

<FloatingOverlay 
  isOpen={isOpen} 
  onDism iss={() => setIsOpen(false)}
/>

lockScroll Если значение установлено в true, прокрутка страницы блокируется при открытом оверлее. Это предотвращает сдвиг контента под слоем, что особенно важно для мобильных устройств.

preventOutsideScroll Блокирует прокрутку только за пределами оверлея, позволяя скроллить содержимое самого оверлея.


Позиционирование FloatingOverlay

FloatingOverlay интегрируется с другими инструментами Floating UI для точного позиционирования:

  • FloatingPortal — используется для рендеринга оверлея вне обычной иерархии DOM, что предотвращает перекрытие родительскими элементами с overflow: hidden.
  • useFloating — хук, который вычисляет координаты для оверлея относительно целевого элемента или курсора, поддерживая автоматическое обновление при изменении размеров окна.

Пример интеграции:

import { useFloating, offset, flip } from '@floating-ui/react';
import { FloatingOverlay, FloatingPortal } from '@floating-ui/react';

const { x, y, reference, floating } = useFloating({
  placement: 'bottom',
  middleware: [offset(8), flip()]
});

return (
  <>
    <button ref={reference} onCl ick={() => setIsOpen(true)}>Открыть оверлей</button>
    {isOpen && (
      <FloatingPortal>
        <FloatingOverlay lockScroll onDism iss={() => setIsOpen(false)}>
          <div ref={floating} style={{ position: 'absolute', top: y ?? 0, left: x ?? 0 }}>
            Содержимое оверлея
          </div>
        </FloatingOverlay>
      </FloatingPortal>
    )}
  </>
);

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

FloatingOverlay автоматически обеспечивает фокус-траппинг: фокус остается внутри оверлея до его закрытия. Это критически важно для доступности:

  • Escape закрывает оверлей.
  • Tab циклично перемещает фокус по интерактивным элементам внутри оверлея.
  • Поддержка экранных ридеров обеспечивается правильной разметкой и aria-атрибутами.
<FloatingOverlay
  isOpen={isOpen}
  onDism iss={() => setIsOpen(false)}
  lockScroll
  initialFocus={floatingRef}
/>

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


Работа с анимациями

FloatingOverlay не ограничивает способ анимации. Обычно используется комбинация CSS-переходов и хука состояния:

.overlay-enter {
  opacity: 0;
  transform: scale(0.95);
}
.overlay-enter-active {
  opacity: 1;
  transform: scale(1);
  transition: opacity 200ms, transform 200ms;
}
.overlay-exit {
  opacity: 1;
  transform: scale(1);
}
.overlay-exit-active {
  opacity: 0;
  transform: scale(0.95);
  transition: opacity 200ms, transform 200ms;
}

Совместимость с мобильными устройствами

  • Поддержка тач-событий и адаптивного позиционирования.
  • preventOutsideScroll предотвращает нежелательную прокрутку фона на устройствах с маленьким экраном.
  • Учет безопасных зон (safe area) на iOS и Android через CSS-переменные env(safe-area-inset-*).

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

  • Использовать FloatingPortal для предотвращения перекрытия контента.
  • Всегда указывать onDismiss, чтобы синхронизировать состояние видимости с приложением.
  • Для сложных взаимодействий с множеством оверлеев использовать id или контекст, чтобы управлять приоритетами закрытия.
  • Блокировка прокрутки (lockScroll) рекомендована для модальных диалогов, но может быть отключена для небольших тултипов.

FloatingOverlay предоставляет готовую инфраструктуру для реализации модальных слоев, сохраняя контроль над позиционированием, фокусом и прокруткой. Его гибкость позволяет интегрировать любые анимации, управлять поведением на мобильных устройствах и поддерживать доступность, делая интерфейсы безопасными и отзывчивыми.