[object Object]

← 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 →