Расширение типов темы

В MUI (Material-UI) тема является центральным объектом для управления визуальными аспектами приложения: цветами, типографикой, отступами, формами компонентов и многим другим. Возможность расширять тему позволяет создавать собственные кастомные свойства и типы, которые будут строго типизированы в TypeScript и безопасны при использовании в компонентах.

1. Основы темы в MUI

Базовая тема в MUI создается с помощью функции createTheme:

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

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

Объект темы содержит следующие основные разделы:

  • palette — цвета приложения;
  • typography — настройки шрифтов;
  • spacing — единицы отступов;
  • shape — радиусы углов и форма компонентов;
  • components — настройка стилей отдельных компонентов через overrides.

2. Расширение темы с пользовательскими свойствами

Чтобы добавить свои свойства к теме, нужно использовать интерфейсы TypeScript для безопасной типизации. MUI предоставляет механизм module augmentation через пространство имен @mui/material/styles.

Пример добавления нового свойства status:

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

declare module '@mui/material/styles' {
  interface Theme {
    status: {
      danger: string;
    };
  }
  interface ThemeOptions {
    status?: {
      danger?: string;
    };
  }
}

const theme = createTheme({
  status: {
    danger: '#e53e3e',
  },
});

Теперь theme.status.danger доступен с полной поддержкой автодополнения и типизации.

3. Расширение палитры цветов

Помимо добавления новых свойств, можно расширять стандартную палитру MUI. Например, добавление нового цвета tertiary:

declare module '@mui/material/styles' {
  interface Palette {
    tertiary: Palette['primary'];
  }
  interface PaletteOptions {
    tertiary?: PaletteOptions['primary'];
  }
}

const theme = createTheme({
  palette: {
    primary: { main: '#1976d2' },
    secondary: { main: '#dc004e' },
    tertiary: { main: '#00bcd4' },
  },
});

После этого можно использовать новый цвет при стилизации компонентов:

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

<Button color="tertiary">Третичная кнопка</Button>

Важно: для корректной работы с компонентами, которые ожидают стандартные цвета (primary, secondary), может потребоваться переопределение типов для ButtonPropsColorOverrides.

4. Расширение типографики

Типографика в MUI имеет базовые варианты (h1, h2, body1 и т.д.). Можно добавить свои варианты:

declare module '@mui/material/styles' {
  interface TypographyVariants {
    customTitle: React.CSSProperties;
  }
  interface TypographyVariantsOptions {
    customTitle?: React.CSSProperties;
  }
}

// Создание темы
const theme = createTheme({
  typography: {
    customTitle: {
      fontSize: '2rem',
      fontWeight: 700,
      letterSpacing: '0.05em',
    },
  },
});

// Использование
import Typography from '@mui/material/Typography';

<Typography variant="customTitle">Заголовок</Typography>

Чтобы использовать новый вариант customTitle в компоненте Typography, также нужно расширить типы пропсов:

declare module '@mui/material/Typography' {
  interface TypographyPropsVariantOverrides {
    customTitle: true;
  }
}

5. Кастомные компоненты с темой

Расширение темы удобно использовать для передачи пользовательских настроек в компоненты:

declare module '@mui/material/styles' {
  interface Theme {
    sidebar: {
      width: number;
      backgroundColor: string;
    };
  }
  interface ThemeOptions {
    sidebar?: {
      width?: number;
      backgroundColor?: string;
    };
  }
}

const theme = createTheme({
  sidebar: {
    width: 240,
    backgroundColor: '#f5f5f5',
  },
});

// Использование в компоненте
const Sidebar = styled('div')(({ theme }) => ({
  width: theme.sidebar.width,
  backgroundColor: theme.sidebar.backgroundColor,
}));

6. Совмещение с sx и кастомными свойствами

Новые свойства темы можно использовать не только в styled компонентах, но и через проп sx:

<Box sx={{ backgroundColor: theme => theme.sidebar.backgroundColor, width: theme => theme.sidebar.width }}>
  Содержимое сайдбара
</Box>

Такое решение позволяет полностью интегрировать кастомные настройки в экосистему MUI с полной поддержкой типизации и автодополнения.

7. Практические советы

  • Всегда объявлять типы для новых свойств через declare module '@mui/material/styles'.
  • Для добавления цветов и типографики не забывать расширять соответствующие интерфейсы и опции.
  • Использовать ThemeOptions при создании темы, а Theme при чтении свойств.
  • Совмещать расширения темы с styled и sx для максимальной гибкости.
  • Следить за типизацией компонентов, чтобы новые свойства корректно проходили через пропсы.

Расширение типов темы в MUI открывает возможности для создания полностью кастомизированного интерфейса, сохраняя строгую типизацию и единообразие в коде приложения.