Add a terminal skin, and make the board's branding settings real - #5
Merged
Conversation
`board.accent`, `board.logoUrl`, `board.faviconUrl` and `board.theme` have been in DEFAULT_SETTINGS since the beginning and were read by nothing. A board could set an accent and watch the page not change. All four now work, and there is a third skin to use them with. **terminal** is a layer over the modern sheet, exactly as classic is: neutral surfaces so the accent is the only colour on the page, hairline rules instead of shadows, monospace for chrome and proportional for prose, and the three dots of a title bar on section headers. Nothing in it hard-codes a hue, so it is a green board, an amber one or a blue one depending on the accent. **The accent is derived, not stored twice.** A colour legible on a dark board is usually illegible on a light one, so the chosen hue is emitted darkened for the light theme and brightened for the dark one. One setting, readable in both. It is baked into the stylesheet rather than written as an inline <style>, because style-src carries no 'unsafe-inline' — and since the sheet is served under a content hash, changing the accent changes the URL and reaches a returning reader immediately instead of waiting out a year-long max-age. `board.accent` defaulted to '#4f46e5', an indigo nothing read. Wiring that up as-is would have repainted every existing board on upgrade, so the default is now empty, meaning "the built-in palette". Two fixes found on the way: - The footer's GitHub link carried `style="display:inline-flex..."`, which the board's own CSP refuses — style-src governs style ATTRIBUTES too, not just <style> blocks — so the icon sat above the word instead of beside it. It is a class now. 30 more inline style attributes elsewhere are still refused the same way; they are a separate change. - `/prefs/theme` deleted the cookie for "system" instead of storing it. On a board whose own default is dark that reads straight back as dark, so the three-state toggle would have cycled dark -> dark. All three choices are stored. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JQRBzkLAusnFQHWMjgBLDZ
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.
board.accent,board.logoUrl,board.faviconUrlandboard.themehave been inDEFAULT_SETTINGSsince the beginning and were read by nothing — a board could set an accent and watch the page not change. All four work now, and there is a third skin to use them with.The terminal skin
A layer over the modern sheet, exactly as
classicis, so a component's structure stays defined in one place:box-shadowso no markup changes and nothing reaches the accessibility treeNothing in it hard-codes a hue. It is a green board, an amber one or a blue one depending on
board.accent.The accent is derived, not stored twice
A colour legible on a dark board is usually illegible on a light one —
#5fff87reads beautifully on near-black and vanishes on white. So the chosen hue is emitted darkened for the light theme and brightened for the dark one, and every token that follows the accent (--ring,--primary-hot,--gradient-brand,--glow-primary,--page-wash,--row-hover) moves with it. One setting, readable in both themes.It is baked into the stylesheet rather than written as an inline
<style>:style-srccarries no'unsafe-inline', and widening the policy for a handful of custom properties is a poor trade. Because the sheet is served under a content hash, changing the accent in the admin panel changes the URL, so the new colour reaches a returning reader immediately instead of waiting out a year-longmax-age.board.accentdefaulted to#4f46e5, an indigo nothing read. Wiring that up as-is would have repainted every existing board on upgrade, so the default is now empty — meaning "the built-in palette".Two bugs found on the way
style="display:inline-flex;…", andstyle-srcgoverns style attributes, not only<style>blocks — so the icon sat above the word instead of beside it. It is a class now. 30 more inline style attributes elsewhere in the app are refused the same way; that is a separate change, not this one./prefs/themedeleted the cookie for "system" instead of storing it. Identical behaviour on a board that defaults tosystem, and wrong on any other: a dark-default board would read the absence of a cookie straight back as dark, so the three-state toggle cycled dark → dark. All three choices are stored now.Checks
pnpm typecheckclean,pnpm test156/156 (10 new: the colour maths, the skin layering, the accent in the served sheet, logo/favicon in the header, andboard.themenever overriding a reader's cookie).Not run:
pnpm format. It reformats ~70 files at HEAD and breaks two tests, so this branch is hand-formatted to match the surrounding code.Rendered at 1280px, dark and light, with the HQTUI wordmark and
#5fff87.🤖 Generated with Claude Code
https://claude.ai/code/session_01JQRBzkLAusnFQHWMjgBLDZ