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

Компоненты

Компоненты дизайн-системы — единый слой UI, через который приложение получает базовые паттерны: кнопки, поля ввода, модальные окна, таблицы, уведомления.

Цель: одинаковое поведение, внешний вид и доступность во всех продуктах.

MUST

  1. Использовать компоненты дизайн-системы для базовых UI-паттернов:

    • Кнопки, поля ввода, чекбоксы, модальные окна, таблицы
  2. Визуальные параметры компонентов управляются токенами:

    • Цвета, отступы, размеры берутся из дизайн-токенов
  3. Компоненты не содержат бизнес-логики:

    • Бизнес-логика остаётся в бизнес-коде

SHOULD

  1. Расширять поведение через публичные props или slots:

    • Не делать форки компонентов
  2. Иметь документированные варианты:

    • Size: small, medium, large
    • Intent: primary, danger, ghost
    • State: default, hover, disabled, loading

FORBIDDEN

  1. Копировать код компонентов в бизнес:
/* ❌ Неправильно — локальная копия */
// components/MyButton.tsx
export const MyButton = ({ children }) => (
<button className="primary">{children}</button>
);
  1. Делать локальные "версии" без причины:
/* ❌ Неправильно — дубликат 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

  1. Новые варианты оформляются через токены и публичные props:
   // ✅ Правильно — через props
<Button variant="danger" size="small" />

// ❌ Неправильно — через стили
<Button className="custom-danger-button" />
  1. Нейминг вариантов следует смыслу, а не контексту:
    • ✅ Правильно: 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} />;
};