[object Object]

← back to Pattern Vault

viewer standard: add Grid/List toggle + per-field on/off menu to internal record-grid viewer

01f96b051050ef864e06fad13a65f799362959ea · 2026-08-12 08:53:17 -0700 · Steve

Files touched

Diff

commit 01f96b051050ef864e06fad13a65f799362959ea
Author: Steve <steve@designerwallcoverings.com>
Date:   Wed Aug 12 08:53:17 2026 -0700

    viewer standard: add Grid/List toggle + per-field on/off menu to internal record-grid viewer
---
 public/index.html | 80 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 80 insertions(+)

diff --git a/public/index.html b/public/index.html
index 5472d3f..b04a914 100644
--- a/public/index.html
+++ b/public/index.html
@@ -37,6 +37,35 @@ dialog button{background:var(--gold);border:0;border-radius:8px;padding:10px 18p
 .note{color:var(--mut);font-size:12px;margin-top:10px}
 footer{border-top:1px solid var(--line);color:var(--mut);text-align:center;padding:26px;font-size:13px}
 footer a{color:var(--gold)}
+
+/* ── Grid / List toggle ── */
+.vtoggle{display:flex;border:1px solid var(--line);border-radius:8px;overflow:hidden}
+.vtoggle button{background:var(--card);color:var(--mut);border:none;padding:7px 14px;font:13px/1 inherit;cursor:pointer}
+.vtoggle button.on{background:var(--gold);color:#1a1208;font-weight:700}
+
+/* ── List view ── */
+.grid.list{display:block;padding:10px 6vw 60px}
+.grid.list .card{display:flex;flex-direction:row;align-items:stretch;margin-bottom:10px;border-radius:10px;transform:none!important}
+.grid.list .card:hover{transform:none!important}
+.grid.list .card img{width:80px;min-width:80px;height:80px;aspect-ratio:auto;object-fit:cover}
+.grid.list .card .pad{flex:1;padding:10px 14px;display:flex;flex-direction:column;justify-content:center;gap:4px}
+.grid.list .origtag{top:6px;left:6px}
+.grid.list .roomtag{display:none}
+
+/* ── Fields menu ── */
+.fieldmenu{position:relative}
+.fbtn{background:var(--card);color:var(--mut);border:1px solid var(--line);border-radius:8px;padding:7px 14px;font:13px/1 inherit;cursor:pointer}
+.fbtn:hover{border-color:var(--gold);color:var(--ink)}
+.fpop{position:absolute;top:calc(100% + 8px);right:0;background:var(--card);border:1px solid var(--line);border-radius:10px;box-shadow:0 12px 30px #0008;padding:8px 4px;z-index:30;min-width:176px}
+.fpop[hidden]{display:none}
+.fpop label{display:flex;align-items:center;gap:10px;padding:6px 14px;font-size:13px;color:var(--mut);cursor:pointer;white-space:nowrap}
+.fpop label:hover{color:var(--ink)}
+.fpop input{accent-color:var(--gold)}
+
+/* ── Field-hide rules (grid mode only) ── */
+.grid:not(.list).hf-title  .card .t     {display:none}
+.grid:not(.list).hf-style  .card .s     {display:none}
+.grid:not(.list).hf-tiers  .card .tiers {display:none}
 </style></head><body>
 <header>
   <h1>The <em>Pattern</em> Vault</h1>
@@ -48,8 +77,21 @@ footer a{color:var(--gold)}
   <label>Sort <select id="sortSel">
     <option value="newest">Newest</option><option value="title">Title A→Z</option>
     <option value="category">Style</option><option value="color">Color</option>
+    <option value="id">ID A→Z</option>
   </select></label>
   <label>Density <input type="range" id="density" min="2" max="6" value="4"></label>
+  <div class="vtoggle">
+    <button id="vGrid" class="on" onclick="setView('grid')">▦ Grid</button>
+    <button id="vList" onclick="setView('list')">☰ List</button>
+  </div>
+  <div class="fieldmenu">
+    <button class="fbtn" onclick="toggleFieldsMenu(event)">Fields ▾</button>
+    <div class="fpop" id="fpop" hidden>
+      <label><input type="checkbox" data-pf="title" checked> Title</label>
+      <label><input type="checkbox" data-pf="style" checked> Style line</label>
+      <label><input type="checkbox" data-pf="tiers" checked> License tiers</label>
+    </div>
+  </div>
 </div>
 <div id="inhouseBand" style="text-align:center;color:var(--mut);font-size:13px;padding:0 6vw 6px"></div>
 <div class="grid" id="grid"></div>
@@ -65,10 +107,48 @@ sortSel.value=localStorage.pvSort||'newest';density.value=localStorage.pvCols||'
 document.documentElement.style.setProperty('--cols',density.value);
 sortSel.onchange=()=>{localStorage.pvSort=sortSel.value;render()};
 density.oninput=()=>{localStorage.pvCols=density.value;document.documentElement.style.setProperty('--cols',density.value)};
+
+// ── Grid / List toggle ──
+const PV_FIELD_DEFAULTS={title:true,style:true,tiers:true};
+function setView(v){
+  const g=document.getElementById('grid');
+  g.classList.toggle('list',v==='list');
+  document.getElementById('vGrid').classList.toggle('on',v!=='list');
+  document.getElementById('vList').classList.toggle('on',v==='list');
+  localStorage.pvView=v;
+}
+(function(){setView(localStorage.pvView||'grid')})();
+
+// ── Fields menu ──
+function getPVFields(){
+  try{return Object.assign({},PV_FIELD_DEFAULTS,JSON.parse(localStorage.pvFields||'{}'));}
+  catch(e){return Object.assign({},PV_FIELD_DEFAULTS);}
+}
+function applyPVFields(prefs){
+  const g=document.getElementById('grid');
+  for(const[k,on]of Object.entries(prefs))g.classList.toggle('hf-'+k,!on);
+  document.querySelectorAll('#fpop [data-pf]').forEach(cb=>{cb.checked=!!prefs[cb.dataset.pf];});
+}
+function toggleFieldsMenu(e){
+  e.stopPropagation();
+  const p=document.getElementById('fpop');
+  p.hidden=!p.hidden;
+}
+document.addEventListener('click',()=>{const p=document.getElementById('fpop');if(p)p.hidden=true;});
+document.querySelectorAll('#fpop [data-pf]').forEach(cb=>{
+  cb.addEventListener('change',()=>{
+    const prefs=getPVFields();
+    prefs[cb.dataset.pf]=cb.checked;
+    localStorage.pvFields=JSON.stringify(prefs);
+    applyPVFields(prefs);
+  });
+});
+applyPVFields(getPVFields());
 function sorted(){const s=sortSel.value,a=[...items];
   if(s==='title')a.sort((x,y)=>x.title.localeCompare(y.title));
   else if(s==='category')a.sort((x,y)=>(x.category||'').localeCompare(y.category||''));
   else if(s==='color')a.sort((x,y)=>(x.dominantHex||'').localeCompare(y.dominantHex||''));
+  else if(s==='id')a.sort((x,y)=>String(x.id||'').localeCompare(String(y.id||'')));
   else a.sort((x,y)=>(y.createdAt||'').localeCompare(x.createdAt||''));return a}
 function render(){const n=items.filter(x=>x.category==='in-house-original').length;
   const band=document.getElementById('inhouseBand');

← 7f0e5a0 trend board 2026-08-10: Deco #1 re-confirmed, NEW paisley la  ·  back to Pattern Vault  ·  design-trend-scout: 2026-08-17 trend-board refresh (WebSearc 2c0dcd3 →