Radix UI предоставляет набор компонентов для построения доступных и настраиваемых пользовательских интерфейсов. Одним из ключевых элементов взаимодействия с пользователем являются диалоги. В отличие от стандартных модальных окон, неблокирующие диалоги не препятствуют взаимодействию с остальной частью интерфейса, что повышает гибкость и удобство работы с приложением.
Компонент диалога в Radix UI строится из нескольких взаимосвязанных частей:
Пример базовой структуры:
import * as Dialog from '@radix-ui/react-dialog';
<Dialog.Root>
<Dialog.Trigger>Открыть диалог</Dialog.Trigger>
<Dialog.Portal>
<Dialog.Overlay className="dialog-overlay" />
<Dialog.Content className="dialog-content">
<Dialog.Title>Заголовок диалога</Dialog.Title>
<Dialog.Description>Описание диалога и инструкции для пользователя</Dialog.Description>
<button onCl ick={() => {}}>Закрыть</button>
</Dialog.Content>
</Dialog.Portal>
</Dialog.Root>
Для реализации неблокирующего диалога важно учитывать два аспекта:
open и
onOpenChange: позволяет программно открывать и
закрывать диалог, интегрируя его с остальными частями интерфейса.const [open, setOpen] = useState(false);
<Dialog.Root open={open} onOpenCha nge={setOpen}>
<Dialog.Trigger>Открыть</Dialog.Trigger>
<Dialog.Content>
<Dialog.Title>Неблокирующий диалог</Dialog.Title>
<Dialog.Description>Можно продолжать работу с основным интерфейсом</Dialog.Description>
<button onCl ick={() => setOpen(false)}>Закрыть</button>
</Dialog.Content>
</Dialog.Root>
Radix UI автоматически заботится о фокусе внутри диалога и его возвращении на триггер при закрытии. Для неблокирующих диалогов важно отключить полностью изоляцию фокуса, чтобы пользователь мог перемещаться по другим элементам страницы, не закрывая диалог. Это достигается через комбинацию:
aria-hidden для основного контента, если
требуется частичное скрытие от screen reader,useFocusTrap или кастомные хуки.Radix UI не навязывает конкретные стили или анимации, но предоставляет классы и состояния, на которые удобно навешивать стили через CSS или Tailwind.
Пример плавного появления диалога:
.dialog-content {
opacity: 0;
transform: translateY(-10px);
transition: opacity 0.2s ease, transform 0.2s ease;
}
[data-state="open"] & {
opacity: 1;
transform: translateY(0);
}
Это позволяет создавать эффект «появления» без блокирования пользовательского взаимодействия с остальной страницей.
Неблокирующие диалоги часто используются параллельно. Radix UI поддерживает независимое управление состоянием каждого диалога, а также позволяет строить слойную структуру через несколько Portal, что предотвращает конфликт z-index и упрощает взаимодействие с несколькими диалогами одновременно.
<Dialog.Root open={dialog1Open} onOpenCha nge={setDialog1Open}>
<Dialog.Trigger>Диалог 1</Dialog.Trigger>
<Dialog.Content>Контент 1</Dialog.Content>
</Dialog.Root>
<Dialog.Root open={dialog2Open} onOpenCha nge={setDialog2Open}>
<Dialog.Trigger>Диалог 2</Dialog.Trigger>
<Dialog.Content>Контент 2</Dialog.Content>
</Dialog.Root>
Диалоги Radix UI идеально подходят для размещения форм, уведомлений и интерактивных компонентов. В неблокирующем режиме формы остаются полностью функциональными, а пользователь может продолжать использовать основное приложение параллельно.
<Dialog.Content>
<form onSub mit={handleSubmit}>
<label>
Имя:
<input type="text" name="name" />
</label>
<button type="submit">Сохранить</button>
</form>
</Dialog.Content>
В этом примере диалог работает как автономный компонент, не блокирующий доступ к остальной части страницы.
Использование этих принципов позволяет создавать гибкие, доступные и полностью неблокирующие диалоги, интегрируемые в сложные интерфейсы.