Перейти к основному содержимому

SVG

SVG pipeline обеспечивает централизованное управление иконками: оптимизацию, генерацию React-компонентов, типизацию и единый интерфейс использования через компонент Icon.

Когда нужен SVG pipeline

MUST

Build pipeline необходим, если хотя бы одно условие верно:

  1. Дизайн предоставляет кастомные SVG
  2. Планируется ребрендинг или темизация
  3. Иконки используются в нескольких подпроектах

Pipeline: что должно получиться

Требования к исходникам

MUST

  1. Все SVG лежат в одной директории:
   icons/
arrow-left.svg
check.svg
warning.svg
  1. Имена файлов в kebab-case и совпадают с дизайном:

    • arrow-left.svg, user-profile.svg
    • ArrowLeft.svg, arrow_left.svg
  2. Обязательно присутствует viewBox:

   <!-- ✅ Правильно -->
<svg viewBox="0 0 24 24">

<!-- ❌ Неправильно -->
<svg width="24" height="24">
  1. Монохромные иконки используют currentColor:
   <svg viewBox="0 0 24 24" fill="none" stroke="currentColor">
<path d="..." />
</svg>

SHOULD

  1. Единый базовый размер (например, 24×24)
  2. Одинаковые правила для stroke/linecap/linejoin

FORBIDDEN

  1. Inline-стили внутри SVG:
   <!-- ❌ Неправильно -->
<path style="fill: red; stroke: blue;" d="..." />

<!-- ✅ Правильно -->
<path fill="currentColor" d="..." />
  1. Жёстко заданные width/height без viewBox:
   <!-- ❌ Неправильно -->
<svg width="24" height="24">

<!-- ✅ Правильно -->
<svg viewBox="0 0 24 24">
  1. Растровые вставки (<image> внутри SVG)

Цвет и стилизация

MUST

  1. Монохромные иконки наследуют цвет через currentColor:
   <svg viewBox="0 0 24 24" fill="none" stroke="currentColor">
<path d="..." />
</svg>
  1. Многоцветные иконки используют токены:
   <svg viewBox="0 0 24 24">
<path fill="var(--color-icon-accent)" d="..." />
<path fill="var(--color-icon-secondary)" d="..." />
</svg>

Примеры

/* ✅ Правильно — currentColor */
<Icon name="arrow-left" className="text-primary" />

/* ✅ Правильно — токен */
<Icon name="warning" style={{ color: 'var(--color-warning)' }} />

/* ❌ Неправильно — захардкоженный цвет в SVG */
<svg><path fill="#ff0000" /></svg>

Использование в коде

MUST

Всегда использовать компонент Icon из UI-kit:

import { Icon } from '@/shared/ui/Icon';

<Icon name="arrow-left" size="m" />
<Icon name="warning" aria-label="Предупреждение" />

FORBIDDEN

Прямой импорт SVG:

/* ❌ Неправильно */
import ArrowLeft from './icons/arrow-left.svg';

<ArrowLeft width={16} height={16} />;

Анимации и inline-SVG

SHOULD

Для анимаций использовать CSS:

<Icon name="spinner" className="animate-spin" />
.animate-spin {
animation: spin 1s linear infinite;
}

@keyframes spin {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}

MAY

Inline-SVG допускается для сложных анимаций:

  • Анимации по путям (path animations)
  • Морфинг форм
  • Сложные keyframes, которые нельзя реализовать через CSS
/* ✅ Допустимо для сложной анимации */
<svg viewBox="0 0 100 100">
<path d="...">
<animate attributeName="d" dur="1s" ... />
</path>
</svg>

Доступность

MUST

  1. Декоративные иконки скрыты от скринридеров:
<Icon name="chevron-right" aria-hidden />
  1. Информативные иконки имеют доступное имя:
   <Icon name="warning" aria-label="Предупреждение" />

<!-- или с визуальным текстом -->
<button>
<Icon name="save" aria-hidden />
<span>Сохранить</span>
</button>

Исключение: внешние библиотеки

Если дизайн-система полностью опирается на внешнюю библиотеку (Material Icons, Font Awesome), отдельный SVG pipeline может не требоваться.

MUST

Всё равно использовать единый компонент Icon как обёртку:

// ✅ Правильно — обёртка над Material Icons
import { Icon } from '@/shared/ui/Icon';

<Icon name="arrow-left" />;

// Внутри компонента Icon:
import { ArrowLeft } from '@mui/icons-material';

export const Icon = ({ name }) => {
const IconComponent = iconMap[name];
return <IconComponent />;
};

Добавление новой иконки