← back to Ffepurchasing
viewer standard: add Grid/List toggle + per-field on/off menu to internal record-grid viewer
e2119b7d7d92433db839223f2f2df171f9ea19ec · 2026-08-12 08:53:18 -0700 · Steve
Files touched
Diff
commit e2119b7d7d92433db839223f2f2df171f9ea19ec
Author: Steve <steve@designerwallcoverings.com>
Date: Wed Aug 12 08:53:18 2026 -0700
viewer standard: add Grid/List toggle + per-field on/off menu to internal record-grid viewer
---
public/index.html | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 57 insertions(+)
diff --git a/public/index.html b/public/index.html
index 17a4aef..01a5b95 100644
--- a/public/index.html
+++ b/public/index.html
@@ -192,6 +192,27 @@ table.products .tven { font-size:10px; letter-spacing:0.18em; text-transform:upp
table.products .tact { padding:6px 12px; background:var(--paper); color:var(--bg); border:0; font-family:inherit; font-size:10px; letter-spacing:0.22em; text-transform:uppercase; font-weight:700; cursor:pointer }
table.products .tact:hover { background:var(--accent); color:#fff }
+/* ===== Fields ▾ popover (admin field toggles) ===== */
+.ffe-fieldmenu { position:relative }
+.ffe-fbtn { background:transparent; border:1px solid var(--line); color:var(--muted); font-family:inherit; font-size:11px; letter-spacing:.22em; text-transform:uppercase; font-weight:700; padding:6px 12px; cursor:pointer; border-radius:2px; white-space:nowrap }
+.ffe-fbtn:hover { border-color:var(--paper); color:var(--paper) }
+.ffe-fpop { position:absolute; top:calc(100% + 8px); left:0; background:var(--bg); border:1px solid var(--line); border-radius:2px; box-shadow:0 14px 34px rgba(16,16,16,.18); padding:8px 4px; z-index:30; min-width:200px }
+html[data-theme="dark"] .ffe-fpop { background:var(--bg-soft) }
+.ffe-fpop[hidden] { display:none }
+.ffe-fpop label { display:flex; align-items:center; gap:10px; padding:7px 14px; font-size:12px; letter-spacing:.08em; text-transform:uppercase; color:var(--muted); cursor:pointer; white-space:nowrap }
+.ffe-fpop label:hover { background:var(--bg-soft); color:var(--paper) }
+.ffe-fpop input { accent-color:var(--accent); margin:0 }
+/* per-field hide rules — card overlay children */
+body.ffehf-pat .card .pat { display:none }
+body.ffehf-aes .card .pat-aes { display:none }
+body.ffehf-sku .card .trade .row:first-child { display:none }
+body.ffehf-net30 .card .trade .row:nth-child(2) { display:none }
+body.ffehf-moq .card .trade .row:nth-child(3), body.ffehf-moq .card .trade .moq-soft { display:none }
+body.ffehf-sample .card .actions { display:none }
+/* table view field toggles */
+body.ffehf-sku table.products .tsku { display:none }
+body.ffehf-net30 table.products .tprice { display:none }
+body.ffehf-moq table.products .tmoq { display:none }
/* ===== WCAG 2.4.7 — keyboard focus indicators ===== */
/* Strictly :focus-visible so mouse clicks do NOT show the ring */
a:focus-visible,
@@ -489,6 +510,17 @@ textarea:focus-visible,
<label class="dens-only">Grid</label>
<input type="range" id="densitySlider" min="4" max="12" step="1" value="6" aria-label="Grid columns">
<span class="ct" id="densityLabel">6 cols</span>
+ <div class="ffe-fieldmenu">
+ <button class="ffe-fbtn" id="ffe-fieldbtn" aria-haspopup="true" aria-expanded="false">Fields ▾</button>
+ <div class="ffe-fpop" id="ffe-fpop" hidden role="menu">
+ <label><input type="checkbox" data-ffef="pat" checked> Pattern name</label>
+ <label><input type="checkbox" data-ffef="aes" checked> Aesthetic tag</label>
+ <label><input type="checkbox" data-ffef="sku" checked> SKU</label>
+ <label><input type="checkbox" data-ffef="net30" checked> NET30 price</label>
+ <label><input type="checkbox" data-ffef="moq" checked> MOQ</label>
+ <label><input type="checkbox" data-ffef="sample" checked> Sample button</label>
+ </div>
+ </div>
<div class="search">
<svg viewBox="0 0 24 24"><circle cx="11" cy="11" r="7"/><path d="M21 21l-5.5-5.5"/></svg>
<input type="text" id="searchInput" placeholder="Search by pattern, color, SKU…" autocomplete="off">
@@ -888,6 +920,31 @@ tb.addEventListener('click', () => setTheme(document.documentElement.dataset.the
sfReadURL(); // deep-link: hydrate facet/q/sort from the URL before first load
loadFacets();
loadGridPage();
+
+// ── FIELDS MENU ───────────────────────────────────────────────────
+const FFE_F_DEF = { pat:true, aes:true, sku:true, net30:true, moq:true, sample:true };
+let FFE_F = Object.assign({}, FFE_F_DEF);
+try { const _s = localStorage.getItem('ffe_fields'); if (_s) FFE_F = Object.assign({}, FFE_F_DEF, JSON.parse(_s)); } catch(_) {}
+function applyFfeFields() {
+ for (const k of Object.keys(FFE_F_DEF)) document.body.classList.toggle('ffehf-'+k, !FFE_F[k]);
+ document.querySelectorAll('#ffe-fpop input[data-ffef]').forEach(cb => { cb.checked = !!FFE_F[cb.dataset.ffef]; });
+ try { localStorage.setItem('ffe_fields', JSON.stringify(FFE_F)); } catch(_) {}
+}
+document.querySelectorAll('#ffe-fpop input[data-ffef]').forEach(cb => {
+ cb.addEventListener('change', () => { FFE_F[cb.dataset.ffef] = cb.checked; applyFfeFields(); });
+});
+applyFfeFields();
+const ffeFBtn = document.getElementById('ffe-fieldbtn');
+const ffeFPop = document.getElementById('ffe-fpop');
+if (ffeFBtn) ffeFBtn.addEventListener('click', e => {
+ e.stopPropagation();
+ const open = ffeFPop.hidden;
+ ffeFPop.hidden = !open;
+ ffeFBtn.setAttribute('aria-expanded', open ? 'true' : 'false');
+});
+document.addEventListener('click', e => {
+ if (!e.target.closest('.ffe-fieldmenu')) { if (ffeFPop) ffeFPop.hidden = true; }
+});
</script>
<!-- ============================================================
DW UNIVERSAL CONTACT MODULE — fashion-house UX
← 57ecf40 fix: take infinite-scroll .loading indicator out of flow (ki
·
back to Ffepurchasing
·
auto-data-snapshot: 2026-08-22T11:19:22 (1 data files) — dat 07a1be4 →