6.9 KiB
6.9 KiB
ADR-005: Design Tokens как единый источник стилей
Статус: принято Дата: 2026-05-10
Контекст
Проект VoIdea работает на нескольких платформах:
- Web (PWA)
- iOS (Swift/SwiftUI)
- Android (Kotlin)
Требуется унифицировать стили (цвета, шрифты, отступы) между всеми платформами.
Рассматривались:
- Ручное копирование — непоследовательно, сложно поддерживать
- Shared library — требует синхронизации
- Design Tokens (JSON) — единый источник, генераторы
Решение
Design Tokens в JSON + генераторы для каждой платформы
docs/design-system/tokens.json (источник истины)
│
├── generators/css_generator.py → app/design-tokens/css/theme.css
├── generators/swift_generator.py → app/design-tokens/swift/Colors.swift
└── generators/kotlin_generator.py → app/design-tokens/kotlin/colors.xml
Структура tokens.json
{
"version": "1.0.0",
"project": "VoIdea",
"themes": ["system", "dark", "light"],
"colors": {
"primary": {
"500": "#6366F1",
"600": "#4F46E5",
"default": "#6366F1",
"hover": "#4F46E5"
},
"background": {
"system": "auto",
"dark": "#0F172A",
"light": "#FFFFFF"
},
"semantic": {
"error": "#EF4444",
"warning": "#F59E0B",
"success": "#22C55E",
"info": "#3B82F6"
}
},
"typography": {
"font_family": {
"primary": "Inter, system-ui, sans-serif"
},
"size": {
"xs": "0.75rem",
"sm": "0.875rem",
"base": "1rem"
}
},
"spacing": {
"xs": "0.25rem",
"sm": "0.5rem",
"md": "1rem",
"lg": "1.5rem"
},
"border_radius": {
"sm": "0.25rem",
"md": "0.5rem",
"lg": "0.75rem"
}
}
Генераторы
CSS Generator
# docs/design-system/generators/css_generator.py
def generate(tokens: dict) -> str:
css = ":root {\n"
for category, values in tokens.items():
if category == "colors":
for name, value in flatten(values):
css += f" --color-{name}: {value};\n"
elif category == "typography":
for name, value in flatten(values):
css += f" --font-{name}: {value};\n"
elif category == "spacing":
for name, value in flatten(values):
css += f" --spacing-{name}: {value};\n"
css += "}\n"
return css
Выход: app/design-tokens/css/theme.css
:root {
--color-primary: #6366F1;
--color-background-dark: #0F172A;
--font-family-primary: Inter, system-ui, sans-serif;
--spacing-md: 1rem;
}
Swift Generator
# docs/design-system/generators/swift_generator.py
def generate(tokens: dict) -> str:
swift = "import SwiftUI\n\n"
swift += "enum Colors {\n"
for name, value in flatten(tokens["colors"]):
snake_to_camel = to_camel_case(name)
swift += f' static let {snake_to_camel} = Color(hex: "{value}")\n'
swift += "}\n"
swift += "enum Typography {\n"
# ... font generation
return swift
Выход: app/design-tokens/swift/Colors.swift
import SwiftUI
enum Colors {
static let primary = Color(hex: "#6366F1")
static let backgroundDark = Color(hex: "#0F172A")
}
enum Typography {
static let fontFamilyPrimary = "Inter"
static let fontSizeBase: CGFloat = 16
}
Kotlin Generator
# docs/design-system/generators/kotlin_generator.py
def generate(tokens: dict) -> str:
xml = '<?xml version="1.0" encoding="utf-8"?>\n'
xml += '<resources>\n'
for name, value in flatten(tokens["colors"]):
safe_name = name.replace("_", "_")
xml += f' <color name="{safe_name}">{value}</color>\n'
xml += '</resources>\n'
return xml
Выход: app/design-tokens/kotlin/colors.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="primary">#6366F1</color>
<color name="background_dark">#0F172A</color>
</resources>
Темы
System (Auto)
@media (prefers-color-scheme: dark) {
:root[data-theme="system"] {
--color-background: #0F172A;
--color-text: #F8FAFC;
}
}
@media (prefers-color-scheme: light) {
:root[data-theme="system"] {
--color-background: #FFFFFF;
--color-text: #0F172A;
}
}
Dark / Light
[data-theme="dark"] {
--color-background: #0F172A;
--color-text: #F8FAFC;
}
[data-theme="light"] {
--color-background: #FFFFFF;
--color-text: #0F172A;
}
CI/CD Integration
# .github/workflows/design-system.yml
on:
push:
paths:
- 'docs/design-system/tokens.json'
jobs:
generate:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Generate CSS
run: python -m generators css
- name: Generate Swift
run: python -m generators swift
- name: Generate Kotlin
run: python -m generators kotlin
- name: Commit
run: |
git add app/design-tokens/
git commit -m "style: regenerate design tokens"
git push
Правила использования
- Никогда не редактировать сгенерированные файлы вручную
- Все изменения только в tokens.json
- После изменения tokens.json → запустить генераторы
- DocAgent обновляет документацию
Maintenance
Обновление tokens.json
- Открыть
docs/design-system/tokens.json - Внести изменения
- Запустить
python -m generators all - Проверить сгенерированные файлы
- Зафиксировать в git
Добавление новых token
{
"new_token": {
"system": "auto",
"dark": "#value",
"light": "#value"
}
}
Последствия
Положительные
- Единый источник истины
- Согласованность между платформами
- Легко добавлять темы
- Автоматическая генерация
Отрицательные
- Дополнительный слой абстракции
- Требует генерацию при изменениях
- Разные форматы вывода
Ответственный
Decision maker: Frontend team Review date: При добавлении новой платформы
Создано: 2026-05-10 Обновляется DocAgent при изменениях