diff options
| author | Craig Jennings <c@cjennings.net> | 2026-06-09 19:07:45 -0500 |
|---|---|---|
| committer | Craig Jennings <c@cjennings.net> | 2026-06-09 19:07:45 -0500 |
| commit | 20eb4659e18a826b8222ce22ab77d4483b9dbed0 (patch) | |
| tree | 803253ac4732a609536361fec20677e32004172e | |
| parent | 23926837f2d1ef733f287f4b2166946dc6703a11 (diff) | |
| download | dotemacs-20eb4659e18a826b8222ce22ab77d4483b9dbed0.tar.gz dotemacs-20eb4659e18a826b8222ce22ab77d4483b9dbed0.zip | |
chore(todo): mark palette-ramps v1 build phases done
All five build phases plus the README close-out landed; the parent stays open pending the manual aesthetic and real-Emacs-fidelity sign-off.
| -rw-r--r-- | todo.org | 24 |
1 files changed, 13 insertions, 11 deletions
@@ -76,19 +76,21 @@ Open design problem to address in the explainer + the ramp feature: a background The v1 feature (ramp generation + background-contrast safety, with the worst-case-floor UX) is designed in [[file:docs/theme-studio-palette-ramps-spec.org][docs/theme-studio-palette-ramps-spec.org]]. Codex review incorporated 2026-06-09: both open decisions resolved (WCAG AA default target; v1 foreground set = distinct syntax hexes + default fg), v1 covered faces closed to region/hl-line/highlight/lazy-highlight/isearch, ramp defaults + function contracts pinned. Spec is Ready (Craig confirmed 2026-06-09); the v1 build is tracked under the sibling parent below. Harmonic fill (feature 2) stays vNext. This task is the explainer doc itself (=docs/design/theme-studio-color-harmony.org=, the methodology). ** TODO [#B] theme-studio palette ramps + contrast safety v1 :feature:theme-studio: -The v1 build from [[file:docs/theme-studio-palette-ramps-spec.org][theme-studio-palette-ramps-spec.org]] (Ready, Codex-reviewed). Two coupled features: a ramp generator (one base color → harmonized tonal ramp) and background-contrast safety (worst-case floor over a face's foreground set + safe-lightness guidance). Phases land in spec order, each leaving the tree green and =make theme-studio-test= passing. Aesthetic and real-Emacs-fidelity sign-off lives under the Manual testing parent below. +The v1 build from [[file:docs/theme-studio-palette-ramps-spec.org][theme-studio-palette-ramps-spec.org]] (Ready, Codex-reviewed). Two coupled features: a ramp generator (one base color → harmonized tonal ramp) and background-contrast safety (worst-case floor over a face's foreground set + safe-lightness guidance). + +All five phases + the README close-out landed 2026-06-09 (commits 1d51a332, 9da6c663, e7021bfe, 1d8b9f9e, 843bbf08, 23926837); =make theme-studio-test= green (78 node tests, 12 browser gates). Code-complete and self-verified. Remaining: the aesthetic and real-Emacs-fidelity sign-off under the Manual testing parent below (does a ramp harmonize, does the safe band read clearly, does a "safe" tint actually read behind real syntax). Mark this DONE once that passes. *** 2026-06-09 Tue @ 18:40:20 -0500 Ramp generator core landed Phase 1 (commit =1d51a332=). =ramp(baseHex, {n, stepL, chromaEase})= in app-core.js → ={steps: [{hex, clamped, offset}], adjusted}= or ={steps: [], error: 'bad-hex'}=. Holds the OKLCH hue, steps lightness by =stepL=, quadratic chroma-ease toward the extremes, gamut-clamps each step; knobs clamp to range with the clamped knob named in =adjusted= (n=2/stepL=0.08/chromaEase=0.5 defaults). 10 node tests (mid/near-white/near-black bases, hue-hold, chroma ease, knob clamping, malformed hex), suite 55→65, =make theme-studio-test= green. The app-core integrity stripper now drops =import= lines too. -*** TODO [#B] Ramp UI in palette :solo: -Phase 2. Base swatch → preview ramp row (darkest→lightest, base marked, clamp badge per step) → add selected steps as named palette entries. Names derive from source swatch (=blue= → =blue+1=/=blue-1=); base preview-only by default; steps insert adjacent to source in =-n..+n= order. Collisions never silent: name collision flags + forces rename, hex collision flags as duplicate but allows add. Add a #ramptest hash-gate pinning generation + insertion + collision behavior. Depends on Phase 1. Verify: hash-gate green + headless screenshot read. -*** TODO [#B] Foreground-set + floor + L_max core :solo: -Phase 3. In app-core.js, all pure, explicit-state, structured errors: =fgSetFor(face, {syntaxAssignments, palette, defaultFg, locks})= → ={set, error?}= (distinct syntax hexes + default fg, locked bg-only roles excluded; out-of-scope face → reason 'out-of-scope'; no assignments → reason 'empty'); =floor(bgHex, fgSet)= → ={ratio, limitingHex, limitingLabel}= (min WCAG over set, argmin, role/palette/hex label; empty set → ratio null); =lMax(hue, chroma, fgSet, target)= → ={L, status}= binary-searching L at tol 0.001, status ok/none/all/clamp. Node tests including the keyword-blue #67809c worst-case fixture, and lMax's none/all/clamp branches. Verify: =make theme-studio-test= green. -*** TODO [#B] Worst-case contrast readout :solo: -Phase 4. For the five v1 covered faces (region, hl-line, highlight, lazy-highlight, isearch), the contrast cell shows floor + limiting foreground instead of a single pair. Readout string =worst: <limitingLabel> <limitingHex> — <ratio> <PASS|FAIL>=; no-set string exactly =no fg set=. Default target WCAG AA (4.5), AAA (7) selectable; APCA shown as a diagnostic only. Package and non-overlay UI cells stay single-pair. Add a #contrasttest hash-gate asserting fields (not punctuation) over the keyword-blue fixture and the no-set string. Depends on Phase 3. Verify: hash-gate green. -*** TODO [#B] Safe-lightness picker guidance :solo: -Phase 5. When a covered face is open in OKLCH mode, mark L_max on the lightness slider and shade the unsafe band above it — a single marker + one-band shade computed once per =(hue, chroma, fgSet, target)= via =lMax=, not a per-pixel foreground-set mask (the existing per-pixel AA/AAA mask stays single-foreground). Add a hash-gate that the marker appears for an in-scope face and is absent for an out-of-scope one. Depends on Phase 3 + the picker. Verify: hash-gate green + headless screenshot read. -*** TODO [#B] README + test-surface close-out :solo: -Update =scripts/theme-studio/README.md=: what a ramp is, the ramp controls and their defaults, what worst-case floor / limiting foreground mean, the five v1 covered faces, and that WCAG drives PASS/FAIL with APCA shown as a diagnostic. Confirm =make theme-studio-test= carries the new node tests and the #ramptest / #contrasttest / safe-lightness gates. Closes the README and unit-test/browser-gate acceptance criteria. +*** 2026-06-09 Tue @ 19:06:46 -0500 Ramp UI in palette landed +Phase 2 (commit =9da6c663=). A "ramp" button opens a panel that generates from the current color and previews the steps (named per source swatch, clamp badge on out-of-gamut steps); the n/stepL/chroma-ease controls default to 2/0.08/0.5. Click a step or "add all" to insert adjacent to the source in -n..+n order; name collisions skip (no overwrite), hex duplicates add with a flag. New #ramptest gate pins count, ordered insertion, collision skip, and the clamp badge. Verified headless + screenshot. +*** 2026-06-09 Tue @ 18:53:16 -0500 Foreground-set + floor + L_max core landed +Phase 3 (commit =e7021bfe=). =fgSetFor=, =floor=, =lMax= and the =COVERED_FACES= constant in app-core.js, all pure and explicit-state. fgSetFor returns {set:[{hex,label}]} or a structured reason ('out-of-scope'/'empty'); floor returns {ratio, limitingHex, limitingLabel}; lMax scans L from black to bracket the dark-side crossing then binary-searches it (tol 0.001), status ok/none/all/clamp. 13 node tests including the keyword-blue #67809c fixture and lMax's none/all/clamp branches. Suite 65→78, =make theme-studio-test= green. +*** 2026-06-09 Tue @ 19:06:46 -0500 Worst-case contrast readout landed +Phase 4 (commit =1d8b9f9e=). The five covered overlay faces show the worst-case floor over their foreground set (live syntax colors + default fg) and name the limiting foreground; a syntax-color edit repaints them. Out-of-scope faces keep the single-pair cell; an empty set reads "no fg set". Verdict is WCAG AA by default. New #contrasttest gate pins the readout, the keyword-blue limiting case, the single-pair fallback, and the no-set string. +*** 2026-06-09 Tue @ 19:06:46 -0500 Safe-lightness picker guidance landed +Phase 5 (commit =843bbf08=). The OKLCH picker gets a "safe for" selector over the covered faces; the C×L plane shades the lightness band too light to keep that face readable, with the L_max ceiling (via =lMax= at the current chroma) as the band's lower edge. A too-dark foreground shades the whole plane. New #safetest gate pins band-shows-for-covered-face and hides-when-none. Verified headless + screenshot. +*** 2026-06-09 Tue @ 19:06:46 -0500 README + test-surface close-out landed +Commit =23926837=. README documents the ramp controls and defaults, the worst-case floor / limiting foreground, the five covered faces, the safe-lightness guidance, and WCAG-drives-PASS-FAIL with APCA as a diagnostic; the browser-gate list is updated. =make theme-studio-test= carries all new node tests and the #ramptest/#contrasttest/#safetest gates. All acceptance criteria met. ** TODO [#C] Internet radio now-playing song :feature:music:emms: Show the currently-playing song while streaming an internet radio station. Lives in =modules/music-config.el= (EMMS + MPV backend, M3U radio stations). The track title comes from the stream's ICY metadata — EMMS exposes it via =emms-track-description= / =emms-playing-time= and updates it on the metadata-change hook; MPV reports the ICY title too. Add an option to show the song in the minibuffer (e.g. echo on track change, or an on-demand command). Consider also a mode-line indicator as a second surface. |
