diff options
| author | Craig Jennings <c@cjennings.net> | 2026-06-09 19:06:21 -0500 |
|---|---|---|
| committer | Craig Jennings <c@cjennings.net> | 2026-06-09 19:06:21 -0500 |
| commit | 23926837f2d1ef733f287f4b2166946dc6703a11 (patch) | |
| tree | 43fedc8ec750eee16a2262ddcb3dd839aca25f4a /scripts/theme-studio/README.md | |
| parent | 843bbf0848adff40714e3d7f01376dfe2f14e1dc (diff) | |
| download | dotemacs-23926837f2d1ef733f287f4b2166946dc6703a11.tar.gz dotemacs-23926837f2d1ef733f287f4b2166946dc6703a11.zip | |
docs(theme-studio): document ramps and contrast safety in the README
The README now covers the ramp generator (the controls and their defaults, naming, and collision behavior), the worst-case-floor readout and its limiting foreground, the five covered overlay faces, the safe-lightness picker guidance, and that WCAG drives PASS/FAIL with APCA as a diagnostic. The browser-gate list is updated with the full set, including #ramptest, #contrasttest, and #safetest.
Closes the README and test-surface acceptance criteria for the palette-ramps v1 build.
Diffstat (limited to 'scripts/theme-studio/README.md')
| -rw-r--r-- | scripts/theme-studio/README.md | 45 |
1 files changed, 44 insertions, 1 deletions
diff --git a/scripts/theme-studio/README.md b/scripts/theme-studio/README.md index 044ccc2e..a2eb59b2 100644 --- a/scripts/theme-studio/README.md +++ b/scripts/theme-studio/README.md @@ -42,7 +42,8 @@ The runner regenerates the page, runs the Python templating tests (`test-colormath.mjs`, including the inline-integrity check), a syntax check of the spliced page script, and the browser hash gates in headless Chrome (`#selftest`, `#cursortest`, `#readouttest`, `#deltatest`, `#oklchtest`, -`#planetest`). It exits non-zero on any failure. The browser gates need a +`#planetest`, `#locktest`, `#sorttest`, `#mocktest`, `#ramptest`, +`#contrasttest`, `#safetest`). It exits non-zero on any failure. The browser gates need a Chromium-family browser; without one they report SKIPPED rather than passing silently. The pure color math and the extracted picker logic (`planeCell`, `paletteWarnings`) live in `colormath.js` so they are unit-tested directly in @@ -92,6 +93,48 @@ Three tiers of faces, plus the palette: per face, shown in a live mock Emacs buffer. - **Package faces** — per-package face tables with a live preview (below). +## Ramps and background-contrast safety + +Two coupled features help build a harmonized palette and keep background tints +readable. Both work in OKLCH, where lightness, chroma, and hue move +independently. The pure math is in `app-core.js` (`ramp`, `fgSetFor`, `floor`, +`lMax`); the DOM is in `app.js`. + +**Ramps.** The "ramp" button on the palette controls generates a tonal ramp from +the current color: lighter and darker steps on a held hue, with the chroma easing +out toward the extremes. Three controls set the shape, with defaults that produce +a sensible first ramp: + +- `steps` — how many steps each direction (default 2, range 1-4). +- `stepL` — the OKLCH lightness delta per step (default 0.08, range 0.04-0.12). +- `chroma ease` — how much chroma drops at the farthest step (default 0.5, range + 0-1; 0 holds chroma flat, 1 fully desaturates the last step). + +Each previewed step is named after the source swatch (`blue` gives `blue+1`, +`blue-1`) and shows a clamp badge when it left the sRGB gamut. Click a step to +add it, or "add all"; steps insert next to the source in order. A name that +already exists is skipped (never overwritten); a generated hex that matches +another entry is added but flagged as a duplicate. + +**Worst-case contrast.** A background overlay sits behind many foregrounds at +once, so one fg/bg contrast pair is the wrong number. For the covered overlay +faces — `region`, `hl-line`, `highlight`, `lazy-highlight`, `isearch` — the +contrast cell shows the *worst-case floor*: the lowest contrast over the face's +foreground set (the syntax-token colors plus the default foreground), naming the +*limiting foreground* that sets it. A tint that clears the default text but fails +the darkest token reads FAIL, with that token named. Package faces and the other +UI rows keep their single-pair readout. + +The verdict is WCAG: AA (4.5) by default, AAA (7) selectable. APCA Lc stays a +picker-only diagnostic and does not drive PASS/FAIL. + +**Safe lightness.** In the OKLCH picker, the "safe for" selector picks one +covered face. The Chroma×Lightness plane then shades the lightness band too light +to keep that face readable over its foreground set, with the L_max ceiling as the +band's lower edge. If even pure black can't satisfy the target (a foreground is +too dark), the whole plane shades; that is a true finding about the foreground, +not a tool bug. + ## Package faces Pick an application from the dropdown to edit its faces. Each row has a |
