Компоненты
Компоненты дизайн-системы — единый слой UI, через который приложение получает базовые паттерны: кнопки, поля ввода, модальные окна, таблицы, уведомления.
Цель: одинаковое поведение, внешний вид и доступность во всех продуктах.
MUST
-
Использовать компоненты дизайн-системы для базовых UI-паттернов:
- Кнопки, поля ввода, чекбоксы, модальные окна, таблицы
-
Визуальные параметры компонентов управляются токенами:
- Цвета, отступы, размеры берутся из дизайн-токенов
-
Компоненты не содержат бизнес-логики:
- Бизнес-логика остаётся в бизнес-ко де
SHOULD
-
Расширять поведение через публичные props или slots:
- Не делать форки компонентов
-
Иметь документированные варианты:
- Size:
small,medium,large - Intent:
primary,danger,ghost - State:
default,hover,disabled,loading
- Size:
FORBIDDEN
- Копировать код компонентов в бизнес:
/* ❌ Неправильно — локальная копия */
// components/MyButton.tsx
export const MyButton = ({ children }) => (
<button className="primary">{children}</button>
);
- Делать локальные "версии" без причины:
/* ❌ Неправильно — дубликат Button из дизайн-системы */
<CustomButton />
Границы ответственности
Дизайн-система отвечает за
- Визуальный стиль (цвета, типографика, spacing)
- Доступность и клавиатурную навигацию
- Базовые состояния:
default,hover,disabled,loading
Бизнес отвечает за
- Бизнес-логику и д анные
- Композицию компонентов для конкретных сценариев
- Интеграцию с API и стейт-менеджментом
Примеры использования
✅ Правильно
import { Button, TextInput } from '@design-system/components';
<Button variant="primary" size="medium">
Отправить
</Button>
<TextInput
label="Email"
placeholder="[email protected]"
error={errors.email}
/>
❌ Неправильно
/* ❌ Использование нативных элементов вместо компонентов */
<button className="primary">Отправить</button>
<input
className="input"
placeholder="Email"
/>
Расширение и вариативность
MUST
- Новые варианты оформляются через токены и публичные props:
// ✅ Правильно — через props
<Button variant="danger" size="small" />
// ❌ Неправильно — через стили
<Button className="custom-danger-button" />
- Нейминг вариантов следует смыслу, а не контексту:
- ✅ Правильно:
primary,danger,ghost,success - ❌ Неправильно:
promo,landing,checkout-v2
- ✅ Правильно:
FORBIDDEN
Добавлять варианты с привязкой к конкретному экрану:
/* ❌ Неправильно — привязка к конкретному экрану */
<Button variant="landing-hero" />
<Button variant="checkout-v2" />
/* ✅ Правильно — универсальные варианты */
<Button variant="primary" size="large" />
<Button variant="secondary" />
Паттерны расширения
MAY
Создание wrapper-компонента в бизнес-коде:
// ✅ Допустимо — обёртка с бизнес-логикой
import { Button } from '@design-system/components';
export const SubmitButton = ({ formId, ...props }) => {
const { isSubmitting } = useFormContext(formId);
return <Button {...props} disabled={isSubmitting} loading={isSubmitting} />;
};