[object Object]

← back to Wallco Ai

YOLO R4 — keyboard shortcuts on isolate modal (W=wallpaper, P=paint, C=copy primary hex, ?=help). Scoped to modal-open state so it doesn't fight the global K/R card handler. Toast feedback on every action; nudge if W/P pressed before Isolate button clicked.

55f8ac2a1a8fd152f627b498cd7d98403f4f5734 · 2026-05-12 00:42:29 -0700 · Steve Abrams

Files touched

Diff

commit 55f8ac2a1a8fd152f627b498cd7d98403f4f5734
Author: Steve Abrams <steve@designerwallcoverings.com>
Date:   Tue May 12 00:42:29 2026 -0700

    YOLO R4 — keyboard shortcuts on isolate modal (W=wallpaper, P=paint, C=copy primary hex, ?=help). Scoped to modal-open state so it doesn't fight the global K/R card handler. Toast feedback on every action; nudge if W/P pressed before Isolate button clicked.
---
 YOLO_BACKLOG.md |  5 +++--
 server.js       | 27 +++++++++++++++++++++++++++
 2 files changed, 30 insertions(+), 2 deletions(-)

diff --git a/YOLO_BACKLOG.md b/YOLO_BACKLOG.md
index 27ed574..8b95a1a 100644
--- a/YOLO_BACKLOG.md
+++ b/YOLO_BACKLOG.md
@@ -29,7 +29,7 @@ User ask verbatim: "show final patterns and 1 room setting on https://wallco.ai/
 - [x] **R1 · Screenshot the isolate modal** — 2026-05-12 00:14 · 6 screenshots saved to tmp/isolate-qa/ · works: palette+SW labels render correctly · issues found: modal bottom cut at 900vh, review-card image-wrap aspect ratio off · *no commit (screenshots only)*
 - [ ] **R2 · ΔE closeness bands** — `/age-themes` and `/api/isolate` response both expose raw ΔE numbers. Add a human-readable closeness band per swatch: ΔE 0-5 "exact", 5-15 "close", 15-30 "approximate", 30+ "not in SW catalog (paint physics ceiling)". Render in both `/age-themes` and the isolate modal.
 - [x] **R3 · Adult band diff-chip clarity** — 2026-05-12 00:48 · resolved differently than architect spec'd. Adult band IS visually subtle (only body 13→15 changes) but renders TWO swatches because the body delta is real. Added explicit `diff-bar` chip strip above every band's compare grid showing each changed prop in `key from → to` format (e.g. Adult: "1 change: body 13 → 15"; Teen: "3 changes: font/body/h"). Diff detection auto-derived from `Object.keys(b.best).filter(k => b.current[k] !== b.best[k])` — single source of truth, no hardcoded annotations. Bands with zero diffs (none today) would render "no change recommended" placeholder. Verified live for all 8 bands.
-- [ ] **R4 · Isolate keyboard shortcuts** — add `W` / `P` to flip wallpaper/paint mode inside the open isolate modal. Add `C` to copy primary hex to clipboard. Document in the ? toast.
+- [x] **R4 · Isolate keyboard shortcuts** — 2026-05-12 00:52 · added scoped keydown handler inside iso-modal (fires only when modal is open). W=wallpaper mode, P=paint mode (both require Isolate button to have been clicked first, else toast nudges user). C=copy primary hex (palette[0].hex via navigator.clipboard with success/fail toast). ? toast shows full shortcut list. Doesn't conflict with global K/R/P card handler because that one early-returns when any modal is open. Verified handler is in served HTML.
 - [ ] **R5 · Isolate modal: source-design SW label** — currently the palette[0] hex shows its SW match, but the design's stored `dominant_hex` (which may differ from extraction) isn't labeled. Show both: "Design's `dominant_hex` = X (SW Y)" + "Extracted palette[0] = Z (SW W)".
 
 ### Visual polish
@@ -69,4 +69,5 @@ TICK · TIMESTAMP · ITEM · STATUS · COMMIT
 - T7 · 2026-05-12 00:28 · R10 tsd mobile QA · done · no fix needed (verified at 390×844)
 - T8 · 2026-05-12 00:35 · R11 dominant_sw · done · /api/isolate response now annotates dominant_hex with SW match
 - T9 · 2026-05-12 00:42 · R9 AI-language scrub · done · 9 public surfaces · admin banner kept per validation-loop · 9faa35b
-- T10 · 2026-05-12 00:48 · R3 Adult diff-chip · done · auto-detect changed props per band, render diff-bar above compare grid
+- T10 · 2026-05-12 00:48 · R3 Adult diff-chip · done · auto-detect changed props per band, render diff-bar above compare grid · 04c43b4
+- T11 · 2026-05-12 00:52 · R4 isolate W/P/C shortcuts · done · scoped keydown handler, toast feedback, clipboard for primary hex
diff --git a/server.js b/server.js
index 9aa3e42..e7f08d4 100644
--- a/server.js
+++ b/server.js
@@ -1760,6 +1760,33 @@ ${_isAdmin ? `
   function closeIso() { isoModal.classList.remove('open'); isoModal.setAttribute('aria-hidden', 'true'); }
   $('#iso-close').addEventListener('click', closeIso);
   document.addEventListener('keydown', e => { if (e.key === 'Escape' && isoModal.classList.contains('open')) closeIso(); });
+  // Isolate-modal-only shortcuts: W=wallpaper, P=paint, C=copy primary hex, ?=help
+  // Scoped to when modal is open; doesn't conflict with global K/R/P card handler
+  // because that one returns early when any modal is open (line ~1714).
+  document.addEventListener('keydown', e => {
+    if (!isoModal.classList.contains('open')) return;
+    if (e.target.matches('input, textarea, select')) return;
+    const key = e.key.toLowerCase();
+    if (key === 'w' || key === 'p') {
+      const toggle = $('#iso-mode-toggle');
+      if (!toggle.classList.contains('visible')) {
+        showToast('Click "Isolate this design" first');
+        return;
+      }
+      e.preventDefault();
+      const mode = key === 'w' ? 'wallpaper' : 'paint';
+      const btn = toggle.querySelector('button[data-mode="' + mode + '"]');
+      if (btn) { btn.click(); showToast(mode === 'wallpaper' ? 'Wallpaper mode' : 'Paint mode'); }
+    } else if (key === 'c') {
+      e.preventDefault();
+      const hex = CURRENT_ISO_DATA && CURRENT_ISO_DATA.palette && CURRENT_ISO_DATA.palette[0] && CURRENT_ISO_DATA.palette[0].hex;
+      if (!hex) { showToast('No palette yet'); return; }
+      navigator.clipboard.writeText(hex).then(() => showToast('Copied ' + hex)).catch(() => showToast('Copy failed'));
+    } else if (key === '?' || (e.shiftKey && key === '/')) {
+      e.preventDefault();
+      showToast('W=wallpaper · P=paint · C=copy primary hex · Esc=close', 4000);
+    }
+  });
 
   async function openIsolate(designId, title, imageUrl) {
     CURRENT_ISO_ID = designId;

← 444eefc YOLO R3 — add diff-bar chip strip to /age-themes bands. Auto  ·  back to Wallco Ai  ·  YOLO R2 — ΔE closeness bands in src/color-isolate. closeness 957e20b →