Theme tokens¶
A theme is a flat map of CSS custom-property values. Pluma ships two:
pluma-teal— default. Cool teal, written quiet.pluma-rose— warm sibling. Same token shape, rose-tinted neutrals.
Switch under Settings → General → Theme. Choice persists across reloads.
Token list¶
All colour tokens are stored as raw R G B triples (no rgb() wrapper) so Tailwind's <alpha-value> mechanism works at the use site: bg-accent/15 → background-color: rgb(20 184 166 / 0.15).
Neutral scale¶
The ink-* tokens drive surfaces and text. ink-950 is the deepest background; ink-50 the brightest foreground. The 400-600 band sits at ~4:1 contrast against ink-900 so secondary text reads cleanly.
| Token | Used for |
|---|---|
--ink-950 |
Page background |
--ink-900 |
Card / surface background |
--ink-850 |
Hover-state surface, slightly raised |
--ink-800 |
Default border |
--ink-700 |
Active border, hover border |
--ink-600 |
Disabled text, low-contrast captions |
--ink-500 |
Secondary text, uppercase labels, footnotes |
--ink-400 |
Italic action text, mid-tone descriptions |
--ink-300 |
Primary captions |
--ink-200 |
Body text |
--ink-100 |
Headline text, primary actions |
--ink-50 |
Maximum-contrast foreground (rarely used) |
Accents¶
| Token | Used for |
|---|---|
--accent |
Primary actions, links, brand glyph |
--accent-soft |
Tinted backgrounds (chips, halos) — same RGB as --accent, consumed with /<alpha> |
--accent-bright |
"Now live" cues, badges |
--speech-accent |
In-chat dialogue prose colour (kept warm cream across themes) |
Semantic¶
| Token | Used for |
|---|---|
--danger |
Errors, destructive actions |
--success |
Confirmations, "running" states |
--warning |
Cautions, low-priority alerts |
--scrollbar-thumb |
Scrollbar thumb colour (typically same as --accent-bright) |
Writing a theme¶
A theme is one .ts file under web/src/themes/. Mirror pluma-teal or pluma-rose for the token shape. Register in web/src/main.ts:
import { plumaRose } from './themes/pluma-rose'
import { myTheme } from './themes/my-theme'
registerTheme(plumaTeal)
registerTheme(plumaRose)
registerTheme(myTheme)
The theme picker (Settings → General) reads listThemes() at render time, so adding one shows up automatically.
Future: shareable themes¶
A planned feature (tracked under smelt-sze) will let users drop theme JSONs into a <datadir>/themes/ directory. Before that ships, Pluma will add:
- A token-name allowlist (only the keys above; rejects anything else).
- A value-shape validator (RGB triples only; rejects raw URLs and arbitrary CSS).
- A Content-Security-Policy header on responses.
This is so a shared theme can't smuggle a tracking pixel via a url(https://evil.com/log) value in some unexpected token. Until the validator lands, theme registration stays code-only.