diff --git a/DESIGN.md b/DESIGN.md new file mode 100644 index 0000000000..e5fbccee64 --- /dev/null +++ b/DESIGN.md @@ -0,0 +1,367 @@ +# Docs Design System + +This file documents **design intent and conventions** for `docs.mergify.com` — the "why" behind +decisions, not the values themselves. For exact values (colors, spacing, typography), read the +source files listed below; the code is the source of truth. + +> Companion file to `CLAUDE.md`: `CLAUDE.md` covers project setup, commands, and codebase rules. +> `DESIGN.md` is the design system this site is built from. Keep them aligned: when a design rule +> changes here, update the matching section in `CLAUDE.md` (or vice-versa) so they don't drift. + +## Source Files + +| What | Where | +| --- | --- | +| Primitive tokens (gray scale + product palette) | [`src/styles/tokens.css`](./src/styles/tokens.css) | +| Semantic tokens + dark-mode remaps | [`src/styles/theme.css`](./src/styles/theme.css) | +| Typography utility classes | [`src/styles/typography.css`](./src/styles/typography.css) | +| Global content rules + section-accent system | [`src/styles/index.css`](./src/styles/index.css) | +| Product accent colors (canonical source) | [`mergify.com/DESIGN.md`](../mergify.com/DESIGN.md) — "Product Accent Colors" section | +| Reusable Astro components | [`src/components/`](./src/components/) | +| Page layout templates | [`src/layouts/`](./src/layouts/) | +| Icons (Phosphor bold + custom SVGs) | Inline `?raw` imports; no icon component abstraction yet | +| Agent instructions | [`AGENTS.md`](./AGENTS.md) — "Design System" section | +| Claude instructions | [`CLAUDE.md`](./CLAUDE.md) — "Design System" section | + +## Visual Theme + +`docs.mergify.com` is a reference site for developers who are already using or evaluating Mergify. +They arrive from search, GitHub links, and product UI. The goal is to answer their question quickly +and get out of the way. It is **not** a conversion funnel — that is `mergify.com`'s job. + +Built with Astro 5 + MDX + plain CSS. No Tailwind (the site predates the Tailwind migration on the +marketing site; adding it is out of scope). Dark mode is supported via the `:root.theme-dark` +class-based mechanism. + +**Key characteristics:** + +- Neutral foundation — primary text and buttons are `gray-900` / `gray-50` (black/white), not + `--color-mergify-blue`. Product palette colors appear only when a surface is *about* that product. +- Clean gray ramp — intentionally diverges from `mergify.com`'s gray scale, which has + `gray-50 == gray-200` collisions. The docs ramp has no duplicates; `gray-50` through `gray-900` + are distinct values you can reach for without reading a gotchas table. +- Light + dark — the marketing site is light-only; docs ships both modes because developers working + in dark terminals expect it. +- Inter variable font, same as the marketing site. Self-hosted via `@fontsource/inter`. +- Compact layout — content shares horizontal space with a left sidebar and right ToC. The hero + typography cap is smaller than marketing's (`clamp(2.5rem, 4.5vw, 3rem)` vs. 64px) because the + reading column is narrower. + +## Color Tokens + +All colors live in three layers. **Components consume only the semantic layer.** + +### Layer 1 — Primitive (`tokens.css`) + +Fixed hex values. Never changes between light and dark mode. Never referenced directly by +components or content rules. + +```css +/* Neutrals */ +--color-white, --color-dark +--color-gray-50 … --color-gray-900 + +/* Product palette — verbatim from mergify.com */ +--color-teal-400, --color-teal-700 +--color-purple-400, --color-purple-700 +/* …etc for orange, blue, coral, rose… */ +--color-blue-800 /* docs-only: link hover */ +``` + +The two exceptions where primitive tokens are allowed: + +1. Inside `tokens.css` itself (where they are defined). +2. Inside `theme.css` (where they are mapped to semantic names). + +Nowhere else. + +### Layer 2 — Semantic (`theme.css`) + +Mode-aware names that components and content rules consume. Defined once for light, remapped once +in `:root.theme-dark`. These are the **only** tokens components should touch. + +```css +--theme-text /* primary text */ +--theme-text-secondary /* supporting text */ +--theme-text-muted /* de-emphasized text, captions */ +--theme-bg /* page background */ +--theme-bg-content /* card / content surface */ +--theme-bg-offset /* raised surface (inline code bg, sidebar) */ +--theme-border /* borders, dividers */ +--theme-link /* link color */ +--theme-link-hover /* link hover */ +--theme-accent /* primary action / heading emphasis */ +``` + +### Layer 3 — Section accents (`index.css`) + +A `--section-accent` custom property set on `` by class. Each documentation section gets +its own accent color; the ToC active-link and sidebar hover states consume it automatically. One +rule block, not one block per section. + +```css +body { --section-accent: var(--theme-link); } +body.section-merge-queue { --section-accent: var(--color-teal-700); } +/* …etc… */ +``` + +### The discipline rule + +**Components never reference primitive tokens directly.** If you find yourself writing +`var(--color-gray-300)` inside a component, stop and use `var(--theme-border)` instead. The +primitive layer exists so `theme.css` has legible, self-documenting mappings — not so consumers +can bypass the semantic layer. + +## Product Accent Colors + +Product colors are verbatim from `mergify.com/DESIGN.md`. The docs site reuses the same palette +without adding new tokens. + +| Product | Dark / Label | Light / Accent | Hex (label) | +| --- | --- | --- | --- | +| Merge Queue | `--color-teal-700` | `--color-teal-400` | #1CB893 | +| CI Insights | `--color-purple-700` | `--color-purple-400` | #4D59E0 | +| Test Insights | `--color-orange-700` | `--color-orange-400` | #F27B2A | +| Merge Protections | `--color-blue-700` | `--color-blue-400` | #43A7E5 | +| Stacks | `--color-coral-700` | `--color-coral-400` | #E53935 | +| Workflow Automation | `--color-rose-700` | `--color-rose-400` | #E61E71 | + +One docs-only addition: `--color-blue-800` (#237caf) for link hover. It is a darker shade of +`blue-700` and exists only because docs is text-heavy with many cross-references; the marketing +site uses product colors for links far less often. + +### Section-accent body classes + +The `` element receives a class based on the active documentation section. This drives the +ToC active-link color and left-sidebar hover highlight. + +| Body class | Section | Accent token | +| --- | --- | --- | +| (no class) | General / configuration | `--theme-link` (blue-700) | +| `section-merge-queue` | Merge Queue | `--color-teal-700` | +| `section-ci-insights` | CI Insights | `--color-purple-700` | +| `section-test-insights` | Test Insights | `--color-orange-700` | +| `section-merge-protections` | Merge Protections | `--color-blue-700` | +| `section-stacks` | Stacks | `--color-coral-700` | +| `section-workflow` | Workflow Automation | `--color-rose-700` | + +The class is applied by the layout; do not hardcode accent colors inside section-specific +components. Consume `var(--section-accent)` and `var(--section-accent-bg)` instead. + +Note on link color vs. Merge Protections accent: both use `blue-700`. On a Merge Protections page, +inline links and product pills share a hue but serve different roles (underlined inline link vs. +solid pill). The visual conflation is minor and preferable to introducing a new shade. + +## Dark Mode + +### Mechanism + +`:root.theme-dark` is added to the `` element by a `