mirror of
https://github.com/antebudimir/feishin.git
synced 2025-12-31 10:03:33 +00:00
feat: add cyan-orange color scheme with enhanced visual effects
- Add new CSS animations (hologramGlow, float, shimmer, scanline) - Introduce cyan and orange color palette variants - Update scrollbar styling with orange theme colors - Modify player components with new gradient backgrounds - Update global theme colors and surface styling - Adjust default settings for enhanced visual experience
This commit is contained in:
parent
7a12e4657f
commit
228fc8e82b
12 changed files with 261 additions and 40 deletions
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "feishin",
|
||||
"version": "0.22.0",
|
||||
"version": "0.23.0",
|
||||
"description": "A modern self-hosted music player.",
|
||||
"keywords": [
|
||||
"subsonic",
|
||||
|
|
|
|||
|
|
@ -22,7 +22,10 @@
|
|||
aspect-ratio: 1/1;
|
||||
overflow: hidden;
|
||||
background: var(--theme-card-default-bg);
|
||||
border-radius: var(--theme-card-poster-radius);
|
||||
border-radius: var(--theme-radius-md);
|
||||
border: 2px solid var(--theme-orange-transparent-40);
|
||||
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
box-shadow: var(--theme-shadow-orange-glow-soft);
|
||||
|
||||
&::before {
|
||||
position: absolute;
|
||||
|
|
@ -39,6 +42,14 @@
|
|||
}
|
||||
|
||||
&:hover {
|
||||
border-color: var(--theme-orange-transparent-70);
|
||||
box-shadow:
|
||||
var(--theme-shadow-orange-glow-medium),
|
||||
0 0 5px var(--theme-orange-transparent-30),
|
||||
0 0 5px var(--theme-orange-transparent-20);
|
||||
transform: scale(1.03);
|
||||
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
|
||||
&::before {
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,6 +23,10 @@
|
|||
display: flex;
|
||||
grid-area: image;
|
||||
align-items: flex-end;
|
||||
|
||||
img {
|
||||
border-radius: var(--theme-radius-md);
|
||||
}
|
||||
}
|
||||
|
||||
.info-column {
|
||||
|
|
|
|||
|
|
@ -3,6 +3,8 @@
|
|||
z-index: 190;
|
||||
width: 100%;
|
||||
height: 65px;
|
||||
border-bottom: 2px solid var(--theme-orange-transparent-30);
|
||||
box-shadow: 0 4px 12px var(--theme-orange-transparent-10);
|
||||
}
|
||||
|
||||
.header {
|
||||
|
|
|
|||
|
|
@ -25,6 +25,11 @@
|
|||
align-items: center;
|
||||
aspect-ratio: 1/1;
|
||||
overflow: hidden;
|
||||
border-radius: var(--theme-radius-md);
|
||||
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
background: var(--theme-card-default-bg);
|
||||
border: 2px solid var(--theme-orange-transparent-40);
|
||||
box-shadow: var(--theme-shadow-orange-glow-soft);
|
||||
|
||||
&::before {
|
||||
position: absolute;
|
||||
|
|
@ -41,6 +46,13 @@
|
|||
}
|
||||
|
||||
&:hover {
|
||||
border-color: var(--theme-orange-transparent-70);
|
||||
box-shadow:
|
||||
var(--theme-shadow-orange-glow-medium),
|
||||
0 0 5px var(--theme-orange-transparent-30),
|
||||
0 0 5px var(--theme-orange-transparent-20);
|
||||
transform: scale(1.03);
|
||||
|
||||
&::before {
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
|
@ -72,7 +84,6 @@
|
|||
height: 100% !important;
|
||||
max-height: 100%;
|
||||
border: 0;
|
||||
border-radius: var(--theme-radius-md);
|
||||
|
||||
img {
|
||||
height: 100%;
|
||||
|
|
|
|||
|
|
@ -38,3 +38,30 @@
|
|||
background: var(--theme-overlay-header);
|
||||
backdrop-filter: blur(var(--image-blur));
|
||||
}
|
||||
|
||||
.scanline-overlay {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
z-index: 1;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: linear-gradient(
|
||||
0deg,
|
||||
transparent 0%,
|
||||
var(--album-color, rgba(0, 255, 255, 0.15)) 50%,
|
||||
transparent 100%
|
||||
);
|
||||
background-size: 100% 200%;
|
||||
animation: scanline 6s linear infinite;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
@keyframes scanline {
|
||||
0% {
|
||||
background-position: 0 -100vh;
|
||||
}
|
||||
100% {
|
||||
background-position: 0 100vh;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -428,6 +428,9 @@ export const FullScreenPlayer = () => {
|
|||
srcLoaded: true,
|
||||
});
|
||||
|
||||
// Convert RGB to RGB with opacity for scanline effect
|
||||
const scanlineColor = background ? background.replace('rgb', 'rgba').replace(')', ', 0.15)') : 'rgba(0, 255, 255, 0.15)';
|
||||
|
||||
const imageUrl = currentSong?.imageUrl && currentSong.imageUrl.replace(/size=\d+/g, 'size=500');
|
||||
const backgroundImage =
|
||||
imageUrl && dynamicIsImage
|
||||
|
|
@ -457,6 +460,14 @@ export const FullScreenPlayer = () => {
|
|||
}
|
||||
/>
|
||||
)}
|
||||
<div
|
||||
className={styles.scanlineOverlay}
|
||||
style={
|
||||
{
|
||||
'--album-color': scanlineColor,
|
||||
} as CSSProperties
|
||||
}
|
||||
/>
|
||||
<div className={styles.responsiveContainer}>
|
||||
<FullScreenPlayerImage />
|
||||
<FullScreenPlayerQueue />
|
||||
|
|
|
|||
|
|
@ -12,13 +12,20 @@
|
|||
width: 100%;
|
||||
padding: 0.5rem;
|
||||
overflow: visible;
|
||||
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
|
||||
button {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
&:focus-visible {
|
||||
outline: 1px var(--theme-colors-primary-filled) solid;
|
||||
outline: 2px var(--theme-orange-base) solid;
|
||||
box-shadow: var(--theme-shadow-orange-glow-soft);
|
||||
}
|
||||
|
||||
&:hover {
|
||||
transform: scale(1.1);
|
||||
filter: drop-shadow(0 0 8px var(--theme-orange-transparent-40));
|
||||
}
|
||||
|
||||
&:disabled {
|
||||
|
|
@ -32,13 +39,21 @@
|
|||
|
||||
.player-button.active {
|
||||
svg {
|
||||
fill: var(--theme-colors-primary-filled);
|
||||
fill: var(--theme-orange-base);
|
||||
filter: drop-shadow(0 0 6px var(--theme-orange-transparent-50));
|
||||
}
|
||||
}
|
||||
|
||||
.main {
|
||||
background: var(--theme-colors-foreground) !important;
|
||||
background: linear-gradient(135deg, var(--theme-orange-base), var(--theme-orange-medium)) !important;
|
||||
border-radius: 50%;
|
||||
box-shadow: var(--theme-shadow-orange-glow-soft);
|
||||
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
|
||||
&:hover {
|
||||
box-shadow: var(--theme-shadow-orange-glow-medium);
|
||||
transform: scale(1.15);
|
||||
}
|
||||
|
||||
svg {
|
||||
display: flex;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,13 @@
|
|||
.container {
|
||||
width: 100vw;
|
||||
height: 100%;
|
||||
border-top: var(--theme-colors-border);
|
||||
border-top: 2px solid var(--theme-orange-transparent-40);
|
||||
background: linear-gradient(
|
||||
180deg,
|
||||
var(--theme-colors-background) 0%,
|
||||
rgba(2, 26, 26, 0.95) 100%
|
||||
);
|
||||
box-shadow: 0 -4px 12px var(--theme-orange-transparent-15);
|
||||
}
|
||||
|
||||
.controls-grid {
|
||||
|
|
|
|||
|
|
@ -530,51 +530,51 @@ const initialState: SettingsState = {
|
|||
font: {
|
||||
builtIn: 'Poppins',
|
||||
custom: null,
|
||||
system: null,
|
||||
type: FontType.BUILT_IN,
|
||||
system: 'Noto Sans Regular',
|
||||
type: FontType.SYSTEM,
|
||||
},
|
||||
general: {
|
||||
accent: 'rgb(53, 116, 252)',
|
||||
accent: 'rgb(214, 46, 83)',
|
||||
albumArtRes: undefined,
|
||||
albumBackground: false,
|
||||
albumBackgroundBlur: 6,
|
||||
albumBackground: true,
|
||||
albumBackgroundBlur: 50,
|
||||
artistBackground: false,
|
||||
artistBackgroundBlur: 6,
|
||||
artistItems,
|
||||
buttonSize: 15,
|
||||
buttonSize: 25,
|
||||
disabledContextMenu: {},
|
||||
doubleClickQueueAll: true,
|
||||
doubleClickQueueAll: false,
|
||||
externalLinks: true,
|
||||
followSystemTheme: false,
|
||||
genreTarget: GenreTarget.TRACK,
|
||||
genreTarget: GenreTarget.ALBUM,
|
||||
homeFeature: true,
|
||||
homeItems,
|
||||
language: 'en',
|
||||
lastFM: true,
|
||||
lastfmApiKey: '',
|
||||
musicBrainz: true,
|
||||
nativeAspectRatio: false,
|
||||
nativeAspectRatio: true,
|
||||
passwordStore: undefined,
|
||||
playButtonBehavior: Play.NOW,
|
||||
playerbarOpenDrawer: false,
|
||||
resume: true,
|
||||
showQueueDrawerButton: false,
|
||||
showQueueDrawerButton: true,
|
||||
sidebarCollapsedNavigation: true,
|
||||
sidebarCollapseShared: false,
|
||||
sidebarItems,
|
||||
sidebarPlaylistList: true,
|
||||
sideQueueType: 'sideQueue',
|
||||
sideQueueType: 'sideDrawerQueue',
|
||||
skipButtons: {
|
||||
enabled: false,
|
||||
enabled: true,
|
||||
skipBackwardSeconds: 5,
|
||||
skipForwardSeconds: 10,
|
||||
skipForwardSeconds: 5,
|
||||
},
|
||||
theme: AppTheme.DEFAULT_DARK,
|
||||
themeDark: AppTheme.DEFAULT_DARK,
|
||||
themeLight: AppTheme.DEFAULT_LIGHT,
|
||||
volumeWheelStep: 5,
|
||||
volumeWidth: 70,
|
||||
zoomFactor: 100,
|
||||
volumeWidth: 200,
|
||||
zoomFactor: 145,
|
||||
},
|
||||
hotkeys: {
|
||||
bindings: {
|
||||
|
|
@ -620,7 +620,7 @@ const initialState: SettingsState = {
|
|||
delayMs: 0,
|
||||
enableAutoTranslation: false,
|
||||
enableNeteaseTranslation: false,
|
||||
fetch: false,
|
||||
fetch: true,
|
||||
follow: true,
|
||||
fontSize: 24,
|
||||
fontSizeUnsync: 24,
|
||||
|
|
@ -636,8 +636,8 @@ const initialState: SettingsState = {
|
|||
},
|
||||
playback: {
|
||||
audioDeviceId: undefined,
|
||||
crossfadeDuration: 5,
|
||||
crossfadeStyle: CrossfadeStyle.EQUALPOWER,
|
||||
crossfadeDuration: 75,
|
||||
crossfadeStyle: CrossfadeStyle.DIPPED,
|
||||
mediaSession: false,
|
||||
mpvExtraParameters: [],
|
||||
mpvProperties: {
|
||||
|
|
@ -666,7 +666,7 @@ const initialState: SettingsState = {
|
|||
webAudio: true,
|
||||
},
|
||||
remote: {
|
||||
enabled: false,
|
||||
enabled: true,
|
||||
password: randomString(8),
|
||||
port: 4333,
|
||||
username: 'feishin',
|
||||
|
|
|
|||
|
|
@ -33,6 +33,48 @@ html {
|
|||
background: var(--theme-colors-background);
|
||||
}
|
||||
|
||||
body::before,
|
||||
html::before {
|
||||
content: '';
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: linear-gradient(
|
||||
105deg,
|
||||
transparent 40%,
|
||||
rgba(0, 183, 255, 0.1) 45%,
|
||||
rgba(0, 183, 255, 0.2) 50%,
|
||||
rgba(0, 183, 255, 0.1) 55%,
|
||||
transparent 60%
|
||||
);
|
||||
background-size: 200% 100%;
|
||||
animation: shimmer 8s infinite;
|
||||
pointer-events: none;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
body::after,
|
||||
html::after {
|
||||
content: '';
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: linear-gradient(
|
||||
0deg,
|
||||
transparent 0%,
|
||||
rgba(0, 255, 255, 0.03) 50%,
|
||||
transparent 100%
|
||||
);
|
||||
background-size: 100% 200%;
|
||||
animation: scanline 6s linear infinite;
|
||||
pointer-events: none;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
input,
|
||||
button,
|
||||
textarea,
|
||||
|
|
@ -59,6 +101,8 @@ img {
|
|||
|
||||
#app {
|
||||
height: inherit;
|
||||
position: relative;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar {
|
||||
|
|
@ -120,6 +164,50 @@ button {
|
|||
}
|
||||
}
|
||||
|
||||
@keyframes hologramGlow {
|
||||
0%,
|
||||
100% {
|
||||
box-shadow:
|
||||
0 0 10px rgba(0, 183, 255, 0.2),
|
||||
0 0 20px rgba(0, 183, 255, 0.1),
|
||||
0 0 40px rgba(0, 255, 255, 0.05);
|
||||
}
|
||||
50% {
|
||||
box-shadow:
|
||||
0 0 20px rgba(0, 183, 255, 0.4),
|
||||
0 0 40px rgba(0, 183, 255, 0.2),
|
||||
0 0 80px rgba(0, 255, 255, 0.1);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes float {
|
||||
0%,
|
||||
100% {
|
||||
transform: translateY(0);
|
||||
}
|
||||
50% {
|
||||
transform: translateY(-10px);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes shimmer {
|
||||
0% {
|
||||
background-position: -100% 0;
|
||||
}
|
||||
100% {
|
||||
background-position: 200% 0;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes scanline {
|
||||
0% {
|
||||
background-position: 0 -100vh;
|
||||
}
|
||||
100% {
|
||||
background-position: 0 100vh;
|
||||
}
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: Archivo;
|
||||
font-weight: 100 1000;
|
||||
|
|
@ -224,6 +312,51 @@ button {
|
|||
:root {
|
||||
--theme-background-noise: url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIzMDAiIGhlaWdodD0iMzAwIj48ZmlsdGVyIGlkPSJhIiB4PSIwIiB5PSIwIj48ZmVUdXJidWxlbmNlIHR5cGU9ImZyYWN0YWxOb2lzZSIgYmFzZUZyZXF1ZW5jeT0iLjc1IiBzdGl0Y2hUaWxlcz0ic3RpdGNoIi8+PGZlQ29sb3JNYXRyaXggdHlwZT0ic2F0dXJhdGUiIHZhbHVlcz0iMCIvPjwvZmlsdGVyPjxwYXRoIGZpbHRlcj0idXJsKCNhKSIgb3BhY2l0eT0iLjA1IiBkPSJNMCAwaDMwMHYzMDBIMHoiLz48L3N2Zz4=');
|
||||
--theme-fullscreen-player-text-shadow: black 0px 0px 10px;
|
||||
|
||||
/* Intro-inspired color palette */
|
||||
--theme-orange-base: rgb(255, 142, 83);
|
||||
--theme-orange-medium: rgb(255, 123, 52);
|
||||
--theme-orange-dark: rgb(255, 89, 0);
|
||||
--theme-orange-transparent-70: rgba(255, 142, 83, 0.7);
|
||||
--theme-orange-transparent-40: rgba(255, 142, 83, 0.4);
|
||||
--theme-orange-transparent-30: rgba(255, 142, 83, 0.3);
|
||||
--theme-orange-transparent-20: rgba(255, 142, 83, 0.2);
|
||||
--theme-orange-transparent-15: rgba(255, 142, 83, 0.15);
|
||||
--theme-orange-transparent-10: rgba(255, 142, 83, 0.1);
|
||||
|
||||
--theme-cyan-primary: rgb(0, 183, 255);
|
||||
--theme-cyan-secondary: rgb(0, 255, 255);
|
||||
--theme-cyan-transparent-80: rgba(0, 183, 255, 0.8);
|
||||
--theme-cyan-transparent-70: rgba(0, 183, 255, 0.7);
|
||||
--theme-cyan-transparent-60: rgba(0, 183, 255, 0.6);
|
||||
--theme-cyan-transparent-50: rgba(0, 183, 255, 0.5);
|
||||
--theme-cyan-transparent-40: rgba(0, 183, 255, 0.4);
|
||||
--theme-cyan-transparent-30: rgba(0, 183, 255, 0.3);
|
||||
--theme-cyan-transparent-20: rgba(0, 183, 255, 0.2);
|
||||
--theme-cyan-transparent-10: rgba(0, 183, 255, 0.1);
|
||||
--theme-cyan-transparent-05: rgba(0, 183, 255, 0.05);
|
||||
--theme-cyan-transparent-03: rgba(0, 183, 255, 0.03);
|
||||
|
||||
/* Gradients */
|
||||
--theme-primary-gradient: linear-gradient(
|
||||
45deg,
|
||||
var(--theme-orange-dark),
|
||||
var(--theme-orange-medium),
|
||||
var(--theme-orange-base)
|
||||
);
|
||||
--theme-cyan-gradient: linear-gradient(
|
||||
90deg,
|
||||
var(--theme-cyan-primary),
|
||||
var(--theme-cyan-secondary)
|
||||
);
|
||||
|
||||
/* Shadows */
|
||||
--theme-shadow-cyan-glow: 0 0 10px var(--theme-cyan-transparent-30);
|
||||
--theme-shadow-cyan-glow-medium: 0 0 15px var(--theme-cyan-transparent-20);
|
||||
--theme-shadow-orange-glow-soft: 0 4px 12px var(--theme-orange-transparent-15);
|
||||
--theme-shadow-orange-glow-medium:
|
||||
0 6px 20px var(--theme-orange-transparent-30), 0 0 20px var(--theme-orange-transparent-20);
|
||||
--theme-text-shadow-cyan: 0 0 20px var(--theme-cyan-transparent-30);
|
||||
--theme-font-size-xs: var(--mantine-font-size-xs);
|
||||
--theme-font-size-sm: var(--mantine-font-size-sm);
|
||||
--theme-font-size-md: var(--mantine-font-size-md);
|
||||
|
|
|
|||
|
|
@ -7,10 +7,10 @@ export const defaultTheme: AppThemeConfiguration = {
|
|||
'overlay-subheader':
|
||||
'linear-gradient(180deg, rgb(0 0 0 / 5%) 0%, var(--theme-colors-background) 100%), var(--theme-background-noise)',
|
||||
'root-font-size': '16px',
|
||||
'scrollbar-handle-active-background': 'rgba(160, 160, 160, 60%)',
|
||||
'scrollbar-handle-background': 'rgba(160, 160, 160, 30%)',
|
||||
'scrollbar-handle-border-radius': '0px',
|
||||
'scrollbar-handle-hover-background': 'rgba(160, 160, 160, 60%)',
|
||||
'scrollbar-handle-active-background': 'rgba(255, 142, 83, 0.7)',
|
||||
'scrollbar-handle-background': 'rgba(255, 142, 83, 0.4)',
|
||||
'scrollbar-handle-border-radius': '0.3rem',
|
||||
'scrollbar-handle-hover-background': 'rgba(255, 142, 83, 0.9)',
|
||||
'scrollbar-size': '12px',
|
||||
'scrollbar-track-active-background': 'transparent',
|
||||
'scrollbar-track-background': 'transparent',
|
||||
|
|
@ -18,17 +18,18 @@ export const defaultTheme: AppThemeConfiguration = {
|
|||
'scrollbar-track-hover-background': 'transparent',
|
||||
},
|
||||
colors: {
|
||||
background: 'rgb(16, 16, 16)',
|
||||
'background-alternate': 'rgb(0, 0, 0)',
|
||||
background: 'rgb(2, 26, 26)',
|
||||
'background-alternate': 'rgb(19, 16, 16)',
|
||||
black: 'rgb(0, 0, 0)',
|
||||
foreground: 'rgb(225, 225, 225)',
|
||||
'foreground-muted': 'rgb(150, 150, 150)',
|
||||
'state-error': 'rgb(204, 50, 50)',
|
||||
'state-info': 'rgb(53, 116, 252)',
|
||||
'state-success': 'rgb(50, 204, 50)',
|
||||
'state-warning': 'rgb(255, 120, 120)',
|
||||
surface: 'rgb(24, 24, 24)',
|
||||
'surface-foreground': 'rgb(215, 215, 215)',
|
||||
foreground: 'rgb(240, 240, 240)',
|
||||
'foreground-muted': 'rgb(187, 187, 187)',
|
||||
primary: 'rgb(255, 142, 83)',
|
||||
'state-error': 'rgb(255, 0, 0)',
|
||||
'state-info': 'rgb(0, 183, 255)',
|
||||
'state-success': 'rgb(0, 255, 255)',
|
||||
'state-warning': 'rgb(255, 142, 83)',
|
||||
surface: 'rgba(2, 26, 26, 0.8)',
|
||||
'surface-foreground': 'rgb(240, 240, 240)',
|
||||
white: 'rgb(255, 255, 255)',
|
||||
},
|
||||
mode: 'dark',
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue