e9cb24481857baa7ceb75734573fd9b5fd130fa0
3
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
e9cb244818 |
the wallpaper, the header and the mark belong to the theme
Asked whether these could follow the theme too. They are the three most visible things
on screen and were the three least reachable: `Background.tsx` hardcoded
`url('/landscape1.webp')`, the header carried `rgba(255,255,255,0.25)` and `#1d2724`
in an inline style, and the logo was an `<img src>`.
Between them that is most of what "the app looks like Officer" actually meant. The
Plain theme turned every panel white and all three stayed exactly as they were, which
is how they were found — the leak detector doing its job on its first outing.
Verified across all three themes:
duck-dark wallpaper=landscape1.webp header=rgba(255,255,255,0.25)
duck-light wallpaper=landscape1.webp header=rgba(255,255,255,0.25)
plain wallpaper=none header=rgb(255,255,255)
── Images could not be done the obvious way ──
`--logo-image: url('/officer-logo.svg')` fails the build. Bun's CSS bundler resolves
`url()` at BUILD time and these files are served from `public/` at RUNTIME, so it goes
looking for a module that does not exist. Colours apply themselves; images cannot.
So a theme publishes a quoted PATH — an ordinary string token the bundler ignores —
and `useThemeAsset` reads it and wraps it in `url()`. One hook rather than the read
inline in two components, because the quote-stripping is the kind of detail that gets
forgotten the second time.
The logo is a `<div role="img">` with a background image rather than an `<img>`, since
CSS cannot set a `src` and a white-labelled build has to replace the mark from its
theme rather than by editing the header.
The header's title colour goes through a `.header-ink` class: `EditableTitle` accepts
a className and not a style, and the token stays the source of truth either way.
Panel radius and the ~985 raw palette usages are still outstanding — see
THEMES-NOTES.md.
tsgo clean.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
||
|
|
1be4bcd39a |
prove the extraction faithful, and fix the one thing that was not
The screenshots said seven dark screens differed and could not say why. Comparing COMPUTED theme variables between the old build and the new one, in the same colour mode, answered it in a single run: 47 of 53 matched exactly, and the six that did not were the `--duck-*` variables — EMPTY in the new build. The utilities were remapped to `--brand-primary`, `--ink` and friends, which is correct. What that missed is code reading the VARIABLE rather than using the utility. `prose.css` does exactly that eleven times — chat markdown links, blockquotes, inline code, checkboxes — and `landing/styles.css` does it six more. All silently resolved to nothing. Fixed by keeping the legacy names as aliases in every theme, pointing at the new source of truth rather than duplicating values. That also covers any plugin or inline style doing the same thing, which I have not enumerated. They retire when the utility rename lands. Every variable now matches. ── What the screenshots are actually worth here ── Less than I assumed. The wallpaper rotates per page load, so a control capture of the same build against itself had 4 of 16 screens differ — and a different 4 each time. Between 5 and 6 come out byte-identical to the baseline on any run; the rest is noise I mistook for signal for two rounds, including one where I removed a `color-scheme` line to test a theory it turned out not to explain. The variable diff is the instrument that settles it, and it is cheap. Added as `scripts/theme-vardiff.ts`. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
105766a4eb |
extract the visual layer into its own workspace
The application no longer knows what it looks like. It imports one stylesheet and
mounts one provider; every colour, surface and radius lives in `src/workspaces/theme`.
Proven both directions, because either alone would be worthless:
Duck renders IDENTICALLY to before — checked against screenshots taken before
anything was touched, not asserted.
Plain renders as white with black ink, no component edits — panels turn white, the
teal avatar turns black, the grid fills vanish.
── What moved ──
`globals.css` held three unrelated things: Tailwind wiring, the token contract, and
the Duck brand's hex values. Split along those seams. `base.css` is structure and
names no colour; a theme file is values and nothing else, scoped to
`[data-theme='<id>']`. Adding a theme is a CSS file plus one registry line.
Light and dark are separate themes rather than a mode — the owner's call, and it
removes a concept from the app. Each is written out in full: a theme that only makes
sense as a diff against another cannot be authored by a stranger or sold to a
customer. `.dark` survives only as a per-theme flag, because 396 `dark:` utilities in
33 components resolve against it; retiring those retires the flag.
The `duck-*` utility names are kept for now and pointed at neutral variables, so a
non-Duck theme can define them sensibly. Renaming 1,470 occurrences in the same commit
as the extraction would make any visual difference impossible to attribute. Worth
recording that `duck-dark` was never a brand colour — `#14532d` in light, near-white
in dark, used by 946 components to mean "text". It is `--ink` now.
Surfaces are complete CSS values rather than HSL triplets: `--panel-bg` has to be able
to be a gradient or an image, or the glass the app already has would be unthemeable.
The old provider is a re-export, so its six call sites are untouched and the
extraction stays one variable.
── Bug found by the Plain theme ──
`useThemeSync` stamped the server's `appearance.colorMode` over the local theme on
every load, so choosing Plain and reloading silently reverted it. Diagnosed by asking
the page what it was wearing rather than reasoning: `stored` said `duck-dark` when the
script had written `plain`. The server value is now a starting point for a browser
that has never chosen, not a continuous instruction.
── Tools ──
Two, both of which lied to me before they worked. The snapshot script photographed
light twice and called it a clean run (one browser context, accumulated init scripts);
it now warns when a light/dark pair is identical. The preview server returned the
shell for missing assets, so the logo and wallpaper vanished and read as regressions
in the comparison — it falls through to upstream now.
Dead Tailwind v3 residue deleted: `components/ui/tailwind.{config.ts,css}`, referenced
by nothing, with content globs pointing at a directory that does not exist.
── Not done, deliberately ──
`THEMES-NOTES.md` has the full list. The headlines: the reference repo has not been
read, so the switching mechanism is deliberately the dumbest thing that works; the
wallpaper, panel radius and logo are still component-owned and Plain proves it; and
~985 raw Tailwind palette usages remain, worst in Soulseek.
tsgo clean.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|