mirror of
https://github.com/Psychotoxical/psysonic.git
synced 2026-07-21 14:55:43 +00:00
fix(themes): route remaining UI colours through theme tokens (#1014)
* fix(themes): route remaining UI colours through theme tokens An audit found several surfaces still wired to the fixed Catppuccin palette or hardcoded hex, so community themes could not recolour them: the 5-star rating, the global search field, the gradient-text flourish, badges and category-avatar text, and the What's New page + sidebar banner. Rewire them to existing contract tokens — no new tokens, and the built-in themes look identical (the values match). Community themes now control these areas. Also fixes device-sync rows referencing an undefined --bg-secondary (they rendered with no background); they now use --bg-card. * docs(themes): note the theme-coverage PR in the Theme Store entry Add PR #1014 to the still-unreleased Theme Store changelog and credits entry, alongside the other follow-ups.
This commit is contained in:
+1
-1
@@ -56,7 +56,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
|
||||
### Themes — community Theme Store
|
||||
|
||||
**By [@Psychotoxical](https://github.com/Psychotoxical), PR [#1009](https://github.com/Psychotoxical/psysonic/pull/1009), [#1011](https://github.com/Psychotoxical/psysonic/pull/1011), [#1012](https://github.com/Psychotoxical/psysonic/pull/1012), [#1013](https://github.com/Psychotoxical/psysonic/pull/1013)**
|
||||
**By [@Psychotoxical](https://github.com/Psychotoxical), PR [#1009](https://github.com/Psychotoxical/psysonic/pull/1009), [#1011](https://github.com/Psychotoxical/psysonic/pull/1011), [#1012](https://github.com/Psychotoxical/psysonic/pull/1012), [#1013](https://github.com/Psychotoxical/psysonic/pull/1013), [#1014](https://github.com/Psychotoxical/psysonic/pull/1014)**
|
||||
|
||||
* New **Settings → Themes** tab: pick a theme, set the day/night scheduler, and browse a built-in **Theme Store** to install, update and uninstall community themes — with search, a dark/light filter, and full-size thumbnail previews.
|
||||
* The app now bundles six core themes (Catppuccin Mocha & Latte, Kanagawa Wave, Stark HUD, and the colour-blind-safe Vision Dark / Vision Navy); every other palette installs on demand from the [psysonic-themes](https://github.com/Psysonic/psysonic-themes) repo. Installed themes are saved locally and apply instantly at startup, even offline.
|
||||
|
||||
@@ -356,7 +356,7 @@ const CONTRIBUTOR_ENTRIES = [
|
||||
'Performance Probe: Monitor/Toggles redesign, live CPU/RSS/thread metrics, overlay pins and sparklines, macOS snapshots (PR #890)',
|
||||
'Performance Probe: opt-in thread-group CPU poll toggle and includeThreadGroups IPC fix (PR #891)',
|
||||
'Queue: switchable display mode — Queue (upcoming only) vs Playlist (full list), with header toggle and settings entry (PR #922)',
|
||||
'Community Theme Store: semantic-token refactor, dedicated Themes tab with day/night scheduler, install/update/uninstall, local .zip import with full contract validation, and 80+ palettes moved to an on-demand CDN repo (PR #1009, #1011, #1012, #1013)',
|
||||
'Community Theme Store: semantic-token refactor, dedicated Themes tab with day/night scheduler, install/update/uninstall, local .zip import with full contract validation, and 80+ palettes moved to an on-demand CDN repo (PR #1009, #1011, #1012, #1013, #1014)',
|
||||
],
|
||||
},
|
||||
{
|
||||
|
||||
@@ -71,7 +71,7 @@ function ComposerRowAvatar({ artist }: { artist: SubsonicArtist }) {
|
||||
className="artist-avatar artist-avatar-initial"
|
||||
style={{ background: color, border: 0 }}
|
||||
>
|
||||
<span style={{ color: 'var(--ctp-crust)', fontWeight: 800 }}>{nameInitial(artist.name)}</span>
|
||||
<span style={{ color: 'var(--text-on-accent)', fontWeight: 800 }}>{nameInitial(artist.name)}</span>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -351,7 +351,7 @@ export default function Composers() {
|
||||
<button
|
||||
className={`btn btn-surface ${viewMode === 'grid' ? 'btn-sort-active' : ''}`}
|
||||
onClick={() => setViewMode('grid')}
|
||||
style={viewMode === 'grid' ? { background: 'var(--accent)', color: 'var(--ctp-crust)', padding: '0.5rem' } : { padding: '0.5rem' }}
|
||||
style={viewMode === 'grid' ? { background: 'var(--accent)', color: 'var(--text-on-accent)', padding: '0.5rem' } : { padding: '0.5rem' }}
|
||||
data-tooltip={t('artists.gridView')}
|
||||
>
|
||||
<LayoutGrid size={20} />
|
||||
@@ -359,7 +359,7 @@ export default function Composers() {
|
||||
<button
|
||||
className={`btn btn-surface ${viewMode === 'list' ? 'btn-sort-active' : ''}`}
|
||||
onClick={() => setViewMode('list')}
|
||||
style={viewMode === 'list' ? { background: 'var(--accent)', color: 'var(--ctp-crust)', padding: '0.5rem' } : { padding: '0.5rem' }}
|
||||
style={viewMode === 'list' ? { background: 'var(--accent)', color: 'var(--text-on-accent)', padding: '0.5rem' } : { padding: '0.5rem' }}
|
||||
data-tooltip={t('artists.listView')}
|
||||
>
|
||||
<List size={20} />
|
||||
|
||||
@@ -423,7 +423,7 @@
|
||||
gap: 8px;
|
||||
height: 52px;
|
||||
padding: 0 14px;
|
||||
background: var(--bg-secondary);
|
||||
background: var(--bg-card);
|
||||
border-bottom: 1px solid var(--border);
|
||||
flex-shrink: 0;
|
||||
}
|
||||
@@ -792,7 +792,7 @@
|
||||
|
||||
.device-sync-browser-row:hover { background: var(--bg-hover); }
|
||||
.device-sync-browser-row.selected { background: var(--accent-dim); }
|
||||
.device-sync-browser-row.indent { padding-left: 36px; background: var(--bg-secondary); }
|
||||
.device-sync-browser-row.indent { padding-left: 36px; background: var(--bg-card); }
|
||||
.device-sync-browser-row.indent:hover { background: var(--bg-hover); }
|
||||
.device-sync-browser-row.indent.selected { background: var(--accent-dim); }
|
||||
|
||||
|
||||
@@ -3,17 +3,17 @@
|
||||
max-width: 880px;
|
||||
margin: 0 auto;
|
||||
padding: 28px 32px 48px;
|
||||
color: #e4e7f5;
|
||||
background: #16182a;
|
||||
color: var(--text-primary);
|
||||
background: var(--bg-card);
|
||||
border-radius: 12px;
|
||||
box-shadow: 0 1px 0 rgba(255,255,255,0.04) inset, 0 8px 24px rgba(0,0,0,0.25);
|
||||
border: 1px solid #2a2d44;
|
||||
border: 1px solid var(--border-subtle);
|
||||
}
|
||||
|
||||
.whats-new__header {
|
||||
padding-bottom: 16px;
|
||||
margin-bottom: 20px;
|
||||
border-bottom: 1px solid #2a2d44;
|
||||
border-bottom: 1px solid var(--border-subtle);
|
||||
}
|
||||
.whats-new__title-row {
|
||||
display: flex;
|
||||
@@ -29,32 +29,32 @@
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
border-radius: 6px;
|
||||
border: 1px solid #3a3f5a;
|
||||
border: 1px solid var(--border);
|
||||
background: transparent;
|
||||
color: #9aa0bd;
|
||||
color: var(--text-muted);
|
||||
cursor: pointer;
|
||||
flex-shrink: 0;
|
||||
transition: background 0.15s, color 0.15s, border-color 0.15s;
|
||||
}
|
||||
.whats-new__close:hover {
|
||||
background: rgba(255,255,255,0.06);
|
||||
color: #e4e7f5;
|
||||
border-color: #4a5072;
|
||||
background: var(--bg-hover);
|
||||
color: var(--text-primary);
|
||||
border-color: var(--border);
|
||||
}
|
||||
.whats-new__icon {
|
||||
color: #8ec8ff;
|
||||
color: var(--accent);
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.whats-new__title {
|
||||
font-size: 22px;
|
||||
font-weight: 700;
|
||||
margin: 0;
|
||||
color: #f1f3fb;
|
||||
color: var(--text-primary);
|
||||
line-height: 1.2;
|
||||
}
|
||||
.whats-new__subtitle {
|
||||
font-size: 13px;
|
||||
color: #9aa0bd;
|
||||
color: var(--text-muted);
|
||||
margin-top: 2px;
|
||||
}
|
||||
.whats-new__date {
|
||||
@@ -66,22 +66,22 @@
|
||||
line-height: 1.65;
|
||||
}
|
||||
.whats-new__empty {
|
||||
color: #9aa0bd;
|
||||
color: var(--text-muted);
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.whats-new-h3 {
|
||||
font-size: 16px;
|
||||
font-weight: 700;
|
||||
color: #f1f3fb;
|
||||
color: var(--text-primary);
|
||||
margin: 22px 0 10px;
|
||||
padding-bottom: 6px;
|
||||
border-bottom: 1px solid #2a2d44;
|
||||
border-bottom: 1px solid var(--border-subtle);
|
||||
}
|
||||
.whats-new-h4 {
|
||||
font-size: 14px;
|
||||
font-weight: 700;
|
||||
color: #dfe3f6;
|
||||
color: var(--text-primary);
|
||||
margin: 14px 0 6px;
|
||||
}
|
||||
|
||||
@@ -99,27 +99,27 @@
|
||||
padding-left: 2px;
|
||||
}
|
||||
.whats-new-list li::marker {
|
||||
color: #6b7192;
|
||||
color: var(--text-muted);
|
||||
}
|
||||
|
||||
.whats-new-quote {
|
||||
border-left: 3px solid #3a3f5a;
|
||||
border-left: 3px solid var(--border);
|
||||
padding: 6px 12px;
|
||||
margin: 10px 0;
|
||||
color: #b6bcd8;
|
||||
background: rgba(255,255,255,0.02);
|
||||
color: var(--text-secondary);
|
||||
background: var(--bg-hover);
|
||||
border-radius: 0 4px 4px 0;
|
||||
}
|
||||
|
||||
.whats-new-hr {
|
||||
border: none;
|
||||
border-top: 1px solid #2a2d44;
|
||||
border-top: 1px solid var(--border-subtle);
|
||||
margin: 18px 0;
|
||||
}
|
||||
|
||||
.whats-new-code {
|
||||
background: #262a3e;
|
||||
color: #d4d7f0;
|
||||
background: var(--bg-elevated);
|
||||
color: var(--text-secondary);
|
||||
padding: 1px 5px;
|
||||
border-radius: 3px;
|
||||
font-family: var(--font-mono, ui-monospace, monospace);
|
||||
@@ -127,13 +127,12 @@
|
||||
}
|
||||
|
||||
.whats-new-link {
|
||||
color: #8ec8ff;
|
||||
color: var(--accent);
|
||||
text-decoration: none;
|
||||
border-bottom: 1px dashed #4a5072;
|
||||
border-bottom: 1px dashed var(--border);
|
||||
cursor: pointer;
|
||||
}
|
||||
.whats-new-link:hover {
|
||||
color: #b6dbff;
|
||||
border-bottom-color: #8ec8ff;
|
||||
color: var(--accent);
|
||||
border-bottom-color: var(--accent);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
/* ─ What's New — banner + page ────────────────────────────────────────────
|
||||
Fixed neutral palette so it reads identically on every theme (light and
|
||||
dark). The banner sits in the sidebar just above Now Playing; the page
|
||||
opens in the main content area. */
|
||||
The banner sits in the sidebar just above Now Playing; the page opens in
|
||||
the main content area. Both follow the active theme. */
|
||||
|
||||
.sidebar-bottom-spacer {
|
||||
margin-top: auto;
|
||||
@@ -15,9 +14,9 @@
|
||||
width: 100%;
|
||||
padding: 8px 10px;
|
||||
margin: 0 0 6px 0;
|
||||
background: #1f2233;
|
||||
color: #dfe3f6;
|
||||
border: 1px solid #3a3f5a;
|
||||
background: var(--bg-card);
|
||||
color: var(--text-secondary);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 8px;
|
||||
font: inherit;
|
||||
font-size: 12px;
|
||||
@@ -28,13 +27,13 @@
|
||||
}
|
||||
|
||||
.whats-new-banner:hover {
|
||||
background: #272b40;
|
||||
border-color: #4a5072;
|
||||
background: var(--bg-hover);
|
||||
border-color: var(--border);
|
||||
}
|
||||
|
||||
.whats-new-banner__icon {
|
||||
flex-shrink: 0;
|
||||
color: #8ec8ff;
|
||||
color: var(--accent);
|
||||
}
|
||||
|
||||
.whats-new-banner__text {
|
||||
@@ -47,12 +46,12 @@
|
||||
|
||||
.whats-new-banner__title {
|
||||
font-weight: 600;
|
||||
color: #f1f3fb;
|
||||
color: var(--text-primary);
|
||||
}
|
||||
|
||||
.whats-new-banner__version {
|
||||
font-size: 10.5px;
|
||||
color: #9aa0bd;
|
||||
color: var(--text-muted);
|
||||
font-variant-numeric: tabular-nums;
|
||||
}
|
||||
|
||||
@@ -64,12 +63,12 @@
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
border-radius: 4px;
|
||||
color: #9aa0bd;
|
||||
color: var(--text-muted);
|
||||
cursor: pointer;
|
||||
}
|
||||
.whats-new-banner__dismiss:hover {
|
||||
background: rgba(255, 255, 255, 0.08);
|
||||
color: #e4e7f5;
|
||||
background: var(--bg-hover);
|
||||
color: var(--text-primary);
|
||||
}
|
||||
|
||||
.whats-new-banner--collapsed {
|
||||
@@ -81,4 +80,3 @@
|
||||
justify-content: center;
|
||||
margin: 0 auto 6px;
|
||||
}
|
||||
|
||||
|
||||
@@ -10,6 +10,6 @@
|
||||
/* Opaque fill — `--accent-dim` is too transparent and disappears against
|
||||
light-toned hero backdrops when the cover art is white-dominant. */
|
||||
background: var(--accent);
|
||||
color: var(--ctp-crust);
|
||||
color: var(--text-on-accent);
|
||||
}
|
||||
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
width: 100%;
|
||||
padding: var(--space-2) var(--space-3);
|
||||
padding-left: 36px;
|
||||
background: var(--ctp-base);
|
||||
border: 1px solid var(--ctp-overlay0);
|
||||
background: var(--input-bg);
|
||||
border: 1px solid var(--input-border);
|
||||
border-radius: var(--radius-md);
|
||||
color: var(--text-primary);
|
||||
font-family: var(--font-sans);
|
||||
|
||||
@@ -2,23 +2,23 @@
|
||||
.star-rating {
|
||||
display: flex;
|
||||
gap: 2px;
|
||||
color: var(--ctp-overlay1);
|
||||
color: var(--text-muted);
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.star-rating .star.filled {
|
||||
color: var(--ctp-yellow);
|
||||
color: var(--highlight);
|
||||
}
|
||||
|
||||
.star-rating .star:hover {
|
||||
color: var(--ctp-yellow);
|
||||
color: var(--highlight);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
/* While clearing: no yellow hover until pointer leaves or next click */
|
||||
/* While clearing: no highlight hover until pointer leaves or next click */
|
||||
.star-rating--suppress-hover .star:hover {
|
||||
color: var(--ctp-overlay1);
|
||||
color: var(--text-muted);
|
||||
}
|
||||
|
||||
.star-rating--disabled {
|
||||
@@ -40,7 +40,7 @@
|
||||
}
|
||||
|
||||
.star-rating .star.star--locked:hover {
|
||||
color: var(--ctp-overlay1);
|
||||
color: var(--text-muted);
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* ─── Utility Classes ─── */
|
||||
.gradient-text {
|
||||
background: linear-gradient(135deg, var(--ctp-mauve), var(--ctp-blue));
|
||||
background: linear-gradient(135deg, var(--accent), var(--accent-2));
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
background-clip: text;
|
||||
|
||||
Reference in New Issue
Block a user