Динамическое изменение цветов

MUI (Material-UI) предоставляет мощный механизм управления темами, который позволяет динамически менять цвета компонентов приложения без необходимости ручного вмешательства в каждый элемент. Ключевым инструментом для этого является объект темы (Theme) и функция createTheme, а также хук useTheme и компонент ThemeProvider.


Создание базовой темы

В MUI темы создаются с помощью функции createTheme. В объекте темы можно задать цветовую палитру, тип палитры (light/dark), а также кастомные переменные.

import { createTheme, ThemeProvider } from '@mui/material/styles';

const lightTheme = createTheme({
  palette: {
    mode: 'light',
    primary: {
      main: '#1976d2',
    },
    secondary: {
      main: '#dc004e',
    },
  },
});

const darkTheme = createTheme({
  palette: {
    mode: 'dark',
    primary: {
      main: '#90caf9',
    },
    secondary: {
      main: '#f48fb1',
    },
  },
});

Ключевой момент: palette.mode автоматически задаёт базовые цвета для текста, фона и элементов, упрощая работу с тёмной и светлой темой.


Применение темы с ThemeProvider

ThemeProvider оборачивает корневой компонент приложения и передаёт тему всем дочерним компонентам.

<ThemeProvider theme={lightTheme}>
  <App />
</ThemeProvider>

Важно: Компоненты MUI, такие как Button, AppBar, Typography, будут автоматически использовать цвета из текущей темы.


Динамическая смена темы

Для динамической смены цветов можно использовать состояние React и переключение между темами:

import { useState } from 'react';

function AppWrapper() {
  const [isDarkMode, setIsDarkMode] = useState(false);

  const theme = isDarkMode ? darkTheme : lightTheme;

  return (
    <ThemeProvider theme={theme}>
      <button onCl ick={() => setIsDarkMode(!isDarkMode)}>
        Переключить тему
      </button>
      <App />
    </ThemeProvider>
  );
}

Ключевой момент: Использование состояния позволяет изменять тему “на лету”, не перезагружая страницу и не изменяя отдельные компоненты вручную.


Кастомизация цветов компонентов

MUI поддерживает кастомные цвета через palette и sx пропсы.

import Button from '@mui/material/Button';

<Button sx={{ backgroundColor: 'primary.main', color: 'secondary.main' }}>
  Кнопка с кастомным цветом
</Button>

Можно также использовать функцию theme внутри sx для доступа к текущей теме:

<Button
  sx={(theme) => ({
    backgroundColor: theme.palette.primary.main,
    color: theme.palette.secondary.contrastText,
  })}
>
  Динамический цвет
</Button>

Особенность: Даже при смене темы кнопка автоматически обновит свои цвета.


Использование кастомных переменных

MUI позволяет добавлять собственные цвета или настройки, расширяя стандартную палитру:

const theme = createTheme({
  palette: {
    mode: 'light',
    primary: { main: '#1976d2' },
    custom: {
      highlight: '#ffeb3b',
      warning: '#f44336',
    },
  },
});

// Использование:
<Button sx={(theme) => ({ backgroundColor: theme.palette.custom.highlight })}>
  Подсветка
</Button>

Ключевой момент: Для новых цветов необходимо объявить их типизацию, если используется TypeScript, чтобы избежать ошибок компиляции.


Динамическая смена отдельных цветов

Можно менять отдельные свойства темы в реальном времени, не создавая новую тему полностью:

import { useMemo } from 'react';

const dynamicTheme = useMemo(() => 
  createTheme({
    palette: {
      primary: { main: isDarkMode ? '#90caf9' : '#1976d2' },
      secondary: { main: isDarkMode ? '#f48fb1' : '#dc004e' },
    },
  }),
  [isDarkMode]
);

Использование useMemo предотвращает ненужное пересоздание темы при каждом рендере, повышая производительность.


Работа с системными предпочтениями цвета

Можно автоматически подстраивать тему под системные настройки пользователя с помощью хука useMediaQuery:

import { useMediaQuery } from '@mui/material';

const prefersDarkMode = useMediaQuery('(prefers-color-scheme: dark)');

const theme = useMemo(() => 
  createTheme({
    palette: { mode: prefersDarkMode ? 'dark' : 'light' },
  }),
  [prefersDarkMode]
);

Преимущество: Пользователь видит интерфейс в привычной цветовой схеме без необходимости вручную переключать тему.


Использование динамических цветов в Styled Components

MUI интегрируется с функцией styled, позволяя задавать динамические цвета внутри кастомных компонентов:

import { styled } from '@mui/material/styles';
import Button from '@mui/material/Button';

const CustomButton = styled(Button)(({ theme, active }) => ({
  backgroundColor: active ? theme.palette.primary.main : theme.palette.secondary.main,
  color: theme.palette.getContrastText(active ? theme.palette.primary.main : theme.palette.secondary.main),
}));

<CustomButton active={true}>Активная кнопка</CustomButton>

Особенность: Цвета реагируют на текущую тему и на дополнительные пропсы компонента.


Советы по производительности

  • Создавать тему через useMemo, чтобы не пересоздавать её на каждом рендере.
  • Использовать стандартные палитры (primary, secondary) для максимальной совместимости с MUI-компонентами.
  • Для динамических кастомных цветов расширять палитру один раз, чтобы избежать дублирования кода.

Dynamically changing colors в MUI строится на основе тем, хука useTheme, компонента ThemeProvider, а также состояния приложения, что обеспечивает гибкость и масштабируемость интерфейса при смене светлой и тёмной темы, кастомных цветов и адаптации к системным настройкам.