Хотите заказать веб-сайт? Связаться с нами

Гибкие методы стилизации компонентов Mantine

Ранее на уроках этого курса мы разобрались с темой и цветовыми схемами. Теперь пришло время самого важного — как применять стили к компонентам. Mantine предлагает несколько подходов, и у каждого есть свои сценарии использования. В этом уроке мы пройдем все способы — от самых быстрых до самых мощных и производительных. Главное правило, которое стоит запомнить: CSS-модули — это рекомендуемый способ для большинства случаев.

Гибкие методы стилизации компонентов Mantine

Компонентные пропсы — самый простой способ

Самый быстрый и очевидный способ изменить внешний вид компонента — использовать его встроенные пропсы.

У каждого компонента есть набор пропсов, которые управляют его внешностью. Например, у Button это color, variant, size и radius.

import { Button, Group } from '@mantine/core';

function Demo() {
  return (
    <Group>
      <Button variant="filled" color="blue" size="sm" radius="md">
        Синяя кнопка
      </Button>
      <Button variant="outline" color="red" size="lg" radius="xl">
        Красная outline
      </Button>
      <Button variant="subtle" color="green" size="xs" radius="xs">
        Зеленая subtle
      </Button>
    </Group>
  );
}

Когда использовать: для базовой стилизации без создания дополнительных файлов. Это самый оптимальный способ кастомизации в большинстве случаев, потому что пропсы управляют сразу несколькими CSS-свойствами.

Стилевые пропсы (Style Props) — для быстрых правок

Стилевые пропсы работают как обычные пропсы, но есть важное отличие: они всегда управляют только одним CSS-свойством. Например, пропс c управляет цветом текста, а bg — фоном. Эти пропсы доступны для любого компонента Mantine.

import { Text, Paper, TextInput, Button } from '@mantine/core';

function Demo() {
  return (
    <>
      {/* Управляем цветом и размером текста */}
      <Text c="blue.8" fz="lg" fw={700}>
        Крупный синий текст
      </Text>
      <Text c="dimmed" fz="sm">
        Приглушенный мелкий текст
      </Text>
      
      {/* Отступы и фон */}
      <Paper p="xl" bg="gray.1" mt="md" radius="md">
        <Text>Бумага с отступами</Text>
      </Paper>
      
      {/* Поля у инпутов в форме */}
      <TextInput label="Имя" />
      <TextInput label="Фамилия" mt="md" />
      <TextInput label="Email" mt="md" />
      
      {/* Размеры и позиционирование */}
      <Button w={200} mt="lg" ta="center">
        Кнопка шириной 200px
      </Button>
    </>
  );
}

Важно: стилевые пропсы не предназначены для первичной стилизации компонентов. Если вы используете более 3-4 стилевых пропсов на один компонент, лучше вынести стили в отдельный файл — это упростит поддержку и будет производительнее.

Проп style — для CSS-переменных и одноразовых правок

Проп style работает так же, как React-проп style, но поддерживает CSS-переменные. Он полезен в двух случаях:

import { Button, Box, Flex } from '@mantine/core';

function Demo({ color }: { color: string }) {
  return (
    <Flex gap="md">
      {/* Применяем одно CSS-свойство */}
      <Button style={{ flex: 1 }}>Растянутая кнопка</Button>
      <Button>Обычная кнопка</Button>
      
      {/* Устанавливаем CSS-переменную на основе пропса */}
      <Box style={{ '--my-color': color }} c="var(--my-color)">
        Текст с динамическим цветом
      </Box>
    </Flex>
  );
}

Когда использовать: для одноразовых правок или когда нужно динамически установить CSS-переменную. Не рекомендуется как основной способ стилизации.

CSS-модули — рекомендованный способ

CSS-модули — это самый производительный и гибкий способ стилизации в Mantine. Они позволяют писать обычный CSS в отдельных файлах, при этом имена классов автоматически локализуются (избегая конфликтов).

Создайте файл Demo.module.css:

/* Demo.module.css */
.root {
  padding: 20px;
  border-radius: 8px;
  background-color: #f8f9fa;
}

.root[data-collapsed] {
  padding: 10px;
  background-color: #e9ecef;
}

.label {
  font-size: 18px;
  font-weight: 600;
  color: #1a1a1a;
}

/* Стилизация дочерних элементов */
.root[data-collapsed] .control {
  max-width: 40px;
}

.control {
  transition: max-width 0.3s ease;
}

А теперь используйте в компоненте:

import { useState } from 'react';
import { Box, Button, Text } from '@mantine/core';
import classes from './Demo.module.css';

function Demo() {
  const [collapsed, setCollapsed] = useState(false);
  
  return (
    <Box 
      className={classes.root} 
      data-collapsed={collapsed || undefined}
    >
      <Text className={classes.label}>Заголовок</Text>
      <Button 
        className={classes.control}
        onClick={() => setCollapsed(!collapsed)}
      >
        {collapsed ? 'Развернуть' : 'Свернуть'}
      </Button>
    </Box>
  );
}

CSS-модули работают отлично с TypeScript, обеспечивая автодополнение для классов. Это рекомендуемый способ для основной стилизации.

Робот собирает из блоков сайт

Собери свой код. Запусти сайт!

От наброска на салфетке до первого работающего лендинга. Наш онлайн-курс «Веб-верстка с нуля и до профессионала» — это интенсивный трек, где ты не будешь зубрить теорию, а с первого дня начнешь превращать идеи в чистый HTML и CSS.

Собери свой первый проект под руководством практикующих разработчиков.

Подробнее о курсе

Styles API — для тонкой настройки внутренних элементов

Самая мощная техника — Styles API. Она позволяет стилизовать любой внутренний элемент компонента, обращаясь к нему по имени (селектору) . У каждого компонента есть документация со списком селекторов — например, у Button есть root, loader, inner, section, label.

import { Button, TextInput } from '@mantine/core';
import classes from './Demo.module.css'; // с CSS-модулями

function Demo() {
  return (
    <>
      {/* Стилизация через classNames (с CSS-модулями) */}
      <Button
        classNames={{
          root: classes.buttonRoot,
          label: classes.buttonLabel,
          inner: classes.buttonInner,
        }}
      >
        Стилизованная кнопка
      </Button>
      
      {/* Стилизация через styles (inline-стили) */}
      <Button
        styles={{
          root: { backgroundColor: 'purple', border: '2px solid darkviolet' },
          label: { color: 'white', fontWeight: 700 },
          inner: { gap: '8px' },
        }}
      >
        Inline-стили
      </Button>
      
      {/* Текстовое поле с кастомным лейблом */}
      <TextInput
        label="Email"
        classNames={{
          root: classes.inputRoot,
          input: classes.inputField,
          label: classes.inputLabel,
        }}
      />
    </>
  );
}

Глобальная настройка через тему

Если вы хотите применить стили ко всем компонентам определенного типа, используйте theme.components:

import { createTheme, MantineProvider } from '@mantine/core';
import classes from './Button.module.css';

const theme = createTheme({
  components: {
    Button: Button.extend({
      classNames: {
        root: classes.globalButtonRoot,
        label: classes.globalButtonLabel,
      },
    }),
    TextInput: TextInput.extend({
      classNames: {
        root: classes.inputRoot,
        input: classes.inputField,
      },
    }),
  },
});

function App() {
  return (
    <MantineProvider theme={theme}>
      {/* Все Button будут использовать глобальные стили */}
      <Button>Стилизован через тему</Button>
    </MantineProvider>
  );
}

Кастомные варианты и размеры (V9)

В Mantine 9 вы можете добавлять свои варианты (значения пропса variant) и размеры через data- атрибуты или CSS-переменные.

// Добавляем кастомный вариант через CSS
import { Button } from '@mantine/core';
import classes from './Demo.module.css';

function Demo() {
  return (
    <Button variant="underline" className={classes.underlineButton}>
      Подчеркнутая кнопка
    </Button>
  );
}
/* Demo.module.css */
.underlineButton[data-variant="underline"] {
  background: transparent;
  border-bottom: 2px solid blue;
  border-radius: 0;
  padding: 4px 0;
  color: blue;
  
  &:hover {
    border-bottom-color: darkblue;
    color: darkblue;
  }
}

Для добавления кастомных размеров используйте CSS-переменные:

/* В CSS-модуле */
.root {
  --button-height-xxl: 80px;
  --button-padding-x-xxl: 48px;
  --button-fz-xxl: 24px;
}

.root[data-size="xxl"] {
  height: var(--button-height-xxl);
  padding-inline: var(--button-padding-x-xxl);
  font-size: var(--button-fz-xxl);
}

Сравнение подходов

Подход Сложность Производительность Гибкость Когда использовать
Компонентные пропсы Высокая Средняя 80% случаев
Стилевые пропсы Средняя Низкая Быстрые правки (до 3-4 пропсов)
style ⭐⭐ Средняя Низкая CSS-переменные, одноразовые правки
CSS-модули ⭐⭐⭐ Высокая Высокая Основной способ
Styles API (classNames) ⭐⭐⭐⭐ Высокая Очень высокая Тонкая настройка внутренних элементов
Styles API (глобально) ⭐⭐⭐⭐ Высокая Очень высокая Единый стиль для всех компонентов типа

Итоги

Сегодня вы узнали о шести способах стилизации в Mantine:

  1. Компонентные пропсы — для базовой стилизации
  2. Стилевые пропсы (c, p, m, bg) — для быстрых правок
  3. Проп style — для CSS-переменных
  4. CSS-модули — основной, наиболее производительный способ
  5. Styles API — для доступа к внутренним элементам компонентов
  6. Кастомные варианты — для расширения variant и size в V9

Что должно быть в вашем проекте после этого урока:

  1. Вы понимаете разницу между компонентными пропсами и стилевыми пропсами
  2. Вы создали хотя бы один CSS-модуль для стилизации компонента
  3. Вы использовали classNames или styles для настройки внутренних элементов
  4. Вы знаете, как добавить кастомный вариант через data-variant

В следующем уроке мы перейдем к практике — создадим полноценную форму с валидацией с использованием @mantine/form. Это один из самых мощных инструментов библиотеки!

Теги: