Add dark website and documentation with GitHub Pages deployment

Include the updated desktop screenshot, active-monitor screenshot capture and editor locking, and Settings window drag areas.
This commit is contained in:
Samuel Onoja committed 2026-09-27 10:34:33 +01:00
1 parent e5e2b74a25
commit 0cd48bcc81
15 files changed
+1794 -12

No files matched your search

+130
View File
@@ -0,0 +1,130 @@
// Progressive enhancement for the handbook. Navigation and content work without JS.
const search = document.querySelector("#docs-search");
const results = document.querySelector("#search-results");
const status = document.querySelector("#search-status");
let indexPromise;
if (search) {
search.closest(".docs-search").hidden = false;
const loadIndex = () =>
(indexPromise ||= fetch("search-index.json")
.then((response) => {
if (!response.ok) throw new Error("Search index unavailable");
return response.json();
})
.catch((error) => {
indexPromise = null;
throw error;
}));
search.addEventListener("focus", () => {
loadIndex().catch(() => {});
});
search.addEventListener("input", async () => {
const query = search.value.trim().toLocaleLowerCase();
if (!query) {
results.hidden = true;
results.replaceChildren();
status.textContent = "";
return;
}
try {
const index = await loadIndex();
if (search.value.trim().toLocaleLowerCase() !== query) return;
const words = query.split(/\s+/);
const matches = index
.filter((item) =>
words.every((word) =>
`${item.page} ${item.heading} ${item.text}`
.toLocaleLowerCase()
.includes(word),
),
)
.sort(
(a, b) =>
Number(b.heading.toLocaleLowerCase().includes(query)) -
Number(a.heading.toLocaleLowerCase().includes(query)),
)
.slice(0, 10);
results.replaceChildren();
for (const item of matches) {
const link = document.createElement("a");
link.href = item.url;
const title = document.createElement("strong");
title.textContent = `${item.page} / ${item.heading}`;
const snippet = document.createElement("span");
const position = Math.max(
0,
item.text.toLocaleLowerCase().indexOf(words[0]) - 45,
);
snippet.textContent = `${position ? "…" : ""}${item.text.slice(position, position + 165)}${item.text.length > position + 165 ? "…" : ""}`;
link.append(title, snippet);
results.append(link);
}
if (!matches.length) {
const empty = document.createElement("p");
empty.textContent =
"No matching sections. Try “wallpaper”, “shortcuts”, or “notifications”.";
results.append(empty);
}
results.hidden = false;
status.textContent = `${matches.length} matching sections.`;
} catch {
if (search.value.trim().toLocaleLowerCase() !== query) return;
results.hidden = true;
status.textContent = "Search is unavailable. Browse the guides below.";
}
});
document.addEventListener("keydown", (event) => {
if (event.key === "Escape") {
results.hidden = true;
search.focus();
}
if (
event.key === "/" &&
!["INPUT", "TEXTAREA"].includes(document.activeElement.tagName) &&
!event.ctrlKey &&
!event.metaKey &&
!event.altKey
) {
event.preventDefault();
search.focus();
}
if (
event.key === "ArrowDown" &&
document.activeElement === search &&
!results.hidden
) {
const first = results.querySelector("a");
if (first) {
event.preventDefault();
first.focus();
}
}
});
document.addEventListener("click", (event) => {
if (!event.target.closest(".docs-search")) results.hidden = true;
});
}
if (navigator.clipboard?.writeText) {
for (const block of document.querySelectorAll(".prose pre")) {
const button = document.createElement("button");
button.type = "button";
button.className = "code-copy";
button.textContent = "Copy";
button.setAttribute("aria-label", "Copy code example");
button.addEventListener("click", async () => {
try {
await navigator.clipboard.writeText(
block.querySelector("code").textContent,
);
button.textContent = "Copied";
if (status) status.textContent = "Code example copied.";
} catch {
button.textContent = "Select to copy";
if (status)
status.textContent =
"Copy failed. Select the code to copy it manually.";
}
});
block.append(button);
}
}