[object Object]

← back to Commercialrealestate

CRCP listings: property panel now docks to the right full-height (no longer a floating center card) + drag its left edge to widen (savable); corner-nav Sections drawer also resizable + saved

890dbe13c6a3a374eeddac10dd73567e77161737 · 2026-08-17 17:29:19 -0700 · steve

Files touched

Diff

commit 890dbe13c6a3a374eeddac10dd73567e77161737
Author: steve <steve@designerwallcoverings.com>
Date:   Mon Aug 17 17:29:19 2026 -0700

    CRCP listings: property panel now docks to the right full-height (no longer a floating center card) + drag its left edge to widen (savable); corner-nav Sections drawer also resizable + saved
---
 public/corner-nav.js | 31 ++++++++++++++++++++++++++++++-
 public/mls.html      | 46 +++++++++++++++++++++++++++++++++++++++++-----
 2 files changed, 71 insertions(+), 6 deletions(-)

diff --git a/public/corner-nav.js b/public/corner-nav.js
index 403e281..c37ffe7 100644
--- a/public/corner-nav.js
+++ b/public/corner-nav.js
@@ -44,12 +44,16 @@
     '.cnav-burger .lbl{font-size:12px;letter-spacing:.3px;} @media(max-width:640px){.cnav-burger .lbl{display:none;}}' +
     '.cnav-ov{position:fixed;inset:0;background:rgba(0,0,0,.5);z-index:9998;opacity:0;pointer-events:none;transition:opacity .18s;}' +
     '.cnav-ov.on{opacity:1;pointer-events:auto;}' +
-    '.cnav-drawer{position:fixed;top:0;bottom:0;width:min(330px,88vw);background:#11161f;color:#e6e8ec;z-index:9999;' +
+    '.cnav-drawer{position:fixed;top:0;bottom:0;width:var(--cnav-w,min(330px,88vw));background:#11161f;color:#e6e8ec;z-index:9999;' +
       'box-shadow:0 0 40px rgba(0,0,0,.5);display:flex;flex-direction:column;transition:transform .2s ease;' +
       'font:14px/1.5 -apple-system,BlinkMacSystemFont,"Segoe UI",Helvetica,Arial,sans-serif;}' +
     '.cnav-drawer.left{left:0;border-right:1px solid #232a38;transform:translateX(-104%);}' +
     '.cnav-drawer.right{right:0;border-left:1px solid #232a38;transform:translateX(104%);}' +
     '.cnav-drawer.on{transform:translateX(0);}' +
+    /* drag the inner vertical edge to widen the drawer (right→left edge, left→right edge); width persists */
+    '.cnav-rsz{position:absolute;top:0;bottom:0;width:9px;cursor:ew-resize;z-index:3;}' +
+    '.cnav-drawer.right .cnav-rsz{left:0;} .cnav-drawer.left .cnav-rsz{right:0;}' +
+    '.cnav-rsz:hover,.cnav-rsz.on{background:rgba(200,162,75,.55);}' +
     '.cnav-hd{display:flex;align-items:center;justify-content:space-between;padding:14px 16px;border-bottom:1px solid #232a38;' +
       'font-size:12px;text-transform:uppercase;letter-spacing:.7px;color:#C8A24B;}' +
     '.cnav-hd .sub{display:block;color:#8A93A2;font-size:10.5px;letter-spacing:.3px;text-transform:none;margin-top:2px;}' +
@@ -144,6 +148,31 @@
     var body = el('div', 'cnav-body');
     d.appendChild(hd); d.appendChild(body); document.body.appendChild(d); d._body = body;
 
+    // ── resizable: drag the inner vertical edge to widen the drawer; width persists per side ──
+    var rsz = el('div', 'cnav-rsz'); rsz.setAttribute('title', 'Drag to widen · double-click to reset'); d.appendChild(rsz);
+    var RKEY = 'cnav_w_' + side;
+    var savedW = parseInt(localStorage.getItem(RKEY));
+    if (!isNaN(savedW) && savedW > 0) d.style.setProperty('--cnav-w', savedW + 'px');
+    (function () {
+      var drag = false, startX = 0, startW = 0;
+      var curW = function () { return d.getBoundingClientRect().width; };
+      rsz.addEventListener('mousedown', function (e) {
+        drag = true; startX = e.clientX; startW = curW();
+        document.body.style.userSelect = 'none'; rsz.classList.add('on'); e.preventDefault();
+      });
+      window.addEventListener('mousemove', function (e) {
+        if (!drag) return;
+        var delta = side === 'right' ? (startX - e.clientX) : (e.clientX - startX);   // right drawer widens by dragging left
+        var w = Math.max(260, Math.min(Math.round(window.innerWidth * 0.95), Math.round(startW + delta)));
+        d.style.setProperty('--cnav-w', w + 'px');
+      });
+      window.addEventListener('mouseup', function () {
+        if (!drag) return; drag = false; document.body.style.userSelect = ''; rsz.classList.remove('on');
+        try { localStorage.setItem(RKEY, String(Math.round(curW()))); } catch (e) {}
+      });
+      rsz.addEventListener('dblclick', function () { d.style.removeProperty('--cnav-w'); try { localStorage.removeItem(RKEY); } catch (e) {} });
+    })();
+
     // Focus trap: keep Tab/Shift+Tab inside the open drawer; arrow keys navigate links.
     d.addEventListener('keydown', function (e) {
       if (!d.classList.contains('on')) return;
diff --git a/public/mls.html b/public/mls.html
index 5cf9582..735bc52 100644
--- a/public/mls.html
+++ b/public/mls.html
@@ -38,9 +38,13 @@
      widths (inline width), which overflows/scrolls and leaves the divider-drag doing nothing to the
      columns. Force 100% so table-layout:fixed stretches the columns to fill — and the records expand
      wider as you drag the divider right. Column drag-resize still works (adjusts proportions). */
-  #tableView table.mls{width:100% !important;}
+  #tableView table.mls{width:var(--rec-w,100%) !important;min-width:100%;}
   #tableView table.mls colgroup[data-cr] col{width:auto !important;}
   #tableView table.mls td,#tableView table.mls th{overflow:hidden;text-overflow:ellipsis;}
+  /* right-edge grip: drag to widen the records past the screen edge (columns get wider, table scrolls) */
+  .recgrip{flex:0 0 7px;align-self:stretch;position:sticky;top:53px;height:calc(100vh - 53px);background:var(--line);cursor:ew-resize;z-index:6;transition:background .12s;}
+  .recgrip:hover,.recgrip.dragging{background:var(--acc);}
+  @media(max-width:820px){ .recgrip{display:none;} }
   table.mls thead th{position:sticky;top:0;background:var(--bg2);color:var(--mut);text-transform:uppercase;letter-spacing:.3px;font-size:10.5px;padding:8px 10px;border-bottom:1px solid var(--line);cursor:pointer;user-select:none;z-index:2;}
   table.mls thead th:hover{color:var(--ink);}
   table.mls thead th.asc::after{content:' ▲';color:var(--acc);} table.mls thead th.desc::after{content:' ▼';color:var(--acc);}
@@ -72,9 +76,13 @@
   .gc .row{display:flex;justify-content:space-between;font-size:12.5px;padding:2px 0;border-top:1px solid var(--line);}
   .gc .row .k{color:var(--mut);} .gc .row .v{font-variant-numeric:tabular-nums;}
   .hide{display:none;}
-  #ov{display:none;position:fixed;inset:0;background:rgba(0,0,0,.6);z-index:60;align-items:flex-start;justify-content:center;padding:40px 14px;overflow-y:auto;}
+  /* property panel docks to the RIGHT as a full-height, resizable side panel (no longer a floating card) */
+  #ov{display:none;position:fixed;inset:0;background:rgba(0,0,0,.6);z-index:60;align-items:stretch;justify-content:flex-end;padding:0;overflow:hidden;}
   #ov.on{display:flex;}
-  #modal{width:min(680px,96vw);background:var(--card);border:1px solid var(--line);border-radius:15px;padding:20px 22px;position:relative;}
+  #modal{width:var(--modal-w,min(760px,96vw));max-width:96vw;height:100vh;overflow-y:auto;background:var(--card);border-left:1px solid var(--line);border-radius:0;padding:20px 26px 40px 22px;position:relative;box-shadow:-12px 0 40px rgba(0,0,0,.4);}
+  /* drag the LEFT edge of the panel to widen it (savable); double-click resets */
+  #modalRsz{position:absolute;top:0;left:0;bottom:0;width:11px;cursor:ew-resize;z-index:3;}
+  #modalRsz:hover,#modalRsz.on{background:color-mix(in srgb,var(--acc) 45%,transparent);}
   #modal h3{margin:0 0 2px;font-size:19px;} .ph-sub{color:var(--warn);font-size:13px;}
   .ph-x{position:absolute;top:12px;right:14px;background:none;border:0;color:var(--mut);font-size:22px;cursor:pointer;}
   .ph-ci{display:flex;gap:14px;flex-wrap:wrap;margin:8px 0;font-size:13.5px;}
@@ -173,7 +181,7 @@
 <div class="wrap">
   <div class="tblbar" id="tblbar">
     <button class="csvbtn" id="csv2" title="Download the current filtered rows as a CSV spreadsheet">⬇ Download CSV</button>
-    <span class="mut" style="font-size:11px">Drag the vertical bar between the filters and the records to widen the table → · double-click it to collapse/restore the filters.</span>
+    <span class="mut" style="font-size:11px">Drag the <b>left</b> bar (filters↔records) to reclaim space · drag the <b>right</b> edge bar to widen the columns wider than the screen (scrolls) · double-click either to reset.</span>
     <span id="acctbar" style="margin-left:auto;display:flex;align-items:center;gap:8px;flex-wrap:wrap;font-size:12px"></span>
   </div>
   <div class="statsbar" id="statsbar"></div>
@@ -182,8 +190,9 @@
   <div id="listView" class="hide"></div>
   <div id="moreWrap" style="text-align:center;padding:16px 0"></div>
 </div>
+<div class="recgrip" id="recgrip" title="Drag left to widen the records / columns (table scrolls past the edge) · double-click to reset to fit"></div>
 </div>
-<div id="ov"><div id="modal"><button class="ph-x" aria-label="Close" onclick="document.getElementById('ov').classList.remove('on')">✕</button><div id="mbody"></div></div></div>
+<div id="ov"><div id="modal"><div id="modalRsz" title="Drag to widen the panel · double-click to reset"></div><button class="ph-x" aria-label="Close" onclick="document.getElementById('ov').classList.remove('on')">✕</button><div id="mbody"></div></div></div>
 <script>
 // Day/Night theme — pre-applied before first paint (see head snippet).
 // apply() only PAINTS — does NOT persist (passive loads must not lock in a theme;
@@ -585,6 +594,33 @@ if($('#csv2')) $('#csv2').addEventListener('click',exportCSV);
   window.addEventListener('mouseup',()=>{ if(!dragging) return; dragging=false; div.classList.remove('dragging'); document.body.classList.remove('raildrag'); try{localStorage.setItem(KEY,String(cur()));}catch(e){} });
   div.addEventListener('dblclick',()=>{ const c=cur(); if(c>10){ lastW=c; setW(0); } else setW(lastW>10?lastW:DEF); try{localStorage.setItem(KEY,String(cur()));}catch(e){} });
 })();
+// ── right-edge grip: drag LEFT to widen the records/columns past the screen edge (table scrolls);
+//    drag RIGHT to shrink back to fit; double-click resets to fill. Persisted. ──
+(function(){
+  const shell=document.querySelector('.shell'), grip=$('#recgrip'), tw=document.querySelector('#tableView'); if(!shell||!grip||!tw) return;
+  const KEY='cre_mls_recw', MULT=2;
+  const contW=()=>tw.clientWidth||1;
+  const curPx=()=>{ const n=parseInt(getComputedStyle(shell).getPropertyValue('--rec-w')); return isNaN(n)?contW():n; };
+  const setPx=w=>{ const min=contW(), max=min*3; w=Math.max(min,Math.min(max,Math.round(w))); shell.style.setProperty('--rec-w', w<=min+2?'100%':(w+'px')); };
+  const saved=parseInt(localStorage.getItem(KEY)); if(!isNaN(saved)&&saved>0) requestAnimationFrame(()=>setPx(saved));
+  let drag=false,startX=0,startW=0;
+  grip.addEventListener('mousedown',e=>{ drag=true; startX=e.clientX; startW=Math.max(contW(),curPx()); grip.classList.add('dragging'); document.body.classList.add('raildrag'); e.preventDefault(); });
+  window.addEventListener('mousemove',e=>{ if(drag) setPx(startW + (startX-e.clientX)*MULT); });   // drag LEFT → wider
+  window.addEventListener('mouseup',()=>{ if(!drag) return; drag=false; grip.classList.remove('dragging'); document.body.classList.remove('raildrag'); const w=curPx(); try{localStorage.setItem(KEY, w>contW()+2?String(w):'0');}catch(e){} });
+  grip.addEventListener('dblclick',()=>{ shell.style.setProperty('--rec-w','100%'); try{localStorage.setItem(KEY,'0');}catch(e){} });
+})();
+// ── property panel: drag its LEFT edge to widen the right-docked panel (savable); double-click resets ──
+(function(){
+  const modal=$('#modal'), rsz=$('#modalRsz'); if(!modal||!rsz) return;
+  const KEY='cre_mls_modalw';
+  const saved=parseInt(localStorage.getItem(KEY)); if(!isNaN(saved)&&saved>0) modal.style.setProperty('--modal-w', saved+'px');
+  const curW=()=>modal.getBoundingClientRect().width;
+  let drag=false,startX=0,startW=0;
+  rsz.addEventListener('mousedown',e=>{ drag=true; startX=e.clientX; startW=curW(); rsz.classList.add('on'); document.body.style.userSelect='none'; e.preventDefault(); });
+  window.addEventListener('mousemove',e=>{ if(!drag) return; const w=Math.max(420, Math.min(Math.round(window.innerWidth*0.96), Math.round(startW+(startX-e.clientX)))); modal.style.setProperty('--modal-w', w+'px'); });
+  window.addEventListener('mouseup',()=>{ if(!drag) return; drag=false; rsz.classList.remove('on'); document.body.style.userSelect=''; try{localStorage.setItem(KEY,String(Math.round(curW())));}catch(e){} });
+  rsz.addEventListener('dblclick',()=>{ modal.style.removeProperty('--modal-w'); try{localStorage.removeItem(KEY);}catch(e){} });
+})();
 // ── per-user settings: sign in with your own un/pw → your view (columns, order, rail width, theme,
 //    heat, sort) follows you across browsers; auto-saves on exit; shows "last saved". Layered on the
 //    existing CRCP accounts system (scrypt-hashed passwords, session cookie). ──

← 5a913c4 CRCP listings: records table fills the full panel width and  ·  back to Commercialrealestate  ·  auto-data-snapshot: 2026-08-17T18:01:33 (8 data files) — scr 7e0658e →