Структура модального окна

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


Компоненты модального окна

  1. Root Компонент Dialog.Root служит контейнером для всего модального окна. Он управляет состоянием открытости (open) и закрытия (onOpenChange) и обеспечивает координацию между внутренними элементами.

    import * as Dialog from '@radix-ui/react-dialog';
    
    <Dialog.Root>
      {/* содержимое модального окна */}
    </Dialog.Root>

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

    • defaultOpen – начальное состояние окна (открыто или закрыто).
    • modal – флаг, определяющий, блокируется ли фон и взаимодействие с ним. По умолчанию true.
  2. Trigger Dialog.Trigger – кнопка или элемент, который открывает модальное окно. Можно использовать любой HTML-элемент, совместимый с событием onClick.

    <Dialog.Trigger asChild>
      <button>Открыть окно</button>
    </Dialog.Trigger>

    Особенности:

    • Использование asChild позволяет передавать стили и свойства дочернего элемента.
    • Не влияет на доступность, Radix UI сам добавляет нужные aria-* атрибуты.
  3. Overlay Dialog.Overlay отвечает за затемнение фона при открытии окна. Это визуальный слой, который обычно перекрывает весь экран.

    <Dialog.Overlay className="overlay" />

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

    • Добавлять анимацию появления/исчезновения через CSS или библиотеку анимаций.
    • Использовать стили с position: fixed; inset: 0; для полной фиксации по экрану.
  4. Content Dialog.Content – основной контейнер контента модального окна. Содержит заголовок, тело, кнопки и другие элементы.

    <Dialog.Content className="modal-content">
      <Dialog.Title>Заголовок окна</Dialog.Title>
      <Dialog.Description>Описание и детали</Dialog.Description>
      {/* Дополнительные элементы */}
    </Dialog.Content>

    Особенности:

    • Автоматически фокусируется при открытии окна.
    • Можно использовать кастомные стили и классы для адаптивного позиционирования.
    • Поддерживает анимации через свойства motion или CSS-транзишены.
  5. Title и Description Dialog.Title и Dialog.Description обеспечивают доступность модального окна для скринридеров. Заголовок служит описанием цели окна, а описание уточняет контекст.

    <Dialog.Title>Форма обратной связи</Dialog.Title>
    <Dialog.Description>Заполните поля и нажмите отправить</Dialog.Description>

    Ключевой момент: использование этих компонентов повышает семантическую корректность и соответствует стандартам ARIA.

  6. Close Dialog.Close – кнопка для закрытия модального окна. Может быть встроена в Content или отдельно.

    <Dialog.Close asChild>
      <button>Закрыть</button>
    </Dialog.Close>

    Особенности:

    • Автоматически вызывает onOpenChange(false).
    • Можно комбинировать с иконками или кастомными компонентами.

Важные аспекты реализации

  • Фокусировка и управление клавиатурой: Radix UI автоматически блокирует взаимодействие с фоном и переводит фокус внутрь окна при открытии. Используется trapFocus и aria-hidden для фоновых элементов.
  • Анимация: Overlay и Content можно анимировать через CSS, используя свойства opacity, transform и transition. Radix UI не навязывает конкретную библиотеку анимаций.
  • Состояние окна: Контролируемое открытие через пропсы open и onOpenChange позволяет синхронизировать модальное окно с глобальным состоянием приложения, например через Redux или Zustand.
  • Кастомизация: Все компоненты можно стилизовать с помощью className, style или библиотеки Tailwind CSS. Radix UI сохраняет доступность даже при полной визуальной кастомизации.

Пример полной структуры модального окна

<Dialog.Root>
  <Dialog.Trigger asChild>
    <button>Открыть окно</button>
  </Dialog.Trigger>

  <Dialog.Portal>
    <Dialog.Overlay className="overlay" />
    <Dialog.Content className="modal-content">
      <Dialog.Title>Регистрация</Dialog.Title>
      <Dialog.Description>Заполните форму для создания аккаунта</Dialog.Description>

      <form>
        <input type="text" placeholder="Имя" />
        <input type="email" placeholder="Email" />
        <button type="submit">Отправить</button>
      </form>

      <Dialog.Close asChild>
        <button className="close-btn">Закрыть</button>
      </Dialog.Close>
    </Dialog.Content>
  </Dialog.Portal>
</Dialog.Root>

Структура:

  • Root – управление состоянием.
  • Trigger – кнопка открытия.
  • Portal – рендеринг модального окна вне основного DOM.
  • Overlay – затемнение фона.
  • Content – основной контейнер.
  • Title и Description – доступность.
  • Close – кнопка закрытия.

Использование этой структуры позволяет создавать доступные, настраиваемые и анимируемые модальные окна, которые легко интегрируются в современные React-приложения.