How the Style Guide Theming System Maps Semantic Roles to Colors in Diagram-Design
The Diagram-Design style guide theming system maps semantic roles to colors through a centralized lookup table in skills/diagram-design/references/style-guide.md, where human-readable tokens like accent and ink are paired with concrete hex values that templates reference at render time.
The Diagram-Design repository implements a robust theming architecture that separates visual intent from implementation details. This article explores how the style guide theming system translates abstract semantic roles into concrete color values, enabling consistent branding across all diagram outputs. By centralizing every color token in a single source-of-truth file, the system ensures that changing one line instantly re-skins every diagram in a project.
How Semantic Role Mapping Works
The mapping process begins with skills/diagram-design/references/style-guide.md, which acts as the central token table. This file contains a markdown table that pairs semantic role names—such as paper, ink, muted, accent, link, error, warning, and success—with their corresponding hex or RGBA values.
When the rendering engine initializes, it parses this file into a Python dictionary that serves as a lookup table during template processing. Rather than embedding hard-coded hex values in SVG or HTML templates, every visual element references a semantic role name using syntax like {{accent}} or fill="accent". At render time, the engine substitutes the concrete color value from the dictionary for each encountered role.
Core Components of the Theming System
The Central Token Table
The file skills/diagram-design/references/style-guide.md defines the complete color vocabulary for the skill. Each row in the table maps a semantic role to a concrete value, creating a contract between design intent and implementation. The default skin ships with values like atomic-tangerine for accents and blue-slate for muted elements, but these can be overridden without modifying diagram logic.
Profile-Based Customization
Users can create brand-specific variants through the profile system. The onboarding flow documented in skills/diagram-design/references/onboarding.md extracts brand palettes and either writes a diff to the central style guide or saves a separate profile to ~/.diagram-design/profiles/<slug>.md. Projects reference these external profiles via .diagram-design marker files, allowing parallel workspaces to maintain different brand skins without altering the installed plugin files.
Automatic Dark and Light Mode Inversion
The style guide theming system handles theme inversion by monitoring the paper color value. When a dark paper color is detected, the engine inverts all other roles to preserve contrast ratios, eliminating the need to maintain separate dark-mode color tables.
Implementation Examples
Loading the Style Guide Dictionary
The load_style_guide function in utils/style_guide.py parses the markdown table into a dictionary:
# utils/style_guide.py
import toml
from pathlib import Path
def load_style_guide(root: Path) -> dict[str, str]:
"""
Reads ``skills/diagram-design/references/style-guide.md`` and returns a
mapping of semantic role names to concrete colour strings.
"""
guide_path = root / "skills" / "diagram-design" / "references" / "style-guide.md"
# The file uses a simple Markdown table; we parse the lines that look like:
# | accent | #eb6c36 |
role_map = {}
for line in guide_path.read_text().splitlines():
if line.startswith("|") and "|" in line[1:]:
parts = [p.strip() for p in line.strip("|").split("|")]
if len(parts) >= 2 and parts[0] and parts[1]:
role, colour = parts[0], parts[1]
# Guard against header rows like "Role | Colour"
if role.lower() != "role":
role_map[role] = colour
return role_map
Referencing Semantic Roles in Templates
Diagram templates never hard-code colors. Instead, they query the role map, as shown in this simplified bar chart renderer:
# diagrams/bar.py (simplified)
from utils.style_guide import load_style_guide
def render_bar_chart(data, project_root):
colors = load_style_guide(project_root)
# “accent” is the focal series colour, “muted” is the non‑focal series
accent_fill = colors["accent"]
muted_fill = colors["muted"]
svg = f'''
<svg width="200" height="100">
<rect x="10" y="20" width="40" height="60" fill="{accent_fill}" />
<rect x="60" y="40" width="40" height="40" fill="{muted_fill}" />
</svg>
'''
return svg
Swapping Themes via the Profile System
The apply_profile function in utils/profile.py enables instant re-skinning by replacing the active style guide:
# utils/profile.py
from pathlib import Path
import shutil
def apply_profile(project_root: Path, profile_slug: str):
"""
Copies the profile file ``~/.diagram-design/profiles/<slug>.md`` over the
installed style‑guide, without touching the repo‑controlled copy.
"""
profile_path = Path.home() / ".diagram-design" / "profiles" / f"{profile_slug}.md"
target = project_root / "skills" / "diagram-design" / "references" / "style-guide.md"
shutil.copyfile(profile_path, target)
Validation and Linting
To prevent "magic" colors from leaking into outputs, the scripts/lint-skin.py script validates that every color used in a diagram originates from a role defined in style-guide.md. This linting step enforces the semantic contract and ensures that all visual tokens remain centrally manageable according to the style guide theming system rules.
Summary
- The style guide theming system centralizes color definitions in
skills/diagram-design/references/style-guide.mdusing semantic roles likepaper,ink, andaccent. - Templates reference role names rather than hex values, enabling instant global updates by modifying a single file.
- The profile system supports brand-specific customization through external files stored in
~/.diagram-design/profiles/and documented inskills/diagram-design/references/profiles.md. - Automatic dark/light inversion detects the
papercolor and adjusts contrast ratios without manual intervention. - The
scripts/lint-skin.pylinter ensures strict adherence to the semantic color palette.
Frequently Asked Questions
What file contains the color definitions in Diagram-Design?
All color definitions reside in skills/diagram-design/references/style-guide.md. This markdown table maps semantic role names to concrete hex or RGBA values, serving as the single source of truth for the entire theming system.
How do I create a custom brand theme without modifying the default files?
Use the profile system. Run the onboarding flow documented in skills/diagram-design/references/onboarding.md to generate a brand palette, then save it as a profile to ~/.diagram-design/profiles/<your-brand>.md. Activate it using the profile command documented in commands/profile.md or by pointing your project to it with a .diagram-design marker file.
Does Diagram-Design support dark mode automatically?
Yes. When the paper role is set to a dark color, the system automatically inverts other semantic roles to maintain contrast ratios. This eliminates the need to maintain separate color tables for light and dark themes.
How does the system prevent hard-coded colors in diagrams?
The scripts/lint-skin.py linter validates every color value in diagram outputs against the roles defined in style-guide.md. If a color appears that isn't mapped to a semantic role, the linter flags it as an error, enforcing the semantic-to-concrete mapping discipline.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →