Skip to content

Commit af912cc

Browse files
feat: add Neon Love theme preset from Love color palette
Add third theme preset using Love dark palette (https://love.holllo.cc): deep purple backgrounds, lavender text, cyan primary accent, lime green now-playing indicator. Includes all component overrides matching the metro-teal pattern (track rows, footer, progress bar, sidebar, titlebar, settings panels, borders, scrobbling toggle). Update pre-Alpine init, theme store validation, settings UI, and unit tests. Closes TASK-293 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 9cc1188 commit af912cc

6 files changed

Lines changed: 262 additions & 43 deletions

File tree

app/frontend/__tests__/ui.store.test.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ function createTestUIStore() {
130130
},
131131

132132
setThemePreset(preset) {
133-
if (['light', 'metro-teal'].includes(preset)) {
133+
if (['light', 'metro-teal', 'neon-love'].includes(preset)) {
134134
this.themePreset = preset;
135135
}
136136
},
@@ -339,6 +339,9 @@ describe('UI Store - Theme Management', () => {
339339
store.setThemePreset('metro-teal');
340340
expect(store.themePreset).toBe('metro-teal');
341341

342+
store.setThemePreset('neon-love');
343+
expect(store.themePreset).toBe('neon-love');
344+
342345
store.setThemePreset('light');
343346
expect(store.themePreset).toBe('light');
344347
});

app/frontend/js/stores/ui.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ export function createUIStore(Alpine) {
141141
},
142142

143143
setThemePreset(preset) {
144-
if (['light', 'metro-teal'].includes(preset)) {
144+
if (['light', 'metro-teal', 'neon-love'].includes(preset)) {
145145
console.log('[settings]', 'set_theme_preset', {
146146
previousPreset: this.themePreset,
147147
newPreset: preset,
@@ -183,9 +183,9 @@ export function createUIStore(Alpine) {
183183
let titleBarTheme;
184184
let contentTheme;
185185

186-
if (this.themePreset === 'metro-teal') {
186+
if (this.themePreset === 'metro-teal' || this.themePreset === 'neon-love') {
187187
document.documentElement.classList.add('dark');
188-
document.documentElement.dataset.themePreset = 'metro-teal';
188+
document.documentElement.dataset.themePreset = this.themePreset;
189189
titleBarTheme = 'dark';
190190
} else {
191191
titleBarTheme = 'light';

app/frontend/main.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -128,9 +128,9 @@ function applyInitialTheme() {
128128
document.documentElement.classList.remove('light', 'dark');
129129
delete document.documentElement.dataset.themePreset;
130130

131-
if (themePreset === 'metro-teal') {
131+
if (themePreset === 'metro-teal' || themePreset === 'neon-love') {
132132
document.documentElement.classList.add('dark');
133-
document.documentElement.dataset.themePreset = 'metro-teal';
133+
document.documentElement.dataset.themePreset = themePreset;
134134
} else {
135135
const contentTheme = theme === 'system'
136136
? (window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light')

app/frontend/styles.css

Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -343,6 +343,158 @@ aside button:hover svg {
343343
background-color: hsl(184 100% 38%) !important;
344344
}
345345

346+
/* Neon Love theme — Love color palette (https://love.holllo.cc)
347+
Dark purple backgrounds with neon rainbow accents, inspired by Tauon Music Box */
348+
[data-theme-preset='neon-love'] {
349+
--background: 268 37% 14%;
350+
--foreground: 251 100% 97%;
351+
--card: 268 34% 19%;
352+
--card-foreground: 251 100% 97%;
353+
--popover: 268 34% 19%;
354+
--popover-foreground: 251 100% 97%;
355+
--primary: 191 76% 58%;
356+
--primary-foreground: 268 37% 14%;
357+
--secondary: 268 30% 22%;
358+
--secondary-foreground: 251 100% 97%;
359+
--muted: 268 30% 22%;
360+
--muted-foreground: 0 0% 67%;
361+
--accent: 191 76% 58%;
362+
--accent-foreground: 268 37% 14%;
363+
--destructive: 0 84% 60%;
364+
--destructive-foreground: 251 100% 97%;
365+
--border: 268 25% 25%;
366+
--input: 268 30% 22%;
367+
--ring: 191 76% 58%;
368+
369+
--mt-playing-bg: 268 40% 18%;
370+
--mt-playing-fg: 81 55% 51%;
371+
--mt-row-even: 268 37% 14%;
372+
--mt-row-odd: 268 34% 16%;
373+
--mt-row-hover: 268 30% 22%;
374+
--mt-progress-bg: 268 25% 25%;
375+
--mt-progress-fill: 191 76% 58%;
376+
--mt-toast-bg: hsl(191 76% 58%);
377+
--mt-toast-fg: #1F1731;
378+
}
379+
380+
[data-theme-preset='neon-love'] .track-row-even {
381+
background-color: hsl(var(--mt-row-even));
382+
}
383+
384+
[data-theme-preset='neon-love'] .track-row-odd {
385+
background-color: hsl(var(--mt-row-odd));
386+
}
387+
388+
[data-theme-preset='neon-love'] .track-row-selected {
389+
background-color: hsl(var(--primary)) !important;
390+
color: hsl(var(--primary-foreground)) !important;
391+
border-bottom: none !important;
392+
}
393+
394+
[data-theme-preset='neon-love'] .track-row-playing {
395+
background-color: hsl(var(--mt-playing-bg)) !important;
396+
box-shadow: inset 2px 0 0 0 hsl(var(--mt-playing-fg)) !important;
397+
color: hsl(var(--mt-playing-fg)) !important;
398+
}
399+
400+
[data-theme-preset='neon-love'] .track-row-playing .text-muted-foreground {
401+
color: hsl(var(--mt-playing-fg)) !important;
402+
}
403+
404+
[data-theme-preset='neon-love'] footer {
405+
background-color: #130e1e;
406+
border-color: #3C2864;
407+
}
408+
409+
[data-theme-preset='neon-love'] .border-border {
410+
border-color: #3C2864;
411+
}
412+
413+
[data-theme-preset='neon-love'] footer button {
414+
color: #E6DEFF !important;
415+
}
416+
417+
[data-theme-preset='neon-love'] footer button:hover {
418+
color: #41C8E5 !important;
419+
}
420+
421+
[data-theme-preset='neon-love'] footer button.text-primary,
422+
[data-theme-preset='neon-love'] footer button.text-red-500 {
423+
color: #41C8E5 !important;
424+
}
425+
426+
[data-theme-preset='neon-love'] [data-testid='player-progressbar'] {
427+
background-color: #3C2864 !important;
428+
}
429+
430+
[data-theme-preset='neon-love'] [data-testid='player-progressbar'] > div:first-child {
431+
background-color: #41C8E5 !important;
432+
}
433+
434+
[data-theme-preset='neon-love'] [data-testid='player-progressbar'] > div:last-child {
435+
background-color: #41C8E5 !important;
436+
}
437+
438+
[data-theme-preset='neon-love'] footer .bg-\[\#8E8E93\]\/20 {
439+
background-color: #3C2864 !important;
440+
}
441+
442+
[data-theme-preset='neon-love'] .track-row-even,
443+
[data-theme-preset='neon-love'] .track-row-odd {
444+
border-bottom: none !important;
445+
}
446+
447+
[data-theme-preset='neon-love'] aside > div:last-child {
448+
border-top: none !important;
449+
}
450+
451+
[data-theme-preset='neon-love'] [data-testid='library-header'] {
452+
background-color: #2A2041 !important;
453+
}
454+
455+
[data-theme-preset='neon-love'] [data-testid='library-header'] .column-header-active {
456+
background: transparent !important;
457+
}
458+
459+
[data-theme-preset='neon-love'] aside {
460+
background-color: #2A2041 !important;
461+
}
462+
463+
[data-theme-preset='neon-love'] .bg-card\/50,
464+
[data-theme-preset='neon-love'] .bg-card {
465+
background-color: #2A2041 !important;
466+
}
467+
468+
[data-theme-preset='neon-love'] .bg-background {
469+
background-color: #1F1731 !important;
470+
}
471+
472+
[data-theme-preset='neon-love'] .titlebar-drag-region {
473+
background-color: #2A2041 !important;
474+
}
475+
476+
[data-theme-preset='neon-love'] [data-testid='settings-view'] .bg-muted\/30 {
477+
background-color: rgba(60, 40, 100, 0.6) !important;
478+
border: 1px solid #3C2864;
479+
}
480+
481+
[data-theme-preset='neon-love'] [data-testid='settings-view'] .border-border\/50 {
482+
border-color: #3C2864 !important;
483+
}
484+
485+
[data-theme-preset='neon-love'] [data-testid='settings-view'] button.border-border:hover {
486+
background-color: rgba(65, 200, 229, 0.15) !important;
487+
border-color: rgba(65, 200, 229, 0.4) !important;
488+
}
489+
490+
[data-theme-preset='neon-love'] [data-testid='lastfm-toggle'].bg-muted {
491+
background-color: hsl(268 30% 25%) !important;
492+
}
493+
494+
[data-theme-preset='neon-love'] [data-testid='lastfm-toggle'].bg-primary {
495+
background-color: hsl(191 76% 58%) !important;
496+
}
497+
346498
@layer components {
347499
/* Disable grid layout animations - instant column sizing at startup and view switch
348500
* This ensures columns snap to their widths immediately rather than animating.

0 commit comments

Comments
 (0)