Закрытие по клику вне

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


Использование DismissableLayer

Radix UI предлагает компонент DismissableLayer, который отвечает за обработку кликов вне компонента и клавиши Escape для закрытия. Этот компонент является основой для реализации закрытия по клику вне.

Пример базового использования:

import * as React from 'react';
import * as DismissableLayer from '@radix-ui/react-dismissable-layer';

export default function Example() {
  const [open, setOpen] = React.useState(false);

  return (
    
{open && ( setOpen(false)} >
Контент, который можно закрыть кликом вне
)}
); }

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

  • DismissableLayer.Root автоматически отслеживает клики за пределами контейнера и нажатие клавиши Escape.
  • onDismiss вызывается при срабатывании любого из этих событий.
  • Состояние open управляет рендерингом компонента.

Контроль за поведением закрытия

DismissableLayer предоставляет дополнительные свойства для тонкой настройки поведения:

  • disableOutsidePointerEvents – предотвращает обработку кликов вне слоя. Полезно, если нужно временно заблокировать закрытие.
  • modal – при true слой ведёт себя как модальное окно, блокируя фокус на остальных элементах страницы.
  • trapFocus – удерживает фокус внутри слоя, предотвращая переход на другие элементы при клавиатурной навигации.

Пример:

 setOpen(false)}
  modal
  trapFocus
>
  
Модальный контент с фокус-трэпом

Использование вместе с другими компонентами Radix

Radix UI предоставляет множество интерактивных компонентов, где DismissableLayer может использоваться как основа для закрытия по клику вне. Например:

Меню (DropdownMenu)

import * as DropdownMenu from '@radix-ui/react-dropdown-menu';


  Открыть меню
  
    Элемент 1
    Элемент 2
  

Внутри DropdownMenu.Content используется DismissableLayer для автоматического закрытия при клике вне меню.

Тултип (Tooltip)

В тултипах также применяется подобный механизм для скрытия подсказки при уходе курсора или клике вне области.


Применение кастомных обработчиков

Можно комбинировать DismissableLayer с собственными логиками закрытия. Например, если нужно закрывать компонент не сразу, а через анимацию:

 {
    // Запуск анимации скрытия
    animateHide().then(() => setOpen(false));
  }}
>
  
Контент с анимацией закрытия

Такой подход позволяет гибко управлять UX, сохраняя стандартное поведение клика вне компонента.


Рекомендации по использованию

  • Для простых всплывающих элементов достаточно стандартного DismissableLayer.Root.
  • Для модальных окон стоит использовать свойства modal и trapFocus.
  • Для сложных интерфейсов с динамическими элементами рекомендуется избегать множественного рендера компонентов одновременно, чтобы не возникали конфликты кликов вне.
  • Для кастомной логики закрытия использовать onDismiss вместе с асинхронными функциями или состояниями React.