Modal режим

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

Структура компонентов Modal

Modal в Radix UI строится из нескольких ключевых компонентов:

  • Dialog — контейнер, управляющий состоянием модального окна.
  • DialogTrigger — элемент, который открывает модальное окно при взаимодействии. Обычно это кнопка или ссылка.
  • DialogPortal — компонент, который позволяет рендерить модальное окно вне текущего DOM-дерева для избежания проблем с z-index и позиционированием.
  • DialogOverlay — затемнённый фон за модальным окном, который предотвращает взаимодействие с остальной страницей.
  • DialogContent — основная область содержимого модального окна. Содержит заголовки, текст, формы и кнопки.
  • DialogTitle — заголовок окна, важный для доступности.
  • DialogDescription — описание окна, предоставляющее дополнительный контекст для пользователя.
  • DialogClose — кнопка для закрытия окна, интегрированная с внутренним управлением состоянием.
import * as Dialog from '@radix-ui/react-dialog';

<Dialog.Root>
  <Dialog.Trigger>Открыть окно</Dialog.Trigger>
  <Dialog.Portal>
    <Dialog.Overlay className="overlay"/>
    <Dialog.Content className="content">
      <Dialog.Title>Заголовок окна</Dialog.Title>
      <Dialog.Description>Описание контента окна</Dialog.Description>
      <button>Действие</button>
      <Dialog.Close>Закрыть</Dialog.Close>
    </Dialog.Content>
  </Dialog.Portal>
</Dialog.Root>

Управление состоянием модального окна

Dialog.Root использует контролируемое и неконтролируемое состояние. По умолчанию состояние неконтролируемое, и окно открывается через DialogTrigger. Для контролируемого состояния используется проп open:

const [isOpen, setIsOpen] = useState(false);

<Dialog.Root open={isOpen} onOpenCha nge={setIsOpen}>
  <Dialog.Trigger>Открыть окно</Dialog.Trigger>
  <Dialog.Portal>
    <Dialog.Overlay />
    <Dialog.Content>
      <Dialog.Title>Контролируемый Modal</Dialog.Title>
      <Dialog.Close>Закрыть</Dialog.Close>
    </Dialog.Content>
  </Dialog.Portal>
</Dialog.Root>

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

Стилизация и анимации

Radix UI предоставляет базовую структуру и классы для элементов, но визуальная часть определяется самостоятельно. Наиболее часто используется CSS-модули, Tailwind или Styled Components.

Пример стилизации с CSS:

.overlay {
  position: fixed;
  inset: 0;
  background: rgba(0,0,0,0.5);
}

.content {
  position: fixed;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  background: white;
  padding: 2rem;
  border-radius: 8px;
  max-width: 500px;
  width: 90%;
}

Для анимаций удобно использовать свойства opacity и transform, управляемые через классы при монтировании/размонтировании модального окна.

Доступность (a11y)

Radix UI обеспечивает встроенную доступность:

  • Фокус автоматически перемещается в DialogContent при открытии окна.
  • Клавиша Escape закрывает окно по умолчанию.
  • Атрибуты aria-labelledby и aria-describedby добавляются автоматически на основе DialogTitle и DialogDescription.
  • Взаимодействие с остальной частью страницы блокируется через DialogOverlay.

Продвинутые возможности

  • Nested Modals: Radix поддерживает вложенные модальные окна, автоматически управляя фокусом и z-index.
  • Custom triggers: DialogTrigger можно использовать с любым элементом, включая кастомные кнопки и иконки.
  • Animations и transitions: можно интегрировать с библиотеками анимации (например, Framer Motion) для плавного появления и исчезновения окон.
  • Portal-targeting: DialogPortal можно рендерить в конкретный контейнер, если требуется сложная структура DOM.

Примеры практического использования

  1. Форма подтверждения действия: модальное окно с кнопками “Подтвердить” и “Отмена”.
  2. Информационные окна: сообщения о результатах операций, предупреждения или подсказки.
  3. Всплывающие интерфейсы сложных форм: регистрация, логин, многошаговые формы, которые не должны ломать основной поток интерфейса.

Ловушки и рекомендации

  • Не использовать модальные окна для навигации по приложению — это нарушает UX и может вызвать проблемы с доступностью.
  • Всегда предоставлять явную кнопку закрытия (DialogClose) и поддерживать клавишу Escape.
  • Если контент большого объема, стоит использовать скроллируемый контейнер внутри DialogContent, чтобы не ломать позиционирование.

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