aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCraig Jennings <c@cjennings.net>2026-07-12 20:24:11 -0500
committerCraig Jennings <c@cjennings.net>2026-07-12 20:24:11 -0500
commit858caec5aa942ba621845d054c000269e0fe0384 (patch)
tree987f5806c2318d2436aa6a08a77651a532e1cd98
parentf536d4c9a9af306e33f52ca0772f7442695964f1 (diff)
downloadarchsetup-858caec5aa942ba621845d054c000269e0fe0384.tar.gz
archsetup-858caec5aa942ba621845d054c000269e0fe0384.zip
feat(gallery): validation lamps and the readout/options/text card order
Every card gets a status lamp at the upper-right for the pre-componentization validation pass: click cycles not-done, in-progress, done, and the state persists per card in localStorage. Below the stage the card now reads readout, then options, then descriptive text, with separators between the zones and no labels — chips moved into a generic options container that future selectors share.
-rw-r--r--docs/prototypes/panel-widget-gallery.html29
-rw-r--r--todo.org2
2 files changed, 25 insertions, 6 deletions
diff --git a/docs/prototypes/panel-widget-gallery.html b/docs/prototypes/panel-widget-gallery.html
index fbf2e0a..99342bc 100644
--- a/docs/prototypes/panel-widget-gallery.html
+++ b/docs/prototypes/panel-widget-gallery.html
@@ -102,12 +102,21 @@ h2::after{content:"";height:1px;background:var(--wash);flex:1}
box-shadow:inset 0 1px 0 rgba(255,255,255,.04),0 6px 14px rgba(0,0,0,.4)}
.wname{color:var(--cream);font-size:.95rem;font-weight:700;display:flex;align-items:center;gap:8px}
.wname .no{color:var(--panel);background:var(--gold);border-radius:4px;font-size:.7rem;padding:0 5px;font-weight:400}
+/* validation lamp: off = not done, amber = in progress, green = done; click cycles, state persists */
+.vlamp{margin-left:auto;flex:0 0 auto;width:10px;height:10px;border-radius:50%;cursor:pointer;
+ background:#221f1b;border:1px solid #33302b}
+.vlamp[data-v="amber"]{background:var(--gold);border-color:#7d5c16;box-shadow:0 0 6px 1px rgba(var(--glow-lo),.6)}
+.vlamp[data-v="green"]{background:var(--pass);border-color:#4a5c22;box-shadow:0 0 6px 1px rgba(116,147,47,.6)}
.stagew{background:var(--well);border:1px solid #201d17;border-radius:9px;padding:14px 12px;
min-height:78px;display:flex;align-items:center;justify-content:center;gap:12px;flex-wrap:wrap}
.wrd{color:var(--gold-hi);font-size:.8rem;letter-spacing:.06em;font-variant-numeric:tabular-nums;
- min-height:.95rem;display:flex;align-items:center;gap:6px}
+ min-height:.95rem;display:flex;align-items:center;gap:6px;
+ border-top:1px solid var(--wash);padding-top:9px;margin-top:2px}
.wrd::before{content:"▸";color:var(--steel);font-size:.7rem}
-.wnote{color:var(--dim);font-size:.85rem;line-height:1.45}
+.opts{display:flex;flex-direction:column;gap:5px}
+.opts:empty{display:none}
+.wnote{color:var(--dim);font-size:.85rem;line-height:1.45;
+ border-top:1px solid var(--wash);padding-top:9px;margin-top:2px}
.wnote b{color:var(--steel);font-weight:400}
/* per-card spec sheet (collapsible) */
@@ -795,7 +804,7 @@ function screenChips(no,el,fams,def){
row.querySelectorAll('.fc').forEach(x=>x.classList.toggle('on',x===b));
setRd(no,'screen '+f);});
row.appendChild(b);});
- cardEl.insertBefore(row,cardEl.querySelector('.wrd'));
+ cardEl.querySelector('.opts').appendChild(row);
}
/* ---- per-card spec sheets ----
input how you drive it, incl. the model: click widgets port to every target (Emacs click-regions
@@ -1517,10 +1526,18 @@ const INFO={
};
const INFO_FIELDS=[['input','input'],['solves','solves'],['use','use'],['limits','limits'],
['origin','origin'],['difficulty','difficulty'],['prefer','prefer when'],['period','period']];
+const VLAMP_TITLES={off:'validation: not done',amber:'validation: in progress',green:'validation: done'};
function card(host, no, name, html, note){
const c=document.createElement('div'); c.className='card';
- c.innerHTML=`<div class="wname"><span class="no">${no}</span>${name}</div>`+
- `<div class="stagew">${html}</div><div class="wrd" id="rd-${no}">—</div><div class="wnote">${note}</div>`;
+ c.innerHTML=`<div class="wname"><span class="no">${no}</span>${name}<span class="vlamp" data-v="off"></span></div>`+
+ `<div class="stagew">${html}</div><div class="wrd" id="rd-${no}">—</div>`+
+ `<div class="opts"></div><div class="wnote">${note}</div>`;
+ const lamp=c.querySelector('.vlamp'), VKEY='gv-'+no, VSTATES=['off','amber','green'];
+ const setV=v=>{lamp.dataset.v=v;lamp.title=VLAMP_TITLES[v];};
+ setV(localStorage.getItem(VKEY)||'off');
+ lamp.addEventListener('click',e=>{e.stopPropagation();
+ const v=VSTATES[(VSTATES.indexOf(lamp.dataset.v)+1)%3];
+ setV(v);localStorage.setItem(VKEY,v);});
const inf=(typeof INFO!=='undefined')&&INFO[no];
if(inf){const d=document.createElement('details'); d.className='winfo';
let rows='';
@@ -4244,7 +4261,7 @@ BOOST.forEach(no=>{const rd=document.getElementById('rd-'+no);
row.appendChild(b);}};
group('on',ON_OPTS,'amber');
group('off',OFF_OPTS,'dark');
- cardEl.insertBefore(row,cardEl.querySelector('.wrd'));})();
+ cardEl.querySelector('.opts').appendChild(row);})();
</script>
</body>
</html>
diff --git a/todo.org b/todo.org
index 7afc720..36959d0 100644
--- a/todo.org
+++ b/todo.org
@@ -59,6 +59,8 @@ New "Palette — design tokens" section above Controls: 33 tiles read live from
Six period families defined (green = P1 phosphor built on =phos=, amber = P3 on the gold family, red = the nixie neon pulled out, blue = P4 white-blue, vfd = the marquee's =--vfd=, white = mono LCD), applied via scoped CSS vars with the shipped color as fallback — defaults are pixel-identical until a chip is clicked. Chips on the five clearly-screen widgets: R10 data matrix (amber), R17 CRT scope (green face), R19 waveform LCD (white), R31 radar (amber — the "in amber" one; green chip gives the classic PPI), N11 oscilloscope (green). Answers to the green question: the kit deliberately has four greens — phos #7fe0a0 (CRT trace), vfd #63e6c8 (marquee, blue-leaning), sevgrn #57d357 (LED), jewel-g #6fce33 (jewel lens); the phosphor-screen green is phos, not the others. Nixie left chipless: neon is only ever orange. Families live in gallery JS, not tokens.json — tokenize the winners once picked, the way amber earned its tokens. CDP-verified: recolors land on all five, interactions intact, zero exceptions.
*** 2026-07-12 Sun @ 13:15:19 -0500 Added spec sheets to all 84 cards
Every card now carries a collapsible "spec sheet" (a details element under the note) with up to 8 fields: input (always present, names the model — click ports everywhere including Emacs click-regions, drag needs a click/key idiom there, display widgets take no real input), solves, use (common vs specialty + where it shines), limits, origin, difficulty, prefer-when, and period (present on 41 of 84 — only where the component is clearly not timeless, e.g. nixie 1955-75 sits with keypads/telegraphs and clashes with VFD and LED seven-seg). Content lives in one INFO object keyed by card number; card() renders it. CDP-verified: 84/84 sheets present (missing-key check), fields render, zero exceptions.
+*** TODO Widget validation pass
+Craig validates every control before any componentization build (his call — the lamps are his worklist, not agent-checkable). Each card carries a status lamp at the upper-right: click cycles off → amber → green, state persists per card in localStorage (key =gv-<no>=). When the pass completes, bake the final statuses into the gallery source and use the green set as the build order for the widgets.js extraction.
*** TODO Component classification taxonomy
Brainstorm WITH Craig (after the squash merge, not solo): break the components down by use — freeform output, binary selection, multi-selection, fine-tuning, etc. The taxonomy identifies use-cases with no appropriate component, which fills out the gallery with some confidence of completeness.
** DOING [#B] Retro widget catalogue :feature:design: