Radix UI предоставляет низкоуровневые компоненты для построения
интерфейсов с управляемым состоянием и доступностью. Для интеграции с
Emotion необходимо использовать компонент styled из
@emotion/styled или хук css из
@emotion/react. Это позволяет полностью контролировать
стили, сохраняя доступность и функциональность компонентов Radix.
/** @jsxImportSource @emotion/react */
import { css } from '@emotion/react';
import styled from '@emotion/styled';
import * as Dialog from '@radix-ui/react-dialog';
const StyledDialogContent = styled(Dialog.Content)`
background-color: white;
border-radius: 8px;
padding: 20px;
box-shadow: 0 10px 25px rgba(0, 0, 0, 0.1);
`;
Использование styled обеспечивает возможность создавать
переиспользуемые компоненты с заранее заданными стилями, сохраняя все
свойства Radix UI, включая анимации, фокус и aria-атрибуты.
css и динамические пропсыИспользование хука css позволяет добавлять динамические
стили на основе пропсов компонента:
const buttonStyle = (primary) => css`
padding: 10px 20px;
border-radius: 6px;
border: none;
cursor: pointer;
background-color: ${primary ? 'blue' : 'gray'};
color: white;
&:hover {
background-color: ${primary ? 'darkblue' : 'darkgray'};
}
`;
function MyButton({ primary, children }) {
return <button css={buttonStyle(primary)}>{children}</button>;
}
При работе с Radix UI можно комбинировать компоненты Radix и стилизованные Emotion-элементы, создавая полностью кастомные интерфейсы с сохранением состояния компонента и доступности.
Radix UI предоставляет свойства состояния для управления анимациями
(open, closed). Emotion позволяет применять
эти состояния в стилях с помощью селекторов и CSS-переменных.
const StyledContent = styled(Dialog.Content)`
opacity: 0;
transform: translateY(-10px);
transition: all 0.3s ease;
&[data-state='open'] {
opacity: 1;
transform: translateY(0);
}
`;
Здесь используется атрибут data-state, который Radix UI
автоматически добавляет к компоненту в зависимости от его состояния. Это
обеспечивает плавное появление и скрытие диалогов без использования
дополнительных библиотек анимации.
Emotion поддерживает создание тем через ThemeProvider,
что позволяет централизованно управлять цветами, отступами и
типографикой для компонентов Radix:
import { ThemeProvider } from '@emotion/react';
const theme = {
colors: {
primary: 'blue',
secondary: 'gray',
background: '#f9f9f9',
},
borderRadius: '8px',
};
const StyledDialogContent = styled(Dialog.Content)`
background-color: ${props => props.theme.colors.background};
border-radius: ${props => props.theme.borderRadius};
padding: 20px;
`;
Тематизация позволяет создавать единообразный дизайн, минимизируя дублирование стилей и улучшая поддержку крупных проектов.
Radix UI ориентирован на композицию: отдельные части компонента
(например, Dialog.Overlay, Dialog.Content)
можно стилизовать независимо друг от друга:
const Overlay = styled(Dialog.Overlay)`
background-color: rgba(0, 0, 0, 0.5);
position: fixed;
inset: 0;
`;
const Content = styled(Dialog.Content)`
background: white;
border-radius: 10px;
padding: 25px;
max-width: 500px;
margin: 100px auto;
position: relative;
`;
Такой подход обеспечивает гибкость при разработке сложных интерфейсов, позволяя отдельно управлять стилями фона, контейнера и интерактивных элементов.
Стилизация через Emotion не мешает встроенной доступности Radix UI. Все aria-атрибуты и фокус-менеджмент сохраняются. Для улучшения UX можно добавлять визуальные индикаторы фокуса:
const FocusableButton = styled.button`
padding: 10px 15px;
border: 2px solid transparent;
border-radius: 6px;
&:focus {
border-color: blue;
outline: none;
}
`;
Это особенно важно для клавиатурной навигации и пользователей с особыми потребностями, так как Radix UI управляет фокусом внутри компонентов, а Emotion только визуализирует состояние.
Полный пример объединяет все предыдущие техники:
function App() {
return (
<Dialog.Root>
<Dialog.Trigger asChild>
<button>Открыть диалог</button>
</Dialog.Trigger>
<Overlay />
<Content>
<Dialog.Title>Заголовок диалога</Dialog.Title>
<Dialog.Description>
Это описание диалога, стилизованного через Emotion.
</Dialog.Description>
<button onCl ick={() => Dialog.Root.close()}>Закрыть</button>
</Content>
</Dialog.Root>
);
}
Этот пример демонстрирует:
styled для контейнеров и
overlay)open/closed)При использовании Emotion с Radix UI следует учитывать:
css объектов
внутри рендер-функций.styled для повторно используемых
компонентов, чтобы минимизировать overhead от генерации CSS на
лету.Эти подходы обеспечивают высокую производительность интерфейсов даже при большом количестве интерактивных компонентов.
Гибкость Radix UI в сочетании с мощью Emotion позволяет создавать современные, доступные и легко кастомизируемые интерфейсы, сохраняя строгий контроль над стилями и состояниями компонентов.