Темизация

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

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-атрибутов.


Использование CSS-in-JS для расширенной темизации

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 позволяет централизованно управлять всеми стилями и переключением тем.


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

  • Централизация стилей через ThemeContext или CSS-in-JS обеспечивает консистентный интерфейс.
  • Динамическая смена темы упрощает поддержку светлой и тёмной версии приложения.
  • React Aria отвечает за доступность, а темизация — за визуальное оформление, их сочетание создаёт полноценный компонентный интерфейс.
  • Интеграция с CSS-in-JS позволяет расширять возможности темизации, используя функции, переменные и адаптивные стили.

Темизация в React Aria — это не просто оформление. Это инструмент для создания единообразных, доступных и визуально гибких интерфейсов, который легко масштабируется на крупные приложения.