aboutsummaryrefslogtreecommitdiff
path: root/scripts/theme-studio/theme-studio.html
Commit message (Collapse)AuthorAgeFilesLines
* feat(theme-studio): add org-faces app for agenda keyword and priority colorsCraig Jennings20 hours1-2/+29
| | | | Surface the org-faces-config.el header-row faces as their own theme-studio app, placed beside elfeed and mu4e so it reads as a custom layer rather than built-in org. The seed mirrors the module defaults exactly across all 28 faces (10 keywords, 4 priorities, and their dim variants), so the editor opens on the live colors. The preview shows a focused agenda block and an auto-dim block covering every face.
* refactor(theme-studio): extract the shared package-preview wrapperCraig Jennings24 hours1-20/+23
| | | | The 20 line-based renderXxxPreview functions each ended with a byte-identical monospace-pre wrapper. They now build their L array and return previewLines(L), so the wrapper lives in one place and can't drift across the family.
* chore(theme-studio): remove dead code and clear a type warningCraig Jennings24 hours1-37/+1
| | | | | | | | | - ramp (app-core.js) and its test-ramp.mjs: superseded by regenColumn, no production caller. - optList (app-core.js) and its tests: superseded by paletteOptionList. - ITALIC in generate.py: computed, never read (ITALIC_MAP is the live one). - a stray empty string in MU4E_FACES that .split() silently dropped. - the dead #familytest alias in the columntest gate, which HASHES never listed. - widen face_rows to Sequence[str], clearing the list-invariance warnings on the APPS calls.
* fix(theme-studio): make broken browser gates fail instead of silently passingCraig Jennings25 hours1-4/+8
| | | | | | run-tests.sh scored each browser gate by grepping the dumped DOM for the gate name and taking the first match. A gate that throws before setting its verdict left its own inlined source as the first match, and that source, "GATENAME '+(ok?'PASS':'FAIL')", contains the literal PASS, so the run reported green for a gate that never produced a verdict. The matcher now requires a resolved "GATENAME PASS" or "GATENAME FAIL". That exposed two gates that had been throwing unnoticed. baseedittest still referenced fam after the variable was renamed to column, so it ReferenceError'd. columntest read getComputedStyle on a palette chip captured before a re-render detached it, so the match returned null and threw. baseedittest now uses column, and columntest re-queries the live chip by its selection index.
* fix(theme-studio): hold the package preview heightCraig Jennings25 hours1-1/+1
| | | | Selecting a compact package (auto-dim, with a 2-row face table and a short preview) collapsed the package section and shortened the page. A 60vh floor on the preview keeps the section sized to the largest of the columns, the preview, or that floor, so switching packages no longer shrinks the page.
* feat(theme-studio): auto-dim split previewCraig Jennings27 hours1-3/+73
| | | | | | | | auto-dim-other-buffers is a package face, not a theme face, so build-inventory.el (it scans only elpa/straight packages) never listed it and the studio couldn't theme it. This adds it as a bespoke app. The preview is a vertical split: the focused window on the left in real syntax colors, the same code on the right collapsed to the single auto-dim-other-buffers face, the way Emacs renders a non-selected window. Both panes follow the language selector. A trailing row shows auto-dim-other-buffers-hide, whose foreground matches the background so it vanishes when dimmed. A #autodimtest gate covers the split, the uniform recolor, and language sync.
* feat(theme-studio): palette generator and preview fidelityCraig Jennings28 hours1-43/+666
| | | | | | | | | | Two strands land together because the generated theme-studio.html bundles every source file into one page and can't be split cleanly. The palette generator is a preview-first panel: palette-generator-core.js plans the palette and palette-generator-ui.js draws it. Generated colors stay inspectable and tunable through the existing selector, and committing one creates a normal base column. It adds source-mode and scheme controls, a configurable accent count, and color names from color-names.json. For preview fidelity, syntax and UI colors now resolve through the real Emacs inherit chains, so the preview matches how Emacs renders the theme. resolveSyntaxFg pins dec to ty (Emacs has no decorator face) and otherwise follows comment-delimiter to comment, doc to string, property to variable, function-call to function-name. resolveUiAttr walks mode-line-inactive to mode-line and line-number-current-line to line-number. The decorator label now reads "decorator to type" to match the type face Emacs uses for it. Design recorded in the two theme-studio specs under docs/.
* Update theme studio palette workflowCraig Jennings46 hours1-110/+194
|
* Add theme studio box color controlsCraig Jennings2 days1-15/+36
|
* Shorten theme studio reset erase labelsCraig Jennings2 days1-12/+12
|
* Clarify theme studio reset and erase actionsCraig Jennings2 days1-16/+36
|
* Add theme studio face color step arrowsCraig Jennings2 days1-14/+61
|
* Preview selected theme studio chip while pickingCraig Jennings2 days1-6/+20
|
* Change theme studio spans to endpoint divisionsCraig Jennings2 days1-14/+26
|
* Remove theme studio save buttonCraig Jennings2 days1-13/+4
|
* Fix theme studio span endpoint tilesCraig Jennings2 days1-10/+20
|
* Sort theme studio dropdown colors by lightnessCraig Jennings2 days1-4/+6
|
* Fix theme studio ground endpoint editCraig Jennings2 days1-3/+14
|
* Fix theme studio fg endpoint selectionCraig Jennings2 days1-3/+15
|
* Refine theme studio tile name editingCraig Jennings2 days1-4/+20
|
* Make theme studio column delete saferCraig Jennings2 days1-3/+13
|
* Add theme studio Rust and Zig samplesCraig Jennings2 days1-1/+1
|
* Add theme studio column deleteCraig Jennings2 days1-5/+37
|
* Refactor theme studio palette testsCraig Jennings2 days1-29/+60
|
* Add theme studio palette clear and lock togglesCraig Jennings2 days1-5/+56
|
* Fix theme studio ground column orderCraig Jennings2 days1-6/+17
|
* Fix theme studio bg-prefixed span inferenceCraig Jennings2 days1-6/+9
|
* Fix theme studio style button stateCraig Jennings2 days1-1/+13
|
* Fix theme studio bg-like imported colorsCraig Jennings2 days1-21/+43
|
* Add theme studio column selection and reorder controlsCraig Jennings2 days1-5/+60
|
* Set theme studio default picker colorCraig Jennings2 days1-6/+7
|
* Group numeric color names by stemCraig Jennings2 days1-2/+2
|
* Treat legacy color names as base columnsCraig Jennings2 days1-2/+2
|
* Pin theme studio preview links and column exportsCraig Jennings2 days1-4/+28
|
* Rename theme studio column browser gateCraig Jennings2 days1-4/+4
|
* Refactor theme studio face assemblyCraig Jennings2 days1-5/+12
|
* Rename theme studio color model to columnsCraig Jennings2 days1-70/+70
|
* Update theme studio color columns and defaultsCraig Jennings2 days1-140/+164
|
* fix(theme-studio): derive box bevel colors from the face backgroundCraig Jennings5 days1-7/+58
| | | | The released/pressed bevel was a flat translucent white/black overlay, which reads weaker than the box Emacs draws. reliefColors in colormath.js now ports Emacs 30's x_alloc_lighter_color: highlight = bg x1.2, shadow = bg x0.6, an additive boost for dark backgrounds, and the same-color fallback for pure black and white. boxCss takes the face's effective bg and derives both edges from it. Pressed swaps the pair, and the translucent pair remains only when no bg is known. Width stays 1px because dupre's :line-width -1 draws 1px lines in Emacs too. The gap was color strength, not width. Five node tests pin hand-computed fixtures from the C source, and a new #beveltest gate pins the wiring.
* fix(theme-studio): re-rate fallback contrast cells on default-fg changeCraig Jennings5 days1-1/+15
| | | | A default-fg (p) change only re-rated the covered overlay faces. UI-face and package ratios that fall back to the default fg kept their old number until something else rebuilt the tables. The p branch now runs the same repaint as a ground-bg change. The new #contrasttest assertion drives the real syntax dropdown (unlocking a locked p row for the test) so the handler wiring is pinned, not just the repaint helper.
* fix(theme-studio): scope applyGround and repaint faces on ground changeCraig Jennings5 days1-3/+28
| | | | The contrast cells already rated a two-color face's own fg-on-bg. They read wrong because applyGround blanketed every .ex cell (the per-face preview cells included) with the ground bg, and a ground-bg change never repainted the UI or package tables. The preview showed fg on the ground bg next to a correct fg-on-face-bg ratio, and ground-dependent ratios went stale. applyGround now blankets only the code panes and syntax example cells and repaints UI faces through paintUI. The ground-bg handler also rebuilds the package table and preview. New #contrasttest assertions pin the two-color pair in both tables, preview-bg survival, and ground-change re-rating.
* feat(theme-studio): group families by lightness-conditioned complete linkageCraig Jennings6 days1-17/+45
| | | | | | | | | | Replace the hue-anchor bucketing and the tent neutral threshold with the model two independent reviews of color-sorting.org converged on (Codex and Fable, with Fable's harness measuring pairwise F1 0.63 → 0.96 on the real palette). Chromatic colors now cluster by complete-linkage agglomeration on a lightness-conditioned hue distance: hue must match tightly at equal lightness and may drift across a lightness gap, because a tonal ramp drifts in hue with lightness by design. A low-chroma noise term widens the tolerance where hue is ill-defined, and a chroma clause keeps a vivid accent out of a soft same-hue family. Complete linkage makes single-linkage chaining structurally impossible. The neutral threshold is floored at both ends instead of tapering to zero, which fixes two real defects: pale warm grays (gray+1, gray+2) that leaked into a color column, and pure white (C=0 at L=1) that evaded a zero threshold. On the sterling/distinguished palette this separates the gold and olive ramps (the green/yellow complaint), keeps the red and blue ramps whole including drifted tints, isolates intense-red, and consolidates every gray and steel into the neutral column. The one residual — pale yellow+2 lands on the olive ramp — is geometrically irreducible from the hex (it sits on the olive trajectory by nearest-neighbor, ramp-line fit, and eye); only its name says gold. That needs the deferred per-hex family-hint override. New node tests cover the gold/olive split, blue pale-tint cohesion, gray/white neutrality, intense-red isolation, and palette-order independence. The count gate now asserts the count action adds all ramp colors to the palette rather than that they all display in one family, since a chroma-eased extreme can sit at the neutral boundary.
* feat(theme-studio): color-families export round-trip and README close-outCraig Jennings6 days1-0/+14
| | | | | | | | Export stays a flat palette and import needs no reconstruction, because families are derived from the hex every render rather than stored. A #roundtriptest gate confirms export to import to export is byte-identical, and that the exported palette is still a flat [hex, name] list. Package seeding is unaffected since it reads the same flat palette. The spec's planned ramp-step warning exemption is dropped after analysis: a generated ramp's steps are a stepL apart, well above the too-similar ΔE threshold, so they never trigger the warning, and exempting same-family pairs would hide genuine near-duplicates that should be flagged (the case #deltatest checks). So the warning stays on the full palette. README documents color families: the hue grouping and its limitation, the ground strip, the per-column count control and regenerate, removed-step references reading "(gone)", and the removal of the standalone ramp panel. Phase 6, the last phase; the color-families v1 build is code-complete.
* feat(theme-studio): base-edit recolors a family; retire the ramp panelCraig Jennings6 days1-115/+50
| | | | | | | | Editing a family's base now recolors the whole family: update-selected on a base with a ramp regenerates the family from the new base at the same count, so references follow the new hexes (shared regenFamilyInPlace with the count control). Editing a ground swatch already writes the bg/fg assignment through the existing repoint, and the gate confirms it. The standalone ramp panel is gone — its button, panel, JS, CSS, and the #ramptest gate are removed. Fanning a color into a ramp now happens from its strip: add a color, then raise its column's count. The ramp() math stays in app-core; only the duplicate UI is retired. Phase 5 of the color-families spec. A #baseedittest gate covers the base-edit recolor (family follows, references repoint, count preserved) and the bg-swatch edit writing the assignment.
* feat(theme-studio): add the live per-family count controlCraig Jennings6 days1-4/+65
| | | | | | | | Each chromatic family column gets a count input (0-4) showing its current per-side reach. Setting N regenerates the family as a symmetric base ±N ramp from its most-saturated color, replacing the family's current members. A reference to a surviving step (matched by signed lightness rank) follows the new hex through repointHex; a reference to a step removed by lowering N is left on its old hex, which is no longer in the palette and renders as "(gone)" — never silently reassigned. The neutral and ground strips get no control. I also fixed the neutral threshold curve: it was flat-high through the darks, which pulled a chroma-eased dark ramp step (a dark desaturated blue) into the neutral column and broke the family. The curve now tapers toward both lightness extremes, peaking near mid, so dark and light tints both keep their hue while mid grays stay neutral. This is the symmetric form of the Munsell scaling and a strict improvement. Phase 4 of the color-families spec. A #counttest gate covers count-up adding symmetric steps, count-down dropping the extremes, the surviving-step repoint, and the removed-step "(gone)".
* feat(theme-studio): group families by hue anchor with a lightness-scaled ↵Craig Jennings6 days1-21/+20
| | | | | | | | | | neutral cut Replace gap-based hue clustering and the flat neutral threshold. Chromatic colors now bucket by nearest perceptual hue anchor (red, orange, yellow, green, teal, blue, purple, pink), so adjacent categories stay separate by construction and there's no single-linkage chaining merging them through intermediate tones. The neutral cut is lightness-scaled rather than flat: a color reads as neutral below a chroma that's highest in the mid-tones and tapers toward the light end, so a faint mid gray goes neutral while an equally-faint pale tint keeps its hue. This fixes the two concrete problems: the grays and steels consolidate into one neutral column, and pale tints (light blues) stay with their hue instead of falling into the grays. What it doesn't fix is hue-adjacent warm colors: this palette's olive-greens sit on top of the golds in OKLCH hue, so they still group together, and a ramp that drifts in hue can split across an anchor boundary. That's a real property of the colors, not a bug, and it's filed for research (a writeup of the problem and the four approaches tried lives outside the repo; the task points to it). 20 family node tests including the yellow/green split and the no-chaining case; suite green.
* style(theme-studio): lay out family strips as vertical columnsCraig Jennings6 days1-3/+2
| | | | Each family now reads top to bottom (dark to light) as a column, with families arranged left to right, rather than horizontal rows stacked down the panel.
* feat(theme-studio): render the palette as hue family stripsCraig Jennings6 days1-25/+59
| | | | | | The palette panel is now a stack of strips: the pinned ground strip (bg, fg) first, then hue-sorted family strips, each dark to light. Grouping comes from familiesFromPalette off the hex every render, so renaming a color never moves it. The flat PALETTE stays the editable truth and chips keep their per-chip remove / rename / select; the move-arrow and drag reordering are gone since the sort is deterministic now (moveColor and the drag state with them). Phase 3 of the color-families spec. A #familytest gate checks the ground strip pins first, families render, chips keep their controls, and a color renamed to anything stays in the same strip. Existing palette flows (delta, heal, ramp gates) stay green.
* feat(theme-studio): add color-family sortCraig Jennings6 days1-0/+18
| | | | | | sortFamilies orders the strips for display: neutrals first by lightness, then chromatic families by base hue, ties broken by base lightness then base hex. Each family's members come back sorted dark to light. Hue is compared rounded so a sub-degree hue hair from gamut quantization doesn't outrank lightness. Sorting is display-only; the stored palette order is untouched. Phase 2 of the color-families spec, pure logic. Four node tests cover the hue order, the neutral pin, within-family lightness order, and the (hue, then lightness) ordering invariant. Suite 91 to 95 green.
* feat(theme-studio): add the color-families model coreCraig Jennings6 days1-0/+87
| | | | | | Four pure functions in app-core.js, all derived from the hex so renaming never moves a color. familiesFromPalette groups a flat palette into the ground strip (the bg/fg assignment hexes, pinned, de-duped) plus hue families: near-neutrals split off by a chroma threshold, the rest cluster by hue proximity with a 25-degree gap and a 360 wrap, each family's base its most-saturated member. regenFamily returns a family's symmetric ramp around the base (n=0 is the base alone, handled without ramp()'s 1-4 clamp). rankByLightness gives each current member a signed offset from the base, and stepRepointPlan maps old positions to new ones across a regenerate, listing the positions that drop out so the caller can leave their references a visible "(gone)". Phase 1 of the color-families spec, pure logic, no UI. 13 node tests cover the gap split/merge, neutrals, absent and de-duped ground hexes, n=0, lightness ranking, and the survivor/removed repoint split. Suite 78 to 91 green.