← back to Wallco Ai
YOLO R6 — text search box on /moodboard. Matches case-insensitive against pin labels + reasons + parent design title. Empty sections auto-collapse, empty-state hint appears on zero matches, query persists across reloads via localStorage. Stacks with the existing type filter (?type=design|color|material).
92ab522e594ec73c45184c5d2e0a527390345ec8 · 2026-05-12 00:58:16 -0700 · Steve Abrams
Files touched
M YOLO_BACKLOG.mdM server.js
Diff
commit 92ab522e594ec73c45184c5d2e0a527390345ec8
Author: Steve Abrams <steve@designerwallcoverings.com>
Date: Tue May 12 00:58:16 2026 -0700
YOLO R6 — text search box on /moodboard. Matches case-insensitive against pin labels + reasons + parent design title. Empty sections auto-collapse, empty-state hint appears on zero matches, query persists across reloads via localStorage. Stacks with the existing type filter (?type=design|color|material).
---
YOLO_BACKLOG.md | 5 +++--
server.js | 59 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 62 insertions(+), 2 deletions(-)
diff --git a/YOLO_BACKLOG.md b/YOLO_BACKLOG.md
index 4cfd578..7df4232 100644
--- a/YOLO_BACKLOG.md
+++ b/YOLO_BACKLOG.md
@@ -34,7 +34,7 @@ User ask verbatim: "show final patterns and 1 room setting on https://wallco.ai/
### Visual polish
-- [ ] **R6 · /moodboard search box** — currently filters by type only (designs/colors/materials). Add a text search that matches against pin labels + reasons. Persist across reloads via localStorage.
+- [x] **R6 · /moodboard search box** — 2026-05-12 01:10 · added `#mb-search` input to the filters bar (pre-pills) with placeholder "search labels + reasons…". Pure client-side filter walks `.mb-card` nodes, matches case-insensitive against `.mb-title` + `.mb-reason` + parent design title. Sections with zero matches auto-collapse via `.mb-hidden`. Empty-state ("No pins match X") appears when query yields zero results. Persists last query in localStorage (key `wallco-mb-search`) and re-applies on load. Stacks with the existing type filter (?type=design|color|material).
- [x] **R7 · why-chip prominence** — 2026-05-12 01:06 · why-chip restyled per debate-team verdict (curator's reasoning, not noise). Bigger (padding 6→8/9→12, font 11→12px+500 weight), full gold border (was 1px #3a3631), gold accent left-bar 3px, subtle gold-tinted bg. Floating "CURATOR" label tag above the chip identifies provenance. Hover state: bg deepens + "tap to open chat →" hint floats bottom-right. Verified live.
- [ ] **R8 · `/age-themes` mobile layout** — at <640px viewport, the 3-column current/best/rationale grid stacks awkwardly. Test at 390×844, fix grid-template-columns + font-size scaling.
- [x] **R9 · AI-language scrub** — 2026-05-12 00:42 · 9 public-facing leaks scrubbed in server.js: schema.org names + meta descriptions on /, /designs, /design/:id, /murals, /samples + shopify tagList. Replaced with "wallco.ai original" / "hand-curated through our proprietary design system" / "never repeated". Admin /age-themes banner kept "AI-generated starting point" per validation-loop honesty rule (admin-only audience). Front-page + /designs meta verified clean live.
@@ -73,4 +73,5 @@ TICK · TIMESTAMP · ITEM · STATUS · COMMIT
- T11 · 2026-05-12 00:52 · R4 isolate W/P/C shortcuts · done · scoped keydown handler, toast feedback, clipboard for primary hex · b204703
- T12 · 2026-05-12 00:58 · R2 ΔE closeness bands · done · 4 bands · 4 surfaces in API · chips on both wallco + tsd · 12 new unit tests · 8c653d7 + ef39b82 + 035592b
- T13 · 2026-05-12 01:02 · R5 source-design SW row · done · new "Design's dominant color" block above palette · stored hex vs extracted distinction explicit · c93962a
-- T14 · 2026-05-12 01:06 · R7 why-chip prominence · done · bigger font, gold left-accent, CURATOR provenance label, hover hint
+- T14 · 2026-05-12 01:06 · R7 why-chip prominence · done · bigger font, gold left-accent, CURATOR provenance label, hover hint · f5c8666
+- T15 · 2026-05-12 01:10 · R6 moodboard search · done · pure client-side filter, localStorage persist, empty-state UX, stacks with type filter
diff --git a/server.js b/server.js
index 1e9332e..94f644a 100644
--- a/server.js
+++ b/server.js
@@ -4041,6 +4041,11 @@ app.get('/moodboard', (req, res) => {
header.top .filters { margin-left:auto; display:flex; gap:8px; }
header.top .filter-pill { background:#2a2825; padding:3px 10px; border-radius:12px; font-size:11px; cursor:pointer; color:#bba; border:1px solid transparent; text-decoration:none; }
header.top .filter-pill.on { background:#d2b15c; color:#0f0e0c; }
+ #mb-search { background:#16140f; border:1px solid #3a3631; border-radius:14px; padding:3px 12px; font:11px/1 -apple-system, system-ui, sans-serif; color:#e8e2d6; min-width:200px; outline:none; transition:border-color .12s; }
+ #mb-search:focus { border-color:#d2b15c; }
+ #mb-search::placeholder { color:#666; }
+ .mb-card.mb-hidden, .mb-design-block.mb-hidden { display:none !important; }
+ .mb-search-empty { padding:32px 24px; text-align:center; color:#666; font-style:italic; font-size:13px; }
header.top .export-link { font-size:11px; color:#d2b15c; text-decoration:none; padding:3px 10px; border:1px solid #3a3631; border-radius:2px; }
header.top .export-link:hover { background:#d2b15c; color:#0f0e0c; }
main { padding: 24px 32px; max-width:1400px; margin:0 auto; }
@@ -4076,6 +4081,7 @@ app.get('/moodboard', (req, res) => {
<a href="/moodboard${filter?'?type='+filter:''}" class="on">Moodboard</a>
</nav>
<div class="filters">
+ <input type="search" id="mb-search" placeholder="search labels + reasons…" autocomplete="off" />
<a class="filter-pill ${!filter?'on':''}" href="/moodboard">All</a>
<a class="filter-pill ${filter==='design'?'on':''}" href="/moodboard?type=design">Designs</a>
<a class="filter-pill ${filter==='color'?'on':''}" href="/moodboard?type=color">Colors</a>
@@ -4114,6 +4120,59 @@ document.querySelectorAll('.mb-unpin').forEach(btn => {
} catch (e) { btn.disabled = false; }
});
});
+
+// R6 — text search across pin labels + reasons. Persists across reloads via
+// localStorage. Pure client-side filter on rendered DOM (no API change needed).
+(function(){
+ var input = document.getElementById('mb-search');
+ if (!input) return;
+ var LS_KEY = 'wallco-mb-search';
+ try { input.value = localStorage.getItem(LS_KEY) || ''; } catch(e) {}
+
+ function applyFilter() {
+ var q = (input.value || '').trim().toLowerCase();
+ try { localStorage.setItem(LS_KEY, q); } catch(e) {}
+ var anyShown = false;
+ document.querySelectorAll('.mb-design-block').forEach(function(block){
+ var blockShown = false;
+ block.querySelectorAll('.mb-card').forEach(function(card){
+ if (!q) { card.classList.remove('mb-hidden'); blockShown = true; return; }
+ var label = (card.querySelector('.mb-title') || {}).textContent || '';
+ var reason = (card.querySelector('.mb-reason') || {}).textContent || '';
+ var match = (label + ' ' + reason).toLowerCase().indexOf(q) !== -1;
+ card.classList.toggle('mb-hidden', !match);
+ if (match) blockShown = true;
+ });
+ // also match against design title in the block header
+ if (q && !blockShown) {
+ var dt = (block.querySelector('.mb-design-title') || {}).textContent || '';
+ if (dt.toLowerCase().indexOf(q) !== -1) {
+ block.querySelectorAll('.mb-card').forEach(function(c){ c.classList.remove('mb-hidden'); });
+ blockShown = true;
+ }
+ }
+ block.classList.toggle('mb-hidden', !blockShown);
+ if (blockShown) anyShown = true;
+ });
+ // empty-state hint
+ var main = document.querySelector('main');
+ var empty = document.getElementById('mb-search-empty');
+ if (q && !anyShown) {
+ if (!empty) {
+ empty = document.createElement('div');
+ empty.id = 'mb-search-empty';
+ empty.className = 'mb-search-empty';
+ main.appendChild(empty);
+ }
+ empty.textContent = 'No pins match "' + q + '"';
+ } else if (empty) {
+ empty.remove();
+ }
+ }
+ input.addEventListener('input', applyFilter);
+ // apply persisted search on load
+ if (input.value) applyFilter();
+})();
</script>
</body></html>`);
});
← 3b36790 YOLO R7 — promote why-chip from subtle pill to prominent cur
·
back to Wallco Ai
·
YOLO R8 — /age-themes mobile layout. Added @media (max-width 1cd8af9 →