Дизайн-система
Почему большие проекты без неё разваливаются, как построить свою, и почему AI-инженер должен знать это лучше дизайнера.
📑 Содержание
Что такое дизайн-система и зачем она нужна
Дизайн-система — это единый язык, на котором говорят дизайнеры, разработчики и AI-агенты. Это не просто UI Kit. Это набор правил, компонентов, токенов и документации, который позволяет создавать интерфейсы быстро, согласованно и без хаоса.
Проблема без дизайн-системы
Представьте: в проекте 50 страниц, 3 разработчика и AI-агент. Дизайнер нарисовал кнопку с `border-radius: 8px`. Разработчик 1 сделал `border-radius: 6px`. Разработчик 2 — `10px`. AI-агент сгенерировал `12px`. Через месяц у вас 5 разных кнопок, 3 оттенка акцентного цвета и ад в CSS. Это реальная проблема большинства проектов.
- Каждый разработчик изобретает свои отступы и цвета
- AI генерирует несогласованные компоненты
- Дизайнер не может проверить реализацию
- Любое изменение дизайна = переписывание всего CSS
- Единый источник правды — токены в коде
- AI получает контекст: «используй радиус M, цвет accent»
- Изменение одного токена меняет весь интерфейс
- Дизайнер и разработчик говорят на одном языке
Из чего состоит: 5 слоёв
Дизайн-система — это не просто «набор компонентов». Это пирамида из 5 слоёв. Каждый слой зависит от предыдущего.
Atomic Design — методология
Эту модель придумал Брэд Фрост в 2013 году. Она называется Atomic Design. Идея проста: интерфейс строится из атомов (кнопки, поля), которые собираются в молекулы (форма поиска), те — в организмы (хедер сайта), а из организмов — страницы.
Для AI-инженера это критически важно: когда вы даёте промпт AI-агенту, вы можете сказать «собери страницу из компонентов Button, Input и Card», и агент поймёт что делать. Без системы — агент сгенерирует хаос.
Дизайн-токены — фундамент всего
Токены — это переменные. Вместо того чтобы писать color: #0fb880 в 50 местах, вы пишете color: var(--color-accent). Когда дизайнер решит сменить акцентный цвет, вы меняете ОДНУ переменную.
Категории токенов
/* ═══════════════════════════
Design Tokens — пример
═══════════════════════════ */
:root {
/* 🎨 Цвета */
--color-accent: #0fb880;
--color-accent-hover: #0ca36e;
--color-bg-primary: #ffffff;
--color-bg-secondary: #f5f5f3;
--color-text-primary: #1a1a1a;
--color-text-secondary: #5c5c50;
--color-border: #d4d4cc;
/* 📏 Отступы */
--space-xs: 4px;
--space-s: 8px;
--space-m: 16px;
--space-l: 24px;
--space-xl: 40px;
/* 🔤 Типографика */
--font-heading: "Onest", sans-serif;
--font-body: "Inter", sans-serif;
--text-xs: 12px;
--text-s: 14px;
--text-m: 16px;
--text-l: 20px;
--text-xl: 28px;
/* ⭕ Радиусы */
--radius-s: 4px;
--radius-m: 8px;
--radius-l: 12px;
--radius-full: 9999px;
/* 🌑 Тени */
--shadow-s: 0 1px 2px rgba(0,0,0,0.04);
--shadow-m: 0 2px 8px rgba(0,0,0,0.08);
--shadow-l: 0 4px 16px rgba(0,0,0,0.12);
}
/* 🌙 Тёмная тема — просто переопределяем токены */
[data-theme="dark"] {
--color-bg-primary: #1a1a1a;
--color-bg-secondary: #242424;
--color-text-primary: #f5f5f3;
--color-text-secondary: #b0b0a4;
--color-border: #3e3e38;
}Токены в Tailwind CSS 4
В Tailwind 4 можно связать CSS-переменные с утилитарными классами через @theme:
/* tailwind.css */
@import "tailwindcss";
@theme {
--color-accent: var(--color-accent);
--spacing-s: var(--space-s);
--spacing-m: var(--space-m);
--text-xs: var(--text-xs);
--radius-m: var(--radius-m);
}
/* Теперь можно писать: */
/* <button className="bg-accent text-white px-m py-s rounded-m"> */Компоненты: от кнопки до страницы
Компонент — это переиспользуемый блок интерфейса. Хороший компонент: изолирован, настраивается через props, задокументирован.
Пример: компонент Button
// Button.tsx — атом дизайн-системы
import { forwardRef } from "react";
interface ButtonProps {
variant?: "primary" | "secondary" | "ghost";
size?: "sm" | "md" | "lg";
children: React.ReactNode;
}
const variantStyles = {
primary: { background: "var(--color-accent)", color: "white" },
secondary: { background: "var(--color-bg-tertiary)", color: "var(--color-text-primary)" },
ghost: { background: "transparent", color: "var(--color-text-secondary)", border: "1px solid var(--color-border)" },
};
const sizeStyles = {
sm: { padding: "4px 10px", fontSize: "var(--text-xs)" },
md: { padding: "8px 16px", fontSize: "var(--text-s)" },
lg: { padding: "12px 24px", fontSize: "var(--text-m)" },
};
export const Button = forwardRef<HTMLButtonElement, ButtonProps>(
({ variant = "primary", size = "md", children }, ref) => (
<button ref={ref} style={{
display: "inline-flex", alignItems: "center", gap: "var(--space-xs)",
border: "none", borderRadius: "var(--radius-m)",
fontWeight: 600, cursor: "pointer",
transition: "opacity 0.15s",
...variantStyles[variant],
...sizeStyles[size],
}}>
{children}
</button>
)
);
// Использование:
<Button variant="primary" size="lg">Купить</Button>
<Button variant="ghost" size="sm">Отмена</Button>Компонент Card с вариантами
// Card.tsx — молекула дизайн-системы
interface CardProps {
padding?: "s" | "m" | "l";
elevated?: boolean;
accent?: boolean;
children: React.ReactNode;
}
export function Card({ padding = "m", elevated, accent, children }: CardProps) {
const pads = { s: "var(--space-s)", m: "var(--space-m)", l: "var(--space-l)" };
return (
<div style={{
padding: pads[padding],
background: "var(--color-surface)",
border: accent ? "1px solid var(--color-accent)" : "1px solid var(--color-border-light)",
borderRadius: "var(--radius-l)",
boxShadow: elevated ? "var(--shadow-m)" : "none",
...(accent && { borderTop: "3px solid var(--color-accent)" }),
}}>
{children}
</div>
);
}Паттерны и правила использования
Компонентов мало. Нужны правила: когда какой компонент использовать, как их комбинировать, чего избегать.
Паттерн: Форма с валидацией
- Поля сгруппированы логически
- Лейблы над полями
- Ошибка под проблемным полем
- Кнопка primary + кнопка ghost для отмены
- Все поля в один столбец без группировки
- Лейблы как placeholder (исчезают)
- Ошибка alert'ом вверху страницы
- Две primary кнопки рядом
Чек-лист качества компонента
Документация: Storybook, Zeroheight
Дизайн-система без документации — как карта без легенды. Инструменты:
Storybook
Стандарт индустрии для изолированной разработки компонентов. Каждый компонент имеет свою «историю» (story) — пример использования с разными props. Позволяет тестировать компоненты визуально, проверять accessibility, делать скриншот-тесты.
// Button.stories.tsx
import type { Meta, StoryObj } from "@storybook/react";
import { Button } from "./Button";
const meta: Meta<typeof Button> = {
title: "Atoms/Button",
component: Button,
argTypes: {
variant: { control: "select", options: ["primary", "secondary", "ghost"] },
size: { control: "select", options: ["sm", "md", "lg"] },
},
};
export default meta;
export const Primary: StoryObj<typeof Button> = {
args: { variant: "primary", children: "Кнопка" },
};
export const AllVariants = {
render: () => (
<div style={{ display: "flex", gap: 12 }}>
<Button variant="primary">Primary</Button>
<Button variant="secondary">Secondary</Button>
<Button variant="ghost">Ghost</Button>
</div>
),
};Другие инструменты документации
Инструменты: Figma, Token Studio, Style Dictionary
Figma
Основной инструмент дизайнеров. Но AI-инженеру тоже полезно знать:
- Dev Mode — показывает CSS-код, отступы, токены прямо из макета
- Variables — аналог CSS-переменных в Figma (цвета, числа, строки)
- Components + Variants — компоненты с вариантами (как props в React)
- Auto Layout — аналог Flexbox в Figma
- Plugins: Tokens Studio, Figma to Code, Design Lint
Tokens Studio (Figma Plugin)
Самый важный плагин для синхронизации токенов между Figma и кодом. Позволяет экспортировать токены в JSON, который можно преобразовать в CSS-переменные через Style Dictionary.
// tokens.json — экспорт из Tokens Studio
{
"color": {
"accent": { "value": "#0fb880", "type": "color" },
"bg": {
"primary": { "value": "#ffffff", "type": "color" },
"secondary": { "value": "#f5f5f3", "type": "color" }
}
},
"spacing": {
"s": { "value": "8px", "type": "spacing" },
"m": { "value": "16px", "type": "spacing" }
}
}Style Dictionary
Инструмент от Amazon, который преобразует токены из одного формата в другой: JSON → CSS, SCSS, JavaScript, iOS, Android. Ключевое звено между дизайном и кодом.
// config.json — Style Dictionary
{
"source": ["tokens/**/*.json"],
"platforms": {
"css": {
"transformGroup": "css",
"buildPath": "src/styles/",
"files": [{ "destination": "tokens.css", "format": "css/variables" }]
},
"ts": {
"transformGroup": "js",
"buildPath": "src/lib/",
"files": [{ "destination": "tokens.ts", "format": "javascript/es6" }]
}
}
}
// Запуск: npx style-dictionary build
// На выходе:
// src/styles/tokens.css — CSS-переменные
// src/lib/tokens.ts — TypeScript-константыAI и дизайн-системы: как автоматизировать
Это главная причина, почему AI-инженеру нужна дизайн-система. AI-агенты (Cursor, Claude, Reasonix) генерируют код на основе промптов. Если у агента нет контекста о вашей дизайн-системе — он сгенерирует случайные стили.
Промпт для AI с дизайн-системой
Ты — frontend-разработчик. Твоя задача — создать страницу настроек
профиля. Используй дизайн-систему проекта:
ТОКЕНЫ (всегда используй эти переменные, не хардкодь цвета):
- Цвета: var(--color-accent), var(--color-bg-primary),
var(--color-text-secondary), var(--color-border)
- Отступы: var(--space-s), var(--space-m), var(--space-l)
- Радиусы: var(--radius-m), var(--radius-l)
- Текст: var(--text-xs), var(--text-s), var(--text-m)
КОМПОНЕНТЫ (используй готовые, не создавай новые):
- Button: <Button variant="primary|secondary|ghost" size="sm|md|lg">
- Card: <Card padding="m" elevated>...</Card>
- Input: <Input label="Название" error="Ошибка" />
ПРАВИЛА:
- Формы: группируй поля в Card, лейблы над полями
- Кнопки: одна primary (главное действие) + ghost (отмена)
- Не используй inline-стили без крайней необходимостиAI-агенты, которые работают с дизайн-системами
Пошаговый план внедрения
Как внедрить дизайн-систему в существующий или новый проект:
Уникальность: как не делать клонов
Главная проблема AI-разработки 2026: все проекты выглядят одинаково. Один и тот же Tailwind, один и тот же shadcn/ui, одни и те же синие кнопки и белые карточки. Пользователь заходит на сайт и думает: «Я это уже видел». Это убивает доверие и конверсию.
Почему AI генерирует одинаковый дизайн
Решение: слой уникальности над дизайн-системой
Дизайн-система даёт фундамент. Но поверх неё нужен слой бренда — то, что делает проект узнаваемым. Это не противоречит системе — это её расширение.
6 приёмов для уникальности
Промпт для AI: «Сделай уникально»
Дайте AI-агенту контекст бренда. Не просто «создай компонент», а «создай компонент в стиле бренда X»:
Ты — frontend-разработчик. Создай карточку товара.
ДИЗАЙН-СИСТЕМА ПРОЕКТА (обязательно используй):
- Цвета: var(--brand-primary), var(--brand-accent)
- Радиусы: var(--radius-card) = 16px (мягкие)
- Шрифты: var(--font-body) = "Onest"
- Кнопки: variant="brand" (не primary/secondary из дефолта)
УНИКАЛЬНОСТЬ БРЕНДА:
- Мы — эко-маркетплейс. Никакого синего (#3b82f6).
- Акцент — золотой на тёмно-зелёном.
- Все карточки с мягкими углами (16px) и тёплыми тенями.
- Между карточками — 20px (не стандартные 16).
- Hover: карточка приподнимается на 4px с золотой тенью.
НЕ ИСПОЛЬЗУЙ:
- Дефолтные цвета Tailwind (blue-500, gray-100)
- Стандартные радиусы (8px, 12px — у нас 16px)
- Inter (у нас Onest)
- Стандартные серые тени (у нас тёплые)Чек-лист: твой проект уникален?
Примеры: Material, Ant, shadcn/ui
Готовые дизайн-системы, которые стоит изучить
Готов построить свою дизайн-систему?
Пройди Blueprint «Корпоративный сайт» — там есть этап «Дизайн-система и токены» с AI-промптами и примерами.