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

SvelteKit предлагает интеграцию с различными UI-библиотеками, среди которых популярны реализации Material Design, такие как Svelte Material UI (SMUI). Основной задачей при работе с Material компонентами является их кастомизация — настройка внешнего вида и поведения под требования конкретного проекта.


Подключение и базовая структура компонентов

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

npm install --save-dev @smui/button @smui/textfield @smui/card

Каждый компонент импортируется отдельно:

<script>
  import Button from '@smui/button';
  import TextField from '@smui/textfield';
</script>

<Button variant="raised">Отправить</Button>
<TextField label="Имя пользователя" />

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


Стилизация через CSS-переменные

SMUI построен на Material Web Components и использует CSS Custom Properties для настройки цветов, размеров и отступов. Пример переопределения базовых переменных:

:global(:root) {
  --mdc-theme-primary: #1e88e5;
  --mdc-theme-secondary: #ff4081;
  --mdc-theme-background: #f5f5f5;
  --mdc-theme-surface: #ffffff;
}

Эти переменные автоматически применяются ко всем компонентам SMUI, которые используют Material Theme. Для локальной кастомизации отдельного компонента можно использовать class и style:

<Button class="custom-btn">Сохранить</Button>

<style>
  .custom-btn {
    background-color: var(--mdc-theme-secondary);
    color: white;
    border-radius: 12px;
  }
</style>

Кастомизация шрифтов и типографики

Material Design имеет собственную систему типографики. В SMUI можно переопределять шрифты через CSS-переменные:

:global(:root) {
  --mdc-typography-font-family: 'Roboto', sans-serif;
  --mdc-typography-button-font-size: 1.1rem;
  --mdc-typography-body1-font-size: 1rem;
}

Для отдельных компонентов можно подключать локальные стили:

<TextField class="custom-textfield" label="Email" />

<style>
  .custom-textfield {
    font-family: 'Montserrat', sans-serif;
    font-size: 1.2rem;
  }
</style>

Использование темизации

SMUI поддерживает тёмную и светлую темы, которые удобно менять динамически. Создаётся объект темы и передаётся через контекст:

import { setContext } from 'svelte';
import { createTheme } from '@smui/theme';

const darkTheme = createTheme({
  primary: '#bb86fc',
  secondary: '#03dac6',
  background: '#121212',
  surface: '#1f1f1f',
});

setContext('smui-theme', darkTheme);

Компоненты автоматически подхватывают значения из текущей темы. Для динамического переключения можно использовать сторы Svelte:

import { writable } from 'svelte/store';

export const darkMode = writable(false);

И менять контекст при изменении состояния:

<script>
  import { darkMode } from './stores.js';
  import { setContext } from 'svelte';
  import { createTheme } from '@smui/theme';

  $: setContext('smui-theme', $darkMode 
    ? createTheme({ primary: '#bb86fc', background: '#121212' }) 
    : createTheme({ primary: '#1e88e5', background: '#ffffff' }));
</script>

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

Помимо визуальных настроек, Material компоненты допускают тонкую настройку поведения через пропсы и события:

  • Button: disabled, ripple, type, обработка on:click.
  • TextField: outlined, filled, value, on:input.
  • Dialog: open, on:close, кастомные кнопки управления.

Пример кастомного TextField с валидацией:

<script>
  let email = '';
  let valid = true;

  function validate() {
    valid = /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email);
  }
</script>

<TextField
  bind:value={email}
  label="Email"
  outlined
  on:input={validate}
  class:invalid={!valid}
/>

<style>
  .invalid {
    --mdc-theme-primary: #d32f2f;
  }
</style>

Создание собственных обёрток для компонентов

Для стандартизации дизайна и сокращения повторяющегося кода удобно создавать обёртки над SMUI компонентами. Например, кнопка проекта с фирменными цветами и стилем:

<!-- components/BrandButton.svelte -->
<script>
  import Button from '@smui/button';
  export let text = '';
  export let onClick;
</script>

<Button class="brand-btn" on:click={onClick}>{text}</Button>

<style>
  .brand-btn {
    background-color: var(--mdc-theme-primary);
    color: white;
    border-radius: 8px;
    padding: 0.6rem 1.2rem;
  }
  .brand-btn:hover {
    background-color: darken(var(--mdc-theme-primary), 10%);
  }
</style>

Использование обёртки:

<BrandButton text="Сохранить" onCl ick={handleSave} />

Такой подход упрощает поддержку и масштабирование интерфейса.


Интеграция с CSS-фреймворками и Tailwind

SMUI совместим с Tailwind CSS, что позволяет комбинировать Material стили и утилитарные классы:

<Button class="bg-blue-600 text-white px-6 py-2 rounded-lg hover:bg-blue-700">
  Отправить
</Button>

При этом можно сохранить тему Material для ripple-эффекта и анимаций.


Кастомизация анимаций и ripple-эффектов

Ripple-эффект управляется через CSS-переменные и проп ripple:

<Button ripple={{ color: '#ff4081', unbounded: true }}>Кликни меня</Button>

Для глобальной настройки:

:global(.mdc-button__ripple) {
  --mdc-ripple-fg-size: 150%;
  --mdc-ripple-fg-opacity: 0.3;
}

Это позволяет добиться уникального визуального отклика, соответствующего фирменному стилю.


Итоговые рекомендации по кастомизации

  • Использовать CSS-переменные для глобальных цветов и типографики.
  • Создавать обёртки компонентов для единообразного стиля.
  • Использовать пропсы и события для изменения поведения.
  • Динамически менять темы через контекст и сторы Svelte.
  • Комбинировать SMUI с Tailwind для гибкой стилизации.
  • Настраивать ripple и анимации через локальные и глобальные CSS-переменные.

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