daybook/issues/017-customizable-document-theme-variants.md
peter a41e8dcfa5 Add issue #017: customizable, switchable document theme variants
Design issue capturing the request to let users customize document-artifact
colors and switch between theme variants, instead of everyone getting one
forced theme. Notes the two separable pieces (structure/skin split via CSS
variables as a prerequisite — the themes currently hardcode colors — and a
switching mechanism), the preset-vs-raw-CSS security tradeoff, dark-mode
interaction, and deck as the concrete trigger. References the existing
planning docs on theme variants/palettes.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-09-03 13:35:32 +01:00

114 lines
5.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 017 — Customizable, switchable theme variants for document artifacts
**Status:** Open
**Type:** Feature / design (not a bug)
## Motivation
Document artifacts (`markdown`, `html_fragment`, `deck`, and the `json`/`csv`
viewers) are effectively locked into a single look. The poster's agent can
pass a `theme` (`report` / `tasks` / `base`), but:
- There's no way for a **viewer** to switch an artifact's appearance — the
theme is fixed at post time and can't even be changed afterward (`theme`
isn't a `PATCH`-editable field; see `ArtifactDetailView.patch`).
- There are only three document themes, differing in more than just color.
- Recent consistency work (unifying artifact backgrounds to one off-white,
issue-driven) further homogenized the look — good for consistency, but it
underlines that everyone gets one palette whether they want it or not.
The ask: let people **customize the colors** for the different document
types, keeping the same structural CSS (same elements/selectors, same
layout), and provide a **way to switch between variants** — so the app isn't
forcing a single theme on everyone.
## Current state (for grounding)
- `theme` is a per-artifact `CharField`, set at create time:
`theme = data.get("theme") or DEFAULT_THEMES.get(kind, "base")`
(`DEFAULT_THEMES` maps markdown/html_fragment→`report`, deck→`deck`).
- Rendered pages link `/static/themes/{theme}.css`. Theme files:
`base.css`, `report.css`, `tasks.css`, `deck.css` (+ `pygments.css`).
- **The theme CSS hardcodes colors** (e.g. `report.css` sets
`background: #faf9f6; color: #1e2b2f` directly). There is no
color-variable layer, so a new palette today means duplicating a whole
theme file rather than swapping a few values.
- `json`/`csv` viewer styling is worse for this: it's inlined into each
artifact's stored HTML at create time (`wrap_json_viewer`/
`wrap_csv_viewer`), so it can't be restyled after the fact at all without
re-rendering.
## Two separable pieces
**1. Structure/skin separation (prerequisite).** Refactor the document
themes so structural rules (layout, spacing, element selectors, code
highlighting) are defined once, and *color* lives in CSS custom properties.
A "palette" then becomes a small set of variable values, not a duplicated
stylesheet. This is the same pattern the app chrome already uses
(`daybook.css` `:root` + `[data-theme="dark"]`); the artifact themes just
never adopted it. Without this, "customizable colors" means maintaining N
near-identical full CSS files.
Note: for `json`/`csv` to be re-skinnable, their viewer CSS needs to move
from inline-baked to a linked stylesheet (or the palette needs to be linked
separately), otherwise only newly-created ones can change.
**2. Switching mechanism.** Once palettes are swappable, decide *who* picks
and *when*:
- **Viewer-side switch** (like the dark-mode toggle): the person browsing
chooses a palette, applied at render/serve time; a personal preference
persisted per user. Doesn't change the stored artifact.
- **Per-artifact, editable**: make `theme`/palette a `PATCH`-editable field
so an artifact's look can be changed after posting.
- **Per-kind or global default**: a Settings option for "default palette for
my markdown artifacts," etc.
These aren't mutually exclusive; a viewer-side personal default is probably
the most flexible and matches the "don't force one theme on everyone" framing.
## Open questions
- **Preset palettes vs. user-authored CSS.** "Customize the CSS" could mean
(a) pick from a set of provided palettes, (b) pick colors via a UI that
generates a palette, or (c) let users paste raw CSS. (c) is the most
flexible but has a real downside: user CSS is an injection surface (less
severe than JS — see issue #014 — but still, e.g. CSS can load external
resources / exfiltrate via background-image URLs). A curated-palette or
color-picker approach (a/b) avoids that; raw-CSS would need the same
"trusted content only" caveat as `html_full`. Recommend starting with
presets + maybe a color-picker, not raw CSS.
- **Interaction with app light/dark mode.** Artifacts currently always
render light regardless of the app's dark mode. Should palettes include
dark artifact variants, and should they follow the app theme or be
independent?
- **Scope: global vs per-user.** `TagColor` is already global/shared across
users by design; would palettes be per-user preferences instead? (Likely
yes — a viewing preference, not shared state.)
- **`html_full`** stays out of this entirely (verbatim, poster owns styling).
- **`deck`** is the concrete trigger: it's intentionally dark, and the
request to make backgrounds consistent stalled on it precisely because
it can't just take the off-white without reworking its text colors —
a palette system with proper light/dark deck variants is the real fix.
## Suggested phasing
1. Refactor `base`/`report`/`tasks`/`deck` (and the json/csv viewers) to
drive all colors from CSS variables — no behavior change, just makes
everything else possible.
2. Ship 2–3 curated palettes per document family.
3. Add a viewer-side palette switch + persisted per-user preference
(mirrors the dark-mode toggle plumbing).
4. Later, optionally: per-artifact editable palette, or a color-picker for
custom palettes.
## References
- `planning/2026-09-02-theme_variants_and_user_palettes.md` — prior design
conversation on this exact topic.
- `planning/framework_artifact_rendering.md` — rendering/theming framework
notes (incl. the "vendor locally, CSS-only" stance and future renderers).
## Resolution
_(pending)_