Создание вариантов компонентов

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


Определение вариантов

Каждый компонент в MUI поддерживает базовый набор стилей, который можно расширять с помощью variants в теме. Пример структуры:

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

const theme = createTheme({
  components: {
    MuiButton: {
      variants: [
        {
          props: { variant: 'dashed' },
          style: {
            border: '2px dashed #1976d2',
            color: '#1976d2',
            padding: '8px 16px',
            textTransform: 'none',
          },
        },
        {
          props: { variant: 'rounded' },
          style: {
            borderRadius: '50px',
            backgroundColor: '#f50057',
            color: '#fff',
            padding: '8px 24px',
          },
        },
      ],
    },
  },
});

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

  • props.variant — имя варианта, которое потом используется в JSX.
  • style — объект CSS-свойств, который применяется при использовании этого варианта.
  • Можно определить несколько вариантов для одного компонента, чтобы покрыть все визуальные потребности.

Использование вариантов в JSX

После добавления вариантов в тему их можно применять в компонентах напрямую:

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

<ThemeProvider theme={theme}>
  <Button variant="dashed">Dashed Button</Button>
  <Button variant="rounded">Rounded Button</Button>
</ThemeProvider>

Если заданный вариант отсутствует, MUI использует стандартный вариант компонента.


Приоритет стилей

Варианты в MUI работают по принципу приоритетов CSS-in-JS:

  1. Встроенные стили компонента (sx или style) имеют наивысший приоритет.
  2. Варианты темы применяются только если соответствующий пропс совпадает.
  3. Стили по умолчанию темы действуют только если нет совпадений выше.

Пример с использованием sx:

<Button
  variant="dashed"
  sx={{ color: 'green', fontWeight: 'bold' }}
>
  Custom Dashed
</Button>

В этом случае цвет кнопки будет зеленым, несмотря на вариант dashed, но другие свойства из варианта сохранятся.


Варианты и адаптивность

В MUI варианты могут включать адаптивные свойства, что делает их мощным инструментом для responsive-дизайна:

variants: [
  {
    props: { variant: 'responsive' },
    style: {
      padding: { xs: '4px 8px', sm: '8px 16px', md: '12px 24px' },
      fontSize: { xs: '12px', sm: '14px', md: '16px' },
    },
  },
]

Использование адаптивных вариантов позволяет задавать разные размеры и отступы для разных экранов без дублирования кода.


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

Через функцию style можно использовать тему и пропсы для создания динамических вариантов:

variants: [
  {
    props: { variant: 'dynamic' },
    style: ({ theme, ownerState }) => ({
      backgroundColor: ownerState.color || theme.palette.primary.main,
      color: theme.palette.getContrastText(ownerState.color || theme.palette.primary.main),
      padding: ownerState.large ? '12px 24px' : '6px 12px',
    }),
  },
]
  • ownerState — объект с текущими пропсами компонента.
  • Позволяет создавать варианты, зависящие от состояния компонента или дополнительных атрибутов.

Варианты для кастомных компонентов

MUI позволяет определять варианты не только для встроенных компонентов, но и для собственных, созданных с помощью styled или Box:

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

const Card = styled('div')(({ theme }) => ({
  padding: theme.spacing(2),
  borderRadius: theme.shape.borderRadius,
}));

Card.variants = [
  {
    props: { variant: 'outlined' },
    style: {
      border: '1px solid #ccc',
    },
  },
];

После добавления в тему или напрямую к компоненту можно использовать эти варианты в JSX так же, как у стандартных компонентов MUI.


Комбинирование вариантов и системных свойств

В MUI компоненты поддерживают системные свойства (sx) и variants) одновременно, что обеспечивает гибкость:

<Button
  variant="rounded"
  sx={{
    backgroundColor: 'secondary.main',
    '&:hover': { backgroundColor: 'secondary.dark' },
  }}
>
  Rounded with Hover
</Button>

Стили из sx не удаляют свойства варианта, а лишь перекрывают их при необходимости.


Лучшие практики использования вариантов

  • Стандартизируйте визуальные стили через варианты вместо постоянного использования sx.
  • Используйте адаптивные варианты для компонентов, которые меняются на разных экранах.
  • Не дублируйте CSS в sx и variants, чтобы избежать конфликтов.
  • Проверяйте совместимость с темой, особенно при использовании динамических свойств и кастомных цветов.

В результате, система вариантов в MUI позволяет создавать однородные, повторно используемые и легко поддерживаемые компоненты, что особенно важно для крупных проектов.