docs(website): a user-facing Appearance page, and PADDOCK_BRAND_ACCENT is now hue-only - #814
Open
edspencer wants to merge 6 commits into
Open
docs(website): a user-facing Appearance page, and PADDOCK_BRAND_ACCENT is now hue-only#814edspencer wants to merge 6 commits into
edspencer wants to merge 6 commits into
Conversation
added 3 commits
August 10, 2026 13:52
…BRAND_ACCENT
The v0.67 visual overhaul shipped four runtime themes, a ten-name accent
picker, a ground tint and an AA-contrast-floor solver, and no page on the
site mentioned any of it -- "Appearance" matched zero pages.
- New configuration/appearance.md, ground-truthed against
packages/web/src/lib/{appearance,accent,theme}.ts and AppearancePanel.tsx.
- Sidebar entry (Starlight does not auto-discover).
- PADDOCK_BRAND_ACCENT in configuration/environment.md and the env-surface
table in architecture/overview.md: only the hue of that hex is used now.
- contributing.md: the first inbound link anywhere to docs/DESIGN.md.
…e does The brief said the picker has an AA-contrast-floor solver. A second source trace disproves it, and I re-verified all four points in this tree: - solve()'s `hit` flag has no consumer anywhere (accent.ts:262,266,284 are the only occurrences -- the return sites). - applyAccent computes report.ok / report.checks and no UI renders them; AppearancePanel holds the AccentReport but reads only .hue and .mode. - There are no solver tests: 24 *.test.ts under packages/web/src/lib/ and neither accent.test.ts nor appearance.test.ts is among them. The shipped contrast guards are static-CSS-only and never see a picked accent. - --accent's floor is AA_MARK + MARGIN = 3.12, not 4.5. Only a600/a700 get 4.62 and --accent-solid's repair pass 4.5. So the picker ATTEMPTS a floor, applies its best effort silently when it cannot reach one, and surfaces nothing either way. The page now says it aims at AA rather than guaranteeing it, and tells a reader what to do if a colour looks wrong. Same treatment for the tint (measured, not enforced) and for PADDOCK_BRAND_ACCENT in environment.md. The code side is a separate finding and is being filed as an issue; nothing in the code is softened here.
Deploying paddock with
|
| Latest commit: |
4995d11
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://894b9055.paddock-7u2.pages.dev |
| Branch Preview URL: | https://docs-appearance-page.paddock-7u2.pages.dev |
added 3 commits
August 10, 2026 14:02
…se honest An earlier commit over-corrected: told the solver did not enforce a floor, I stripped out the floor and the repair pass entirely and under-claimed a real feature. Re-read from source and restored, with the parts that ARE unenforced scoped precisely rather than generalised. What source shows (accent.ts): - AA_TEXT = 4.5 / AA_MARK = 3 are real WCAG AA floors, correctly applied per channel (:63-65). The earlier '--accent targets 3.12 not 4.5' framing was misleading: 3.12 is AA_MARK + MARGIN, the correct floor for a non-text mark. Text channels get AA_TEXT + MARGIN = 4.62. - solve()'s `floor` genuinely is the guarantee and `target` genuinely is a preference -- `floor = target` by default and callers pass a lower floor explicitly (:255-262, :505). - repairFill re-reads what the theme DERIVED and writes a repaired value (:634), which is what makes the floor hold for themes not yet written. What is genuinely unenforced, now stated as exactly that and no wider: - #813 -- an accent that cannot physically reach the floor is applied silently; solve()'s `hit` is discarded and report.ok is never rendered. - #816 -- the tint's ground check is measured and folded into report.ok (appearance.ts:216-226) but never repaired; the check hardcodes `repaired: false`. The page now names that asymmetry against the accent rather than implying a repair that does not happen. Both issues are linked from the page, which is house style here.
Two precision fixes on the accent section. Neither walks back the floor or
the repair pass -- both are real and stay.
- Dropped the '13.6:1' figure for terminal. accent.ts:73 records that
rounding moved three of 110 measured combinations from a solved 4.50 to a
RENDERED 4.48, so a solved ratio is not the painted one and must not be
published as if it were -- same class as the blend-mode finding from the
theme work. The point survives without the number ('clears the floor
several times over') and cannot rot.
- Kept 4.5 and 3, now attributed to WCAG as the standard's own thresholds
rather than asserted as what the rendered pixel achieves.
- The note is now the honest three-part shape: the mechanism is real, the
residual case is silent (#813), and the precision is unverified -- the
solve is arithmetic on colour values, MARGIN exists to absorb the 8-bit
rounding, and nothing samples the rendered result. Confirmed no test file
under packages/web/src imports lib/accent.
…e solve
'Untested' was too blunt and unfair to the theme work. What exists:
styles/{themes,tokens,theme-parchment,theme-terminal,theme-scifi}.test.ts --
a real contrast suite that walks each theme's palette pair by pair. What
does not exist is any test of the SOLVER: there is no accent.test.ts or
appearance.test.ts, and the guards that do exist parse the static
stylesheets, so a runtime-solved accent is never in their sample. The
source makes the same point at accent.ts, in the repairFill comment: 'a
SOLVED hue is a value no static guard ever sees.'
The page now draws that line explicitly rather than implying the theming
is unverified. It is the more interesting fact and the fairer one.
Also correcting my own earlier commit message: lib/accent IS imported by
non-test source (AppearancePanel.tsx and lib/appearance.ts). The narrow
claim -- no TEST file imports it -- is the accurate one and is what the
page rests on.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
v0.67 shipped four runtime themes, a ten-name accent picker and a ground tint, all
switchable from the Config screen. No page on the docs site mentioned any of it:
"Appearance"matched zero pages underwebsite/src/content/docs/. This is thelargest documentation gap in the v0.66.2 → v0.69.0 range.
Every claim is ground-truthed against source in this branch, not against the
changelog. Cites below are by file + symbol per
CLAUDE.md, not by line number.What's in it
New
configuration/appearance.md— where the section lives and why it is on/configrather than in a dialog; the four themes with their registry blurbs andthat Foundation is the default; the accent strip and the ten named colours;
what the solver actually promises (below); the ground tint; the per-device /
localStoragescope, stated plainly because it is the thing a reader will getwrong; light/dark as a separate toggle; how
PADDOCK_BRAND_ACCENTcomposes; anda contributor pointer to
docs/DESIGN.md.It records as a
:::notethat the instance-default half of the two-scope model(
theme:in the config file plus aPADDOCK_THEME) is a deliberate stubrather than a defect —
PADDOCK_THEMEappears nowhere inpackages/except thesource comment saying it is not built yet.
Sidebar entry in
website/astro.config.mjs, first in the Configuration group.Starlight does not auto-discover; without this the page is unreachable.
configuration/environment.md—PADDOCK_BRAND_ACCENTno longer sets acolour. Only the hue of that hex survives; the theme supplies the saturation
and solves the lightness against its own surfaces (
appearance.ts,instanceDefaultHue, which discardsLandC). The server still injects its:root{--accent…}block (server/src/brand.ts,accentRootStyle), but the[data-theme]blocks and the solved inline values outrank it.architecture/overview.md— the same correction in the env-surface table.contributing.md— the first inbound link anywhere todocs/DESIGN.md.It is 573 lines, current and contributor-facing, and
grep -rn 'DESIGN.md' website/ README.md CONTRIBUTING.mdreturned nothing before this PR.docs/DESIGN.mditself is untouched.How the page scopes the AA claim
This was the hardest paragraph in the PR. Its final shape is three-part: the
mechanism is real, the residual case is silent, the precision is unverified.
Real, and documented as such:
AA_TEXT = 4.5/AA_MARK = 3(accent.ts) are correctly applied per channel.Text channels solve against
AA_TEXT + MARGIN;--accentusesAA_MARK + MARGIN— the correct WCAG floor for a non-text mark, not an under-application of the
text floor.
solve()takesfloor = target, andsolveChannelspasses a lower floorexplicitly — so the floor genuinely is the guarantee and matching the theme
genuinely is a preference. The page says exactly that.
repairFill(defined inapplyAccent) re-reads what the theme derived andwrites a repaired value; it is called for
--accent-solidand--accent-solid-hover, with a third repair pass for--accent-text. That is whatmakes the floor hold for a theme nobody has written yet.
Silent, and linked:
cannot physically reach the floor is applied with no warning:
solve()'shitisdiscarded by every caller, and
report.ok/report.checksare never rendered(
AppearancePanel.tsxreads only.hueand.mode).ground check is measured by
tintGroundand folded intoreport.okbyapplyAppearance, but never repaired; the pushed check hardcodesrepaired: false. The page names that asymmetry against the accent explicitly,because "folds it into the same readability check" otherwise implies a repair that
does not happen.
Unverified, and scoped precisely:
quoted a solved
13.6:1;accent.ts'sMARGINcomment records that roundingmoved three of 110 combinations from a solved 4.50 to a rendered 4.48, so a
solved ratio is not a painted one. The page now names WCAG's own thresholds as
the thing being aimed at and quotes no achieved figure.
palettes are covered by a real suite (
styles/themes.test.ts,tokens.test.ts,theme-{parchment,terminal,scifi}.test.ts), but those checks parse the staticstylesheets. There is no
accent.test.tsorappearance.test.ts, so the runtimesolve is never exercised — the source makes the same point in
repairFill'scomment: "a SOLVED hue is a value no static guard ever sees."
No code is softened to match the docs.
Checks
cd website && npm install && npm run build→ exit 0, 53 pages.ORPHANS []/DANGLING []./configuration/environment/#branding-per-instanceresolves in the built output.127.0.0.1count acrosswebsite/src/content/docs/**+README.mdis 46, unchanged — this diff adds none. No hostnames, LAN IPs or box-specific
values in the diff.
Not in scope
swatches and the accent strip would be the site's only post-overhaul images —
an argument for shooting them with the rest of the re-shoot, not here. Another
agent owns media; this page ships prose-only and reads fine without a picture.
configuration/instance-settings.mdAppearance row and the Config screen: one measure, a surface, and rows (structural) #768section-rail/filter subsection. The Appearance page covers the filter/rail
behaviour in its "Where it is" section; the table row is a one-line follow-up.