Repository navigation
Design Tokens
This is the recommended semantic token surface the app reads, defined in schema/allowed-tokens.json (frozen from the built-in themes' token surface). Community themes are free-form — this list is the simplest way to recolour the whole app in one place, not a mandatory contract. The hard gate is the safety floor in the validator; see Validator & CI.
All tokens below are colour values only, except layout, which is lengths.
Declared directly on the theme root selector (not as a custom property):
[data-theme='<id>'] {
color-scheme: dark; /* or light — must match manifest.mode */
}
Live app state exposed as attributes on the same root element as data-theme, so themes can react to it:
| Attribute | Values |
|---|---|
data-playing |
true / false
|
data-fullscreen |
true / false
|
data-sidebar-collapsed |
true / false
|
data-lyrics-open |
true / false
|
[data-theme='<id>'][data-playing='true'] { /* glow the player bar, etc. */ }This is the recommended semantic token surface the app reads, defined in [schema/allowed-tokens.json](https://github.com/Psysonic/psysonic-themes/blob/main/schema/allowed-tokens.json) (frozen from the built-in themes' token surface). Community themes are free-form — this list is the simplest way to recolour the whole app in one place, not a mandatory contract. The hard gate is the safety floor in the validator; see Validator & CI.
All tokens below are colour values only, except layout, which is lengths.
| Token | Purpose |
|---|---|
--accent |
Primary accent / brand colour |
--accent-dim |
Low-alpha accent for fills/backgrounds (e.g. selected row) |
--accent-glow |
Accent glow / focus halo colour |
--accent-2 |
Secondary accent — second stop of two-colour gradient flourishes |
--bg-app |
Main app background |
--bg-sidebar |
Sidebar / navigation background |
--bg-card |
Card / panel surface |
--bg-hover |
Hover / elevated surface |
--bg-elevated |
Highest elevated surface |
--bg-player |
Player bar background |
--bg-deep |
Deepest background / gradient stop |
--bg-glass |
Translucent glass background (use rgba — sits over blurred surfaces) |
--border |
Default border colour |
--border-subtle |
Subtle / hairline border |
--text-primary |
Primary text |
--text-secondary |
Secondary text |
--text-muted |
Muted / tertiary text |
--text-on-accent |
Text/icon colour drawn on top of --accent
|
--danger |
Error / destructive |
--positive |
Success / positive |
--warning |
Warning |
--highlight |
Highlight / rating colour |
--select-arrow |
Dropdown chevron — the one token whose value is url(data:...). Recolour by changing stroke=%23RRGGBB inside the URI |
| Token | Purpose | Falls back to |
|---|---|---|
--volume-accent |
Volume slider fill | --accent |
--waveform-played |
Waveform — played portion | --accent |
--waveform-unplayed |
Waveform — unplayed portion | — |
--waveform-buffered |
Waveform — buffered portion | — |
--player-title |
Player-bar track title colour | --text-primary |
--player-artist |
Player-bar artist colour | --text-secondary |
Added 2026-06-06. Each defaults to a base token, so omitting all of them is fine — a theme that sets only the core tokens still looks complete. Set one to recolour that region independently (e.g. give the sidebar its own hover without touching every other hover).
Sidebar: --sidebar-item-hover, --sidebar-item-active-bg, --sidebar-item-active-text, --sidebar-text, --sidebar-trigger-bg, --sidebar-border
Player bar: --player-control, --player-control-hover, --player-control-hover-bg, --player-time-toggle-hover, --player-time-toggle-active, --player-border
Rows / tracklists: --row-hover, --row-playing-bg, --row-playing-text, --row-divider, --row-text, --row-text-secondary, --row-text-muted, --col-header-text, --col-resize-active
Cards: --card-hover-border, --card-title, --card-subtitle, --card-placeholder-bg
Menus / dropdowns / modals: --menu-bg, --menu-item-hover, --menu-item-active-text, --menu-divider, --border-dropdown (falls back to --border), --shadow-dropdown, --modal-bg, --modal-scrim
Inputs / controls: --input-bg, --input-border, --input-focus-border, --button-hover, --slider-track, --slider-thumb, --slider-thumb-hover, --scrollbar-thumb, --scrollbar-thumb-hover, --scrollbar-track
Added 2026-07-14, requires app ≥ 1.50.0. The one non-colour group — these exist because the intuitive fix is to override app CSS that carries behaviour, which silently breaks a feature.
| Token | Purpose |
|---|---|
--rail-shadow-room |
Space reserved inside a horizontal album rail's clip box so an outer card shadow can paint (default 8px). Raise this if your cards use a larger shadow/glow. |
Don't set
overflow: visibleon.album-gridto stop shadow clipping instead of using this token — a rail must clip (overflow-x: autoforcesoverflow-yto compute toauto), and removing that clip container disables the rail's prev/next scroll arrows entirely. This exact mistake has shipped and been fixed in multiple themes — see FAQ.