← 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
M shopify/theme-LIVE-pull-20260728-colorbar/layout/theme.liquidM shopify/theme-LIVE-pull-20260728-colorbar/snippets/color-palette.liquidA shopify/theme-LIVE-pull-20260728-colorbar/snippets/dw-hover-meta.liquid
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 →