kitfly 0.2.1 → 0.2.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +79 -0
- package/README.md +38 -21
- package/VERSION +1 -1
- package/dist/_raw/content/guide/branding.md +146 -0
- package/dist/_raw/content/guide/data-driven-content.md +204 -0
- package/dist/_raw/content/reference/configuration.md +145 -7
- package/dist/_raw/content/reference/environment-variables.md +26 -1
- package/dist/_raw/content/reference/gantt-widget.md +468 -0
- package/dist/_raw/content/reference/glossary.md +25 -1
- package/dist/_raw/content/reference/key-concepts.md +30 -2
- package/dist/_raw/content/reference/plugins.md +170 -1
- package/dist/_raw/docs/decisions/ADR-0006-data-driven-content.md +350 -0
- package/dist/content/deployment/preflight.html +11 -8
- package/dist/content/deployment/recipes/aws-s3.html +11 -8
- package/dist/content/deployment/recipes/cloudflare-pages.html +11 -8
- package/dist/content/deployment/recipes/cloudflare-r2.html +11 -8
- package/dist/content/deployment/recipes/fly-io.html +11 -8
- package/dist/content/deployment/recipes/github-pages.html +11 -8
- package/dist/content/deployment/recipes/netlify.html +11 -8
- package/dist/content/deployment/recipes/vercel.html +11 -8
- package/dist/content/deployment/secrets-and-env-vars.html +11 -8
- package/dist/content/deployment.html +11 -8
- package/dist/content/guide/approaches.html +11 -8
- package/dist/content/guide/branding.html +509 -0
- package/dist/content/guide/data-driven-content.html +542 -0
- package/dist/content/guide/features.html +11 -8
- package/dist/content/guide/getting-started.html +11 -8
- package/dist/content/guide/kitfly-overview.html +11 -8
- package/dist/content/reference/configuration.html +136 -11
- package/dist/content/reference/design-catalog.html +11 -8
- package/dist/content/reference/environment-variables.html +51 -10
- package/dist/content/reference/gantt-widget.html +899 -0
- package/dist/content/reference/glossary.html +25 -10
- package/dist/content/reference/key-concepts.html +34 -11
- package/dist/content/reference/plugins.html +261 -10
- package/dist/content/reference/slides-authoring-guidelines.html +11 -8
- package/dist/content/reference/structure.html +11 -8
- package/dist/content/reference.html +11 -8
- package/dist/content/templates/crucible.html +11 -8
- package/dist/content/templates/handbook.html +11 -8
- package/dist/content/templates/minimal.html +11 -8
- package/dist/content/templates/overview.html +11 -8
- package/dist/content/templates/pipeline.html +11 -8
- package/dist/content/templates/productbook.html +11 -8
- package/dist/content/templates/runbook.html +11 -8
- package/dist/content/templates/servicebook.html +11 -8
- package/dist/content-index.json +37 -2
- package/dist/docs/decisions/ADR-0001-minimalist-site-code.html +11 -8
- package/dist/docs/decisions/ADR-0002-ai-accessibility.html +11 -8
- package/dist/docs/decisions/ADR-0003-single-file-bundle.html +11 -8
- package/dist/docs/decisions/ADR-0004-bun-runtime.html +11 -8
- package/dist/docs/decisions/ADR-0005-plugin-contract-and-distribution.html +11 -8
- package/dist/docs/decisions/ADR-0006-data-driven-content.html +751 -0
- package/dist/docs/decisions/DDR-0001-viewport-locked-layout.html +11 -8
- package/dist/docs/decisions/DDR-0002-theme-system.html +11 -8
- package/dist/docs/decisions/DDR-0003-bounded-logo-slot.html +11 -8
- package/dist/docs/decisions/DDR-0004-slides-rendering-model.html +11 -8
- package/dist/docs/decisions/DDR-0005-deterministic-layout-boundary.html +11 -8
- package/dist/docs/userguide/cli/build.html +11 -8
- package/dist/docs/userguide/cli/bundle.html +11 -8
- package/dist/docs/userguide/cli/dev.html +11 -8
- package/dist/docs/userguide/cli/init.html +11 -8
- package/dist/docs/userguide/cli/servers.html +11 -8
- package/dist/docs/userguide/cli/stop.html +11 -8
- package/dist/docs/userguide/cli/update.html +11 -8
- package/dist/docs/userguide/cli/version.html +11 -8
- package/dist/docs/userguide/cli.html +11 -8
- package/dist/docs/userguide/sharing.html +11 -8
- package/dist/index.html +11 -8
- package/dist/llms.txt +3 -3
- package/dist/provenance.json +4 -5
- package/dist/reports/license-inventory.csv +199 -0
- package/dist/schemas/plugin-registry.schema.html +11 -8
- package/dist/schemas/plugin-schemas-notes.html +11 -8
- package/dist/schemas/plugin.schema.html +11 -8
- package/dist/schemas/plugins.schema.html +11 -8
- package/dist/schemas/v0/common.schema.html +15 -12
- package/dist/schemas/v0/plugin-registry.schema.html +14 -11
- package/dist/schemas/v0/plugin.schema.html +14 -11
- package/dist/schemas/v0/plugins.schema.html +14 -11
- package/dist/schemas/v0/site.schema.html +68 -9
- package/dist/schemas/v0/theme.schema.html +22 -19
- package/dist/schemas.html +11 -8
- package/dist/styles.css +39 -4
- package/package.json +1 -1
- package/plugins-dist/latex-runtime.js +140 -0
- package/plugins-dist/latex.js +178 -0
- package/plugins-dist/planning-visuals.css +261 -0
- package/plugins-dist/planning-visuals.js +669 -0
- package/plugins-dist/slides-charts-lite-runtime.js +179 -0
- package/plugins-dist/slides-charts-lite.js +198 -0
- package/registry/plugins.yaml +40 -1
- package/schemas/v0/site.schema.json +56 -0
- package/scripts/build-all.ts +5 -0
- package/scripts/build.ts +264 -80
- package/scripts/bundle.ts +188 -17
- package/scripts/dev.ts +294 -171
- package/scripts/embed-docs.ts +119 -0
- package/src/__tests__/brief.test.ts +151 -0
- package/src/__tests__/build.test.ts +293 -1
- package/src/__tests__/bundle.test.ts +195 -0
- package/src/__tests__/docs.test.ts +117 -0
- package/src/__tests__/fixtures/fences/planning-visuals/invalid/bad-month-format.md +10 -0
- package/src/__tests__/fixtures/fences/planning-visuals/invalid/marker-format-mismatch.md +13 -0
- package/src/__tests__/fixtures/fences/planning-visuals/invalid/milestone-format-mismatch.md +13 -0
- package/src/__tests__/fixtures/fences/planning-visuals/invalid/missing-tracks.md +5 -0
- package/src/__tests__/fixtures/fences/planning-visuals/invalid/track-reversed.md +10 -0
- package/src/__tests__/fixtures/fences/planning-visuals/valid/markers-basic.md +15 -0
- package/src/__tests__/fixtures/fences/planning-visuals/valid/markers-no-milestones.md +13 -0
- package/src/__tests__/fixtures/fences/planning-visuals/valid/month-basic.md +16 -0
- package/src/__tests__/fixtures/fences/planning-visuals/valid/no-milestones.md +10 -0
- package/src/__tests__/fixtures/fences/planning-visuals/valid/week-basic.md +20 -0
- package/src/__tests__/init.test.ts +51 -2
- package/src/__tests__/latex-runtime.bun.test.ts +35 -0
- package/src/__tests__/planning-visuals-fence-contract.test.ts +28 -0
- package/src/__tests__/planning-visuals-runtime-regressions.bun.test.ts +68 -0
- package/src/__tests__/planning-visuals-runtime.bun.test.ts +192 -0
- package/src/__tests__/shared.test.ts +719 -1
- package/src/__tests__/slides-charts-lite-runtime.bun.test.ts +45 -0
- package/src/cli.ts +124 -22
- package/src/commands/docs.ts +71 -0
- package/src/commands/init.ts +1 -1
- package/src/generated/embedded-docs.ts +2384 -0
- package/src/server-registry.ts +50 -10
- package/src/shared.ts +1174 -43
- package/src/site/styles.css +39 -4
- package/src/site/template.html +5 -2
- package/src/templates/brief.ts +486 -0
- package/src/templates/deck.ts +59 -0
- package/src/templates/driver.ts +46 -13
- package/src/templates/handbook.ts +32 -0
- package/src/templates/runbook.ts +32 -0
|
@@ -0,0 +1,899 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
+
<title>Gantt Widget Examples - Kitfly Docs</title>
|
|
7
|
+
<link rel="icon" type="image/png" sizes="32x32" href="../../assets/brand/kitfly-favicon-32.png">
|
|
8
|
+
<link rel="icon" type="image/png" sizes="64x64" href="../../assets/brand/kitfly-neon-256.png">
|
|
9
|
+
<link rel="stylesheet" href="../../styles.css">
|
|
10
|
+
<style id="kitfly-theme">
|
|
11
|
+
:root { --color-bg: #ffffff;
|
|
12
|
+
--color-bg-sidebar: #f5f7f8;
|
|
13
|
+
--color-text: #374151;
|
|
14
|
+
--color-text-muted: #6b7280;
|
|
15
|
+
--color-border: #e5e7eb;
|
|
16
|
+
--color-link: #007182;
|
|
17
|
+
--color-link-hover: #0a6172;
|
|
18
|
+
--color-accent: #152F46;
|
|
19
|
+
--color-code-bg: #f5f7f8;
|
|
20
|
+
--color-logo: #152F46;
|
|
21
|
+
--sidebar-width: 280px;
|
|
22
|
+
--font-sans: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
|
|
23
|
+
--font-headings: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
|
|
24
|
+
--font-mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace; }
|
|
25
|
+
html { font-size: 16px; }
|
|
26
|
+
@media (prefers-color-scheme: dark) {
|
|
27
|
+
:root:not([data-theme="light"]) { --color-bg: #0d1117;
|
|
28
|
+
--color-bg-sidebar: #152F46;
|
|
29
|
+
--color-text: #e5e7eb;
|
|
30
|
+
--color-text-muted: #9ca3af;
|
|
31
|
+
--color-border: #374151;
|
|
32
|
+
--color-link: #709EA6;
|
|
33
|
+
--color-link-hover: #8fb5bc;
|
|
34
|
+
--color-accent: #f9fafb;
|
|
35
|
+
--color-code-bg: #152F46;
|
|
36
|
+
--color-logo: #f9fafb; }
|
|
37
|
+
}
|
|
38
|
+
[data-theme="dark"] { --color-bg: #0d1117;
|
|
39
|
+
--color-bg-sidebar: #152F46;
|
|
40
|
+
--color-text: #e5e7eb;
|
|
41
|
+
--color-text-muted: #9ca3af;
|
|
42
|
+
--color-border: #374151;
|
|
43
|
+
--color-link: #709EA6;
|
|
44
|
+
--color-link-hover: #8fb5bc;
|
|
45
|
+
--color-accent: #f9fafb;
|
|
46
|
+
--color-code-bg: #152F46;
|
|
47
|
+
--color-logo: #f9fafb; }
|
|
48
|
+
[data-theme="light"] { --color-bg: #ffffff;
|
|
49
|
+
--color-bg-sidebar: #f5f7f8;
|
|
50
|
+
--color-text: #374151;
|
|
51
|
+
--color-text-muted: #6b7280;
|
|
52
|
+
--color-border: #e5e7eb;
|
|
53
|
+
--color-link: #007182;
|
|
54
|
+
--color-link-hover: #0a6172;
|
|
55
|
+
--color-accent: #152F46;
|
|
56
|
+
--color-code-bg: #f5f7f8;
|
|
57
|
+
--color-logo: #152F46;
|
|
58
|
+
--sidebar-width: 280px;
|
|
59
|
+
--font-sans: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
|
|
60
|
+
--font-headings: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
|
|
61
|
+
--font-mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace; }
|
|
62
|
+
</style>
|
|
63
|
+
<!-- Syntax highlighting - Prism.js -->
|
|
64
|
+
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/prismjs@1/themes/prism.min.css" id="prism-light">
|
|
65
|
+
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/prismjs@1/themes/prism-okaidia.min.css" id="prism-dark" disabled>
|
|
66
|
+
|
|
67
|
+
<script>
|
|
68
|
+
// Apply saved theme immediately to prevent flash
|
|
69
|
+
(function() {
|
|
70
|
+
const saved = localStorage.getItem('theme');
|
|
71
|
+
if (saved) {
|
|
72
|
+
document.documentElement.setAttribute('data-theme', saved);
|
|
73
|
+
}
|
|
74
|
+
// Set Prism theme based on saved or system preference
|
|
75
|
+
const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
|
|
76
|
+
const isDark = saved === 'dark' || (!saved && prefersDark);
|
|
77
|
+
if (isDark) {
|
|
78
|
+
document.getElementById('prism-light')?.setAttribute('disabled', '');
|
|
79
|
+
document.getElementById('prism-dark')?.removeAttribute('disabled');
|
|
80
|
+
}
|
|
81
|
+
})();
|
|
82
|
+
</script>
|
|
83
|
+
</head>
|
|
84
|
+
<body class="mode-docs">
|
|
85
|
+
<div class="mobile-header">
|
|
86
|
+
<button class="nav-toggle" onclick="toggleNav()" aria-label="Toggle navigation">
|
|
87
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
88
|
+
<path d="M3 12h18M3 6h18M3 18h18"/>
|
|
89
|
+
</svg>
|
|
90
|
+
</button>
|
|
91
|
+
<a href="../../" class="mobile-logo" title="Home" data-initial="K">
|
|
92
|
+
<img src="../../assets/brand/kitfly-neon-256.png" alt="Kitfly" class="logo-img logo-icon" onerror="this.onerror=null;this.style.display='none';this.parentElement.classList.add('logo-fallback')">
|
|
93
|
+
</a>
|
|
94
|
+
<button class="mobile-theme-toggle" onclick="toggleTheme()" title="Toggle theme" aria-label="Toggle theme">
|
|
95
|
+
<svg class="icon-sun" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
96
|
+
<circle cx="12" cy="12" r="5"/>
|
|
97
|
+
<path d="M12 1v2M12 21v2M4.22 4.22l1.42 1.42M18.36 18.36l1.42 1.42M1 12h2M21 12h2M4.22 19.78l1.42-1.42M18.36 5.64l1.42-1.42"/>
|
|
98
|
+
</svg>
|
|
99
|
+
<svg class="icon-moon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
100
|
+
<path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"/>
|
|
101
|
+
</svg>
|
|
102
|
+
</button>
|
|
103
|
+
</div>
|
|
104
|
+
<div class="layout">
|
|
105
|
+
<nav class="sidebar">
|
|
106
|
+
<div class="sidebar-header">
|
|
107
|
+
<div class="logo logo-icon">
|
|
108
|
+
<a href="/" class="logo-icon" data-initial="K">
|
|
109
|
+
<img src="../../assets/brand/kitfly-neon-256.png" alt="Kitfly" class="logo-img" onerror="this.onerror=null;this.style.display='none';this.parentElement.classList.add('logo-fallback')">
|
|
110
|
+
</a>
|
|
111
|
+
<span class="logo-text">
|
|
112
|
+
<a href="/" class="brand">Kitfly</a>
|
|
113
|
+
<a href="../../" class="product">Kitfly Docs</a>
|
|
114
|
+
</span>
|
|
115
|
+
</div>
|
|
116
|
+
<div class="header-tools">
|
|
117
|
+
<button class="theme-toggle" onclick="toggleTheme()" title="Toggle theme" aria-label="Toggle theme">
|
|
118
|
+
<svg class="icon-sun" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
119
|
+
<circle cx="12" cy="12" r="5"/>
|
|
120
|
+
<path d="M12 1v2M12 21v2M4.22 4.22l1.42 1.42M18.36 18.36l1.42 1.42M1 12h2M21 12h2M4.22 19.78l1.42-1.42M18.36 5.64l1.42-1.42"/>
|
|
121
|
+
</svg>
|
|
122
|
+
<svg class="icon-moon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
123
|
+
<path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"/>
|
|
124
|
+
</svg>
|
|
125
|
+
</button>
|
|
126
|
+
<div class="sidebar-meta">
|
|
127
|
+
<span class="meta-version">unversioned</span>
|
|
128
|
+
<span class="meta-branch">main</span>
|
|
129
|
+
</div>
|
|
130
|
+
</div>
|
|
131
|
+
</div>
|
|
132
|
+
<div class="sidebar-nav">
|
|
133
|
+
<ul><li><a href="../../index.html" class="nav-home">Home</a></li><li><span class="nav-section">Guide</span><ul><li><a href="../../content/guide/approaches.html">approaches</a></li><li><a href="../../content/guide/branding.html">branding</a></li><li><a href="../../content/guide/data-driven-content.html">data-driven-content</a></li><li><a href="../../content/guide/features.html">features</a></li><li><a href="../../content/guide/getting-started.html">getting-started</a></li><li><a href="../../content/guide/kitfly-overview.html">kitfly-overview</a></li></ul></li><li><span class="nav-section">Templates</span><ul><li><a href="../../content/templates/crucible.html">crucible</a></li><li><a href="../../content/templates/handbook.html">handbook</a></li><li><a href="../../content/templates/minimal.html">minimal</a></li><li><a href="../../content/templates/overview.html">overview</a></li><li><a href="../../content/templates/pipeline.html">pipeline</a></li><li><a href="../../content/templates/productbook.html">productbook</a></li><li><a href="../../content/templates/runbook.html">runbook</a></li><li><a href="../../content/templates/servicebook.html">servicebook</a></li></ul></li><li><a href="../../content/reference.html" class="nav-section">Reference</a><ul><li><a href="../../content/reference/configuration.html">configuration</a></li><li><a href="../../content/reference/design-catalog.html">design-catalog</a></li><li><a href="../../content/reference/environment-variables.html">environment-variables</a></li><li><a href="../../content/reference/gantt-widget.html" class="active">gantt-widget</a></li><li><a href="../../content/reference/glossary.html">glossary</a></li><li><a href="../../content/reference/key-concepts.html">key-concepts</a></li><li><a href="../../content/reference/plugins.html">plugins</a></li><li><a href="../../content/reference/slides-authoring-guidelines.html">slides-authoring-guidelines</a></li><li><a href="../../content/reference/structure.html">structure</a></li></ul></li><li><a href="../../content/deployment.html" class="nav-section">Deployment</a><ul><li><a href="../../content/deployment/preflight.html">preflight</a></li><li><details><summary class="nav-group">recipes</summary><ul><li><a href="../../content/deployment/recipes/aws-s3.html">aws-s3</a></li><li><a href="../../content/deployment/recipes/cloudflare-pages.html">cloudflare-pages</a></li><li><a href="../../content/deployment/recipes/cloudflare-r2.html">cloudflare-r2</a></li><li><a href="../../content/deployment/recipes/fly-io.html">fly-io</a></li><li><a href="../../content/deployment/recipes/github-pages.html">github-pages</a></li><li><a href="../../content/deployment/recipes/netlify.html">netlify</a></li><li><a href="../../content/deployment/recipes/vercel.html">vercel</a></li></ul></details></li><li><a href="../../content/deployment/secrets-and-env-vars.html">secrets-and-env-vars</a></li></ul></li><li><span class="nav-section">User Guide</span><ul><li><details><summary class="nav-group"><a href="../../docs/userguide/cli.html">cli</a></summary><ul><li><a href="../../docs/userguide/cli/build.html">build</a></li><li><a href="../../docs/userguide/cli/bundle.html">bundle</a></li><li><a href="../../docs/userguide/cli/dev.html">dev</a></li><li><a href="../../docs/userguide/cli/init.html">init</a></li><li><a href="../../docs/userguide/cli/servers.html">servers</a></li><li><a href="../../docs/userguide/cli/stop.html">stop</a></li><li><a href="../../docs/userguide/cli/update.html">update</a></li><li><a href="../../docs/userguide/cli/version.html">version</a></li></ul></details></li><li><a href="../../docs/userguide/sharing.html">sharing</a></li></ul></li><li><span class="nav-section">Decisions</span><ul><li><a href="../../docs/decisions/ADR-0001-minimalist-site-code.html">ADR-0001-minimalist-site-code</a></li><li><a href="../../docs/decisions/ADR-0002-ai-accessibility.html">ADR-0002-ai-accessibility</a></li><li><a href="../../docs/decisions/ADR-0003-single-file-bundle.html">ADR-0003-single-file-bundle</a></li><li><a href="../../docs/decisions/ADR-0004-bun-runtime.html">ADR-0004-bun-runtime</a></li><li><a href="../../docs/decisions/ADR-0005-plugin-contract-and-distribution.html">ADR-0005-plugin-contract-and-distribution</a></li><li><a href="../../docs/decisions/ADR-0006-data-driven-content.html">ADR-0006-data-driven-content</a></li><li><a href="../../docs/decisions/DDR-0001-viewport-locked-layout.html">DDR-0001-viewport-locked-layout</a></li><li><a href="../../docs/decisions/DDR-0002-theme-system.html">DDR-0002-theme-system</a></li><li><a href="../../docs/decisions/DDR-0003-bounded-logo-slot.html">DDR-0003-bounded-logo-slot</a></li><li><a href="../../docs/decisions/DDR-0004-slides-rendering-model.html">DDR-0004-slides-rendering-model</a></li><li><a href="../../docs/decisions/DDR-0005-deterministic-layout-boundary.html">DDR-0005-deterministic-layout-boundary</a></li></ul></li><li><a href="../../schemas.html" class="nav-section">Schemas</a><ul><li><a href="../../schemas/plugin-registry.schema.html">plugin-registry.schema</a></li><li><a href="../../schemas/plugin-schemas-notes.html">plugin-schemas-notes</a></li><li><a href="../../schemas/plugin.schema.html">plugin.schema</a></li><li><a href="../../schemas/plugins.schema.html">plugins.schema</a></li><li><details><summary class="nav-group">v0</summary><ul><li><a href="../../schemas/v0/common.schema.html">common.schema</a></li><li><a href="../../schemas/v0/plugin-registry.schema.html">plugin-registry.schema</a></li><li><a href="../../schemas/v0/plugin.schema.html">plugin.schema</a></li><li><a href="../../schemas/v0/plugins.schema.html">plugins.schema</a></li><li><a href="../../schemas/v0/site.schema.html">site.schema</a></li><li><a href="../../schemas/v0/theme.schema.html">theme.schema</a></li></ul></details></li></ul></li></ul>
|
|
134
|
+
</div>
|
|
135
|
+
</nav>
|
|
136
|
+
<main class="content">
|
|
137
|
+
<article class="prose">
|
|
138
|
+
<nav class="breadcrumbs"><a href="../../content/guide/approaches.html">Content</a><span class="separator">›</span><a href="../../content/reference/configuration.html">Reference</a><span class="separator">›</span><span>gantt-widget</span></nav>
|
|
139
|
+
<div class="page-meta">Last updated: 2026-03-06</div>
|
|
140
|
+
<h1 id="gantt-widget-examples">Gantt Widget Examples</h1>
|
|
141
|
+
<p>The <code>:::gantt</code> widget renders a horizontal bar chart on a shared time axis. It ships in the <code>planning-visuals</code> plugin and works in both docs and slides mode.</p>
|
|
142
|
+
<p>Enable the plugin in <code>kitfly.plugins.yaml</code>:</p>
|
|
143
|
+
<pre><code class="language-yaml">plugins:
|
|
144
|
+
- planning-visuals@0.2.4
|
|
145
|
+
</code></pre>
|
|
146
|
+
<h2 id="minimal-example-week">Minimal example (week)</h2>
|
|
147
|
+
<p>The smallest valid gantt — three required fields plus at least one track:</p>
|
|
148
|
+
<pre><code class="language-markdown">:::gantt
|
|
149
|
+
time-unit: week
|
|
150
|
+
time-start: "2026-W20"
|
|
151
|
+
time-end: "2026-W28"
|
|
152
|
+
tracks:
|
|
153
|
+
|
|
154
|
+
- label: "Sprint 1"
|
|
155
|
+
depth: 1
|
|
156
|
+
start: "2026-W20"
|
|
157
|
+
end: "2026-W23"
|
|
158
|
+
- label: "Sprint 2"
|
|
159
|
+
depth: 1
|
|
160
|
+
start: "2026-W24"
|
|
161
|
+
end: "2026-W28"
|
|
162
|
+
:::
|
|
163
|
+
</code></pre>
|
|
164
|
+
<p>No label, no milestones, no today marker — all optional. Tracks default to <code>status: planned</code> (muted/gray bars).</p>
|
|
165
|
+
<h2 id="minimal-example-month">Minimal example (month)</h2>
|
|
166
|
+
<p>Same structure, different time unit. Dates use <code>YYYY-MM</code> format:</p>
|
|
167
|
+
<pre><code class="language-markdown">:::gantt
|
|
168
|
+
time-unit: month
|
|
169
|
+
time-start: "2026-06"
|
|
170
|
+
time-end: "2026-12"
|
|
171
|
+
tracks:
|
|
172
|
+
|
|
173
|
+
- label: "Discovery"
|
|
174
|
+
depth: 1
|
|
175
|
+
start: "2026-06"
|
|
176
|
+
end: "2026-08"
|
|
177
|
+
- label: "Build"
|
|
178
|
+
depth: 1
|
|
179
|
+
start: "2026-09"
|
|
180
|
+
end: "2026-12"
|
|
181
|
+
:::
|
|
182
|
+
</code></pre>
|
|
183
|
+
<p>Month mode is natural for business audiences — no ISO week numbers to decode.</p>
|
|
184
|
+
<h2 id="status-colors">Status colors</h2>
|
|
185
|
+
<p>Four statuses control bar color. Use them to show progress at a glance:</p>
|
|
186
|
+
<pre><code class="language-markdown">:::gantt
|
|
187
|
+
label: "Status Reference"
|
|
188
|
+
time-unit: week
|
|
189
|
+
time-start: "2026-W14"
|
|
190
|
+
time-end: "2026-W26"
|
|
191
|
+
tracks:
|
|
192
|
+
|
|
193
|
+
- label: "Completed work"
|
|
194
|
+
depth: 1
|
|
195
|
+
start: "2026-W14"
|
|
196
|
+
end: "2026-W17"
|
|
197
|
+
status: complete
|
|
198
|
+
- label: "In progress"
|
|
199
|
+
depth: 1
|
|
200
|
+
start: "2026-W18"
|
|
201
|
+
end: "2026-W21"
|
|
202
|
+
status: active
|
|
203
|
+
- label: "Waiting on vendor"
|
|
204
|
+
depth: 1
|
|
205
|
+
start: "2026-W19"
|
|
206
|
+
end: "2026-W23"
|
|
207
|
+
status: blocked
|
|
208
|
+
- label: "Not started"
|
|
209
|
+
depth: 1
|
|
210
|
+
start: "2026-W22"
|
|
211
|
+
end: "2026-W26"
|
|
212
|
+
status: planned
|
|
213
|
+
:::
|
|
214
|
+
</code></pre>
|
|
215
|
+
<table>
|
|
216
|
+
<thead>
|
|
217
|
+
<tr>
|
|
218
|
+
<th>Status</th>
|
|
219
|
+
<th>Color</th>
|
|
220
|
+
<th>Use for</th>
|
|
221
|
+
</tr>
|
|
222
|
+
</thead>
|
|
223
|
+
<tbody><tr>
|
|
224
|
+
<td><code>complete</code></td>
|
|
225
|
+
<td>Green</td>
|
|
226
|
+
<td>Done, signed off</td>
|
|
227
|
+
</tr>
|
|
228
|
+
<tr>
|
|
229
|
+
<td><code>active</code></td>
|
|
230
|
+
<td>Accent/blue</td>
|
|
231
|
+
<td>Currently in progress</td>
|
|
232
|
+
</tr>
|
|
233
|
+
<tr>
|
|
234
|
+
<td><code>blocked</code></td>
|
|
235
|
+
<td>Amber/orange</td>
|
|
236
|
+
<td>Waiting, at risk</td>
|
|
237
|
+
</tr>
|
|
238
|
+
<tr>
|
|
239
|
+
<td><code>planned</code></td>
|
|
240
|
+
<td>Muted/gray</td>
|
|
241
|
+
<td>Not started (default)</td>
|
|
242
|
+
</tr>
|
|
243
|
+
</tbody></table>
|
|
244
|
+
<p>All colors adapt to dark mode automatically.</p>
|
|
245
|
+
<h2 id="hierarchy-and-depth-filtering">Hierarchy and depth filtering</h2>
|
|
246
|
+
<p>The key feature: <code>depth</code> + <code>max-depth</code> lets one data set produce multiple views.</p>
|
|
247
|
+
<h3 id="full-detail-max-depth-2">Full detail (<code>max-depth: 2</code>)</h3>
|
|
248
|
+
<pre><code class="language-markdown">:::gantt
|
|
249
|
+
label: "Client Rollout — Detail View"
|
|
250
|
+
time-unit: week
|
|
251
|
+
time-start: "2026-W18"
|
|
252
|
+
time-end: "2026-W40"
|
|
253
|
+
max-depth: 2
|
|
254
|
+
today: "2026-W28"
|
|
255
|
+
tracks:
|
|
256
|
+
|
|
257
|
+
- label: "Wave 1 — Pilot"
|
|
258
|
+
depth: 1
|
|
259
|
+
start: "2026-W20"
|
|
260
|
+
end: "2026-W30"
|
|
261
|
+
status: active
|
|
262
|
+
- label: "Apex Advisory (45 sites)"
|
|
263
|
+
depth: 2
|
|
264
|
+
start: "2026-W20"
|
|
265
|
+
end: "2026-W26"
|
|
266
|
+
status: complete
|
|
267
|
+
- label: "Beacon Logistics (80 sites)"
|
|
268
|
+
depth: 2
|
|
269
|
+
start: "2026-W24"
|
|
270
|
+
end: "2026-W30"
|
|
271
|
+
status: active
|
|
272
|
+
milestones:
|
|
273
|
+
- label: "Pilot Review"
|
|
274
|
+
date: "2026-W31"
|
|
275
|
+
tracks:
|
|
276
|
+
- label: "Wave 2 — Scale"
|
|
277
|
+
depth: 1
|
|
278
|
+
start: "2026-W33"
|
|
279
|
+
end: "2026-W40"
|
|
280
|
+
status: planned
|
|
281
|
+
- label: "Crestview Energy (120 sites)"
|
|
282
|
+
depth: 2
|
|
283
|
+
start: "2026-W33"
|
|
284
|
+
end: "2026-W37"
|
|
285
|
+
status: planned
|
|
286
|
+
- label: "Dunmore Foods (90 sites)"
|
|
287
|
+
depth: 2
|
|
288
|
+
start: "2026-W36"
|
|
289
|
+
end: "2026-W40"
|
|
290
|
+
status: planned
|
|
291
|
+
:::
|
|
292
|
+
</code></pre>
|
|
293
|
+
<h3 id="summary-view-max-depth-1">Summary view (<code>max-depth: 1</code>)</h3>
|
|
294
|
+
<p>Use the same data with <code>max-depth: 1</code> to show only wave-level bars — ideal for executive slides:</p>
|
|
295
|
+
<pre><code class="language-markdown">:::gantt
|
|
296
|
+
label: "Client Rollout — Summary View"
|
|
297
|
+
time-unit: week
|
|
298
|
+
time-start: "2026-W18"
|
|
299
|
+
time-end: "2026-W40"
|
|
300
|
+
max-depth: 1
|
|
301
|
+
today: "2026-W28"
|
|
302
|
+
tracks:
|
|
303
|
+
|
|
304
|
+
- label: "Wave 1 — Pilot"
|
|
305
|
+
depth: 1
|
|
306
|
+
start: "2026-W20"
|
|
307
|
+
end: "2026-W30"
|
|
308
|
+
status: active
|
|
309
|
+
- label: "Apex Advisory (45 sites)"
|
|
310
|
+
depth: 2
|
|
311
|
+
start: "2026-W20"
|
|
312
|
+
end: "2026-W26"
|
|
313
|
+
status: complete
|
|
314
|
+
- label: "Beacon Logistics (80 sites)"
|
|
315
|
+
depth: 2
|
|
316
|
+
start: "2026-W24"
|
|
317
|
+
end: "2026-W30"
|
|
318
|
+
status: active
|
|
319
|
+
milestones:
|
|
320
|
+
- label: "Pilot Review"
|
|
321
|
+
date: "2026-W31"
|
|
322
|
+
tracks:
|
|
323
|
+
- label: "Wave 2 — Scale"
|
|
324
|
+
depth: 1
|
|
325
|
+
start: "2026-W33"
|
|
326
|
+
end: "2026-W40"
|
|
327
|
+
status: planned
|
|
328
|
+
- label: "Crestview Energy (120 sites)"
|
|
329
|
+
depth: 2
|
|
330
|
+
start: "2026-W33"
|
|
331
|
+
end: "2026-W37"
|
|
332
|
+
status: planned
|
|
333
|
+
- label: "Dunmore Foods (90 sites)"
|
|
334
|
+
depth: 2
|
|
335
|
+
start: "2026-W36"
|
|
336
|
+
end: "2026-W40"
|
|
337
|
+
status: planned
|
|
338
|
+
:::
|
|
339
|
+
</code></pre>
|
|
340
|
+
<p>Depth-2 tracks and milestones are hidden. The data is identical — only <code>max-depth</code> changes.</p>
|
|
341
|
+
<h2 id="milestones">Milestones</h2>
|
|
342
|
+
<p>Milestones are point-in-time markers (diamonds). They have a <code>date</code> instead of <code>start</code>/<code>end</code>, and they're listed separately from tracks. Interleave freely — source order controls layout:</p>
|
|
343
|
+
<pre><code class="language-markdown">:::gantt
|
|
344
|
+
time-unit: month
|
|
345
|
+
time-start: "2026-03"
|
|
346
|
+
time-end: "2026-12"
|
|
347
|
+
milestones:
|
|
348
|
+
|
|
349
|
+
- label: "Kick-off"
|
|
350
|
+
date: "2026-03"
|
|
351
|
+
tracks:
|
|
352
|
+
- label: "Design Phase"
|
|
353
|
+
depth: 1
|
|
354
|
+
start: "2026-04"
|
|
355
|
+
end: "2026-06"
|
|
356
|
+
status: complete
|
|
357
|
+
milestones:
|
|
358
|
+
- label: "Design Sign-off"
|
|
359
|
+
date: "2026-07"
|
|
360
|
+
tracks:
|
|
361
|
+
- label: "Build Phase"
|
|
362
|
+
depth: 1
|
|
363
|
+
start: "2026-07"
|
|
364
|
+
end: "2026-10"
|
|
365
|
+
status: active
|
|
366
|
+
milestones:
|
|
367
|
+
- label: "Launch"
|
|
368
|
+
date: "2026-11"
|
|
369
|
+
:::
|
|
370
|
+
</code></pre>
|
|
371
|
+
<p>Milestones respect <code>max-depth</code> filtering. A milestone with <code>depth: 2</code> is hidden when <code>max-depth: 1</code>.</p>
|
|
372
|
+
<h2 id="chart-level-markers">Chart-level markers</h2>
|
|
373
|
+
<p>Markers are vertical annotation lines that span the full chart height — use them for gates, deadlines, and phase boundaries. Unlike row-level milestones (diamonds), markers are chart-level annotations with a label at the top:</p>
|
|
374
|
+
<pre><code class="language-markdown">:::gantt
|
|
375
|
+
label: "Platform Migration"
|
|
376
|
+
time-unit: week
|
|
377
|
+
time-start: "2026-W14"
|
|
378
|
+
time-end: "2026-W30"
|
|
379
|
+
markers:
|
|
380
|
+
|
|
381
|
+
- label: "Go/No-Go"
|
|
382
|
+
date: "2026-W18"
|
|
383
|
+
color: "#f59e0b"
|
|
384
|
+
- label: "Phase 1 Sign-Off"
|
|
385
|
+
date: "2026-W26"
|
|
386
|
+
color: "var(--color-link)"
|
|
387
|
+
tracks:
|
|
388
|
+
- label: "Phase 1 — Foundation"
|
|
389
|
+
depth: 1
|
|
390
|
+
start: "2026-W14"
|
|
391
|
+
end: "2026-W24"
|
|
392
|
+
status: active
|
|
393
|
+
- label: "Phase 2 — Integration"
|
|
394
|
+
depth: 1
|
|
395
|
+
start: "2026-W25"
|
|
396
|
+
end: "2026-W30"
|
|
397
|
+
status: planned
|
|
398
|
+
:::
|
|
399
|
+
</code></pre>
|
|
400
|
+
<p>Markers are <strong>not</strong> subject to <code>max-depth</code> or <code>max-tracks</code> — they always render if their date is within the axis range. A marker whose date falls outside the axis produces a build-time warning and is silently omitted.</p>
|
|
401
|
+
<p>Labels default to the right of the line. Near the right edge of the chart (<del>85%+), labels automatically flip to the left. Keep labels short (</del>20 chars) — longer text is truncated with ellipsis.</p>
|
|
402
|
+
<p><code>color</code> is optional on each marker. If provided, it tints the marker line and label. Supported values are any valid CSS color (<code>#hex</code>, <code>rgb(...)</code>, <code>hsl(...)</code>, named color, or CSS variable like <code>var(--color-link)</code>).</p>
|
|
403
|
+
<h2 id="truncation-with-max-tracks">Truncation with <code>max-tracks</code></h2>
|
|
404
|
+
<p>For slides, cap the visible rows to avoid overflow:</p>
|
|
405
|
+
<pre><code class="language-markdown">:::gantt
|
|
406
|
+
label: "Regional Deployment"
|
|
407
|
+
time-unit: month
|
|
408
|
+
time-start: "2026-01"
|
|
409
|
+
time-end: "2026-12"
|
|
410
|
+
max-tracks: 4
|
|
411
|
+
tracks:
|
|
412
|
+
|
|
413
|
+
- label: "North America"
|
|
414
|
+
depth: 1
|
|
415
|
+
start: "2026-01"
|
|
416
|
+
end: "2026-04"
|
|
417
|
+
status: complete
|
|
418
|
+
- label: "Europe"
|
|
419
|
+
depth: 1
|
|
420
|
+
start: "2026-03"
|
|
421
|
+
end: "2026-06"
|
|
422
|
+
status: active
|
|
423
|
+
- label: "Asia Pacific"
|
|
424
|
+
depth: 1
|
|
425
|
+
start: "2026-05"
|
|
426
|
+
end: "2026-09"
|
|
427
|
+
status: planned
|
|
428
|
+
- label: "Latin America"
|
|
429
|
+
depth: 1
|
|
430
|
+
start: "2026-07"
|
|
431
|
+
end: "2026-10"
|
|
432
|
+
status: planned
|
|
433
|
+
- label: "Middle East"
|
|
434
|
+
depth: 1
|
|
435
|
+
start: "2026-09"
|
|
436
|
+
end: "2026-12"
|
|
437
|
+
status: planned
|
|
438
|
+
:::
|
|
439
|
+
</code></pre>
|
|
440
|
+
<p>Rows 5+ are hidden and replaced with a "+1 more" indicator. <code>max-tracks</code> applies after <code>max-depth</code> filtering.</p>
|
|
441
|
+
<h2 id="cross-year-ranges">Cross-year ranges</h2>
|
|
442
|
+
<p>Both week and month mode handle year boundaries. The axis shows the year at transitions:</p>
|
|
443
|
+
<pre><code class="language-markdown">:::gantt
|
|
444
|
+
label: "Multi-Year Program"
|
|
445
|
+
time-unit: month
|
|
446
|
+
time-start: "2026-10"
|
|
447
|
+
time-end: "2027-06"
|
|
448
|
+
tracks:
|
|
449
|
+
|
|
450
|
+
- label: "Phase 3 — Consolidation"
|
|
451
|
+
depth: 1
|
|
452
|
+
start: "2026-10"
|
|
453
|
+
end: "2027-01"
|
|
454
|
+
status: active
|
|
455
|
+
- label: "Phase 4 — Expansion"
|
|
456
|
+
depth: 1
|
|
457
|
+
start: "2027-02"
|
|
458
|
+
end: "2027-06"
|
|
459
|
+
status: planned
|
|
460
|
+
:::
|
|
461
|
+
</code></pre>
|
|
462
|
+
<h2 id="today-marker">Today marker</h2>
|
|
463
|
+
<p>The <code>today</code> parameter draws a vertical dashed line. Useful when set by a generator to the build date:</p>
|
|
464
|
+
<pre><code class="language-markdown">:::gantt
|
|
465
|
+
time-unit: week
|
|
466
|
+
time-start: "2026-W20"
|
|
467
|
+
time-end: "2026-W32"
|
|
468
|
+
today: "2026-W26"
|
|
469
|
+
tracks:
|
|
470
|
+
|
|
471
|
+
- label: "Current Sprint"
|
|
472
|
+
depth: 1
|
|
473
|
+
start: "2026-W24"
|
|
474
|
+
end: "2026-W28"
|
|
475
|
+
status: active
|
|
476
|
+
:::
|
|
477
|
+
</code></pre>
|
|
478
|
+
<h2 id="data-driven-usage">Data-driven usage</h2>
|
|
479
|
+
<p>Generators can emit <code>:::gantt</code> blocks as snippets. The template author places them without understanding the data model:</p>
|
|
480
|
+
<pre><code class="language-yaml"># In a data file (e.g., data/rollout.yaml)
|
|
481
|
+
snippets:
|
|
482
|
+
- slot: "rollout-summary"
|
|
483
|
+
content: ":::gantt\ntime-unit: week\ntime-start: \"2026-W18\"\ntime-end: \"2026-W40\"\nmax-depth: 1\ntracks:\n - label: \"Wave 1\"\n depth: 1\n start: \"2026-W20\"\n end: \"2026-W30\"\n status: active\n:::"
|
|
484
|
+
</code></pre>
|
|
485
|
+
<pre><code class="language-markdown"><!-- In a markdown file -->
|
|
486
|
+
|
|
487
|
+
## Rollout Timeline
|
|
488
|
+
|
|
489
|
+
{{ snippet:rollout-summary }}
|
|
490
|
+
</code></pre>
|
|
491
|
+
<h2 id="milestones-vs-markers">Milestones vs markers</h2>
|
|
492
|
+
<p>Both are point-in-time features — here's when to use which:</p>
|
|
493
|
+
<table>
|
|
494
|
+
<thead>
|
|
495
|
+
<tr>
|
|
496
|
+
<th></th>
|
|
497
|
+
<th>Milestones (<code>milestones:</code>)</th>
|
|
498
|
+
<th>Markers (<code>markers:</code>)</th>
|
|
499
|
+
</tr>
|
|
500
|
+
</thead>
|
|
501
|
+
<tbody><tr>
|
|
502
|
+
<td><strong>What it draws</strong></td>
|
|
503
|
+
<td>Diamond icon in a single row</td>
|
|
504
|
+
<td>Vertical line spanning the full chart</td>
|
|
505
|
+
</tr>
|
|
506
|
+
<tr>
|
|
507
|
+
<td><strong>Where the label goes</strong></td>
|
|
508
|
+
<td>Left column (same as tracks)</td>
|
|
509
|
+
<td>Above the axis, next to the line</td>
|
|
510
|
+
</tr>
|
|
511
|
+
<tr>
|
|
512
|
+
<td><strong>Has depth?</strong></td>
|
|
513
|
+
<td>Yes — subject to <code>max-depth</code></td>
|
|
514
|
+
<td>No — always visible</td>
|
|
515
|
+
</tr>
|
|
516
|
+
<tr>
|
|
517
|
+
<td><strong>Counted by <code>max-tracks</code>?</strong></td>
|
|
518
|
+
<td>Yes</td>
|
|
519
|
+
<td>No</td>
|
|
520
|
+
</tr>
|
|
521
|
+
<tr>
|
|
522
|
+
<td><strong>Use for</strong></td>
|
|
523
|
+
<td>Per-track events: "Acme go-live", "QA sign-off"</td>
|
|
524
|
+
<td>Chart-wide gates: "Go/No-Go", "Funding deadline"</td>
|
|
525
|
+
</tr>
|
|
526
|
+
</tbody></table>
|
|
527
|
+
<p>Rule of thumb: if it belongs to a specific track or wave, use a milestone. If it's a date the whole chart cares about, use a marker.</p>
|
|
528
|
+
<h2 id="edge-cases-and-errors">Edge cases and errors</h2>
|
|
529
|
+
<p>Kitfly validates <code>:::gantt</code> blocks at build time. If something is wrong, <code>bun run build</code> (or <code>bun run dev</code>) fails fast with an error pointing to the file and line.</p>
|
|
530
|
+
<p><strong>Build errors</strong> (block will not render):</p>
|
|
531
|
+
<table>
|
|
532
|
+
<thead>
|
|
533
|
+
<tr>
|
|
534
|
+
<th>What you wrote</th>
|
|
535
|
+
<th>Error</th>
|
|
536
|
+
<th>Fix</th>
|
|
537
|
+
</tr>
|
|
538
|
+
</thead>
|
|
539
|
+
<tbody><tr>
|
|
540
|
+
<td>Missing <code>time-unit</code>, <code>time-start</code>, <code>time-end</code>, or <code>tracks</code></td>
|
|
541
|
+
<td>Required field missing</td>
|
|
542
|
+
<td>Add the field</td>
|
|
543
|
+
</tr>
|
|
544
|
+
<tr>
|
|
545
|
+
<td><code>time-unit: weeks</code> (plural)</td>
|
|
546
|
+
<td>Invalid time-unit</td>
|
|
547
|
+
<td>Use <code>week</code> or <code>month</code></td>
|
|
548
|
+
</tr>
|
|
549
|
+
<tr>
|
|
550
|
+
<td><code>2026-14</code> with <code>time-unit: week</code></td>
|
|
551
|
+
<td>Invalid time-start format</td>
|
|
552
|
+
<td>Use <code>2026-W14</code> (capital W, two-digit week)</td>
|
|
553
|
+
</tr>
|
|
554
|
+
<tr>
|
|
555
|
+
<td><code>2026-4</code> with <code>time-unit: month</code></td>
|
|
556
|
+
<td>Invalid time-start format</td>
|
|
557
|
+
<td>Use <code>2026-04</code> (two-digit month)</td>
|
|
558
|
+
</tr>
|
|
559
|
+
<tr>
|
|
560
|
+
<td>Week date with <code>time-unit: month</code> (or vice versa)</td>
|
|
561
|
+
<td>Format mismatch</td>
|
|
562
|
+
<td>All dates must match the <code>time-unit</code></td>
|
|
563
|
+
</tr>
|
|
564
|
+
<tr>
|
|
565
|
+
<td><code>time-start</code> after <code>time-end</code></td>
|
|
566
|
+
<td>Range error</td>
|
|
567
|
+
<td>Swap them</td>
|
|
568
|
+
</tr>
|
|
569
|
+
<tr>
|
|
570
|
+
<td>Track with <code>start</code> after <code>end</code></td>
|
|
571
|
+
<td>Range error</td>
|
|
572
|
+
<td>Swap them</td>
|
|
573
|
+
</tr>
|
|
574
|
+
<tr>
|
|
575
|
+
<td>Track missing <code>label</code>, <code>depth</code>, <code>start</code>, or <code>end</code></td>
|
|
576
|
+
<td>Required field missing</td>
|
|
577
|
+
<td>Add the field</td>
|
|
578
|
+
</tr>
|
|
579
|
+
<tr>
|
|
580
|
+
<td>Milestone missing <code>label</code> or <code>date</code></td>
|
|
581
|
+
<td>Required field missing</td>
|
|
582
|
+
<td>Add the field</td>
|
|
583
|
+
</tr>
|
|
584
|
+
<tr>
|
|
585
|
+
<td>Marker missing <code>label</code> or <code>date</code></td>
|
|
586
|
+
<td>Required field missing</td>
|
|
587
|
+
<td>Add the field</td>
|
|
588
|
+
</tr>
|
|
589
|
+
</tbody></table>
|
|
590
|
+
<p><strong>Build warnings</strong> (block renders, but something may look wrong):</p>
|
|
591
|
+
<table>
|
|
592
|
+
<thead>
|
|
593
|
+
<tr>
|
|
594
|
+
<th>What you wrote</th>
|
|
595
|
+
<th>Warning</th>
|
|
596
|
+
<th>What happens</th>
|
|
597
|
+
</tr>
|
|
598
|
+
</thead>
|
|
599
|
+
<tbody><tr>
|
|
600
|
+
<td>Track extends outside the axis range</td>
|
|
601
|
+
<td>"Track range is outside axis and will be clipped"</td>
|
|
602
|
+
<td>Bar clips to the visible axis</td>
|
|
603
|
+
</tr>
|
|
604
|
+
<tr>
|
|
605
|
+
<td>Milestone date outside the axis range</td>
|
|
606
|
+
<td>"Milestone date is outside axis"</td>
|
|
607
|
+
<td>Diamond not rendered</td>
|
|
608
|
+
</tr>
|
|
609
|
+
<tr>
|
|
610
|
+
<td>Marker date outside the axis range</td>
|
|
611
|
+
<td>"Marker date is outside axis"</td>
|
|
612
|
+
<td>Line and label not rendered</td>
|
|
613
|
+
</tr>
|
|
614
|
+
</tbody></table>
|
|
615
|
+
<p><strong>Silent defaults</strong> (no error, no warning):</p>
|
|
616
|
+
<table>
|
|
617
|
+
<thead>
|
|
618
|
+
<tr>
|
|
619
|
+
<th>What you wrote</th>
|
|
620
|
+
<th>What happens</th>
|
|
621
|
+
</tr>
|
|
622
|
+
</thead>
|
|
623
|
+
<tbody><tr>
|
|
624
|
+
<td>Omit <code>status</code> on a track</td>
|
|
625
|
+
<td>Defaults to <code>planned</code> (gray)</td>
|
|
626
|
+
</tr>
|
|
627
|
+
<tr>
|
|
628
|
+
<td>Omit <code>depth</code> on a milestone</td>
|
|
629
|
+
<td>Defaults to 1</td>
|
|
630
|
+
</tr>
|
|
631
|
+
<tr>
|
|
632
|
+
<td>Omit <code>max-depth</code></td>
|
|
633
|
+
<td>All depths rendered</td>
|
|
634
|
+
</tr>
|
|
635
|
+
<tr>
|
|
636
|
+
<td>Omit <code>max-tracks</code></td>
|
|
637
|
+
<td>All rows rendered</td>
|
|
638
|
+
</tr>
|
|
639
|
+
<tr>
|
|
640
|
+
<td>Omit <code>milestones</code>, <code>markers</code>, <code>today</code>, or <code>label</code></td>
|
|
641
|
+
<td>Feature simply absent</td>
|
|
642
|
+
</tr>
|
|
643
|
+
<tr>
|
|
644
|
+
<td>Unknown <code>status</code> value (e.g., <code>status: done</code>)</td>
|
|
645
|
+
<td>Treated as <code>planned</code></td>
|
|
646
|
+
</tr>
|
|
647
|
+
</tbody></table>
|
|
648
|
+
<p>For the full fence contract (indentation rules, block shape, supported types), see <a href="plugins.md#triple-colon-fence-contract-planning-visuals">Plugins — planning-visuals</a>.</p>
|
|
649
|
+
<h2 id="quick-reference">Quick reference</h2>
|
|
650
|
+
<table>
|
|
651
|
+
<thead>
|
|
652
|
+
<tr>
|
|
653
|
+
<th>What you want</th>
|
|
654
|
+
<th>How</th>
|
|
655
|
+
</tr>
|
|
656
|
+
</thead>
|
|
657
|
+
<tbody><tr>
|
|
658
|
+
<td>Week axis</td>
|
|
659
|
+
<td><code>time-unit: week</code>, dates as <code>YYYY-Www</code></td>
|
|
660
|
+
</tr>
|
|
661
|
+
<tr>
|
|
662
|
+
<td>Month axis</td>
|
|
663
|
+
<td><code>time-unit: month</code>, dates as <code>YYYY-MM</code></td>
|
|
664
|
+
</tr>
|
|
665
|
+
<tr>
|
|
666
|
+
<td>Title above chart</td>
|
|
667
|
+
<td><code>label: "My Title"</code></td>
|
|
668
|
+
</tr>
|
|
669
|
+
<tr>
|
|
670
|
+
<td>Executive summary</td>
|
|
671
|
+
<td><code>max-depth: 1</code></td>
|
|
672
|
+
</tr>
|
|
673
|
+
<tr>
|
|
674
|
+
<td>Detail view</td>
|
|
675
|
+
<td><code>max-depth: 2</code> (or omit for all)</td>
|
|
676
|
+
</tr>
|
|
677
|
+
<tr>
|
|
678
|
+
<td>Cap rows for slides</td>
|
|
679
|
+
<td><code>max-tracks: 6</code></td>
|
|
680
|
+
</tr>
|
|
681
|
+
<tr>
|
|
682
|
+
<td>Progress marker</td>
|
|
683
|
+
<td><code>today: "2026-W26"</code></td>
|
|
684
|
+
</tr>
|
|
685
|
+
<tr>
|
|
686
|
+
<td>Done bar (green)</td>
|
|
687
|
+
<td><code>status: complete</code></td>
|
|
688
|
+
</tr>
|
|
689
|
+
<tr>
|
|
690
|
+
<td>In-progress bar (blue)</td>
|
|
691
|
+
<td><code>status: active</code></td>
|
|
692
|
+
</tr>
|
|
693
|
+
<tr>
|
|
694
|
+
<td>At-risk bar (amber)</td>
|
|
695
|
+
<td><code>status: blocked</code></td>
|
|
696
|
+
</tr>
|
|
697
|
+
<tr>
|
|
698
|
+
<td>Not started (gray)</td>
|
|
699
|
+
<td><code>status: planned</code> (or omit)</td>
|
|
700
|
+
</tr>
|
|
701
|
+
<tr>
|
|
702
|
+
<td>Point-in-time marker</td>
|
|
703
|
+
<td>Use <code>milestones:</code> list with <code>date:</code></td>
|
|
704
|
+
</tr>
|
|
705
|
+
<tr>
|
|
706
|
+
<td>Chart-level gate line</td>
|
|
707
|
+
<td>Use <code>markers:</code> list with <code>label:</code> + <code>date:</code></td>
|
|
708
|
+
</tr>
|
|
709
|
+
<tr>
|
|
710
|
+
<td>Marker-specific color</td>
|
|
711
|
+
<td>Add optional <code>color:</code> per marker</td>
|
|
712
|
+
</tr>
|
|
713
|
+
</tbody></table>
|
|
714
|
+
|
|
715
|
+
</article>
|
|
716
|
+
<aside class="toc"><span class="toc-title">On this page</span><ul><li><a href="#minimal-example-week">Minimal example (week)</a></li><li><a href="#minimal-example-month">Minimal example (month)</a></li><li><a href="#status-colors">Status colors</a></li><li><a href="#hierarchy-and-depth-filtering">Hierarchy and depth filtering</a></li><li><a href="#milestones">Milestones</a></li><li><a href="#chart-level-markers">Chart-level markers</a></li><li><a href="#cross-year-ranges">Cross-year ranges</a></li><li><a href="#today-marker">Today marker</a></li><li><a href="#data-driven-usage">Data-driven usage</a></li><li><a href="#milestones-vs-markers">Milestones vs markers</a></li><li><a href="#edge-cases-and-errors">Edge cases and errors</a></li><li><a href="#quick-reference">Quick reference</a></li></ul></aside>
|
|
717
|
+
</main>
|
|
718
|
+
</div>
|
|
719
|
+
|
|
720
|
+
<footer class="site-footer">
|
|
721
|
+
<div class="footer-content">
|
|
722
|
+
<div class="footer-left">
|
|
723
|
+
|
|
724
|
+
|
|
725
|
+
<span class="footer-commit" title="Commit: 4062660">Published 2026-03-09</span>
|
|
726
|
+
</div>
|
|
727
|
+
<div class="footer-center">
|
|
728
|
+
<span class="footer-copyright"><a href="https://3leaps.net" class="footer-link">© 2026 3 Leaps, LLC</a></span>
|
|
729
|
+
<span class="footer-separator">·</span><a href="/" class="footer-link">Kitfly</a>
|
|
730
|
+
</div>
|
|
731
|
+
<div class="footer-right">
|
|
732
|
+
<a href="https://kitfly.dev" class="footer-link">Built with Kitfly</a>
|
|
733
|
+
</div>
|
|
734
|
+
</div>
|
|
735
|
+
</footer>
|
|
736
|
+
<!-- Syntax highlighting - Prism.js -->
|
|
737
|
+
<script src="https://cdn.jsdelivr.net/npm/prismjs@1/components/prism-core.min.js"></script>
|
|
738
|
+
<script src="https://cdn.jsdelivr.net/npm/prismjs@1/plugins/autoloader/prism-autoloader.min.js"></script>
|
|
739
|
+
<!-- Mermaid diagram support -->
|
|
740
|
+
<script type="module">
|
|
741
|
+
import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@11/dist/mermaid.esm.min.mjs';
|
|
742
|
+
|
|
743
|
+
function getMermaidTheme() {
|
|
744
|
+
const theme = document.documentElement.getAttribute('data-theme');
|
|
745
|
+
const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
|
|
746
|
+
const isDark = theme === 'dark' || (!theme && prefersDark);
|
|
747
|
+
return isDark ? 'dark' : 'neutral';
|
|
748
|
+
}
|
|
749
|
+
|
|
750
|
+
mermaid.initialize({
|
|
751
|
+
startOnLoad: true,
|
|
752
|
+
theme: getMermaidTheme()
|
|
753
|
+
});
|
|
754
|
+
|
|
755
|
+
// Re-render mermaid diagrams when theme changes
|
|
756
|
+
window.reinitMermaid = async function() {
|
|
757
|
+
mermaid.initialize({ startOnLoad: false, theme: getMermaidTheme() });
|
|
758
|
+
const diagrams = document.querySelectorAll('.mermaid');
|
|
759
|
+
for (const el of diagrams) {
|
|
760
|
+
const code = el.getAttribute('data-mermaid-source');
|
|
761
|
+
if (code) {
|
|
762
|
+
el.innerHTML = code;
|
|
763
|
+
el.removeAttribute('data-processed');
|
|
764
|
+
}
|
|
765
|
+
}
|
|
766
|
+
await mermaid.run({ nodes: diagrams });
|
|
767
|
+
};
|
|
768
|
+
</script>
|
|
769
|
+
|
|
770
|
+
<script>
|
|
771
|
+
function toggleTheme() {
|
|
772
|
+
const html = document.documentElement;
|
|
773
|
+
const current = html.getAttribute('data-theme');
|
|
774
|
+
const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
|
|
775
|
+
|
|
776
|
+
let next;
|
|
777
|
+
if (current === 'dark') {
|
|
778
|
+
next = 'light';
|
|
779
|
+
} else if (current === 'light') {
|
|
780
|
+
next = 'dark';
|
|
781
|
+
} else {
|
|
782
|
+
// No explicit theme set, toggle from system preference
|
|
783
|
+
next = prefersDark ? 'light' : 'dark';
|
|
784
|
+
}
|
|
785
|
+
|
|
786
|
+
html.setAttribute('data-theme', next);
|
|
787
|
+
localStorage.setItem('theme', next);
|
|
788
|
+
|
|
789
|
+
// Switch Prism theme
|
|
790
|
+
const prismLight = document.getElementById('prism-light');
|
|
791
|
+
const prismDark = document.getElementById('prism-dark');
|
|
792
|
+
if (next === 'dark') {
|
|
793
|
+
prismLight?.setAttribute('disabled', '');
|
|
794
|
+
prismDark?.removeAttribute('disabled');
|
|
795
|
+
} else {
|
|
796
|
+
prismLight?.removeAttribute('disabled');
|
|
797
|
+
prismDark?.setAttribute('disabled', '');
|
|
798
|
+
}
|
|
799
|
+
|
|
800
|
+
// Re-render mermaid diagrams with new theme
|
|
801
|
+
if (window.reinitMermaid) {
|
|
802
|
+
window.reinitMermaid();
|
|
803
|
+
}
|
|
804
|
+
if (window.reinitCharts) {
|
|
805
|
+
window.reinitCharts();
|
|
806
|
+
}
|
|
807
|
+
}
|
|
808
|
+
|
|
809
|
+
// Slides mode hash routing
|
|
810
|
+
(function initSlidesMode() {
|
|
811
|
+
const shell = document.querySelector('.slides-shell');
|
|
812
|
+
if (!shell) return;
|
|
813
|
+
|
|
814
|
+
const slides = Array.from(document.querySelectorAll('.slide'));
|
|
815
|
+
if (!slides.length) return;
|
|
816
|
+
|
|
817
|
+
const prevBtn = document.querySelector('.slide-prev');
|
|
818
|
+
const nextBtn = document.querySelector('.slide-next');
|
|
819
|
+
const counter = document.querySelector('.slide-counter');
|
|
820
|
+
const progressBar = document.querySelector('.slide-progress-bar');
|
|
821
|
+
const navLinks = Array.from(document.querySelectorAll('.sidebar-nav a[href^="#slide-"]'));
|
|
822
|
+
let current = 0;
|
|
823
|
+
|
|
824
|
+
function setActive(n) {
|
|
825
|
+
current = Math.max(0, Math.min(n, slides.length - 1));
|
|
826
|
+
slides.forEach((slide, idx) => slide.classList.toggle('active', idx === current));
|
|
827
|
+
navLinks.forEach((link) => {
|
|
828
|
+
const active = link.getAttribute('href') === '#' + slides[current].id;
|
|
829
|
+
link.classList.toggle('active', active);
|
|
830
|
+
});
|
|
831
|
+
if (counter) counter.textContent = (current + 1) + ' / ' + slides.length;
|
|
832
|
+
if (progressBar) progressBar.style.width = (((current + 1) / slides.length) * 100) + '%';
|
|
833
|
+
if (prevBtn) prevBtn.disabled = current === 0;
|
|
834
|
+
if (nextBtn) nextBtn.disabled = current === slides.length - 1;
|
|
835
|
+
history.replaceState(null, '', '#' + slides[current].id);
|
|
836
|
+
}
|
|
837
|
+
|
|
838
|
+
function setFromHash() {
|
|
839
|
+
const hash = window.location.hash || '';
|
|
840
|
+
const idx = slides.findIndex((s) => '#' + s.id === hash);
|
|
841
|
+
if (idx >= 0) setActive(idx);
|
|
842
|
+
else setActive(0);
|
|
843
|
+
}
|
|
844
|
+
|
|
845
|
+
prevBtn?.addEventListener('click', () => setActive(current - 1));
|
|
846
|
+
nextBtn?.addEventListener('click', () => setActive(current + 1));
|
|
847
|
+
|
|
848
|
+
document.addEventListener('keydown', (e) => {
|
|
849
|
+
if (e.key === 'ArrowRight' || e.key === ' ') {
|
|
850
|
+
e.preventDefault();
|
|
851
|
+
setActive(current + 1);
|
|
852
|
+
} else if (e.key === 'ArrowLeft') {
|
|
853
|
+
e.preventDefault();
|
|
854
|
+
setActive(current - 1);
|
|
855
|
+
} else if (e.key === 'Home') {
|
|
856
|
+
e.preventDefault();
|
|
857
|
+
setActive(0);
|
|
858
|
+
} else if (e.key === 'End') {
|
|
859
|
+
e.preventDefault();
|
|
860
|
+
setActive(slides.length - 1);
|
|
861
|
+
}
|
|
862
|
+
});
|
|
863
|
+
|
|
864
|
+
window.addEventListener('hashchange', setFromHash);
|
|
865
|
+
setFromHash();
|
|
866
|
+
})();
|
|
867
|
+
|
|
868
|
+
// Copy code button
|
|
869
|
+
document.querySelectorAll('.prose pre code').forEach(block => {
|
|
870
|
+
const button = document.createElement('button');
|
|
871
|
+
button.className = 'copy-button';
|
|
872
|
+
button.textContent = 'Copy';
|
|
873
|
+
button.onclick = async () => {
|
|
874
|
+
await navigator.clipboard.writeText(block.textContent);
|
|
875
|
+
button.textContent = 'Copied!';
|
|
876
|
+
setTimeout(() => button.textContent = 'Copy', 2000);
|
|
877
|
+
};
|
|
878
|
+
block.parentElement.appendChild(button);
|
|
879
|
+
});
|
|
880
|
+
|
|
881
|
+
// Mobile nav toggle
|
|
882
|
+
function toggleNav() {
|
|
883
|
+
document.querySelector('.sidebar').classList.toggle('open');
|
|
884
|
+
}
|
|
885
|
+
|
|
886
|
+
// Close nav when clicking outside on mobile
|
|
887
|
+
document.addEventListener('click', (e) => {
|
|
888
|
+
const sidebar = document.querySelector('.sidebar');
|
|
889
|
+
const toggle = document.querySelector('.nav-toggle');
|
|
890
|
+
if (sidebar.classList.contains('open') &&
|
|
891
|
+
!sidebar.contains(e.target) &&
|
|
892
|
+
!toggle.contains(e.target)) {
|
|
893
|
+
sidebar.classList.remove('open');
|
|
894
|
+
}
|
|
895
|
+
});
|
|
896
|
+
</script>
|
|
897
|
+
|
|
898
|
+
</body>
|
|
899
|
+
</html>
|