React Aria предоставляет мощные инструменты для управления доступностью и поведением компонентов, но для создания визуально согласованных интерфейсов критически важно использовать систему темизации. Она позволяет централизованно управлять стилями, поддерживать светлые и тёмные темы, а также настраивать дизайн под разные пользовательские предпочтения.
1. Контекст темы React Aria не навязывает конкретный способ стилизации, однако концепция ThemeContext позволяет передавать тему через дерево компонентов. Основная идея: определить объект с цветами, размерами шрифтов и другими визуальными параметрами, и сделать его доступным через React Context.
Пример создания контекста темы:
import React, { createContext, useContext } from 'react';
const ThemeContext = createContext({
colors: {
primary: '#0b5fff',
background: '#ffffff',
text: '#000000',
},
spacing: {
small: '8px',
medium: '16px',
large: '24px',
},
});
export const useTheme = () => useContext(ThemeContext);
export const ThemeProvider = ({ theme, children }) => (
<ThemeContext.Provider value={theme}>
{children}
</ThemeContext.Provider>
);
Использование в компоненте:
import { useTheme } from './ThemeContext';
function Button({ label }) {
const theme = useTheme();
return (
<button style={{
backgroundColor: theme.colors.primary,
color: theme.colors.text,
padding: theme.spacing.medium
}}>
{label}
</button>
);
}
2. Динамическая смена темы Для поддержки тёмной и светлой темы можно хранить состояние темы и переключать её через состояние React.
import React, { useState } from 'react';
import { ThemeProvider } from './ThemeContext';
const lightTheme = {
colors: { primary: '#0b5fff', background: '#ffffff', text: '#000000' },
spacing: { small: '8px', medium: '16px', large: '24px' },
};
const darkTheme = {
colors: { primary: '#1a73e8', background: '#121212', text: '#ffffff' },
spacing: { small: '8px', medium: '16px', large: '24px' },
};
function App() {
const [isDark, setIsDark] = useState(false);
return (
<ThemeProvider theme={isDark ? darkTheme : lightTheme}>
<button onCl ick={() => setIsDark(prev => !prev)}>
Сменить тему
</button>
<Button label="Пример кнопки" />
</ThemeProvider>
);
}
Такой подход обеспечивает согласованность всех компонентов без дублирования стилей.
React Aria предоставляет хуки для управления поведением компонентов:
useButton, useCheckbox, useDialog
и др. Темизация влияет на стили компонентов, а сами хуки управляют
доступностью и интерактивностью.
Пример кнопки с темой и хуком useButton:
import { useButton } from '@react-aria/button';
import { useRef } from 'react';
import { useTheme } from './ThemeContext';
function AriaButton({ label, onPress }) {
const ref = useRef();
const { buttonProps } = useButton({ onPress }, ref);
const theme = useTheme();
return (
<button
{...buttonProps}
ref={ref}
style={{
backgroundColor: theme.colors.primary,
color: theme.colors.text,
padding: theme.spacing.medium,
border: 'none',
borderRadius: '4px',
cursor: 'pointer'
}}
>
{label}
</button>
);
}
Здесь тема определяет визуальное оформление, а useButton
гарантирует правильную обработку клавиатуры, фокуса и
ARIA-атрибутов.
React Aria легко интегрируется с библиотеками типа
styled-components или @vanilla-extract/css.
Это позволяет создавать тематические стили, реагирующие на
изменение темы.
Пример с styled-components:
import styled, { ThemeProvider } from 'styled-components';
import { useButton } from '@react-aria/button';
const StyledButton = styled.button`
background-color: ${({ theme }) => theme.colors.primary};
color: ${({ theme }) => theme.colors.text};
padding: ${({ theme }) => theme.spacing.medium};
border: none;
border-radius: 4px;
cursor: pointer;
`;
function AriaStyledButton({ label, onPress }) {
const ref = useRef();
const { buttonProps } = useButton({ onPress }, ref);
return <StyledButton {...buttonProps} ref={ref}>{label}</StyledButton>;
}
Использование ThemeProvider от
styled-components позволяет централизованно управлять всеми
стилями и переключением тем.
Темизация в React Aria — это не просто оформление. Это инструмент для создания единообразных, доступных и визуально гибких интерфейсов, который легко масштабируется на крупные приложения.