From 689397ef8319dce1c5e0a278badf1a2a42f5f107 Mon Sep 17 00:00:00 2001 From: Wojtek Majewski Date: Mon, 9 Jun 2025 20:58:01 +0200 Subject: [PATCH] feat: add D2 theme support and update documentation with architecture diagrams - Introduced 'astro-d2' package and integrated D2 theme overrides for light and dark modes - Updated documentation to include detailed D2 architecture and task lifecycle diagrams - Modified package.json to include 'astro-d2' dependency - Enhanced Astro configuration with new theme settings and diagrams for better clarity --- .claude/commands/create-d2-diagram.md | 78 + .github/actions/setup-d2/action.yml | 23 + .github/workflows/ci.yml | 4 + pkgs/website/.gitignore | 3 + pkgs/website/astro.config.mjs | 2 + pkgs/website/package.json | 1 + pkgs/website/src/assets/pgflow-theme.d2 | 32 + pkgs/website/src/components/D2.astro | 85 + pkgs/website/src/content/docs/d2-demo.mdx | 2185 +++++++++++++++++++++ pkgs/website/src/diagrams/test.d2 | 16 + pnpm-lock.yaml | 15 + 11 files changed, 2444 insertions(+) create mode 100644 .claude/commands/create-d2-diagram.md create mode 100644 .github/actions/setup-d2/action.yml create mode 100644 pkgs/website/src/assets/pgflow-theme.d2 create mode 100644 pkgs/website/src/components/D2.astro create mode 100644 pkgs/website/src/content/docs/d2-demo.mdx create mode 100644 pkgs/website/src/diagrams/test.d2 diff --git a/.claude/commands/create-d2-diagram.md b/.claude/commands/create-d2-diagram.md new file mode 100644 index 000000000..a2e3be3bc --- /dev/null +++ b/.claude/commands/create-d2-diagram.md @@ -0,0 +1,78 @@ +# Create D2 Diagram with Theme Import + +You are helping create D2 diagrams in the pgflow documentation that use the shared pgflow theme. + +## Quick Reference + +### Basic D2 Code Block with Import + +````markdown +```d2 +...@../../assets/pgflow-theme.d2 + +direction: right + +nodeA: "Node A" +nodeB: "Node B" +nodeA -> nodeB +``` +```` + +**CRITICAL**: There MUST be a blank line after the code fence and before the import line! + +## Theme File Location + +The shared theme is at: `pkgs/website/src/assets/pgflow-theme.d2` + +## Path Resolution + +From content files, use relative path: `...@../../assets/pgflow-theme.d2` + +- From `src/content/docs/*.mdx` → `../../assets/pgflow-theme.d2` +- From `src/content/docs/subdir/*.mdx` → `../../../assets/pgflow-theme.d2` + +## How It Works + +1. The `...@path` syntax tells D2 to import and merge the theme configuration +2. The astro-d2 plugin processes this during build +3. D2 resolves the relative path from the markdown file's location +4. The theme vars are merged with your diagram code + +## Common Patterns + +### Simple Workflow +````markdown +```d2 +...@../../assets/pgflow-theme.d2 + +direction: right +start -> process -> end +``` +```` + +### With Custom Styling +````markdown +```d2 +...@../../assets/pgflow-theme.d2 + +direction: down + +start: "Start" { + style: { + fill: "#003b34" + stroke: "#00574d" + font-color: "#a3d4cb" + } +} +``` +```` + +## Troubleshooting + +**Diagram shows code instead of rendering?** +- Ensure blank line after ` ```d2 ` +- Check relative path is correct from file location + +**Import not found?** +- Verify theme file exists at `src/assets/pgflow-theme.d2` +- Count directory levels correctly (`../` for each parent) diff --git a/.github/actions/setup-d2/action.yml b/.github/actions/setup-d2/action.yml new file mode 100644 index 000000000..6c5ab9ada --- /dev/null +++ b/.github/actions/setup-d2/action.yml @@ -0,0 +1,23 @@ +name: 'Setup D2' +description: 'Install D2 diagramming tool with retry logic' + +runs: + using: 'composite' + steps: + - name: Install D2 + shell: bash + run: | + for i in 1 2 3 4 5; do + echo "Attempt $i to install D2..." + if curl -fsSL https://d2lang.com/install.sh | sh -s --; then + echo "D2 installed successfully" + break + else + if [ $i -eq 5 ]; then + echo "Failed to install D2 after 5 attempts" + exit 1 + fi + echo "Install failed, retrying in 5 seconds..." + sleep 5 + fi + done diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5ffb4c0d1..7705b2a6a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -47,6 +47,8 @@ jobs: - name: Verify NX_BASE and NX_HEAD are set run: echo "BASE=$NX_BASE HEAD=$NX_HEAD" + - uses: ./.github/actions/setup-d2 + - name: Quality gate (lint + typecheck + test) run: pnpm nx affected -t lint typecheck test --parallel --configuration=production --base="$NX_BASE" --head="$NX_HEAD" @@ -119,6 +121,8 @@ jobs: - name: Verify NX_BASE and NX_HEAD are set run: echo "BASE=$NX_BASE HEAD=$NX_HEAD" + - uses: ./.github/actions/setup-d2 + - name: Check if website is affected id: check-affected run: | diff --git a/pkgs/website/.gitignore b/pkgs/website/.gitignore index cf375bbc0..03c5568a5 100644 --- a/pkgs/website/.gitignore +++ b/pkgs/website/.gitignore @@ -19,4 +19,7 @@ pnpm-debug.log* # macOS-specific files .DS_Store + +# generated files public/edge-worker/ +public/d2/ diff --git a/pkgs/website/astro.config.mjs b/pkgs/website/astro.config.mjs index 16fc10e46..afbaa7814 100644 --- a/pkgs/website/astro.config.mjs +++ b/pkgs/website/astro.config.mjs @@ -7,6 +7,7 @@ import starlightSidebarTopics from 'starlight-sidebar-topics'; import robotsTxt from 'astro-robots-txt'; import starlightLlmsTxt from 'starlight-llms-txt'; import starlightContextualMenu from 'starlight-contextual-menu'; +import d2 from 'astro-d2'; import { fileURLToPath } from 'url'; import path from 'path'; @@ -54,6 +55,7 @@ export default defineConfig({ redirects, integrations: [ + d2(), react({ include: ['**/components/**/*.tsx'], exclude: ['**/pages/**/*'], diff --git a/pkgs/website/package.json b/pkgs/website/package.json index 39707815e..641430f7b 100644 --- a/pkgs/website/package.json +++ b/pkgs/website/package.json @@ -27,6 +27,7 @@ "@types/react-dom": "^19.1.7", "@vercel/analytics": "^1.5.0", "astro": "^5.7.14", + "astro-d2": "^0.8.0", "astro-robots-txt": "^1.0.0", "react": "^19.1.1", "react-dom": "^19.1.1", diff --git a/pkgs/website/src/assets/pgflow-theme.d2 b/pkgs/website/src/assets/pgflow-theme.d2 new file mode 100644 index 000000000..d2529a998 --- /dev/null +++ b/pkgs/website/src/assets/pgflow-theme.d2 @@ -0,0 +1,32 @@ +vars: { + d2-config: { + theme-id: 0 + dark-theme-overrides: { + # Canvas background + N7: "#121a19" + + # Neutrals - desaturated grays for default nodes + N1: "#e8eced" + N2: "#c5cacc" + N3: "#95a0a3" + N4: "#4a5759" + N5: "#2d3739" + N6: "#1a2324" + + # Borders - neutral grays + B1: "#3a4547" + B2: "#4a5759" + B3: "#5a6769" + B4: "#1a2324" + B5: "#2d3739" + B6: "#4a5759" + + # Semantic colors - intentional states + AA2: "#d97706" + AA4: "#dc2626" + AA5: "#92400e" + AB4: "#059669" + AB5: "#2563eb" + } + } +} diff --git a/pkgs/website/src/components/D2.astro b/pkgs/website/src/components/D2.astro new file mode 100644 index 000000000..3b2025fef --- /dev/null +++ b/pkgs/website/src/components/D2.astro @@ -0,0 +1,85 @@ +--- +import { execSync } from 'node:child_process'; + +const { + padding = 100, + sketch = false, + theme = 0, + darkTheme = 200, + code, + layout = 'dagre', +} = Astro.props; + +// Theme configuration that will be prepended to all diagrams +const themeConfig = `vars: { + d2-config: { + theme-id: ${theme} + theme-overrides: { + # Neutrals - desaturated grays for default nodes + N1: "#e8eced" + N2: "#c5cacc" + N3: "#95a0a3" + N4: "#4a5759" + N5: "#2d3739" + N6: "#1a2324" + N7: "#ffffff" + + # Borders - neutral grays + B1: "#3a4547" + B2: "#4a5759" + B3: "#5a6769" + B4: "#1a2324" + B5: "#2d3739" + B6: "#4a5759" + + # Semantic colors - intentional states + AA2: "#d97706" + AA4: "#dc2626" + AA5: "#92400e" + AB4: "#059669" + AB5: "#2563eb" + } + dark-theme-overrides: { + # Neutrals - desaturated grays for default nodes + N1: "#e8eced" + N2: "#c5cacc" + N3: "#95a0a3" + N4: "#4a5759" + N5: "#2d3739" + N6: "#1a2324" + N7: "#121a19" + + # Borders - neutral grays + B1: "#3a4547" + B2: "#4a5759" + B3: "#5a6769" + B4: "#1a2324" + B5: "#2d3739" + B6: "#4a5759" + + # Semantic colors - intentional states + AA2: "#d97706" + AA4: "#dc2626" + AA5: "#92400e" + AB4: "#059669" + AB5: "#2563eb" + } + } +} + +`; + +// Prepend theme config to the user's diagram code +const fullCode = themeConfig + code; + +// Generate the diagram SVG +const output = execSync( + `d2 --layout=${layout} --theme=${theme} --sketch=${sketch} --pad=${padding} --dark-theme=${darkTheme} - -`, + { + input: fullCode, + encoding: 'utf8', + } +); +--- + + diff --git a/pkgs/website/src/content/docs/d2-demo.mdx b/pkgs/website/src/content/docs/d2-demo.mdx new file mode 100644 index 000000000..dc2554bc1 --- /dev/null +++ b/pkgs/website/src/content/docs/d2-demo.mdx @@ -0,0 +1,2185 @@ +--- +title: D2 Diagram Demo +description: Demonstration of D2 diagram theming with Starlight color palette integration. +sidebar: + hidden: true +editUrl: false +tableOfContents: false +lastUpdated: false +topic: pgflow +--- + +import D2 from '@/components/D2.astro'; +import testDiagram from '@/diagrams/test.d2?raw'; + +## Theme Import Demo (Using D2 Import Syntax) + +This diagram demonstrates D2's **import feature** using the `...@path` syntax. Instead of repeating theme configuration in every diagram, you can: + +1. Define your theme once in a shared file (`src/assets/pgflow-theme.d2`) +2. Import it in any D2 code block with a simple relative path + +**Key benefit:** Update theme colors in one place and all diagrams automatically use the new theme! + +```d2 +...@../../assets/pgflow-theme.d2 + +direction: right + +# Simple workflow with imported theme - no custom styles! +start: "Start" +process: "Process" +success: "Success" + +start -> process -> success +``` + +**How it works:** The `...@../../assets/pgflow-theme.d2` syntax tells D2 to import and merge the theme configuration from the specified file. No need for separate D2 files or components! + +## Simple Workflow Example (Using Custom Component) + +This diagram uses our custom `` component that **automatically injects the pgflow theme** - no theme configuration needed in your code! + + + +**Key benefit:** Notice there's NO theme configuration in the diagram code above - the `` component (defined in `src/components/D2.astro`) automatically prepends the theme to every diagram! + +## Color Palette Demo (Dark Mode) + +This diagram demonstrates all available semantic colors from the website's CSS variables in a branching tree structure with 4 parallel lanes. + +```d2 +vars: { + d2-config: { + theme-id: 0 + dark-theme-overrides: { + # Dark mode canvas + N7: "#121a19" + # Edge colors + B1: "#495d59" + B2: "#495d59" + } + } +} + +direction: down + +# Root node +root: "Color Palette" { + shape: rectangle + style: { + border-radius: 8 + fill: "#007b6e" + stroke: "#00574d" + font-color: "#e7f0ee" + } +} + +# Level 1: Teal variants (4 lanes start) +teal_dark: "Teal Dark\n#003b34" { + shape: rectangle + style: { + border-radius: 8 + fill: "#003b34" + stroke: "#00574d" + font-color: "#a3d4cb" + } +} + +teal_medium: "Teal Medium\n#00574d" { + shape: rectangle + style: { + border-radius: 8 + fill: "#00574d" + stroke: "#007b6e" + font-color: "#a3d4cb" + } +} + +teal_base: "Teal Base\n#007b6e" { + shape: rectangle + style: { + border-radius: 8 + fill: "#007b6e" + stroke: "#00574d" + font-color: "#e7f0ee" + } +} + +teal_light: "Teal Light\n#a3d4cb" { + shape: rectangle + style: { + border-radius: 8 + fill: "#a3d4cb" + stroke: "#007b6e" + font-color: "#003b34" + } +} + +# Connections from root to level 1 +root -> teal_dark +root -> teal_medium +root -> teal_base +root -> teal_light + +# Level 2: Blue variants +blue_dark: "Blue Dark\n#1a2947" { + shape: rectangle + style: { + border-radius: 8 + fill: "#1a2947" + stroke: "#5c8dd6" + font-color: "#d4e3f7" + } +} + +blue_medium: "Blue Medium\n#34578f" { + shape: rectangle + style: { + border-radius: 8 + fill: "#34578f" + stroke: "#5c8dd6" + font-color: "#d4e3f7" + } +} + +blue_base: "Blue Base\n#5c8dd6" { + shape: rectangle + style: { + border-radius: 8 + fill: "#5c8dd6" + stroke: "#34578f" + font-color: "#ffffff" + } +} + +blue_light: "Blue Light\n#d4e3f7" { + shape: rectangle + style: { + border-radius: 8 + fill: "#d4e3f7" + stroke: "#5c8dd6" + font-color: "#1a2947" + } +} + +# Connections level 1 -> level 2 +teal_dark -> blue_dark +teal_medium -> blue_medium +teal_base -> blue_base +teal_light -> blue_light + +# Level 3: Green variants +green_dark: "Green Dark\n#1a4136" { + shape: rectangle + style: { + border-radius: 8 + fill: "#1a4136" + stroke: "#33cc7f" + font-color: "#99e6c0" + } +} + +green_medium: "Green Medium\n#247056" { + shape: rectangle + style: { + border-radius: 8 + fill: "#247056" + stroke: "#33cc7f" + font-color: "#99e6c0" + } +} + +green_base: "Green Base\n#33cc7f" { + shape: rectangle + style: { + border-radius: 8 + fill: "#33cc7f" + stroke: "#247056" + font-color: "#ffffff" + } +} + +green_light: "Green Light\n#99e6c0" { + shape: rectangle + style: { + border-radius: 8 + fill: "#99e6c0" + stroke: "#33cc7f" + font-color: "#1a4136" + } +} + +# Connections level 2 -> level 3 +blue_dark -> green_dark +blue_medium -> green_medium +blue_base -> green_base +blue_light -> green_light + +# Level 4: Purple variants +purple_dark: "Purple Dark\n#472952" { + shape: rectangle + style: { + border-radius: 8 + fill: "#472952" + stroke: "#b77ddb" + font-color: "#ead9f5" + } +} + +purple_medium: "Purple Medium\n#805099" { + shape: rectangle + style: { + border-radius: 8 + fill: "#805099" + stroke: "#b77ddb" + font-color: "#ead9f5" + } +} + +purple_base: "Purple Base\n#b77ddb" { + shape: rectangle + style: { + border-radius: 8 + fill: "#b77ddb" + stroke: "#805099" + font-color: "#ffffff" + } +} + +purple_light: "Purple Light\n#ead9f5" { + shape: rectangle + style: { + border-radius: 8 + fill: "#ead9f5" + stroke: "#b77ddb" + font-color: "#472952" + } +} + +# Connections level 3 -> level 4 +green_dark -> purple_dark +green_medium -> purple_medium +green_base -> purple_base +green_light -> purple_light + +# Level 5: Orange variants +orange_dark: "Orange Dark\n#4d3d2b" { + shape: rectangle + style: { + border-radius: 8 + fill: "#4d3d2b" + stroke: "#d9a66e" + font-color: "#f5e8d6" + } +} + +orange_medium: "Orange Medium\n#a87c45" { + shape: rectangle + style: { + border-radius: 8 + fill: "#a87c45" + stroke: "#d9a66e" + font-color: "#f5e8d6" + } +} + +orange_base: "Orange Base\n#d9a66e" { + shape: rectangle + style: { + border-radius: 8 + fill: "#d9a66e" + stroke: "#a87c45" + font-color: "#4d3d2b" + } +} + +orange_light: "Orange Light\n#f5e8d6" { + shape: rectangle + style: { + border-radius: 8 + fill: "#f5e8d6" + stroke: "#d9a66e" + font-color: "#4d3d2b" + } +} + +# Connections level 4 -> level 5 +purple_dark -> orange_dark +purple_medium -> orange_medium +purple_base -> orange_base +purple_light -> orange_light + +# Level 6: Red variants +red_dark: "Red Dark\n#4f1f1f" { + shape: rectangle + style: { + border-radius: 8 + fill: "#4f1f1f" + stroke: "#e85c5c" + font-color: "#f7d1d1" + } +} + +red_medium: "Red Medium\n#a33636" { + shape: rectangle + style: { + border-radius: 8 + fill: "#a33636" + stroke: "#e85c5c" + font-color: "#f7d1d1" + } +} + +red_base: "Red Base\n#e85c5c" { + shape: rectangle + style: { + border-radius: 8 + fill: "#e85c5c" + stroke: "#a33636" + font-color: "#ffffff" + } +} + +red_light: "Red Light\n#f7d1d1" { + shape: rectangle + style: { + border-radius: 8 + fill: "#f7d1d1" + stroke: "#e85c5c" + font-color: "#4f1f1f" + } +} + +# Connections level 5 -> level 6 +orange_dark -> red_dark +orange_medium -> red_medium +orange_base -> red_base +orange_light -> red_light + +# Level 7: Gray variants +gray_dark: "Gray Dark\n#182b28" { + shape: rectangle + style: { + border-radius: 8 + fill: "#182b28" + stroke: "#495d59" + font-color: "#c2cdca" + } +} + +gray_medium: "Gray Medium\n#2a3d39" { + shape: rectangle + style: { + border-radius: 8 + fill: "#2a3d39" + stroke: "#495d59" + font-color: "#c2cdca" + } +} + +gray_base: "Gray Base\n#495d59" { + shape: rectangle + style: { + border-radius: 8 + fill: "#495d59" + stroke: "#2a3d39" + font-color: "#e7f0ee" + } +} + +gray_light: "Gray Light\n#92a8a3" { + shape: rectangle + style: { + border-radius: 8 + fill: "#92a8a3" + stroke: "#495d59" + font-color: "#182b28" + } +} + +# Connections level 6 -> level 7 +red_dark -> gray_dark +red_medium -> gray_medium +red_base -> gray_base +red_light -> gray_light +``` + +## Theme Selection: What We've Decided + +### Primary Node Colors (Default shapes) + +These are the main colors for regular nodes in your diagrams. + +```d2 +vars: { + d2-config: { + theme-id: 0 + dark-theme-overrides: { + N7: "#121a19" + B1: "#495d59" + B2: "#495d59" + } + } +} + +direction: right + +teal_dark: "Teal Dark\n#003b34\n(Main Default)" { + shape: rectangle + style: { + border-radius: 8 + fill: "#003b34" + stroke: "#00574d" + font-color: "#a3d4cb" + } +} + +teal_medium: "Teal Medium\n#00574d" { + shape: rectangle + style: { + border-radius: 8 + fill: "#00574d" + stroke: "#007b6e" + font-color: "#a3d4cb" + } +} + +teal_base: "Teal Base\n#007b6e" { + shape: rectangle + style: { + border-radius: 8 + fill: "#007b6e" + stroke: "#00574d" + font-color: "#e7f0ee" + } +} + +gray_dark: "Gray Dark\n#182b28" { + shape: rectangle + style: { + border-radius: 8 + fill: "#182b28" + stroke: "#495d59" + font-color: "#c2cdca" + } +} + +gray_medium: "Gray Medium\n#2a3d39" { + shape: rectangle + style: { + border-radius: 8 + fill: "#2a3d39" + stroke: "#495d59" + font-color: "#c2cdca" + } +} + +gray_base: "Gray Base\n#495d59" { + shape: rectangle + style: { + border-radius: 8 + fill: "#495d59" + stroke: "#2a3d39" + font-color: "#e7f0ee" + } +} +``` + +### Semantic Colors (Special meanings) + +These colors will be used for nodes with specific meanings. + +```d2 +vars: { + d2-config: { + theme-id: 0 + dark-theme-overrides: { + N7: "#121a19" + B1: "#495d59" + B2: "#495d59" + } + } +} + +direction: right + +success: "Success/Positive\nGreen Dark\n#1a4136" { + shape: rectangle + style: { + border-radius: 8 + fill: "#1a4136" + stroke: "#33cc7f" + font-color: "#99e6c0" + } +} + +error: "Error/Danger\nRed Dark\n#4f1f1f" { + shape: rectangle + style: { + border-radius: 8 + fill: "#4f1f1f" + stroke: "#e85c5c" + font-color: "#f7d1d1" + } +} + +warning: "Warning/Caution\nOrange Dark\n#4d3d2b" { + shape: rectangle + style: { + border-radius: 8 + fill: "#4d3d2b" + stroke: "#d9a66e" + font-color: "#f5e8d6" + } +} + +info: "Info/Note\nBlue Dark\n#1a2947" { + shape: rectangle + style: { + border-radius: 8 + fill: "#1a2947" + stroke: "#5c8dd6" + font-color: "#d4e3f7" + } +} + +highlight: "Special/Highlight\nPurple Dark\n#472952" { + shape: rectangle + style: { + border-radius: 8 + fill: "#472952" + stroke: "#b77ddb" + font-color: "#ead9f5" + } +} +``` + +## Theme Selection: What We Need to Decide + +### Neutrals - Option A: Teal-Tinted Grays + +These neutrals have a slight teal/green tint that harmonizes with the primary theme colors. + +```d2 +vars: { + d2-config: { + theme-id: 0 + dark-theme-overrides: { + N7: "#121a19" + B1: "#495d59" + B2: "#495d59" + } + } +} + +direction: right + +n1: "N1 (Lightest)\n#e7f0ee\nFor: Light text" { + shape: rectangle + style: { + border-radius: 8 + fill: "#e7f0ee" + stroke: "#495d59" + font-color: "#182b28" + } +} + +n2: "N2\n#c2cdca\nFor: Borders" { + shape: rectangle + style: { + border-radius: 8 + fill: "#c2cdca" + stroke: "#495d59" + font-color: "#182b28" + } +} + +n3: "N3\n#92a8a3\nFor: Medium text" { + shape: rectangle + style: { + border-radius: 8 + fill: "#92a8a3" + stroke: "#495d59" + font-color: "#182b28" + } +} + +n4: "N4\n#495d59\nFor: Dark text" { + shape: rectangle + style: { + border-radius: 8 + fill: "#495d59" + stroke: "#2a3d39" + font-color: "#e7f0ee" + } +} + +n5: "N5\n#2a3d39\nFor: Subtle fills" { + shape: rectangle + style: { + border-radius: 8 + fill: "#2a3d39" + stroke: "#495d59" + font-color: "#c2cdca" + } +} + +n6: "N6\n#182b28\nFor: Dark fills" { + shape: rectangle + style: { + border-radius: 8 + fill: "#182b28" + stroke: "#495d59" + font-color: "#c2cdca" + } +} + +n7: "N7 (Canvas)\n#121a19\nBackground" { + shape: rectangle + style: { + border-radius: 8 + fill: "#121a19" + stroke: "#495d59" + font-color: "#c2cdca" + } +} +``` + +### Neutrals - Option B: Pure Neutral Grays + +These are more traditional neutral grays without tint - more subtle and less themed. + +```d2 +vars: { + d2-config: { + theme-id: 0 + dark-theme-overrides: { + N7: "#121a19" + B1: "#495d59" + B2: "#495d59" + } + } +} + +direction: right + +n1_pure: "N1 (Lightest)\n#e8e8e8\nFor: Light text" { + shape: rectangle + style: { + border-radius: 8 + fill: "#e8e8e8" + stroke: "#495d59" + font-color: "#1a1a1a" + } +} + +n2_pure: "N2\n#c4c4c4\nFor: Borders" { + shape: rectangle + style: { + border-radius: 8 + fill: "#c4c4c4" + stroke: "#495d59" + font-color: "#1a1a1a" + } +} + +n3_pure: "N3\n#9a9a9a\nFor: Medium text" { + shape: rectangle + style: { + border-radius: 8 + fill: "#9a9a9a" + stroke: "#495d59" + font-color: "#1a1a1a" + } +} + +n4_pure: "N4\n#5a5a5a\nFor: Dark text" { + shape: rectangle + style: { + border-radius: 8 + fill: "#5a5a5a" + stroke: "#2a2a2a" + font-color: "#e8e8e8" + } +} + +n5_pure: "N5\n#3a3a3a\nFor: Subtle fills" { + shape: rectangle + style: { + border-radius: 8 + fill: "#3a3a3a" + stroke: "#5a5a5a" + font-color: "#c4c4c4" + } +} + +n6_pure: "N6\n#252525\nFor: Dark fills" { + shape: rectangle + style: { + border-radius: 8 + fill: "#252525" + stroke: "#5a5a5a" + font-color: "#c4c4c4" + } +} + +n7_pure: "N7 (Canvas)\n#121a19\nBackground" { + shape: rectangle + style: { + border-radius: 8 + fill: "#121a19" + stroke: "#5a5a5a" + font-color: "#c4c4c4" + } +} +``` + +### Complete State Machine - Using Option A (Teal-Tinted Neutrals) + +This diagram shows how neutrals are used for background elements, borders, and secondary nodes. + +```d2 +vars: { + d2-config: { + theme-id: 0 + dark-theme-overrides: { + # Canvas background (N7) + N7: "#121a19" + + # Neutrals for text and borders + N1: "#e7f0ee" + N2: "#c2cdca" + N3: "#92a8a3" + N4: "#495d59" + N5: "#2a3d39" + N6: "#182b28" + + # Edge colors + B1: "#495d59" + B2: "#495d59" + } + } +} + +direction: down + +# Main entry point - Primary teal +start: "Start Workflow" { + shape: rectangle + style: { + border-radius: 8 + fill: "#003b34" + stroke: "#00574d" + font-color: "#e7f0ee" + } +} + +# Input validation - Gray dark (N6 tint) +validate: "Validate Input" { + shape: rectangle + style: { + border-radius: 8 + fill: "#182b28" + stroke: "#495d59" + font-color: "#c2cdca" + } +} + +# Configuration check - Gray medium (N5 tint) +configure: "Load Config" { + shape: rectangle + style: { + border-radius: 8 + fill: "#2a3d39" + stroke: "#495d59" + font-color: "#c2cdca" + } +} + +# Authorization - Info blue +authorize: "Authorize" { + shape: rectangle + style: { + border-radius: 8 + fill: "#1a2947" + stroke: "#5c8dd6" + font-color: "#d4e3f7" + } +} + +# Primary processing - Teal medium +process: "Process Data" { + shape: rectangle + style: { + border-radius: 8 + fill: "#00574d" + stroke: "#007b6e" + font-color: "#e7f0ee" + } +} + +# Transform step - Teal base +transform: "Transform" { + shape: rectangle + style: { + border-radius: 8 + fill: "#007b6e" + stroke: "#00574d" + font-color: "#e7f0ee" + } +} + +# Quality check - Gray base (N4 tint) +quality_check: "Quality Check" { + shape: rectangle + style: { + border-radius: 8 + fill: "#495d59" + stroke: "#2a3d39" + font-color: "#e7f0ee" + } +} + +# Error state - Red dark +error: "Error Handler" { + shape: rectangle + style: { + border-radius: 8 + fill: "#4f1f1f" + stroke: "#e85c5c" + font-color: "#f7d1d1" + } +} + +# Warning state - Orange dark +warning: "Needs Review" { + shape: rectangle + style: { + border-radius: 8 + fill: "#4d3d2b" + stroke: "#d9a66e" + font-color: "#f5e8d6" + } +} + +# Retry logic - Purple highlight +retry: "Retry Logic" { + shape: rectangle + style: { + border-radius: 8 + fill: "#472952" + stroke: "#b77ddb" + font-color: "#ead9f5" + } +} + +# Success state - Green dark +success: "Success!" { + shape: rectangle + style: { + border-radius: 8 + fill: "#1a4136" + stroke: "#33cc7f" + font-color: "#99e6c0" + } +} + +# Notification - Light gray (N3 tint for less important) +notify: "Send Notification" { + shape: rectangle + style: { + border-radius: 8 + fill: "#92a8a3" + stroke: "#495d59" + font-color: "#182b28" + } +} + +# Cleanup - Very light gray (N2 tint for background tasks) +cleanup: "Cleanup" { + shape: rectangle + style: { + border-radius: 8 + fill: "#c2cdca" + stroke: "#495d59" + font-color: "#182b28" + } +} + +# Flow connections +start -> validate +validate -> configure +configure -> authorize +authorize -> process +process -> transform +transform -> quality_check +quality_check -> success: "Pass" +quality_check -> warning: "Minor issues" +quality_check -> error: "Failed" +warning -> retry +error -> retry +retry -> process: "Retry" +retry -> error: "Max retries" +success -> notify +notify -> cleanup +``` + +### Complete State Machine - Using Option B (Pure Neutral Grays) + +Same diagram with pure gray neutrals for comparison. + +```d2 +vars: { + d2-config: { + theme-id: 0 + dark-theme-overrides: { + # Canvas background (N7) + N7: "#121a19" + + # Pure neutral grays + N1: "#e8e8e8" + N2: "#c4c4c4" + N3: "#9a9a9a" + N4: "#5a5a5a" + N5: "#3a3a3a" + N6: "#252525" + + # Edge colors + B1: "#495d59" + B2: "#495d59" + } + } +} + +direction: down + +# Main entry point - Primary teal +start: "Start Workflow" { + shape: rectangle + style: { + border-radius: 8 + fill: "#003b34" + stroke: "#00574d" + font-color: "#e8e8e8" + } +} + +# Input validation - Gray dark (N6 pure) +validate: "Validate Input" { + shape: rectangle + style: { + border-radius: 8 + fill: "#252525" + stroke: "#5a5a5a" + font-color: "#c4c4c4" + } +} + +# Configuration check - Gray medium (N5 pure) +configure: "Load Config" { + shape: rectangle + style: { + border-radius: 8 + fill: "#3a3a3a" + stroke: "#5a5a5a" + font-color: "#c4c4c4" + } +} + +# Authorization - Info blue +authorize: "Authorize" { + shape: rectangle + style: { + border-radius: 8 + fill: "#1a2947" + stroke: "#5c8dd6" + font-color: "#d4e3f7" + } +} + +# Primary processing - Teal medium +process: "Process Data" { + shape: rectangle + style: { + border-radius: 8 + fill: "#00574d" + stroke: "#007b6e" + font-color: "#e8e8e8" + } +} + +# Transform step - Teal base +transform: "Transform" { + shape: rectangle + style: { + border-radius: 8 + fill: "#007b6e" + stroke: "#00574d" + font-color: "#e8e8e8" + } +} + +# Quality check - Gray base (N4 pure) +quality_check: "Quality Check" { + shape: rectangle + style: { + border-radius: 8 + fill: "#5a5a5a" + stroke: "#3a3a3a" + font-color: "#e8e8e8" + } +} + +# Error state - Red dark +error: "Error Handler" { + shape: rectangle + style: { + border-radius: 8 + fill: "#4f1f1f" + stroke: "#e85c5c" + font-color: "#f7d1d1" + } +} + +# Warning state - Orange dark +warning: "Needs Review" { + shape: rectangle + style: { + border-radius: 8 + fill: "#4d3d2b" + stroke: "#d9a66e" + font-color: "#f5e8d6" + } +} + +# Retry logic - Purple highlight +retry: "Retry Logic" { + shape: rectangle + style: { + border-radius: 8 + fill: "#472952" + stroke: "#b77ddb" + font-color: "#ead9f5" + } +} + +# Success state - Green dark +success: "Success!" { + shape: rectangle + style: { + border-radius: 8 + fill: "#1a4136" + stroke: "#33cc7f" + font-color: "#99e6c0" + } +} + +# Notification - Light gray (N3 pure for less important) +notify: "Send Notification" { + shape: rectangle + style: { + border-radius: 8 + fill: "#9a9a9a" + stroke: "#5a5a5a" + font-color: "#1a1a1a" + } +} + +# Cleanup - Very light gray (N2 pure for background tasks) +cleanup: "Cleanup" { + shape: rectangle + style: { + border-radius: 8 + fill: "#c4c4c4" + stroke: "#5a5a5a" + font-color: "#1a1a1a" + } +} + +# Flow connections +start -> validate +validate -> configure +configure -> authorize +authorize -> process +process -> transform +transform -> quality_check +quality_check -> success: "Pass" +quality_check -> warning: "Minor issues" +quality_check -> error: "Failed" +warning -> retry +error -> retry +retry -> process: "Retry" +retry -> error: "Max retries" +success -> notify +notify -> cleanup +``` + +## Color Palette Demo (Light Mode) + +```d2 +vars: { + d2-config: { + theme-id: 0 + theme-overrides: { + # Light mode canvas + N7: "#ffffff" + # Edge colors - using dark mode colors + B1: "#495d59" + B2: "#495d59" + } + } +} + +direction: down + +# Root node +root: "Color Palette" { + shape: rectangle + style: { + border-radius: 8 + fill: "#007b6e" + stroke: "#00574d" + font-color: "#ffffff" + } +} + +# Level 1: Teal variants (4 lanes start) +teal_dark: "Teal Dark\n#003b34" { + shape: rectangle + style: { + border-radius: 8 + fill: "#003b34" + stroke: "#00574d" + font-color: "#ffffff" + } +} + +teal_medium: "Teal Medium\n#00574d" { + shape: rectangle + style: { + border-radius: 8 + fill: "#00574d" + stroke: "#003b34" + font-color: "#ffffff" + } +} + +teal_base: "Teal Base\n#007b6e" { + shape: rectangle + style: { + border-radius: 8 + fill: "#007b6e" + stroke: "#00574d" + font-color: "#ffffff" + } +} + +teal_light: "Teal Light\n#bce0d9" { + shape: rectangle + style: { + border-radius: 8 + fill: "#bce0d9" + stroke: "#00574d" + font-color: "#003b34" + } +} + +# Connections from root to level 1 +root -> teal_dark +root -> teal_medium +root -> teal_base +root -> teal_light + +# Level 2: Blue variants +blue_dark: "Blue Dark\n#2d4f99" { + shape: rectangle + style: { + border-radius: 8 + fill: "#2d4f99" + stroke: "#4d7acc" + font-color: "#ffffff" + } +} + +blue_medium: "Blue Medium\n#4d7acc" { + shape: rectangle + style: { + border-radius: 8 + fill: "#4d7acc" + stroke: "#2d4f99" + font-color: "#ffffff" + } +} + +blue_base: "Blue Base\n#8faed9" { + shape: rectangle + style: { + border-radius: 8 + fill: "#8faed9" + stroke: "#4d7acc" + font-color: "#2d4f99" + } +} + +blue_light: "Blue Light\n#e0eaf7" { + shape: rectangle + style: { + border-radius: 8 + fill: "#e0eaf7" + stroke: "#4d7acc" + font-color: "#2d4f99" + } +} + +# Connections level 1 -> level 2 +teal_dark -> blue_dark +teal_medium -> blue_medium +teal_base -> blue_base +teal_light -> blue_light + +# Level 3: Green variants +green_dark: "Green Dark\n#1f7a54" { + shape: rectangle + style: { + border-radius: 8 + fill: "#1f7a54" + stroke: "#3db87a" + font-color: "#ffffff" + } +} + +green_medium: "Green Medium\n#3db87a" { + shape: rectangle + style: { + border-radius: 8 + fill: "#3db87a" + stroke: "#1f7a54" + font-color: "#ffffff" + } +} + +green_base: "Green Base\n#7dd9a8" { + shape: rectangle + style: { + border-radius: 8 + fill: "#7dd9a8" + stroke: "#3db87a" + font-color: "#1f7a54" + } +} + +green_light: "Green Light\n#e6f7ee" { + shape: rectangle + style: { + border-radius: 8 + fill: "#e6f7ee" + stroke: "#3db87a" + font-color: "#1f7a54" + } +} + +# Connections level 2 -> level 3 +blue_dark -> green_dark +blue_medium -> green_medium +blue_base -> green_base +blue_light -> green_light + +# Level 4: Purple variants +purple_dark: "Purple Dark\n#6e3a85" { + shape: rectangle + style: { + border-radius: 8 + fill: "#6e3a85" + stroke: "#a366bf" + font-color: "#ffffff" + } +} + +purple_medium: "Purple Medium\n#a366bf" { + shape: rectangle + style: { + border-radius: 8 + fill: "#a366bf" + stroke: "#6e3a85" + font-color: "#ffffff" + } +} + +purple_base: "Purple Base\n#d1aee0" { + shape: rectangle + style: { + border-radius: 8 + fill: "#d1aee0" + stroke: "#a366bf" + font-color: "#6e3a85" + } +} + +purple_light: "Purple Light\n#f2e8f7" { + shape: rectangle + style: { + border-radius: 8 + fill: "#f2e8f7" + stroke: "#a366bf" + font-color: "#6e3a85" + } +} + +# Connections level 3 -> level 4 +green_dark -> purple_dark +green_medium -> purple_medium +green_base -> purple_base +green_light -> purple_light + +# Level 5: Orange variants +orange_dark: "Orange Dark\n#995c2e" { + shape: rectangle + style: { + border-radius: 8 + fill: "#995c2e" + stroke: "#cc9366" + font-color: "#ffffff" + } +} + +orange_medium: "Orange Medium\n#cc9366" { + shape: rectangle + style: { + border-radius: 8 + fill: "#cc9366" + stroke: "#995c2e" + font-color: "#ffffff" + } +} + +orange_base: "Orange Base\n#e5c9a8" { + shape: rectangle + style: { + border-radius: 8 + fill: "#e5c9a8" + stroke: "#cc9366" + font-color: "#995c2e" + } +} + +orange_light: "Orange Light\n#f5ede0" { + shape: rectangle + style: { + border-radius: 8 + fill: "#f5ede0" + stroke: "#cc9366" + font-color: "#995c2e" + } +} + +# Connections level 4 -> level 5 +purple_dark -> orange_dark +purple_medium -> orange_medium +purple_base -> orange_base +purple_light -> orange_light + +# Level 6: Red variants +red_dark: "Red Dark\n#a12e2e" { + shape: rectangle + style: { + border-radius: 8 + fill: "#a12e2e" + stroke: "#d94d4d" + font-color: "#ffffff" + } +} + +red_medium: "Red Medium\n#d94d4d" { + shape: rectangle + style: { + border-radius: 8 + fill: "#d94d4d" + stroke: "#a12e2e" + font-color: "#ffffff" + } +} + +red_base: "Red Base\n#eba6a6" { + shape: rectangle + style: { + border-radius: 8 + fill: "#eba6a6" + stroke: "#d94d4d" + font-color: "#a12e2e" + } +} + +red_light: "Red Light\n#f7dede" { + shape: rectangle + style: { + border-radius: 8 + fill: "#f7dede" + stroke: "#d94d4d" + font-color: "#a12e2e" + } +} + +# Connections level 5 -> level 6 +orange_dark -> red_dark +orange_medium -> red_medium +orange_base -> red_base +orange_light -> red_light + +# Level 7: Gray variants +gray_dark: "Gray Dark\n#182b28" { + shape: rectangle + style: { + border-radius: 8 + fill: "#182b28" + stroke: "#2a3d39" + font-color: "#ffffff" + } +} + +gray_medium: "Gray Medium\n#495d59" { + shape: rectangle + style: { + border-radius: 8 + fill: "#495d59" + stroke: "#2a3d39" + font-color: "#ffffff" + } +} + +gray_base: "Gray Base\n#7c918d" { + shape: rectangle + style: { + border-radius: 8 + fill: "#7c918d" + stroke: "#495d59" + font-color: "#182b28" + } +} + +gray_light: "Gray Light\n#e7f0ee" { + shape: rectangle + style: { + border-radius: 8 + fill: "#e7f0ee" + stroke: "#7c918d" + font-color: "#182b28" + } +} + +# Connections level 6 -> level 7 +red_dark -> gray_dark +red_medium -> gray_medium +red_base -> gray_base +red_light -> gray_light +``` + +## Theme Selection: What We've Decided + +### Primary Node Colors (Default shapes) + +These are the main colors for regular nodes in your diagrams. + +```d2 +vars: { + d2-config: { + theme-id: 0 + dark-theme-overrides: { + N7: "#121a19" + B1: "#495d59" + B2: "#495d59" + } + } +} + +direction: right + +teal_dark: "Teal Dark\n#003b34\n(Main Default)" { + shape: rectangle + style: { + border-radius: 8 + fill: "#003b34" + stroke: "#00574d" + font-color: "#a3d4cb" + } +} + +teal_medium: "Teal Medium\n#00574d" { + shape: rectangle + style: { + border-radius: 8 + fill: "#00574d" + stroke: "#007b6e" + font-color: "#a3d4cb" + } +} + +teal_base: "Teal Base\n#007b6e" { + shape: rectangle + style: { + border-radius: 8 + fill: "#007b6e" + stroke: "#00574d" + font-color: "#e7f0ee" + } +} + +gray_dark: "Gray Dark\n#182b28" { + shape: rectangle + style: { + border-radius: 8 + fill: "#182b28" + stroke: "#495d59" + font-color: "#c2cdca" + } +} + +gray_medium: "Gray Medium\n#2a3d39" { + shape: rectangle + style: { + border-radius: 8 + fill: "#2a3d39" + stroke: "#495d59" + font-color: "#c2cdca" + } +} + +gray_base: "Gray Base\n#495d59" { + shape: rectangle + style: { + border-radius: 8 + fill: "#495d59" + stroke: "#2a3d39" + font-color: "#e7f0ee" + } +} +``` + +### Semantic Colors (Special meanings) + +These colors will be used for nodes with specific meanings. + +```d2 +vars: { + d2-config: { + theme-id: 0 + dark-theme-overrides: { + N7: "#121a19" + B1: "#495d59" + B2: "#495d59" + } + } +} + +direction: right + +success: "Success/Positive\nGreen Dark\n#1a4136" { + shape: rectangle + style: { + border-radius: 8 + fill: "#1a4136" + stroke: "#33cc7f" + font-color: "#99e6c0" + } +} + +error: "Error/Danger\nRed Dark\n#4f1f1f" { + shape: rectangle + style: { + border-radius: 8 + fill: "#4f1f1f" + stroke: "#e85c5c" + font-color: "#f7d1d1" + } +} + +warning: "Warning/Caution\nOrange Dark\n#4d3d2b" { + shape: rectangle + style: { + border-radius: 8 + fill: "#4d3d2b" + stroke: "#d9a66e" + font-color: "#f5e8d6" + } +} + +info: "Info/Note\nBlue Dark\n#1a2947" { + shape: rectangle + style: { + border-radius: 8 + fill: "#1a2947" + stroke: "#5c8dd6" + font-color: "#d4e3f7" + } +} + +highlight: "Special/Highlight\nPurple Dark\n#472952" { + shape: rectangle + style: { + border-radius: 8 + fill: "#472952" + stroke: "#b77ddb" + font-color: "#ead9f5" + } +} +``` + +## Theme Selection: What We Need to Decide + +### Neutrals - Option A: Teal-Tinted Grays + +These neutrals have a slight teal/green tint that harmonizes with the primary theme colors. + +```d2 +vars: { + d2-config: { + theme-id: 0 + dark-theme-overrides: { + N7: "#121a19" + B1: "#495d59" + B2: "#495d59" + } + } +} + +direction: right + +n1: "N1 (Lightest)\n#e7f0ee\nFor: Light text" { + shape: rectangle + style: { + border-radius: 8 + fill: "#e7f0ee" + stroke: "#495d59" + font-color: "#182b28" + } +} + +n2: "N2\n#c2cdca\nFor: Borders" { + shape: rectangle + style: { + border-radius: 8 + fill: "#c2cdca" + stroke: "#495d59" + font-color: "#182b28" + } +} + +n3: "N3\n#92a8a3\nFor: Medium text" { + shape: rectangle + style: { + border-radius: 8 + fill: "#92a8a3" + stroke: "#495d59" + font-color: "#182b28" + } +} + +n4: "N4\n#495d59\nFor: Dark text" { + shape: rectangle + style: { + border-radius: 8 + fill: "#495d59" + stroke: "#2a3d39" + font-color: "#e7f0ee" + } +} + +n5: "N5\n#2a3d39\nFor: Subtle fills" { + shape: rectangle + style: { + border-radius: 8 + fill: "#2a3d39" + stroke: "#495d59" + font-color: "#c2cdca" + } +} + +n6: "N6\n#182b28\nFor: Dark fills" { + shape: rectangle + style: { + border-radius: 8 + fill: "#182b28" + stroke: "#495d59" + font-color: "#c2cdca" + } +} + +n7: "N7 (Canvas)\n#121a19\nBackground" { + shape: rectangle + style: { + border-radius: 8 + fill: "#121a19" + stroke: "#495d59" + font-color: "#c2cdca" + } +} +``` + +### Neutrals - Option B: Pure Neutral Grays + +These are more traditional neutral grays without tint - more subtle and less themed. + +```d2 +vars: { + d2-config: { + theme-id: 0 + dark-theme-overrides: { + N7: "#121a19" + B1: "#495d59" + B2: "#495d59" + } + } +} + +direction: right + +n1_pure: "N1 (Lightest)\n#e8e8e8\nFor: Light text" { + shape: rectangle + style: { + border-radius: 8 + fill: "#e8e8e8" + stroke: "#495d59" + font-color: "#1a1a1a" + } +} + +n2_pure: "N2\n#c4c4c4\nFor: Borders" { + shape: rectangle + style: { + border-radius: 8 + fill: "#c4c4c4" + stroke: "#495d59" + font-color: "#1a1a1a" + } +} + +n3_pure: "N3\n#9a9a9a\nFor: Medium text" { + shape: rectangle + style: { + border-radius: 8 + fill: "#9a9a9a" + stroke: "#495d59" + font-color: "#1a1a1a" + } +} + +n4_pure: "N4\n#5a5a5a\nFor: Dark text" { + shape: rectangle + style: { + border-radius: 8 + fill: "#5a5a5a" + stroke: "#2a2a2a" + font-color: "#e8e8e8" + } +} + +n5_pure: "N5\n#3a3a3a\nFor: Subtle fills" { + shape: rectangle + style: { + border-radius: 8 + fill: "#3a3a3a" + stroke: "#5a5a5a" + font-color: "#c4c4c4" + } +} + +n6_pure: "N6\n#252525\nFor: Dark fills" { + shape: rectangle + style: { + border-radius: 8 + fill: "#252525" + stroke: "#5a5a5a" + font-color: "#c4c4c4" + } +} + +n7_pure: "N7 (Canvas)\n#121a19\nBackground" { + shape: rectangle + style: { + border-radius: 8 + fill: "#121a19" + stroke: "#5a5a5a" + font-color: "#c4c4c4" + } +} +``` + +### Complete State Machine - Using Option A (Teal-Tinted Neutrals) + +This diagram shows how neutrals are used for background elements, borders, and secondary nodes. + +```d2 +vars: { + d2-config: { + theme-id: 0 + dark-theme-overrides: { + # Canvas background (N7) + N7: "#121a19" + + # Neutrals for text and borders + N1: "#e7f0ee" + N2: "#c2cdca" + N3: "#92a8a3" + N4: "#495d59" + N5: "#2a3d39" + N6: "#182b28" + + # Edge colors + B1: "#495d59" + B2: "#495d59" + } + } +} + +direction: down + +# Main entry point - Primary teal +start: "Start Workflow" { + shape: rectangle + style: { + border-radius: 8 + fill: "#003b34" + stroke: "#00574d" + font-color: "#e7f0ee" + } +} + +# Input validation - Gray dark (N6 tint) +validate: "Validate Input" { + shape: rectangle + style: { + border-radius: 8 + fill: "#182b28" + stroke: "#495d59" + font-color: "#c2cdca" + } +} + +# Configuration check - Gray medium (N5 tint) +configure: "Load Config" { + shape: rectangle + style: { + border-radius: 8 + fill: "#2a3d39" + stroke: "#495d59" + font-color: "#c2cdca" + } +} + +# Authorization - Info blue +authorize: "Authorize" { + shape: rectangle + style: { + border-radius: 8 + fill: "#1a2947" + stroke: "#5c8dd6" + font-color: "#d4e3f7" + } +} + +# Primary processing - Teal medium +process: "Process Data" { + shape: rectangle + style: { + border-radius: 8 + fill: "#00574d" + stroke: "#007b6e" + font-color: "#e7f0ee" + } +} + +# Transform step - Teal base +transform: "Transform" { + shape: rectangle + style: { + border-radius: 8 + fill: "#007b6e" + stroke: "#00574d" + font-color: "#e7f0ee" + } +} + +# Quality check - Gray base (N4 tint) +quality_check: "Quality Check" { + shape: rectangle + style: { + border-radius: 8 + fill: "#495d59" + stroke: "#2a3d39" + font-color: "#e7f0ee" + } +} + +# Error state - Red dark +error: "Error Handler" { + shape: rectangle + style: { + border-radius: 8 + fill: "#4f1f1f" + stroke: "#e85c5c" + font-color: "#f7d1d1" + } +} + +# Warning state - Orange dark +warning: "Needs Review" { + shape: rectangle + style: { + border-radius: 8 + fill: "#4d3d2b" + stroke: "#d9a66e" + font-color: "#f5e8d6" + } +} + +# Retry logic - Purple highlight +retry: "Retry Logic" { + shape: rectangle + style: { + border-radius: 8 + fill: "#472952" + stroke: "#b77ddb" + font-color: "#ead9f5" + } +} + +# Success state - Green dark +success: "Success!" { + shape: rectangle + style: { + border-radius: 8 + fill: "#1a4136" + stroke: "#33cc7f" + font-color: "#99e6c0" + } +} + +# Notification - Light gray (N3 tint for less important) +notify: "Send Notification" { + shape: rectangle + style: { + border-radius: 8 + fill: "#92a8a3" + stroke: "#495d59" + font-color: "#182b28" + } +} + +# Cleanup - Very light gray (N2 tint for background tasks) +cleanup: "Cleanup" { + shape: rectangle + style: { + border-radius: 8 + fill: "#c2cdca" + stroke: "#495d59" + font-color: "#182b28" + } +} + +# Flow connections +start -> validate +validate -> configure +configure -> authorize +authorize -> process +process -> transform +transform -> quality_check +quality_check -> success: "Pass" +quality_check -> warning: "Minor issues" +quality_check -> error: "Failed" +warning -> retry +error -> retry +retry -> process: "Retry" +retry -> error: "Max retries" +success -> notify +notify -> cleanup +``` + +### Complete State Machine - Using Option B (Pure Neutral Grays) + +Same diagram with pure gray neutrals for comparison. + +```d2 +vars: { + d2-config: { + theme-id: 0 + dark-theme-overrides: { + # Canvas background (N7) + N7: "#121a19" + + # Pure neutral grays + N1: "#e8e8e8" + N2: "#c4c4c4" + N3: "#9a9a9a" + N4: "#5a5a5a" + N5: "#3a3a3a" + N6: "#252525" + + # Edge colors + B1: "#495d59" + B2: "#495d59" + } + } +} + +direction: down + +# Main entry point - Primary teal +start: "Start Workflow" { + shape: rectangle + style: { + border-radius: 8 + fill: "#003b34" + stroke: "#00574d" + font-color: "#e8e8e8" + } +} + +# Input validation - Gray dark (N6 pure) +validate: "Validate Input" { + shape: rectangle + style: { + border-radius: 8 + fill: "#252525" + stroke: "#5a5a5a" + font-color: "#c4c4c4" + } +} + +# Configuration check - Gray medium (N5 pure) +configure: "Load Config" { + shape: rectangle + style: { + border-radius: 8 + fill: "#3a3a3a" + stroke: "#5a5a5a" + font-color: "#c4c4c4" + } +} + +# Authorization - Info blue +authorize: "Authorize" { + shape: rectangle + style: { + border-radius: 8 + fill: "#1a2947" + stroke: "#5c8dd6" + font-color: "#d4e3f7" + } +} + +# Primary processing - Teal medium +process: "Process Data" { + shape: rectangle + style: { + border-radius: 8 + fill: "#00574d" + stroke: "#007b6e" + font-color: "#e8e8e8" + } +} + +# Transform step - Teal base +transform: "Transform" { + shape: rectangle + style: { + border-radius: 8 + fill: "#007b6e" + stroke: "#00574d" + font-color: "#e8e8e8" + } +} + +# Quality check - Gray base (N4 pure) +quality_check: "Quality Check" { + shape: rectangle + style: { + border-radius: 8 + fill: "#5a5a5a" + stroke: "#3a3a3a" + font-color: "#e8e8e8" + } +} + +# Error state - Red dark +error: "Error Handler" { + shape: rectangle + style: { + border-radius: 8 + fill: "#4f1f1f" + stroke: "#e85c5c" + font-color: "#f7d1d1" + } +} + +# Warning state - Orange dark +warning: "Needs Review" { + shape: rectangle + style: { + border-radius: 8 + fill: "#4d3d2b" + stroke: "#d9a66e" + font-color: "#f5e8d6" + } +} + +# Retry logic - Purple highlight +retry: "Retry Logic" { + shape: rectangle + style: { + border-radius: 8 + fill: "#472952" + stroke: "#b77ddb" + font-color: "#ead9f5" + } +} + +# Success state - Green dark +success: "Success!" { + shape: rectangle + style: { + border-radius: 8 + fill: "#1a4136" + stroke: "#33cc7f" + font-color: "#99e6c0" + } +} + +# Notification - Light gray (N3 pure for less important) +notify: "Send Notification" { + shape: rectangle + style: { + border-radius: 8 + fill: "#9a9a9a" + stroke: "#5a5a5a" + font-color: "#1a1a1a" + } +} + +# Cleanup - Very light gray (N2 pure for background tasks) +cleanup: "Cleanup" { + shape: rectangle + style: { + border-radius: 8 + fill: "#c4c4c4" + stroke: "#5a5a5a" + font-color: "#1a1a1a" + } +} + +# Flow connections +start -> validate +validate -> configure +configure -> authorize +authorize -> process +process -> transform +transform -> quality_check +quality_check -> success: "Pass" +quality_check -> warning: "Minor issues" +quality_check -> error: "Failed" +warning -> retry +error -> retry +retry -> process: "Retry" +retry -> error: "Max retries" +success -> notify +notify -> cleanup +``` diff --git a/pkgs/website/src/diagrams/test.d2 b/pkgs/website/src/diagrams/test.d2 new file mode 100644 index 000000000..e59521063 --- /dev/null +++ b/pkgs/website/src/diagrams/test.d2 @@ -0,0 +1,16 @@ +direction: down + +# Simple workflow - theme applied automatically! +start: "Start Workflow" +validate: "Validate Input" +process: "Process Data" +transform: "Transform Results" +save: "Save to Database" +success: "Complete" + +# Flow connections +start -> validate +validate -> process +process -> transform +transform -> save +save -> success diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 75a7c5dc7..774bb83cd 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -373,6 +373,9 @@ importers: astro: specifier: ^5.7.14 version: 5.12.4(@types/node@18.16.20)(jiti@2.4.2)(less@4.1.3)(stylus@0.64.0)(typescript@5.8.3) + astro-d2: + specifier: ^0.8.0 + version: 0.8.0(astro@5.12.4) astro-robots-txt: specifier: ^1.0.0 version: 1.0.0 @@ -10006,6 +10009,18 @@ packages: hasBin: true dev: false + /astro-d2@0.8.0(astro@5.12.4): + resolution: {integrity: sha512-vs1crOjTmYeQg+kHUymB8AhcmFRZyiQBuK1bsuMoTbX1upX3ljhny8DdvOWoiEVUBQAwlUojjwO5bB8tRo8hCw==} + engines: {node: '>=18'} + peerDependencies: + astro: '>=5.0.0' + dependencies: + astro: 5.12.4(@types/node@18.16.20)(jiti@2.4.2)(less@4.1.3)(stylus@0.64.0)(typescript@5.8.3) + hast-util-from-html: 2.0.3 + hast-util-to-html: 9.0.5 + unist-util-visit: 5.0.0 + dev: false + /astro-expressive-code@0.41.3(astro@5.12.4): resolution: {integrity: sha512-u+zHMqo/QNLE2eqYRCrK3+XMlKakv33Bzuz+56V1gs8H0y6TZ0hIi3VNbIxeTn51NLn+mJfUV/A0kMNfE4rANw==} peerDependencies: