From 02c57752ba6a9ff83e4241bfa0f82b49b005e1ae Mon Sep 17 00:00:00 2001 From: Obvious Date: Sun, 11 Oct 2026 20:42:30 +0000 Subject: [PATCH] feat(command palette): Ctrl/Cmd+K search over workspaces, shots, lessons, glossary MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Native palette (web/palette.js): case-insensitive substring search over the three workspaces, the shot catalog (/shots, fetched once and cached), the 43 lesson titles and 47 glossary terms, plus actions — share this view, OpenUSD export, start/resume the guided study, open the edit drawer, open the catalog. Keyboard-first (arrows/Enter/Esc), focus trapped by native showModal and restored to the opener on close; runs every action through existing public surfaces (router hash grammar, window.FusionLab hooks, replay/app handlers) — no new app paths, no dependencies, ES5-compatible IIFE. Companion edits: header ⌘K stub enabled with aria-haspopup/aria-expanded; palette styles from the existing token set (no new palette); a small additive window.FusionLab.guided.start(lessonId) hook in guide.js so a lesson item opens that exact lesson through the same jump the per-panel "?" buttons use. Co-authored-by: Tapan Ganatma Nakkina --- web/guide.js | 12 +++ web/index.html | 3 +- web/palette.js | 243 +++++++++++++++++++++++++++++++++++++++++++++++++ web/style.css | 18 ++++ 4 files changed, 275 insertions(+), 1 deletion(-) create mode 100644 web/palette.js diff --git a/web/guide.js b/web/guide.js index a6c8c60..6caa016 100644 --- a/web/guide.js +++ b/web/guide.js @@ -246,6 +246,18 @@ modeSeg.addEventListener('click', (e) => { const b = e.target.closest('button'); if (b) setMode(b.dataset.v); }); welcome.addEventListener('click', (e) => { const b = e.target.closest('[data-mode]'); if (b) setMode(b.dataset.mode); }); + // ---------------------------------------------------------------- the command palette's hook + // The palette (web/palette.js) starts or resumes the study through this — the same jump the per-panel + // "?" buttons take (find the lesson, setMode). Additive: existing FusionLab keys untouched. + window.FusionLab = Object.assign(window.FusionLab || {}, { guided: { + start(lessonId) { + if (!L) return false; // lessons not loaded (boot failed): the palette reports it, nothing breaks + if (lessonId != null) { const i = L.steps.findIndex((s) => s.id === lessonId); if (i >= 0) idx = i; } + setMode('guided'); + return true; + }, + } }); + async function boot() { const [lessons, glossary] = await Promise.all(['lessons', 'glossary'].map((f) => fetch(`/static/${f}.json`).then((r) => r.json()))); L = lessons; G = glossary.terms; diff --git a/web/index.html b/web/index.html index f6c507c..ddabebc 100644 --- a/web/index.html +++ b/web/index.html @@ -14,6 +14,7 @@ +
@@ -28,7 +29,7 @@

FUSIONLAB · open-data tokamak twin

- +