Skip to content

Commit ece7b04

Browse files
devGregAclaude
authored andcommitted
docs: redesign documentation site UI
Presentation-only redesign of docs.defectdojo.com. The rendered text of all 612 pages is byte-identical to the previous build (verified by diffing extracted page text across before/after builds); no content files are touched. Highlights: - Token-based design system (CSS custom properties for light and dark) using the DefectDojo brand palette, with navy header and footer shared with trust.defectdojo.com - Code blocks restyled as navy cards in both color modes by retheming the doks expressive-code frame variables: language labels in the header band, terminal dots for shell fences, styled copy button, and a brand-tuned Chroma syntax palette - The Open Source / Pro version toggle is rebuilt from a select dropdown into an accessible segmented control (radiogroup semantics). Behavior is unchanged: same localStorage key and values, anti-flash reveal, edition-aware "Model Your Assets" nav link, and instances stay in sync across the desktop sidebar and mobile offcanvas - Reading experience: 16px root font size (was 85 percent), 72ch measure, refined heading scale, framed screenshots, styled tables and callouts - Mobile fixes: the header now shows the brand on small screens, and the offcanvas navigation actually opens. The site disables the full Bootstrap bundle (doks.bootstrapJavascript = false), so the offcanvas plugin never loaded and mobile nav buttons were dead on the live site; custom.js now imports just the Offcanvas plugin - Homepage: navy hero with blueprint grid, prominent DocSearch trigger, quick-nav cards overlapping the hero edge; all copy unchanged Note: netlify.toml pins HUGO_VERSION=0.125.1, which cannot build doks-core 1.8.3 (it requires Hugo 0.146+ for layouts/_partials). The production pipeline evidently uses a newer Hugo already; this change was built and verified with Hugo 0.148.1 extended. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
1 parent e206852 commit ece7b04

7 files changed

Lines changed: 1256 additions & 645 deletions

File tree

docs/assets/js/custom.js

Lines changed: 81 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,25 @@
11
// custom js
22

3-
4-
// version toggler
3+
// Mobile navigation: the site sets doks.bootstrapJavascript = false, so no
4+
// Bootstrap plugins load and the header's offcanvas toggles are dead markup.
5+
// Importing the Offcanvas plugin evaluates its module, which registers the
6+
// data-bs-toggle="offcanvas" click handling; the window reference keeps the
7+
// import (and its side effects) from being tree-shaken.
8+
import { Offcanvas } from 'bootstrap';
9+
10+
window.ddOffcanvas = Offcanvas;
11+
12+
13+
// Edition toggler (Open Source / Pro)
14+
//
15+
// The sidebar renders both edition menus (.version-opensource / .version-pro);
16+
// this shows one, persists the choice, and keeps every segmented control on
17+
// the page (desktop sidebar + mobile offcanvas) in sync. The sidebar and the
18+
// control start hidden (see _custom.scss) and are revealed only after the
19+
// stored edition is applied, so there is no flash of the wrong menu.
520
(() => {
621
"use strict";
722

8-
console.log("[VersionToggle] custom.js loaded");
9-
1023
// Asset-modelling landing pages per edition. The top nav is otherwise
1124
// static, so a single URL can't be correct for both editions: we keep the
1225
// "Model Your Assets" nav link in sync with the selected version, and —
@@ -28,28 +41,24 @@
2841
};
2942

3043
const setVersion = (version) => {
31-
console.log("[VersionToggle] Setting version to:", version);
32-
3344
document.querySelectorAll(".version-opensource, .version-pro").forEach(el => {
3445
el.style.display = el.classList.contains(`version-${version}`) ? "block" : "none";
3546
});
3647

3748
localStorage.setItem("version", version);
38-
console.log("[VersionToggle] localStorage updated:", localStorage.getItem("version"));
39-
40-
// Update dropdown
41-
const selects = document.querySelectorAll("#version-select");
42-
selects.forEach(sel => {
43-
sel.value = version;
44-
sel.dataset.version = version;
45-
sel.style.visibility = "visible";
49+
50+
// Sync every segmented control instance, then reveal it
51+
document.querySelectorAll(".dd-version-seg").forEach(seg => {
52+
seg.querySelectorAll("button[data-version-value]").forEach(btn => {
53+
btn.setAttribute("aria-checked", btn.dataset.versionValue === version ? "true" : "false");
54+
});
55+
seg.style.visibility = "visible";
4656
});
4757

48-
// unhide sidebar after version is applied
58+
// Unhide sidebar after version is applied
4959
const sidebar = document.querySelector(".docs-sidebar");
5060
if (sidebar) {
5161
sidebar.style.visibility = "visible";
52-
console.log("[VersionToggle] Sidebar revealed");
5362
}
5463

5564
// Edition-aware top nav: route "Model Your Assets" to the page that
@@ -63,18 +72,17 @@
6372

6473
const initVersionToggle = () => {
6574
const storedVersion = localStorage.getItem("version") || "opensource";
66-
console.log("[VersionToggle] Stored version:", storedVersion);
6775
setVersion(storedVersion);
6876
};
6977

70-
// Delegated listener on body
71-
document.body.addEventListener("change", (e) => {
72-
if (e.target && e.target.id === "version-select") {
73-
console.log("[VersionToggle] Dropdown changed to:", e.target.value);
74-
setVersion(e.target.value);
78+
// Delegated listener on body — catches every control instance
79+
document.body.addEventListener("click", (e) => {
80+
const btn = e.target.closest("button[data-version-value]");
81+
if (btn) {
82+
setVersion(btn.dataset.versionValue);
7583
// Only on an explicit user toggle (not on load) follow the page to
7684
// the matching edition when viewing an asset-modelling page.
77-
switchAssetPageForVersion(e.target.value);
85+
switchAssetPageForVersion(btn.dataset.versionValue);
7886
}
7987
});
8088

@@ -91,6 +99,56 @@
9199
})();
92100

93101

102+
// Code block language labels — stamp the fence language onto each
103+
// expressive-code frame's (empty) title span so CSS can render it in the
104+
// header band via attr(data-lang). Frames whose fence "language" is really
105+
// an editor artifact (paths, line ranges) get a generic "code" label.
106+
(() => {
107+
"use strict";
108+
109+
const CLEAN_LANG = /^[a-z0-9_+#.-]{1,16}$/i;
110+
111+
const init = () => {
112+
document.querySelectorAll(".docs-content .expressive-code .frame").forEach(frame => {
113+
const title = frame.querySelector(".header .title");
114+
if (!title || title.textContent.trim() !== "" || title.dataset.lang) return;
115+
const code = frame.querySelector("pre code[data-lang]");
116+
let lang = code ? code.dataset.lang : "";
117+
if (!lang || lang === "fallback" || !CLEAN_LANG.test(lang)) lang = "code";
118+
title.dataset.lang = lang;
119+
frame.classList.add("dd-has-lang");
120+
});
121+
};
122+
123+
if (document.readyState === "loading") {
124+
document.addEventListener("DOMContentLoaded", init);
125+
} else {
126+
init();
127+
}
128+
})();
129+
130+
131+
// Homepage hero search field — forwards to the DocSearch modal
132+
(() => {
133+
"use strict";
134+
135+
const init = () => {
136+
const trigger = document.getElementById("ddHomeSearch");
137+
if (!trigger) return;
138+
trigger.addEventListener("click", () => {
139+
const btn = document.getElementsByClassName("DocSearch-Button")[0];
140+
if (btn) btn.click();
141+
});
142+
};
143+
144+
if (document.readyState === "loading") {
145+
document.addEventListener("DOMContentLoaded", init);
146+
} else {
147+
init();
148+
}
149+
})();
150+
151+
94152
// Scroll progress bar — shows reading progress on doc pages
95153
(() => {
96154
"use strict";

0 commit comments

Comments
 (0)