[object Object]

← back to Linenwallpaper

upgrade: mobile-optimized grid density slider with touch buttons

2914d00fc890ae7fb8d5645e0e8c71845e108908 · 2026-06-22 21:31:52 -0700 · Steve Abrams

Files touched

Diff

commit 2914d00fc890ae7fb8d5645e0e8c71845e108908
Author: Steve Abrams <steve@designerwallcoverings.com>
Date:   Mon Jun 22 21:31:52 2026 -0700

    upgrade: mobile-optimized grid density slider with touch buttons
---
 public/index.html | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/public/index.html b/public/index.html
index aeb5f2f..73df1a9 100644
--- a/public/index.html
+++ b/public/index.html
@@ -941,10 +941,9 @@ document.addEventListener('DOMContentLoaded', function(){ try { renderRailSectio
      Inject before   <script src="/hero-4grid.js" defer></script>
 <script src="/dw-theme-nav.js" defer></script>
 
-<!-- GRID DENSITY SLIDER (DW STANDARD) -->
+<!-- GRID DENSITY SLIDER (MOBILE-OPTIMIZED) -->
 <script>
-(function(){const e={storageKey:"dw_grid_cols",minCols:2,maxCols:6,defaultCols:3},l=[".grid","[role=region] .grid","main .grid",".product-grid",".collection-grid","[data-collection-grid]"];function t(){const o=l.map(e=>document.querySelector(e)).find(e=>e&&e.children.length>0);if(!o||document.getElementById("dw-density-slider"))return;const n=`<div id="dw-density-slider" style="display:flex;align-items:center;gap:16px;margin:24px 0;padding:12px 0;border-bottom:1px solid rgba(0,0,0,.08)"><label for="dw-col-range" style="font-size:12px;font-weight:600;letter-spacing:.05em;text-transform:uppercase;color:#666;margin:0">Columns</label><input type="range" id="dw-col-range" min="2" max="6" step="1" style="flex:0 1 180px;cursor:pointer" aria-label="Grid columns"><span id="dw-col-label" style="font-size:12px;color:#666;min-width:60px;text-align:right">3 cols</span></div>`;const a=document.createElement("style");a.textContent="#dw-col-range{height:4px;border-radius:2px;background:#ddd;outline:none;-webkit-appearance:none;appearance:none}#dw-col-range::-webkit-slider-thumb{-webkit-appearance:none;appearance:none;width:16px;height:16px;border-radius:50%;background:#000;cursor:pointer;box-shadow:0 1px 3px rgba(0,0,0,.2)}#dw-col-range::-moz-range-thumb{width:16px;height:16px;border-radius:50%;background:#000;cursor:pointer;border:0;box-shadow:0 1px 3px rgba(0,0,0,.2)}#dw-col-range::-moz-range-track{background:0;border:0}@media (max-width:768px){#dw-density-slider{display:none}}",document.head.appendChild(a);const r=document.createElement("div");r.innerHTML=n,o.parentNode.insertBefore(r.firstElementChild,o);let c=e.defaultCols;try{const n=localStorage.getItem(e.storageKey);if(n){const s=parseInt(n,10);s>=e.minCols&&s<=e.maxCols&&(c=s)}}catch(e){}const i=document.getElementById("dw-col-range"),s=document.getElementById("dw-col-label");function d(e){o.style.gridTemplateColumns=`repeat(${e}, 1fr)`,s.textContent=`${e} col${1===e?"":"s"}`,i.value=e;try{localStorage.setItem(e.storageKey,String(e))}catch(e){}}i.addEventListener("input",e=>d(parseInt(e.target.value,10))),d(c)}document.readyState="loading"===document.readyState?document.addEventListener("DOMContentLoaded",t):t(),setTimeout(()=>{document.getElementById("dw-density-slider")||t()},500)})();
-
+(function(){ const CFG = { storageKey: 'dw_grid_cols', minCols: 1, maxCols: 6, defaultCols: 3, mobileBreakpoint: 768 }; const GRID_SEL = [ '[data-collection-grid]', '.collection-grid', '.product-grid', '[role="region"] .grid', 'main .grid', '.grid' ]; function findGrid() { for (const sel of GRID_SEL) { const el = document.querySelector(sel); if (el && el.children.length > 0) return el; } return null; } function init() { const grid = findGrid(); if (!grid || document.getElementById('dw-density-slider')) return; const html = `<div id="dw-density-slider" class="dw-grid-control"><div class="dw-grid-label">Columns</div><div class="dw-grid-buttons"><button data-cols="1" aria-label="1 column" title="1">1</button><button data-cols="2" aria-label="2 columns" title="2">2</button><button data-cols="3" aria-label="3 columns" title="3" class="active">3</button><button data-cols="4" aria-label="4 columns" title="4">4</button><button data-cols="5" aria-label="5 columns" title="5">5</button><button data-cols="6" aria-label="6 columns" title="6">6</button></div><input type="range" id="dw-col-range" class="dw-slider" min="1" max="6" step="1" value="3" aria-label="Grid columns"><span id="dw-col-label" class="dw-col-label">3 cols</span></div>`; const style = document.createElement('style'); style.textContent = '#dw-density-slider { display: flex; align-items: center; gap: 12px; margin: 16px 0; padding: 12px; border: 1px solid rgba(0,0,0,.08); border-radius: 4px; background: #fafafa; flex-wrap: wrap; } .dw-grid-label { font-size: 11px; font-weight: 700; letter-spacing: .08em; text-transform: uppercase; color: #666; order: -1; flex-basis: 100%; } .dw-grid-buttons { display: flex; gap: 6px; flex-basis: 100%; order: 0; } .dw-grid-buttons button { flex: 1; min-width: 36px; height: 36px; border: 1px solid #ddd; background: #fff; color: #666; font-weight: 600; font-size: 13px; cursor: pointer; border-radius: 4px; transition: all .15s; touch-action: manipulation; } .dw-grid-buttons button:active { transform: scale(0.95); } .dw-grid-buttons button.active { background: #000; color: #fff; border-color: #000; } .dw-slider { display: none; } #dw-col-label { display: none; } @media (min-width: 769px) { #dw-density-slider { flex-wrap: nowrap; gap: 16px; background: transparent; border: none; padding: 12px 0; margin: 24px 0; } .dw-grid-label { flex-basis: auto; order: 0; } .dw-grid-buttons { display: none; } .dw-slider { display: block; flex: 0 1 200px; height: 4px; border-radius: 2px; background: #ddd; outline: none; -webkit-appearance: none; appearance: none; cursor: pointer; } .dw-slider::-webkit-slider-thumb { -webkit-appearance: none; appearance: none; width: 18px; height: 18px; border-radius: 50%; background: #000; cursor: pointer; box-shadow: 0 1px 3px rgba(0,0,0,.2); } .dw-slider::-moz-range-thumb { width: 18px; height: 18px; border-radius: 50%; background: #000; cursor: pointer; border: 0; box-shadow: 0 1px 3px rgba(0,0,0,.2); } .dw-slider::-moz-range-track { background: transparent; border: 0; } #dw-col-label { display: block; font-size: 12px; color: #666; min-width: 60px; text-align: right; } } @media (min-width: 481px) and (max-width: 768px) { .dw-grid-buttons button { height: 40px; font-size: 14px; } }'; document.head.appendChild(style); const div = document.createElement('div'); div.innerHTML = html; grid.parentNode.insertBefore(div.firstElementChild, grid); let cols = CFG.defaultCols; try { const saved = localStorage.getItem(CFG.storageKey); if (saved) { const n = parseInt(saved, 10); if (n >= CFG.minCols && n <= CFG.maxCols) cols = n; } } catch (e) {} const range = document.getElementById('dw-col-range'); const label = document.getElementById('dw-col-label'); const buttons = document.querySelectorAll('.dw-grid-buttons button'); function set(n) { grid.style.gridTemplateColumns = `repeat(${n}, 1fr)`; label.textContent = `${n} col${n === 1 ? '' : 's'}`; range.value = n; buttons.forEach(btn => { btn.classList.toggle('active', parseInt(btn.dataset.cols) === n); }); try { localStorage.setItem(CFG.storageKey, String(n)); } catch (e) {} } range.addEventListener('input', e => set(parseInt(e.target.value, 10))); buttons.forEach(btn => { btn.addEventListener('click', e => { e.preventDefault(); set(parseInt(btn.dataset.cols, 10)); }); }); set(cols); } if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', init); } else { init(); } setTimeout(() => { if (!document.getElementById('dw-density-slider')) init(); }, 500); })();
 </script>
 </body> in every DW-family sister site.
      Self-contained: CSS + 4 modals + JS submission handlers.

← b9d5fe0 feat: add grid density slider (DW standard) — adjustable col  ·  back to Linenwallpaper  ·  enhance: smart product name hiding on 6-column grids b4da2f9 →