Типизация sx пропса

В библиотеке MUI (Material-UI) sx пропс является одним из ключевых инструментов для стилизации компонентов. Он предоставляет удобный способ применять стили напрямую через объект, поддерживая синтаксис CSS-in-JS и доступ к теме. Типизация sx пропса позволяет получить автодополнение, проверку типов и предотвратить ошибки при передаче стилей.


Основы типизации sx

Пропс sx принимает объект, массив объектов или функцию, возвращающую объект стилей. В TypeScript типизация выглядит следующим образом:

import { SxProps, Theme } from '@mui/material/styles';
import Box from '@mui/material/Box';

const styles: SxProps<Theme> = {
  display: 'flex',
  flexDirection: 'column',
  gap: 2,
};

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

  • SxProps<Theme> — универсальный тип, который обеспечивает совместимость со всеми стандартными свойствами CSS и расширениями темы MUI.
  • Тип Theme импортируется из @mui/material/styles и позволяет использовать значения из темы, например palette, spacing и typography.

Использование функции в sx

Функция в sx получает текущую тему и возвращает объект стилей:

<Box
  sx={(theme) => ({
    color: theme.palette.primary.main,
    padding: theme.spacing(2),
    '&:hover': {
      backgroundColor: theme.palette.action.hover,
    },
  })}
/>

Особенности:

  • Позволяет использовать динамические стили на основе темы.
  • Тип theme строго соответствует типу темы приложения, что даёт автодополнение и проверку типов.
  • Можно комбинировать с условной логикой для изменения стилей в зависимости от состояния компонента.

Массив объектов в sx

sx поддерживает массив объектов, что позволяет комбинировать несколько наборов стилей:

const baseStyles: SxProps<Theme> = {
  display: 'flex',
  alignItems: 'center',
};

const hoverStyles: SxProps<Theme> = {
  '&:hover': {
    backgroundColor: 'grey.100',
  },
};

<Box sx={[baseStyles, hoverStyles]} />

Преимущества массива:

  • Легко разделять базовые и условные стили.
  • Удобно переиспользовать наборы стилей.
  • Типизация массива объектов также контролируется через SxProps<Theme>.

Интеграция с темой и palette

sx полностью поддерживает работу с темой MUI. Все свойства цвета, отступов и шрифтов можно задавать через объект темы:

<Box
  sx={{
    color: (theme) => theme.palette.success.main,
    margin: (theme) => theme.spacing(3),
    typography: 'h6',
  }}
/>

Важные моменты:

  • Использование theme.spacing(n) гарантирует единообразные отступы.
  • Доступ к palette позволяет использовать системные цвета MUI (primary, secondary, error, success, warning, info).
  • Свойство typography позволяет применить готовые стили заголовков и текста из темы.

Типизация для кастомных компонентов

Для собственных компонентов, которые оборачиваются в Box или другие MUI-компоненты, можно указать типизацию sx следующим образом:

import { SxProps, Theme } from '@mui/material/styles';

interface CustomButtonProps {
  sx?: SxProps<Theme>;
  label: string;
}

const CustomButton: React.FC<CustomButtonProps> = ({ sx, label }) => (
  <Box component="button" sx={sx}>
    {label}
  </Box>
);

Особенности:

  • sx остаётся опциональным.
  • Можно передавать объекты, функции или массивы объектов стилей.
  • Поддерживается строгая проверка типов через SxProps<Theme>.

Типизация и условные стили

TypeScript позволяет безопасно комбинировать условные стили:

const isActive = true;

<Box
  sx={{
    backgroundColor: isActive ? 'primary.main' : 'grey.300',
    padding: 2,
    '&:hover': {
      backgroundColor: isActive ? 'primary.dark' : 'grey.400',
    },
  }}
/>

Преимущества:

  • Типизация предотвращает ошибки в названиях цветов и других CSS-свойств.
  • Можно использовать любое логическое выражение для динамических стилей.

Использование утилит MUI для типизации

MUI предоставляет вспомогательные типы для более точной типизации:

  • SystemStyleObject<Theme> — для объектов стилей с поддержкой темы.
  • SxProps<Theme> — для передачи в sx, поддерживает объекты, массивы и функции.
  • Theme — основная тема приложения, включающая palette, spacing, typography, breakpoints.
import { SxProps, Theme, SystemStyleObject } from '@mui/material/styles';

const styleObject: SystemStyleObject<Theme> = {
  display: 'flex',
  justifyContent: 'space-between',
};
const sxStyle: SxProps<Theme> = styleObject;

Расширение темы для sx

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

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

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

const theme = createTheme({
  custom: {
    mainColor: '#FF5722',
  },
});

<Box
  sx={(theme: Theme) => ({
    color: theme.custom.mainColor,
  })}
/>

Особенности:

  • Расширение интерфейса темы позволяет использовать новые свойства в sx.
  • TypeScript контролирует доступ только к существующим свойствам темы.
  • Полная интеграция с автодополнением редактора.

Выводы по типизации sx

  • sx пропс является гибким и типобезопасным способом стилизации.
  • Поддерживаются объекты, массивы объектов и функции.
  • Интеграция с темой обеспечивает консистентность цветов, отступов и типографики.
  • Типы SxProps<Theme> и SystemStyleObject<Theme> позволяют предотвращать ошибки на этапе компиляции.
  • Расширение темы открывает возможности для создания кастомных систем стилей, полностью типизированных для TypeScript.