Skip to content
PПромтбук
RUEN
02Дизайн-системы

Построение цветовой системы

От raw-палитры к семантическим токенам, темам и контрасту — с проверкой на edge-кейсах.

Построй цветовую систему для: {{brand}}. Опорный акцент: {{accent}}.

Тезис: цвет — это трёхслойная система. Сырая палитра → семантические токены → компонентные роли. Никогда не пиши hex в компоненте.

Слой 1. Raw-палитра

Для каждого цветового канала — шкала из 11 ступеней: 50, 100, 200, …, 900, 950.

  • Neutrals — обязательно, обычно cool/warm grey с лёгким тёплым или холодным наклоном (не чистый #888)
  • Accent (brand) — один основной, шкала 50→950
  • Семантические — success, warning, danger, info (каждый своей шкалой)
  • Опционально: secondary accent (только если он реально нужен — фичи, иллюстрации)

Правила построения шкалы:

  • 50 — близко к фону (для tints), 900-950 — близко к тексту
  • Между ступенями — равномерный шаг по воспринимаемой яркости (OKLCH или HSL.L), не по hex
  • На каждой ступени контраст к 50 и к 950 предсказуем
  • Используй OKLCH для генерации, не HSL — у HSL зелёный и жёлтый "тяжелее" остальных
:root {
  --neutral-50:  oklch(0.98 0.005 250);
  --neutral-100: oklch(0.96 0.005 250);
  /* … */
  --neutral-950: oklch(0.15 0.01 250);

  --accent-500: oklch(0.62 0.18 250);
  /* … */
}

Слой 2. Семантические токены

Никогда не используй raw в компонентах. Используй роль.

:root {
  /* Поверхности */
  --bg: var(--neutral-50);
  --bg-subtle: var(--neutral-100);
  --bg-elevated: #fff;
  --bg-inverse: var(--neutral-950);

  /* Текст */
  --fg: var(--neutral-900);
  --fg-muted: var(--neutral-600);
  --fg-subtle: var(--neutral-500);
  --fg-on-accent: #fff;
  --fg-inverse: var(--neutral-50);

  /* Границы */
  --border: var(--neutral-200);
  --border-strong: var(--neutral-300);

  /* Интерактив */
  --accent: var(--accent-500);
  --accent-hover: var(--accent-600);
  --accent-active: var(--accent-700);
  --accent-fg: #fff;

  /* Состояния */
  --success: var(--green-500);
  --success-bg: var(--green-50);
  --danger: var(--red-500);
  --danger-bg: var(--red-50);
}

Слой 3. Темы

Тёмная тема — другие назначения тех же ролей, не новая палитра:

[data-theme="dark"] {
  --bg: var(--neutral-950);
  --bg-subtle: var(--neutral-900);
  --bg-elevated: var(--neutral-800);
  --fg: var(--neutral-50);
  --fg-muted: var(--neutral-400);
  --border: var(--neutral-800);
  --border-strong: var(--neutral-700);

  /* Акцент в тёмной обычно ступенью светлее */
  --accent: var(--accent-400);
  --accent-hover: var(--accent-300);
}

Правила:

  • Не используй #000 для фона (используй 950)
  • Не используй #fff для текста (используй 50)
  • Цветные акценты в тёмной — на 1-2 ступени светлее (восприятие)
  • Тени почти не работают — используй яркую границу или внутренний highlight

Контраст

КонтекстWCAGМинимум
Body textAA4.5:1
Large text (≥ 18px / 14px bold)AA3:1
UI components (border, иконки)AA3:1
Любой текстAAA7:1

Каждую пару fg / bg и accent-fg / accent проверь до того, как ушло в код.

Edge-кейсы (обязательная проверка)

Прогон по списку — каждый кейс должен жить:

  1. Текст на акценте--fg-on-accent контрастен --accent в обоих темах
  2. Disabled — есть отдельный токен, не просто opacity: 0.5 (контраст портится)
  3. Placeholder — ≥ 3:1 к фону инпута (часто проваливается)
  4. Focus ring на акцентной кнопке — виден на самом акценте
  5. Selected row / hover row — отличимы друг от друга и от default
  6. Toast/badge на цветном фоне — успех на danger не сливается
  7. Графики — палитра серии (≥ 6 цветов) отличима у дальтоников (deuteranopia/protanopia)
  8. Принт — токены деградируют в greyscale без потери иерархии
  9. Высокая контрастность ОС (forced-colors: active) — компоненты не разваливаются
  10. Изображения и логотип — версия для тёмной готова

Проверка на компонентах

Не прими систему пока не прогнал по этим экранам в обеих темах:

  • Кнопки: primary, secondary, ghost, destructive, disabled
  • Инпут: default, focus, error, disabled, with-icon
  • Стол: header, row, hover, selected, footer
  • Тост: success, warning, danger, info
  • Карточка на цветном фоне (success-bg)
  • Модалка с overlay
  • Code-блок (если есть)
  • Пустое состояние

Формат вывода

  1. Токены в OKLCH (raw + semantic) — готовый CSS
  2. Tailwind config маппинг (если используется)
  3. Таблица контраста — все важные пары fg/bg, обе темы
  4. Edge-case чек-лист — отмечено, что прошло
  5. Скриншоты компонентов в обеих темах (или JSX-превью, который можно скопировать)

Анти-паттерны

  • Hex в компоненте (bg-[#3b82f6])
  • Палитра в HSL без проверки воспринимаемой яркости — зелёный/жёлтый выпадают
  • Тёмная как filter: invert(1)
  • "У нас десять акцентов" — система ломается; держи один, максимум два
  • Семантика повторяет имя цвета (--blue вместо --accent) — нельзя ребрендить
  • Контраст проверяется "на глаз" вместо чисел
К подразделу «Дизайн-системы»
Похожие промты