[object Object]

← back to Wallco Ai

edit modal: large + live preview image at top + Adjust tab default

ffcec80c00432a573b2209faac61536187b16990 · 2026-05-11 20:39:44 -0700 · SteveStudio2

Per Steve — 'show image at top and the various adjustments in sliders to
show live changes. show large.'

LAYOUT CHANGES
  - Modal grew 720px → 1100px (max width 96vw on smaller viewports).
  - Added <img id='edit-preview-img'> at the top of the modal, max-height
    48vh, object-fit:contain on a dark backdrop. Live readout line
    immediately below: 'Hue X° · Sat Y% · Vib … · Blur …px'.
  - Tabs reordered: ADJUST is now first and default-active so users land
    directly on the sliders. Order: ADJUST → COLOR → INFO → STYLE → SAVE.

LIVE PREVIEW WIRING
  - applyFilter() now mirrors filter + opacity to BOTH the page-level
    <img.detail-img> AND the modal's #edit-preview-img.
  - recolor() writes its new canvas.toDataURL to both images so a 905K-
    pixel pixel-domain recolor instantly appears in the modal preview.
  - Adjusted readout shows all 8 active filter values inline so the
    user can see exactly what state the design is in.

The bigger preview also makes texture changes (subtle hue tints, sepia,
blur) actually visible at a usable size — the old 280px panel didn't
leave room to see what the slider was doing.

Verified by recording a new click-through at 1440×1000:
  - Adjust tab default: hue cycles -180° → +180° → 0°, sat 50% → 200%
    → 100% — preview updates frame-by-frame with no flicker.
  - Color tab: click swatch → complementary → image goes olive→indigo
    in modal preview.
  - Save → Bake → redirects to new design (the chain still works).

Video: ~/Videos/shipped-apps/wallco-ai-modal-with-live-preview-*.mp4

Files touched

Diff

commit ffcec80c00432a573b2209faac61536187b16990
Author: SteveStudio2 <stevestudio2@SteveStacStudio.lan>
Date:   Mon May 11 20:39:44 2026 -0700

    edit modal: large + live preview image at top + Adjust tab default
    
    Per Steve — 'show image at top and the various adjustments in sliders to
    show live changes. show large.'
    
    LAYOUT CHANGES
      - Modal grew 720px → 1100px (max width 96vw on smaller viewports).
      - Added <img id='edit-preview-img'> at the top of the modal, max-height
        48vh, object-fit:contain on a dark backdrop. Live readout line
        immediately below: 'Hue X° · Sat Y% · Vib … · Blur …px'.
      - Tabs reordered: ADJUST is now first and default-active so users land
        directly on the sliders. Order: ADJUST → COLOR → INFO → STYLE → SAVE.
    
    LIVE PREVIEW WIRING
      - applyFilter() now mirrors filter + opacity to BOTH the page-level
        <img.detail-img> AND the modal's #edit-preview-img.
      - recolor() writes its new canvas.toDataURL to both images so a 905K-
        pixel pixel-domain recolor instantly appears in the modal preview.
      - Adjusted readout shows all 8 active filter values inline so the
        user can see exactly what state the design is in.
    
    The bigger preview also makes texture changes (subtle hue tints, sepia,
    blur) actually visible at a usable size — the old 280px panel didn't
    leave room to see what the slider was doing.
    
    Verified by recording a new click-through at 1440×1000:
      - Adjust tab default: hue cycles -180° → +180° → 0°, sat 50% → 200%
        → 100% — preview updates frame-by-frame with no flicker.
      - Color tab: click swatch → complementary → image goes olive→indigo
        in modal preview.
      - Save → Bake → redirects to new design (the chain still works).
    
    Video: ~/Videos/shipped-apps/wallco-ai-modal-with-live-preview-*.mp4
---
 server.js | 35 +++++++++++++++++++++++++----------
 1 file changed, 25 insertions(+), 10 deletions(-)

diff --git a/server.js b/server.js
index a0de36c..c3867fd 100644
--- a/server.js
+++ b/server.js
@@ -1433,7 +1433,7 @@ ${htmlHeader('/designs')}
             </section>
 
             <!-- ADJUST ─────────────────────────────────────────────────────── -->
-            <section class="edit-tabpane" data-pane="adjust">
+            <section class="edit-tabpane active" data-pane="adjust">
               <h3 class="pane-h">Live image adjustments</h3>
               <label class="adj"><span>Hue</span>       <input type="range" id="adj-hue"  min="-180" max="180" step="1" value="0"><em id="adj-hue-v">0°</em></label>
               <label class="adj"><span>Saturation</span><input type="range" id="adj-sat"  min="0"   max="200" step="1" value="100"><em id="adj-sat-v">100%</em></label>
@@ -1467,8 +1467,12 @@ ${htmlHeader('/designs')}
         .edit-modal { position:fixed; inset:0; z-index:200; display:flex; align-items:center; justify-content:center; }
         .edit-modal[hidden] { display:none; }
         .edit-modal-backdrop { position:absolute; inset:0; background:rgba(10,9,8,.7); backdrop-filter:blur(6px); }
-        .edit-modal-sheet { position:relative; width:min(720px, 92vw); max-height:88vh; background:#1a1816; color:#e8e2d6; border-radius:12px; border:1px solid #2a2a2a; box-shadow:0 24px 80px rgba(0,0,0,.6); display:flex; flex-direction:column; overflow:hidden; }
-        .edit-modal-head { display:flex; justify-content:space-between; align-items:center; padding:18px 22px 14px; border-bottom:1px solid #2a2a2a; }
+        .edit-modal-sheet { position:relative; width:min(1100px, 96vw); max-height:94vh; background:#1a1816; color:#e8e2d6; border-radius:12px; border:1px solid #2a2a2a; box-shadow:0 24px 80px rgba(0,0,0,.6); display:flex; flex-direction:column; overflow:hidden; }
+        .edit-modal-head { display:flex; justify-content:space-between; align-items:center; padding:14px 22px; border-bottom:1px solid #2a2a2a; flex-shrink:0; }
+        /* Big live preview image at the top */
+        .edit-preview-wrap { position:relative; padding:14px 22px; background:#0f0e0c; border-bottom:1px solid #2a2a2a; flex-shrink:0; }
+        .edit-preview-img { display:block; width:100%; max-height:48vh; object-fit:contain; border-radius:6px; transition:filter .12s ease, opacity .12s ease; background:#000; }
+        .edit-preview-readout { font:11px var(--mono,monospace); color:#888; margin-top:8px; text-align:center; }
         .edit-modal-head h2 { margin:0; font-family:'Cormorant Garamond',serif; font-weight:300; font-size:22px; color:#f0eadc; }
         .edit-modal-close { background:transparent; border:0; color:#888; font-size:22px; cursor:pointer; padding:0 6px; line-height:1; }
         .edit-modal-close:hover { color:#fff; }
@@ -1855,19 +1859,28 @@ ${htmlHeader('/designs')}
         });
 
         // ── 1. CSS-filter live adjustments ─────────────────────────────────
+        var previewImg = document.getElementById('edit-preview-img');
         var adjState = { hue:0, sat:100, vib:100, bri:100, con:100, opa:100, sep:0, blur:0 };
         function applyFilter() {
-          img.style.filter =
+          var vibBoost = (adjState.vib - 100) / 200;
+          var filter =
             'hue-rotate(' + adjState.hue + 'deg) ' +
             'saturate(' + (adjState.sat / 100) + ') ' +
             'brightness(' + (adjState.bri / 100) + ') ' +
             'contrast(' + (adjState.con / 100) + ') ' +
             'sepia(' + (adjState.sep / 100) + ') ' +
-            'blur(' + adjState.blur + 'px)';
-          img.style.opacity = adjState.opa / 100;
-          // "Vibrance" approximated as saturation*0.5 boost on the saturate filter
-          var vibBoost = (adjState.vib - 100) / 200;
-          img.style.filter += ' saturate(' + (1 + vibBoost) + ')';
+            'blur(' + adjState.blur + 'px) ' +
+            'saturate(' + (1 + vibBoost) + ')';
+          var opacity = adjState.opa / 100;
+          img.style.filter = filter;
+          img.style.opacity = opacity;
+          if (previewImg) { previewImg.style.filter = filter; previewImg.style.opacity = opacity; }
+          var ro = document.getElementById('edit-preview-readout');
+          if (ro) ro.textContent =
+            'Hue ' + adjState.hue + '°  ·  Sat ' + adjState.sat + '%  ·  Vib ' + adjState.vib +
+            '%  ·  Bri ' + adjState.bri + '%  ·  Con ' + adjState.con +
+            '%  ·  Opa ' + adjState.opa + '%  ·  Sep ' + adjState.sep +
+            '%  ·  Blur ' + adjState.blur + 'px';
         }
         var sliders = [
           ['hue',  '°'], ['sat','%'], ['vib','%'], ['bri','%'],
@@ -2020,7 +2033,9 @@ ${htmlHeader('/designs')}
           }
           ctx.putImageData(imgData, 0, 0);
           // Replace the img src with the canvas data URL
-          img.src = canvas.toDataURL('image/png');
+          var dataUrl = canvas.toDataURL('image/png');
+          img.src = dataUrl;
+          if (previewImg) previewImg.src = dataUrl;
           document.getElementById('wheel-readout').textContent =
             'Recolored ' + changed.toLocaleString() + ' pixels  (' + fromHex + ' → ' + toHex + ')';
           // After recolor, re-extract palette

← c63100c crawl_pd: use Wikimedia thumbnail URLs (iiurlwidth=1280) ins  ·  back to Wallco Ai  ·  Sync /age-themes route to v9 — teen body 14→16/h22, adult li f5a303a →