From 4d0941b524e77d459cd8fc03fc0e1c0b8f4d57f9 Mon Sep 17 00:00:00 2001 From: tegwick Date: Wed, 18 Mar 2026 00:18:56 +0100 Subject: [PATCH] fix(dashboard): robust shift-mode tracking via mousemove + element highlights MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - updateMode() now subscribes to keydown, keyup AND mousemove so the body class stays in sync regardless of where focus is (mirrors the pattern from the working modifier-click demo) - cursor: copy replaces crosshair (matches copy-affordance semantics) - figure, h2–h4 and [data-widget-name] elements get a dashed indigo outline + subtle background tint when shift is held, so the user can see which elements are annotatable before clicking Co-Authored-By: Claude Sonnet 4.6 --- dashboard/src/components/improvement-modal.js | 43 +++++++++++++------ 1 file changed, 30 insertions(+), 13 deletions(-) diff --git a/dashboard/src/components/improvement-modal.js b/dashboard/src/components/improvement-modal.js index 8b58c44..03520ea 100644 --- a/dashboard/src/components/improvement-modal.js +++ b/dashboard/src/components/improvement-modal.js @@ -140,9 +140,21 @@ function _ensureStyles() { @keyframes _im-tin { from { opacity:0; transform:translateX(-50%) translateY(6px) } to { opacity:1; transform:translateX(-50%) translateY(0) } } @keyframes _im-tout { from { opacity:1 } to { opacity:0 } } -/* ── Shift-held cursor override (applied to ) ─────────────────────── */ -.impr-shift-mode, -.impr-shift-mode * { cursor: crosshair !important; } +/* ── Shift-held mode: cursor + element highlighting ─────────────────────── */ +.impr-mode-shift, +.impr-mode-shift * { cursor: copy !important; } + +/* Highlight "widget" elements so the user sees what can be annotated */ +.impr-mode-shift #observablehq-main figure, +.impr-mode-shift #observablehq-main h2, +.impr-mode-shift #observablehq-main h3, +.impr-mode-shift #observablehq-main h4, +.impr-mode-shift #observablehq-main [data-widget-name] { + outline: 1px dashed rgba(99, 102, 241, 0.45); + background: rgba(99, 102, 241, 0.055) !important; + border-radius: 4px; + transition: background 0.1s, outline 0.1s; +} `; document.head.append(s); } @@ -197,7 +209,7 @@ function _toast(msg) { let _initialized = false; /** - * Wire right-click → improvement modal on the current page. + * Wire Shift+click → improvement modal on the current page. * Safe to call multiple times — only the first call takes effect. * * @param {object} opts @@ -209,15 +221,20 @@ export function initImprovementModal({ apiBase = "http://127.0.0.1:8000", domain _initialized = true; _ensureStyles(); - // Shift-held cursor indicator - document.addEventListener("keydown", (e) => { - if (e.key === "Shift") document.body.classList.add("impr-shift-mode"); - }); - document.addEventListener("keyup", (e) => { - if (e.key === "Shift") document.body.classList.remove("impr-shift-mode"); - }); - // Remove shift-mode if window loses focus while Shift is held - window.addEventListener("blur", () => document.body.classList.remove("impr-shift-mode")); + // Track modifier state via keydown, keyup, AND mousemove so mode + // stays in sync even when focus changes between elements. + function _updateMode(e) { + if (e.shiftKey) { + document.body.classList.add("impr-mode-shift"); + } else { + document.body.classList.remove("impr-mode-shift"); + } + } + window.addEventListener("keydown", _updateMode); + window.addEventListener("keyup", _updateMode); + window.addEventListener("mousemove", _updateMode); + // Clear on blur in case Shift is held when the window loses focus + window.addEventListener("blur", () => document.body.classList.remove("impr-mode-shift")); document.addEventListener("click", (e) => { if (!e.shiftKey) return;