feat(ui): Add Catppuccin Latte (#5250)

Add Catppuccin Latte (the light version) theme based on the existing Catppuccin Macchiato theme.
The palette and player styling are adapted for light mode while staying as close as practical
to the existing Macchiato theme behavior. I've opted to use gray for the
color for controls.

The dark version appears to mix a few control/accent colors,
so for Latte I standardized those choices. This might be worth looking
into in a separate PR. It uses gray and blue.

Signed-off-by: Love Billenius <lovebillenius@disroot.org>
Co-authored-by: Deluan Quintão <deluan@navidrome.org>
Signed-off-by: Deluan <deluan@navidrome.org>
This commit is contained in:
Love 2026-06-06 02:42:27 +02:00 committed by Deluan
parent 29c123854c
commit e15896bf32
3 changed files with 309 additions and 0 deletions

View file

@ -0,0 +1,203 @@
const stylesheet = `
.react-jinke-music-player-main.light-theme svg,
.react-jinke-music-player .music-player-controller,
.react-jinke-music-player .audio-circle-process-bar circle[class='stroke'] {
color: #6c6f85;
stroke: #6c6f85;
}
.react-jinke-music-player-main svg:active,
.react-jinke-music-player-main svg:hover {
color: #7c7f93;
}
.react-jinke-music-player-main.light-theme svg:active,
.react-jinke-music-player-main.light-theme svg:hover {
color: #7c7f93;
}
.react-jinke-music-player-mobile-play-model-tip,
.react-jinke-music-player-main.light-theme .play-mode-title {
background-color: #6c6f85;
color: #eff1f5;
}
.react-jinke-music-player-main .music-player-panel .panel-content .rc-slider-handle,
.react-jinke-music-player-main .music-player-panel .panel-content .rc-slider-track {
background-color: #6c6f85;
}
.react-jinke-music-player-main ::-webkit-scrollbar-thumb {
background-color: #6c6f85;
}
.react-jinke-music-player-main .music-player-panel .panel-content .rc-slider-handle:active {
box-shadow: 0 0 2px #6c6f85;
}
.react-jinke-music-player-main .audio-item.playing svg {
color: #6c6f85;
}
.react-jinke-music-player-main .audio-item.playing .player-singer {
color: #6c6f85 !important;
}
.react-jinke-music-player-main .loading svg {
color: #6c6f85 !important;
}
.react-jinke-music-player-main .music-player-panel .panel-content .rc-slider-handle {
border: hidden;
box-shadow:
rgba(76, 79, 105, 0.12) 0px 4px 6px,
rgba(76, 79, 105, 0.08) 0px 5px 7px;
}
.rc-slider-rail,
.rc-slider-track {
height: 6px;
}
.rc-slider {
padding: 3px 0;
}
.react-jinke-music-player-main.light-theme .rc-switch-checked {
background-color: #6c6f85 !important;
border: 1px solid #6c6f85;
}
.sound-operation > div:nth-child(4) {
transform: translateX(-50%) translateY(5%) !important;
}
.sound-operation {
padding: 4px 0;
}
.react-jinke-music-player-main .music-player-panel {
background-color: #e6e9ef;
color: #4c4f69;
box-shadow: 0 0 8px rgba(76, 79, 105, 0.15);
}
.react-jinke-music-player-main.light-theme .music-player-panel {
color: #4c4f69;
}
.audio-lists-panel {
background-color: #e6e9ef;
bottom: 6.25rem;
box-shadow:
rgba(76, 79, 105, 0.12) 0px 4px 6px,
rgba(76, 79, 105, 0.08) 0px 5px 7px;
}
.audio-lists-panel-content .audio-item.playing {
background-color: rgba(0, 0, 0, 0);
}
.audio-lists-panel-content .audio-item:nth-child(2n+1) {
background-color: rgba(0, 0, 0, 0);
}
.audio-lists-panel-content .audio-item:active,
.audio-lists-panel-content .audio-item:hover {
background-color: rgba(76, 79, 105, 0.08);
}
.audio-lists-panel-header {
border-bottom: 1px solid #ccd0da;
box-shadow: none;
}
.react-jinke-music-player-main .music-player-panel .panel-content .player-content .audio-lists-btn {
background-color: rgba(0, 0, 0, 0);
box-shadow: 0 0 0 0;
}
.react-jinke-music-player-main.light-theme .audio-lists-panel-header {
background-color: #e6e9ef;
color: #4c4f69;
}
.audio-lists-panel-content .audio-item {
line-height: 32px;
color: #4c4f69;
}
.react-jinke-music-player-main .music-player-panel .panel-content .img-content {
box-shadow:
rgba(76, 79, 105, 0.12) 0px 4px 6px,
rgba(76, 79, 105, 0.08) 0px 5px 7px;
}
.react-jinke-music-player-main .music-player-lyric {
color: #6c6f85; /* subtext0 */
-webkit-text-stroke: 0.35px #eff1f5;
font-weight: bolder;
}
.react-jinke-music-player-main .lyric-btn-active,
.react-jinke-music-player-main .lyric-btn-active svg {
color: #6c6f85 !important;
}
.audio-lists-panel-content .audio-item.playing,
.audio-lists-panel-content .audio-item.playing svg {
color: #6c6f85;
}
.audio-lists-panel-content .audio-item:active .group:not([class=".player-delete"]) svg,
.audio-lists-panel-content .audio-item:hover .group:not([class=".player-delete"]) svg {
color: #6c6f85;
}
.audio-lists-panel-content .audio-item .player-icons {
scale: 75%;
}
.audio-lists-panel-content .audio-item:active,
.audio-lists-panel-content .audio-item:hover {
background-color: #dce0e8; /* surface1 */
}
/* Mobile */
.react-jinke-music-player-mobile-cover {
border: none;
box-shadow:
rgba(76, 79, 105, 0.12) 0px 4px 6px,
rgba(76, 79, 105, 0.08) 0px 5px 7px;
}
.react-jinke-music-player .music-player-controller {
border: none;
background-color: #e6e9ef;
border-color: #e6e9ef;
box-shadow:
rgba(76, 79, 105, 0.12) 0px 4px 6px,
rgba(76, 79, 105, 0.08) 0px 5px 7px;
color: #6c6f85;
}
.react-jinke-music-player .music-player-controller.music-player-playing:before {
border: 1px solid rgba(76, 79, 105, 0.18);
}
.react-jinke-music-player .music-player-controller .music-player-controller-setting {
background: rgba(108, 111, 133, 0.2);
color: #eff1f5;
}
.react-jinke-music-player-mobile-progress .rc-slider-handle,
.react-jinke-music-player-mobile-progress .rc-slider-track {
background-color: #6c6f85;
}
.react-jinke-music-player-mobile-progress .rc-slider-handle {
border: none;
}
`
export default stylesheet

View file

@ -0,0 +1,104 @@
import stylesheet from './catppuccinLatte.css.js'
export default {
themeName: 'Catppuccin Latte',
palette: {
primary: { main: '#8839ef' }, // mauve
secondary: {
main: '#ccd0da', // surface0
contrastText: '#4c4f69', // text
},
type: 'light',
background: {
default: '#eff1f5', // base
},
},
overrides: {
MuiPaper: {
root: {
color: '#4c4f69', // text
backgroundColor: '#e6e9ef', // mantle
},
},
MuiButton: {
textPrimary: {
color: '#1e66f5', // blue
},
textSecondary: {
color: '#4c4f69', // text
},
},
MuiChip: {
clickable: {
background: '#ccd0da', // surface0
},
},
MuiFormGroup: {
root: {
color: '#4c4f69',
},
},
MuiFormHelperText: {
root: {
Mui: {
error: {
color: '#d20f39', // red
},
},
},
},
MuiTableHead: {
root: {
color: '#4c4f69',
background: '#e6e9ef',
},
},
MuiTableCell: {
root: {
color: '#4c4f69',
background: '#e6e9ef !important',
},
head: {
color: '#4c4f69',
background: '#e6e9ef !important',
},
},
NDLogin: {
systemNameLink: {
color: '#8839ef', // mauve
},
icon: {},
welcome: {
color: '#4c4f69',
},
card: {
minWidth: 300,
background: '#eff1f5',
},
avatar: {},
button: {
boxShadow: '3px 3px 5px #ccd0da',
},
},
NDMobileArtistDetails: {
bgContainer: {
background:
'linear-gradient(to bottom, rgba(255 255 255 / 72%), rgb(239 241 245))!important',
},
},
},
player: {
theme: 'light',
stylesheet,
},
}

View file

@ -9,6 +9,7 @@ import ElectricPurpleTheme from './electricPurple'
import NordTheme from './nord'
import GruvboxDarkTheme from './gruvboxDark'
import CatppuccinMacchiatoTheme from './catppuccinMacchiato'
import CatppuccinLatteTheme from './catppuccinLatte'
import DraculaTheme from './dracula'
import NuclearTheme from './nuclear'
import NutballTheme from './nutball'
@ -26,6 +27,7 @@ export default {
// New themes should be added here, in alphabetic order
AmusicTheme,
CatppuccinMacchiatoTheme,
CatppuccinLatteTheme,
DraculaTheme,
ElectricPurpleTheme,
ExtraDarkTheme,