[object Object]

← back to Designer Wallcoverings

PDP + collection UX: full-width color coordinates (2-row+show-more), uniform larger similar cards, hover-chip SKU+type, desc threshold 1500 (Steve 2026-07-28)

61339a0db5709481da5be695437efcc2f973f68d · 2026-07-28 12:17:24 -0700 · steve@designerwallcoverings.com

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

Files touched

Diff

commit 61339a0db5709481da5be695437efcc2f973f68d
Author: steve@designerwallcoverings.com <steve@designerwallcoverings.com>
Date:   Tue Jul 28 12:17:24 2026 -0700

    PDP + collection UX: full-width color coordinates (2-row+show-more), uniform larger similar cards, hover-chip SKU+type, desc threshold 1500 (Steve 2026-07-28)
    
    Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---
 .../layout/theme.liquid                            |  2 +
 .../snippets/color-palette.liquid                  | 18 +++--
 .../snippets/dw-hover-meta.liquid                  | 82 ++++++++++++++++++++++
 3 files changed, 98 insertions(+), 4 deletions(-)

diff --git a/shopify/theme-LIVE-pull-20260728-colorbar/layout/theme.liquid b/shopify/theme-LIVE-pull-20260728-colorbar/layout/theme.liquid
index 228bd6a4..d9a024be 100644
--- a/shopify/theme-LIVE-pull-20260728-colorbar/layout/theme.liquid
+++ b/shopify/theme-LIVE-pull-20260728-colorbar/layout/theme.liquid
@@ -1358,5 +1358,7 @@ alt="web statistics"></a></div></noscript>
 {% endif %}
 <!-- DW min-qty end -->
 {% unless customer %}{% render 'dw-signin-modal' %}{% endunless %}
+{% comment %} Steve 2026-07-28: hover any product chip → show its SKU + product type (site-wide) {% endcomment %}
+{% render 'dw-hover-meta' %}
 </body>
 </html>
diff --git a/shopify/theme-LIVE-pull-20260728-colorbar/snippets/color-palette.liquid b/shopify/theme-LIVE-pull-20260728-colorbar/snippets/color-palette.liquid
index 94a33425..d6f2f1e0 100644
--- a/shopify/theme-LIVE-pull-20260728-colorbar/snippets/color-palette.liquid
+++ b/shopify/theme-LIVE-pull-20260728-colorbar/snippets/color-palette.liquid
@@ -293,11 +293,21 @@
     function ciApplyRows(){
       var grid = ciEl('[data-dw-ci-grid]'); if(!grid) return;
       var rows = parseInt(grid.getAttribute('data-rows') || String(CI_START_ROWS), 10);
-      grid.style.gridTemplateRows = 'repeat(' + rows + ',auto)';
-      grid.style.gridAutoRows = '0';
-      grid.style.overflow = 'hidden';
+      // Hide extra cards by COUNT (rows × columns) so the grid flows to EXACTLY N clean
+      // rows — no partial 3rd-row sliver from row-gap the old overflow-clip left behind.
+      var cols = (getComputedStyle(grid).gridTemplateColumns || '').split(' ').filter(Boolean).length || 1;
+      var visible = rows * cols, hiddenAny = false;
+      for(var i=0;i<grid.children.length;i++){
+        var show = i < visible;
+        grid.children[i].style.display = show ? '' : 'none';
+        if(!show) hiddenAny = true;
+      }
+      // JS controls visibility by count, so let the grid flow naturally (no clip artefacts)
+      grid.style.gridTemplateRows = 'none';
+      grid.style.gridAutoRows = 'auto';
+      grid.style.overflow = 'visible';
       var more = ciEl('[data-dw-ci-more]');
-      if(more){ more.hidden = !(grid.scrollHeight > grid.clientHeight + 4); }
+      if(more){ more.hidden = !hiddenAny; }
     }
     if(CI){
       var _more = ciEl('[data-dw-ci-more]');
diff --git a/shopify/theme-LIVE-pull-20260728-colorbar/snippets/dw-hover-meta.liquid b/shopify/theme-LIVE-pull-20260728-colorbar/snippets/dw-hover-meta.liquid
new file mode 100644
index 00000000..d93d0f26
--- /dev/null
+++ b/shopify/theme-LIVE-pull-20260728-colorbar/snippets/dw-hover-meta.liquid
@@ -0,0 +1,82 @@
+{%- comment -%}
+  dw-hover-meta — hover ANY product chip/card to reveal its SKU + product type
+  (Steve 2026-07-28). Universal + delegated so it works on every card variant:
+  Boost collection cards (.boost-sd__product-item), the custom infinite-scroll cards
+  (.dw-if-card), and the PDP CLIP chips (.dw-similar__card, .dw-color-index__card,
+  .pairs-well__card) — including cards injected after load. Data is pulled ONCE per
+  handle from Shopify's own /products/{handle}.js ($0) and cached.
+{%- endcomment -%}
+<style>
+  .dw-hovermeta{position:absolute;z-index:9999;display:flex;flex-direction:column;gap:3px;pointer-events:none;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif;}
+  .dw-hovermeta[hidden]{display:none;}
+  .dw-hovermeta__sku{background:rgba(17,17,17,.92);color:#fff;font-size:12px;font-weight:700;letter-spacing:.03em;padding:4px 9px;border-radius:4px;align-self:flex-start;font-variant-numeric:tabular-nums;box-shadow:0 2px 8px rgba(0,0,0,.25);}
+  .dw-hovermeta__type{background:rgba(17,17,17,.72);color:#fff;font-size:10px;letter-spacing:.09em;text-transform:uppercase;padding:3px 9px;border-radius:4px;align-self:flex-start;box-shadow:0 2px 8px rgba(0,0,0,.18);}
+</style>
+<script>
+(function(){
+  if(window.__dwHoverMeta) return; window.__dwHoverMeta = true;
+  /* every "chip"/product-card variant across the store */
+  var CARD_SEL = '.boost-sd__product-item, .dw-if-card, .dw-similar__card, .dw-color-index__card, .pairs-well__card, .dwsm-card__product';
+  var cache = {};          // handle -> {sku,type}
+  var tip = null, curCard = null;
+
+  function ensureTip(){
+    if(tip) return tip;
+    tip = document.createElement('div'); tip.className = 'dw-hovermeta'; tip.hidden = true;
+    document.body.appendChild(tip); return tip;
+  }
+  function handleOf(card){
+    var a = card.matches('a[href*="/products/"]') ? card : card.querySelector('a[href*="/products/"]');
+    if(!a) return '';
+    var m = (a.getAttribute('href')||'').split('?')[0].match(/\/products\/([^\/?#]+)/);
+    return m ? m[1] : '';
+  }
+  function load(h){
+    if(cache[h]) return Promise.resolve(cache[h]);
+    return fetch('/products/'+encodeURIComponent(h)+'.js', {headers:{'Accept':'application/json'}})
+      .then(function(r){ return r.ok ? r.json() : null; })
+      .then(function(p){
+        var d = {sku:'', type:''};
+        if(p){
+          var vs = p.variants || [];
+          // prefer the sellable (non-Sample) variant's SKU
+          var v = vs.filter(function(x){ return x && x.sku && !/sample/i.test(x.sku) && !/sample/i.test(x.title||''); })[0] || vs[0] || {};
+          d.sku = v.sku || '';
+          d.type = p.type || '';
+        }
+        cache[h] = d; return d;
+      })
+      .catch(function(){ cache[h] = {sku:'',type:''}; return cache[h]; });
+  }
+  function position(card){
+    var t = ensureTip(), r = card.getBoundingClientRect();
+    t.style.left = Math.round(window.pageXOffset + r.left + 8) + 'px';
+    t.style.top  = Math.round(window.pageYOffset + r.top  + 8) + 'px';
+  }
+  function show(card){
+    var h = handleOf(card); if(!h) return;
+    curCard = card; var t = ensureTip();
+    load(h).then(function(d){
+      if(curCard !== card) return;                 // moved off before fetch resolved
+      if(!d || (!d.sku && !d.type)){ t.hidden = true; return; }
+      t.innerHTML = (d.sku ? '<span class="dw-hovermeta__sku">'+d.sku+'</span>' : '')
+                  + (d.type ? '<span class="dw-hovermeta__type">'+d.type+'</span>' : '');
+      position(card); t.hidden = false;
+    });
+  }
+  function hide(){ curCard = null; if(tip) tip.hidden = true; }
+
+  document.addEventListener('mouseover', function(e){
+    var card = e.target.closest && e.target.closest(CARD_SEL);
+    if(card && card !== curCard) show(card);
+  }, true);
+  document.addEventListener('mouseout', function(e){
+    var card = e.target.closest && e.target.closest(CARD_SEL);
+    if(!card) return;
+    var to = e.relatedTarget;
+    if(!to || !(to.closest && to.closest(CARD_SEL))) hide();       // left the card entirely
+  }, true);
+  // keep the tip glued to the card while scrolling
+  window.addEventListener('scroll', function(){ if(curCard && tip && !tip.hidden) position(curCard); }, {passive:true});
+})();
+</script>

← dda80057 auto-save: 2026-07-28T12:00:18 (19 files) — DW-Programming/1  ·  back to Designer Wallcoverings  ·  auto-save: 2026-07-28T12:30:33 (8 files) — DW-Programming/15 6542c69a →