← back to Lifestyle Asset Intel
yolo tick #25: family-detail grid gets sort + density + search controls
41093f5c91f14eaf0de84dac71800807ede159e0 · 2026-05-13 20:47:54 -0700 · Steve Abrams
Family detail page (/family/:slug) was missing the standing-rule controls
that index.ejs has — Steve's MEMORY says every grid view needs sort +
density + grid-search. Added the same controls block + data-* attrs on
each card + id=grid so the existing public/js/app.js machinery wires
itself up automatically. No server changes; client-side only.
Files touched
Diff
commit 41093f5c91f14eaf0de84dac71800807ede159e0
Author: Steve Abrams <steve@designerwallcoverings.com>
Date: Wed May 13 20:47:54 2026 -0700
yolo tick #25: family-detail grid gets sort + density + search controls
Family detail page (/family/:slug) was missing the standing-rule controls
that index.ejs has — Steve's MEMORY says every grid view needs sort +
density + grid-search. Added the same controls block + data-* attrs on
each card + id=grid so the existing public/js/app.js machinery wires
itself up automatically. No server changes; client-side only.
---
views/family.ejs | 36 +++++++++++++++++++++++++++++++++---
1 file changed, 33 insertions(+), 3 deletions(-)
diff --git a/views/family.ejs b/views/family.ejs
index 1178a23..2e5a064 100644
--- a/views/family.ejs
+++ b/views/family.ejs
@@ -34,9 +34,39 @@
<% if (!out.assets.length) { %>
<p class="muted">No assets in this family yet.</p>
<% } else { %>
- <div class="grid" style="--cols: 4;">
+ <div class="controls" role="region" aria-label="Grid controls">
+ <label>Sort
+ <select id="sort">
+ <option value="newest">Newest snapshot</option>
+ <option value="brand">Brand A→Z</option>
+ <option value="family">Family A→Z</option>
+ <option value="q50_asc">Q50 ascending</option>
+ <option value="q50_desc">Q50 descending</option>
+ <option value="liquidity_desc">Liquidity ↓</option>
+ <option value="confidence_desc">Confidence ↓</option>
+ <option value="recency_desc">Recently revalued</option>
+ </select>
+ </label>
+ <label>Density
+ <input type="range" id="density" min="3" max="8" step="1" value="4" aria-label="Grid density">
+ <output id="densityOut">4</output>
+ </label>
+ <label class="grow">Search
+ <input type="search" id="search" placeholder="material, color, hardware…" aria-label="Filter assets in family">
+ </label>
+ </div>
+ <section class="grid" id="grid">
<% out.assets.forEach(function (a) { %>
- <a class="card" href="/asset/<%= a.slug %>">
+ <a class="card"
+ href="/asset/<%= a.slug %>"
+ data-brand="<%= a.brand_name %>"
+ data-family="<%= a.family_name %>"
+ data-material="<%= a.material || '' %>"
+ data-color="<%= a.color || '' %>"
+ data-q50="<%= a.q50 || 0 %>"
+ data-liquidity="<%= a.liquidity_score || 0 %>"
+ data-confidence="<%= a.confidence || 0 %>"
+ data-asof="<%= a.as_of || '' %>">
<div class="card-head">
<span class="brand-tag"><%= a.brand_name %></span>
<span class="family-tag"><%= a.family_name %> <%= a.size || '' %><% if (a.attrs && a.attrs.exotic) { %> <span class="exotic-badge" title="Exotic skin or special edition">EXOTIC</span><% } %></span>
@@ -56,7 +86,7 @@
</div>
</a>
<% }); %>
- </div>
+ </section>
<% } %>
</section>
</main>
← e863c10 yolo tick #24: /api/family ?sort= (assets/comps/value/name/s
·
back to Lifestyle Asset Intel
·
yolo tick #26: /api/index list endpoint with sort + latest-p a2a7ff0 →