mirror of
https://github.com/kbenestad/mdcms.git
synced 2026-06-18 15:24:32 +00:00
Clarifies that nav-link, nav-link-active, and nav-section-heading affect not just nav links but also the site name, description, and theme toggle — all sidebar elements that inherit from these variables. Adds a rule of thumb for when to set the keys explicitly (saturation >20%, or lightness outside the neutral range). https://claude.ai/code/session_01NQKywehSj8Ku4yKhwB4VNB
200 lines
7.4 KiB
Markdown
200 lines
7.4 KiB
Markdown
# mdcms theme authoring guide for Claude Design
|
|
|
|
This document explains the `theme.yml` format so that Claude Design can produce
|
|
complete, correct theme files that render well in all nav configurations and in
|
|
both light and dark mode.
|
|
|
|
---
|
|
|
|
## Full theme.yml structure
|
|
|
|
```yaml
|
|
# mdcms v0.4 | DO NOT REMOVE THIS COMMENT
|
|
# mdcms theme — <theme name>
|
|
|
|
# ──────────────────────────────────
|
|
# Colours
|
|
# ──────────────────────────────────
|
|
light:
|
|
accent: "#2563EB" # brand colour; used for links, active nav border, accents
|
|
background: "#FFFFFF" # main content area background
|
|
nav-background: "#F8FAFC" # sidebar/nav panel background
|
|
text: "#1E293B" # body text
|
|
text-muted: "#64748B" # secondary text, captions
|
|
nav-link: "#1E293B" # inactive nav link text
|
|
nav-link-active: "#2563EB" # active (current page) nav link text
|
|
nav-section-heading: "#64748B" # nav section label text (uppercase, small)
|
|
# divider: "#CBD5E1" # omit to auto-derive via color-mix(background, text)
|
|
|
|
dark:
|
|
accent: "#60A5FA"
|
|
background: "#0F172A"
|
|
nav-background: "#1E293B"
|
|
text: "#F1F5F9"
|
|
text-muted: "#94A3B8"
|
|
nav-link: "#E2E8F0"
|
|
nav-link-active: "#60A5FA"
|
|
nav-section-heading: "#94A3B8"
|
|
# divider: "#334155" # omit to auto-derive via color-mix(background, text)
|
|
|
|
# ──────────────────────────────────
|
|
# Semantic colours
|
|
# colours-semantic applies to both modes.
|
|
# colours-semantic-dark overrides for dark mode only.
|
|
# ──────────────────────────────────
|
|
colours-semantic:
|
|
info: "#2563EB"
|
|
warning: "#D97706"
|
|
success: "#16A34A"
|
|
error: "#DC2626"
|
|
|
|
colours-semantic-dark:
|
|
info: "#60A5FA"
|
|
warning: "#F59E0B"
|
|
success: "#34D399"
|
|
error: "#F87171"
|
|
|
|
# ──────────────────────────────────
|
|
# Callout defaults
|
|
# primary-colour → left border and icon
|
|
# background-colour → tinted background (rendered at ~8% opacity)
|
|
# ──────────────────────────────────
|
|
callouts:
|
|
info:
|
|
icon: info
|
|
primary-colour: "#2563EB"
|
|
background-colour: "#2563EB"
|
|
warning:
|
|
icon: warning
|
|
primary-colour: "#D97706"
|
|
background-colour: "#D97706"
|
|
success:
|
|
icon: success
|
|
primary-colour: "#16A34A"
|
|
background-colour: "#16A34A"
|
|
error:
|
|
icon: error
|
|
primary-colour: "#DC2626"
|
|
background-colour: "#DC2626"
|
|
|
|
# ──────────────────────────────────
|
|
# Typography
|
|
# Format: "provider:Font Name:weight" (provider: bunny | google)
|
|
# ──────────────────────────────────
|
|
font-body: "bunny:IBM Plex Sans:400"
|
|
font-heading: "bunny:IBM Plex Sans:700"
|
|
font-size: 1.0 # unitless multiplier (1.0 = 16px base)
|
|
line-height: 1.7 # unitless multiplier
|
|
|
|
# ──────────────────────────────────
|
|
# Layout
|
|
# ──────────────────────────────────
|
|
main-width: 80em
|
|
nav-width: 20em
|
|
```
|
|
|
|
---
|
|
|
|
## Critical rule: nav contrast
|
|
|
|
The renderer defaults `nav-link-active` to `accent` and `nav-link` to `text`.
|
|
When `nav-background` and `accent` share the same hue (or are very close),
|
|
active nav links become invisible — the coloured text disappears into a
|
|
coloured background.
|
|
|
|
The nav colour keys also control the **site name, site description, and
|
|
dark/light mode toggle** — all three live inside the sidebar and inherit from
|
|
the same variables. On muted or neutral nav backgrounds the content-area
|
|
fallbacks (`text`, `text-muted`) are fine. On any saturated or bold nav
|
|
background the contrast between `text` and `text-muted` is likely too low for
|
|
these elements to remain legible, so all three nav colour keys must be set
|
|
explicitly.
|
|
|
|
**Rule of thumb:** if `nav-background` has a saturation above roughly 20 % or
|
|
a lightness below 30 % (dark sidebar) or above 85 % (near-white sidebar that
|
|
differs noticeably from the page background), set `nav-link`,
|
|
`nav-link-active`, and `nav-section-heading` explicitly for that mode.
|
|
|
|
**Always set all three nav colour keys explicitly** whenever `nav-background`
|
|
is anything other than a neutral near-white (light) or near-black (dark).
|
|
|
|
### Pattern: accent-coloured nav (e.g. brand red, navy, forest green)
|
|
|
|
```yaml
|
|
light:
|
|
accent: "#D00C33"
|
|
nav-background: "#D00C33" # same as accent — nav links MUST be overridden
|
|
nav-link: "#FFFFFF"
|
|
nav-link-active: "#FFFFFF"
|
|
nav-section-heading: "rgba(255,255,255,0.65)"
|
|
|
|
dark:
|
|
accent: "#D00C33"
|
|
nav-background: "#000000"
|
|
nav-link: "#E2E2E2"
|
|
nav-link-active: "#FFFFFF"
|
|
nav-section-heading: "#888888"
|
|
```
|
|
|
|
### Pattern: dark nav in light mode (sidebar darker than content)
|
|
|
|
```yaml
|
|
light:
|
|
nav-background: "#1E293B"
|
|
nav-link: "#CBD5E1"
|
|
nav-link-active: "#FFFFFF"
|
|
nav-section-heading: "#64748B"
|
|
```
|
|
|
|
### Pattern: transparent / very light nav (default behaviour)
|
|
|
|
When `nav-background` is a light neutral, the defaults work fine.
|
|
You can omit `nav-link`, `nav-link-active`, and `nav-section-heading`
|
|
and the renderer will fall back to `text`, `accent`, and `text-muted`.
|
|
|
|
---
|
|
|
|
## Semantic colours and dark mode
|
|
|
|
`colours-semantic` values are applied globally (both modes). The callout
|
|
background is rendered at ~8% opacity, so a colour that looks fine on white
|
|
can wash out on a dark background — or conversely, a colour bright enough for
|
|
dark mode may be too vivid on white.
|
|
|
|
The solution is `colours-semantic-dark`: it overrides semantic colours in dark
|
|
mode only. Typical approach:
|
|
|
|
- **`colours-semantic`** — choose saturated but not neon values that work on white
|
|
- **`colours-semantic-dark`** — use lighter, more luminous variants of the same hues
|
|
|
|
```yaml
|
|
colours-semantic:
|
|
info: "#1D4ED8" # deep blue — strong on white
|
|
warning: "#B45309" # amber — strong on white
|
|
success: "#15803D" # green — strong on white
|
|
error: "#B91C1C" # red — strong on white
|
|
|
|
colours-semantic-dark:
|
|
info: "#93C5FD" # light blue — visible on dark background
|
|
warning: "#FCD34D" # light amber
|
|
success: "#6EE7B7" # light green
|
|
error: "#FCA5A5" # light red/pink
|
|
```
|
|
|
|
Match `callouts` `primary-colour` / `background-colour` values to
|
|
`colours-semantic` (light mode callout values), since the callout block
|
|
uses its own per-callout colour settings rather than the semantic variables.
|
|
|
|
---
|
|
|
|
## Checklist before finalising a theme
|
|
|
|
- [ ] `nav-link`, `nav-link-active`, `nav-section-heading` specified for both
|
|
`light` and `dark` whenever `nav-background` is non-neutral
|
|
- [ ] All three nav link colours contrast against `nav-background` (WCAG AA minimum)
|
|
- [ ] `colours-semantic-dark` provided with lighter variants of each colour
|
|
- [ ] `callouts` `primary-colour` matches `colours-semantic` values for consistency
|
|
- [ ] `divider` omitted unless the auto-derived value looks wrong (check hr and table borders)
|
|
- [ ] Dark mode `background` is not pure `#000000` unless intentional (use `#0A0A0A`+)
|
|
- [ ] `font-size` between `0.85` and `1.15`; `line-height` between `1.5` and `1.9`
|
|
- [ ] Version comment on line 1: `# mdcms v0.4 | DO NOT REMOVE THIS COMMENT`
|