docs: add design system authoring guide (#961)

* fix(i18n): add loom and trading-terminal to FR/RU summaries only

* docs: add design system authoring guide

* fix: remove loom/trading-terminal from locale (missing dirs), fix docs contradictions
This commit is contained in:
NotLeaped84 2026-05-09 13:04:11 +05:30 committed by GitHub
parent 1bf7836471
commit 4c15ea45fa
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

328
docs/design-systems.md Normal file
View file

@ -0,0 +1,328 @@
# Design System Authoring Guide
**Parent:** [`spec.md`](spec.md) · **Siblings:** [`architecture.md`](architecture.md) · [`skills-protocol.md`](skills-protocol.md) · [`agent-adapters.md`](agent-adapters.md)
This guide covers everything a contributor needs to submit a design system that passes review the first time. If you are adding a design system to `design-systems/<slug>/DESIGN.md`, read this document before opening a PR.
---
## 1. The 9-Section Schema
Every `DESIGN.md` must have these nine section headings:
```
## 1. Visual Theme & Atmosphere
## 2. Color
## 3. Typography
## 4. Spacing
## 5. Layout & Composition
## 6. Components
## 7. Motion & Interaction
## 8. Voice & Brand
## 9. Anti-patterns
```
The schema parser extracts headings with `## [0-9].*` — it matches the section number prefix, not the full text. You can add context after the number (e.g., `## 4. Spacing & Grid` or `## 4. Spacing and layout`). Only the `## [digit].` prefix is required. Empty section bodies are acceptable (for rarely-used tokens like motion), but the nine numbered headings must be present.
### Header format
The first H1 becomes the label shown in the design-system picker dropdown. The `> Category:` line immediately after the H1 determines grouping:
```markdown
# Design System Inspired by YourBrand
> Category: Developer Tools
> One-line summary for the picker preview.
```
Available categories: AI & LLM, Developer Tools, Productivity & SaaS, Backend & Data, Design & Creative, Fintech & Crypto, E-Commerce & Retail, Media & Consumer, Automotive, Editorial & Print, Retro & Nostalgic, Bold & Expressive, Modern & Minimal, Professional & Corporate. If none fit, introduce a new one with a PR comment explaining why.
---
## 2. The Review Framework: Lens A and Lens B
All design system PRs are reviewed against two lenses. Understanding these before you submit eliminates most round-trips.
### Lens A — Code Correctness (P1/P2)
Is the file structurally valid and machine-processable? Failing Lens A is blocking.
**Checks:**
- All 9 section headings present and in order
- Color tokens are real hex codes (`#RRGGBB` or `#RGB`), not `#REPLACE_ME`, `currentColor`, or CSS variable names
- No duplicate folder names in `design-systems/`
- CSS variables wrapped in `:root {}` blocks (not bare in the document)
- Font labels for catalog extraction present (see Section 3 below)
- `prefers-reduced-motion` targets specific elements, not a global `*` selector
- Dark mode tokens use `[data-theme="dark"]` override pattern, not duplicate token blocks
### Lens B — Reasoning Completeness (P3)
Is the content substantive and useful, not just syntactically valid? Failing Lens B generates a P3 comment, not a hard block.
**Checks:**
- Color palette lists all roles used in the design system, not just primary/secondary
- Type scale includes Display, H1, Body, Caption (minimum 4 tiers)
- Components section has real CSS, not Lorem Ipsum or placeholder `/* TODO */` blocks
- Anti-patterns are specific (e.g., "Do not use rounded corners > 4px" rather than "Avoid bad design")
- Dark mode is a genuine override with different token values, not a copy of the light block
- Prior art section names real, specific products or design systems (not "inspired by good design")
---
## 3. CSS Variable Structure
### `:root` block (required)
All CSS variables must be inside a `:root {}` block. Bare CSS variable declarations at the top level of a section are invalid.
```css
/* Correct */
:root {
--color-primary: #625DF5;
--color-bg: #FFFFFF;
--font-sans: "Inter", -apple-system, BlinkMacSystemFont, sans-serif;
}
/* Incorrect — not valid standalone CSS outside :root */
--color-primary: #625DF5;
```
Every color, spacing, typography, and shadow token belongs in `:root`. The exception is component-scoped overrides (e.g., `.card { --card-padding: 16px; }`) which belong under Components.
### Dark mode pattern
Use `[data-theme="dark"]` to override tokens for dark mode:
```css
:root {
--color-primary: #625DF5;
--color-bg: #FFFFFF;
}
[data-theme="dark"] {
--color-primary: #7B75FF;
--color-bg: #0D0D0D;
}
```
Do not create separate CSS blocks for light and dark without using the `[data-theme="dark"]` selector — it breaks the semantic token system.
### Font labels for catalog extraction
Include this block in the Typography section for the daemon's parser regexes:
```
Font labels for catalog extraction:
Display: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif
Body: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif
Mono: "JetBrains Mono", ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace
```
Labels must be `Display:`, `Body:`, `Mono:` with a colon, followed by the full font stack. The daemon reads these to populate the design-system catalog.
---
## 4. Accessibility Requirements
### WCAG AA contrast ratios
All text and data colors must pass **4.5:1 minimum** contrast ratio against their background (4.5:1 for normal text, 3:1 for large text at 18px+ or 14px+ bold).
**How to verify:**
- Use a contrast checker tool (e.g., WebAIM Contrast Checker, or `#B37A00` on `#FFFFFF`)
- Test each foreground token against its paired background token — not against white by default
**Common mistakes:**
- Claiming WCAG compliance without testing — the review will catch this
- Using a color that "looks fine" on white but fails on the actual dark surface
- Warning/caution colors like `#B37A00` (3.05:1 on white, 5.35:1 on `#FFF3CD`) — verify against the correct background context
**Tertiary text tokens** (timestamps, metadata, grid labels) on dark surfaces must still pass 4.5:1. Do not use `#4A6080` on `#0A0A0A` — that is 2.1:1. Use `#808086` on `#0A0A0A` instead (4.54:1).
### Focus states
Every interactive component (buttons, links, input fields, cards with click handlers) must have a `:focus-visible` style:
```css
.button-primary:focus-visible {
outline: 2px solid var(--color-primary);
outline-offset: 2px;
}
```
This is a Lens A accessibility requirement. Keyboard-only users get no visual feedback without it.
---
## 5. Component Section Best Practices
The Components section is the most commonly rejected part of a design system. Common failures:
**Do not use hardcoded colors in component CSS.** Every color must reference a semantic token:
```css
/* Correct */
.button-primary {
background: var(--color-primary);
color: var(--color-text);
}
/* Incorrect — hardcoded white breaks dark mode */
.button-primary {
background: var(--color-primary);
color: #ffffff;
}
```
**Use semantic names for states.** Prefer `--color-state-success` over `#00D26A` directly in component CSS.
**Example component structure:**
```css
/* Status Badge */
.badge {
font-size: 10px;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.05em;
padding: 2px 8px;
border-radius: 2px;
}
.badge-success {
background: rgba(38, 222, 129, 0.15);
color: var(--color-success);
border: 1px solid rgba(38, 222, 129, 0.3);
}
.badge-warning {
background: rgba(255, 159, 67, 0.15);
color: var(--color-warning);
border: 1px solid rgba(255, 159, 67, 0.3);
}
.badge-critical {
background: rgba(255, 71, 87, 0.15);
color: var(--color-critical);
border: 1px solid rgba(255, 71, 87, 0.3);
}
```
---
## 6. Motion & Interaction
### `prefers-reduced-motion`
Target specific properties, not all elements globally:
```css
/* Correct — targets only the elements that animate */
@keyframes pulse-glow {
0%, 100% { text-shadow: 0 0 8px currentColor; }
50% { text-shadow: 0 0 20px currentColor; }
}
@media (prefers-reduced-motion: reduce) {
.alert-banner { animation-duration: 0.01ms !important; }
.countdown { animation: none; }
}
/* Incorrect — global * selector disables transitions everywhere */
@media (prefers-reduced-motion: reduce) {
* { animation-duration: 0.01ms !important; }
}
```
### Timing conventions
```css
--transition-fast: 100ms ease-in;
--transition-base: 150ms ease-out;
--transition-slow: 300ms ease-out;
```
Match easing to purpose: `ease-in` for entering, `ease-out` for leaving, `linear` for continuous motion (scrolling, data updates).
---
## 7. Locale Coverage Requirements
When adding a new design system, you must also add its localized catalog entry. This is a **separate PR** (do not mix design system and i18n changes).
### Which locales need updating?
Use this decision tree to decide which array to add to:
**Does a localized summary already exist for this design system?**
- **Yes** → Add to `*_DESIGN_SYSTEM_SUMMARIES` only (FR + RU). **Never also add to the fallback array**`buildLocalizedContentIds()` concatenates both without deduplication, producing a duplicate that fails the test.
- **No** (no translation yet) → Add to `*_DESIGN_SYSTEM_IDS_WITH_EN_FALLBACK` only. This makes the system appear in the catalog with English fallbacks.
| Locale | File to update | Array |
|--------|---------------|-------|
| German | `apps/web/src/i18n/content.ts` | `DE_DESIGN_SYSTEM_IDS_WITH_EN_FALLBACK` |
| French | `apps/web/src/i18n/content.fr.ts` | `FR_DESIGN_SYSTEM_SUMMARIES` (if localized copy exists) or `FR_DESIGN_SYSTEM_IDS_WITH_EN_FALLBACK` (if not) |
| Russian | `apps/web/src/i18n/content.ru.ts` | `RU_DESIGN_SYSTEM_SUMMARIES` (if localized copy exists) or `RU_DESIGN_SYSTEM_IDS_WITH_EN_FALLBACK` (if not) |
> ⚠️ **The duplicate-ID trap:** `buildLocalizedContentIds()` concatenates summary keys and fallback IDs **without deduplication**. Adding to both arrays produces the same ID twice, and the e2e test's curated ID list rejects duplicates. This is exactly what caused the loom/trading-terminal #929 failure.
### Test behavior
The `e2e/tests/localized-content.test.ts` test verifies that every `design-systems/*/DESIGN.md` on disk has a corresponding catalog entry. If your design system directory does not exist in the locale PR's branch, do not add it to the DE fallback array — the test builds the expected ID list from the filesystem.
---
## 8. Anti-patterns Section
The anti-patterns section is where reviewers check if you understand what your design system is **not**. Good anti-patterns are specific and bounded:
```markdown
## 9. Anti-patterns
- Do not use decorative colors in data displays — every hue must convey operational meaning
- Do not use rounded corners greater than 4px — this aesthetic is functional, not friendly
- Do not use proportional fonts for telemetry values — monospace exclusively for data
- Do not animate non-alert elements — motion is reserved for signals that matter
- Do not use light mode — low-light environments are the only context
```
Bad anti-patterns are vague:
- ❌ "Avoid bad design"
- ❌ "Don't overcomplicate things"
- ❌ "Use good colors"
---
## 9. Pre-submission Checklist
Before opening a PR, verify:
- [ ] All 9 section headings present in order
- [ ] No `#REPLACE_ME` or placeholder hex codes
- [ ] All CSS variables wrapped in `:root {}`
- [ ] Font labels block present (Display / Body / Mono)
- [ ] `[data-theme="dark"]` block overrides light tokens, not copies them
- [ ] Interactive components have `:focus-visible` styles
- [ ] All color tokens verified at 4.5:1+ contrast against their paired background
- [ ] No hardcoded colors (like `#ffffff`) in component CSS — use semantic tokens
- [ ] `prefers-reduced-motion` targets specific elements, not `*`
- [ ] Anti-patterns are specific and bounded, not vague prose
- [ ] Dark mode section explicitly states the design intent if dark-only
- [ ] No duplicate CSS block definitions (check for `.panel` appearing twice)
- [ ] Category choice confirmed against existing category list
---
## 10. Design System Size Guide
A well-documented design system is typically 300600 lines. Being too brief (under 100 lines) triggers a Lens B review asking for more substance. Being verbose does not help if the content is generic.
**Focus areas:**
- Color: 3050 lines (palette tables + CSS blocks)
- Components: 100200 lines (36 components, fully specified)
- Visual Theme: 3040 lines (atmosphere + use cases + prior art)
- Anti-patterns: 815 lines (one per key mistake to avoid)
The mission-control design system (`design-systems/mission-control/DESIGN.md`) is a good reference — tight scope (3 primary colors, dark only, 6 components).