Radix UI предоставляет мощный набор компонентов для построения интерфейсов с доступностью по умолчанию. Работа с анимациями в Radix UI строится на принципе контролируемой визуальной трансформации компонентов, что позволяет плавно изменять состояние элементов без потери доступности и управления фокусом.
Анимации в Radix UI обычно применяются через
CSS-переходы и Keyframe-анимации,
используя вспомогательные утилиты вроде
@radix-ui/react-animations или интеграцию с библиотеками
стилей типа stitches или tailwindcss. Основной
подход заключается в управлении состояниями компонентов
(open, closed, active) и
связывании этих состояний с соответствующими CSS-классами анимации.
У каждого компонента Radix UI есть управляемое состояние, которое можно использовать для запуска анимаций:
import * as Dialog from '@radix-ui/react-dialog';
<Dialog.Root>
<Dialog.Trigger>Открыть диалог</Dialog.Trigger>
<Dialog.Content className={isOpen ? 'fade-in' : 'fade-out'}>
Содержимое диалога
</Dialog.Content>
</Dialog.Root>
В этом примере используется условное присвоение класса в зависимости
от состояния isOpen. Важно: компоненты
Radix UI сами обеспечивают управление фокусом и доступность, поэтому
анимации не должны нарушать эти механизмы.
Использование keyframes позволяет создавать сложные, последовательные анимации:
@keyframes slideIn {
from { transform: translateY(-20px); opacity: 0; }
to { transform: translateY(0); opacity: 1; }
}
@keyframes slideOut {
from { transform: translateY(0); opacity: 1; }
to { transform: translateY(-20px); opacity: 0; }
}
.fade-in { animation: slideIn 0.3s ease-out forwards; }
.fade-out { animation: slideOut 0.2s ease-in forwards; }
Ключевой момент: использовать forwards для
сохранения конечного состояния анимации, иначе элемент может
вернуться к исходному стилю после завершения анимации.
При работе с Radix UI часто применяется CSS-in-JS,
например @stitches/react. Это позволяет динамически
привязывать состояния компонентов к анимациям:
import { styled, keyframes } from '@stitches/react';
import * as Dialog from '@radix-ui/react-dialog';
const slideIn = keyframes({
'0%': { transform: 'translateY(-20px)', opacity: 0 },
'100%': { transform: 'translateY(0)', opacity: 1 },
});
const Content = styled(Dialog.Content, {
animation: `${slideIn} 0.3s ease-out`,
});
Такой подход обеспечивает полную интеграцию стилей и логики компонента, позволяя легко изменять параметры анимации без дублирования CSS.
Для элементов с динамическим появлением (Dropdown,
Popover, Dialog) рекомендуется использовать
анимацию при монтировании и размонтировании:
import { keyframes, styled } from '@stitches/react';
import * as Popover from '@radix-ui/react-popover';
const fadeIn = keyframes({ from: { opacity: 0 }, to: { opacity: 1 } });
const fadeOut = keyframes({ from: { opacity: 1 }, to: { opacity: 0 } });
const StyledContent = styled(Popover.Content, {
'&[data-state="open"]': { animation: `${fadeIn} 0.2s ease-out` },
'&[data-state="closed"]': { animation: `${fadeOut} 0.2s ease-in` },
});
Особенность: Radix UI автоматически добавляет
атрибут data-state, который отражает текущее состояние
компонента (open или closed). Это упрощает
связывание анимаций с состоянием без дополнительной логики.
Для сложных интерфейсов часто требуется комбинировать несколько анимаций:
const scaleUp = keyframes({ from: { transform: 'scale(0.95)' }, to: { transform: 'scale(1)' } });
const fadeIn = keyframes({ from: { opacity: 0 }, to: { opacity: 1 } });
const AnimatedContent = styled(Dialog.Content, {
'&[data-state="open"]': {
animation: `${scaleUp} 0.3s ease-out, ${fadeIn} 0.3s ease-out`,
},
});
Такой подход позволяет одновременно изменять трансформацию и прозрачность, создавая ощущение глубины и динамики интерфейса.
Для создания каскадных эффектов можно использовать
CSS-переменные или утилиты stitches:
const fadeInDelay = keyframes({ from: { opacity: 0 }, to: { opacity: 1 } });
const Item = styled('div', {
variants: {
delay: {
1: { animation: `${fadeInDelay} 0.3s ease-out 0.1s forwards` },
2: { animation: `${fadeInDelay} 0.3s ease-out 0.2s forwards` },
3: { animation: `${fadeInDelay} 0.3s ease-out 0.3s forwards` },
},
},
});
Такой способ позволяет поэтапно отображать элементы меню или списков, создавая более плавный и отзывчивый интерфейс.
Radix UI хорошо сочетается с библиотекой
react-transition-group для контролируемых
монтирования/размонтирования элементов с анимацией:
import { CSSTransition } from 'react-transition-group';
import * as Dialog from '@radix-ui/react-dialog';
<Dialog.Root>
<Dialog.Trigger>Открыть</Dialog.Trigger>
<CSSTransition in={isOpen} timeout={300} classNames="dialog">
<Dialog.Content className="dialog-content">
Содержимое
</Dialog.Content>
</CSSTransition>
</Dialog.Root>
CSSTransition позволяет сохранять доступность и
управление фокусом Radix, одновременно добавляя полноценную
анимацию монтирования и размонтирования.
data-state для привязки анимаций к
состояниям компонентов.display: none без размонтирования компонента.transform и opacity обычно оптимизированы для
GPU-ускорения.Эти подходы обеспечивают плавные, управляемые анимации в интерфейсах Radix UI без ущерба для доступности и стабильности компонентов.