Redesign aside
parent
66e6d4d630
commit
5a0af121c2
|
|
@ -9,11 +9,16 @@ type Props = {
|
|||
export function SongAside({ song, onSelect }: Props) {
|
||||
if (!song) return <div>No songs</div>
|
||||
|
||||
const maxDots = 5
|
||||
const filledDots = Math.min(maxDots, Math.max(0, Math.round(song.difficulty || 0)))
|
||||
const difficultyLabel = getStepmaniaDifficultyLabel(song.difficulty)
|
||||
|
||||
return (
|
||||
<div className="song-aside">
|
||||
<div className="song-aside__body">
|
||||
<div className="song-aside__kicker">Previewing Track</div>
|
||||
<h2 className="song-aside__title">{song.title}</h2>
|
||||
<div className="song-aside__artist">{song.artist}</div>
|
||||
</div>
|
||||
|
||||
<div className="song-aside__banner" aria-hidden="true">
|
||||
<img src={song.bannerUrl} alt="" className="song-aside__banner-bg" />
|
||||
<img
|
||||
|
|
@ -23,36 +28,23 @@ export function SongAside({ song, onSelect }: Props) {
|
|||
/>
|
||||
</div>
|
||||
|
||||
<div className="song-aside__body">
|
||||
<h2 className="song-aside__title">{song.title}</h2>
|
||||
<div className="song-aside__artist">{song.artist}</div>
|
||||
|
||||
<div className="song-aside__stats">
|
||||
<div className="song-aside__stat">
|
||||
<span className="song-aside__label">BPM</span>
|
||||
<span className="song-aside__value">{song.bpm}</span>
|
||||
</div>
|
||||
<div className="song-aside__stat">
|
||||
<span className="song-aside__label">Duration</span>
|
||||
<span className="song-aside__value">{song.duration}</span>
|
||||
</div>
|
||||
<div className="song-aside__stat">
|
||||
<span className="song-aside__label">Genre</span>
|
||||
<span className="song-aside__value">{song.genre}</span>
|
||||
</div>
|
||||
<div className="song-aside__stat song-aside__stat--difficulty">
|
||||
<span className="song-aside__label">Difficulty</span>
|
||||
<div className="song-aside__difficulty" aria-label={`Difficulty ${song.difficulty} out of 5`}>
|
||||
{Array.from({ length: maxDots }).map((_, i) => (
|
||||
<span
|
||||
key={i}
|
||||
className={`song-aside__difficulty-dot${i < filledDots ? ' song-aside__difficulty-dot--filled' : ''}`}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
<div className="song-aside__stats">
|
||||
<div className="song-aside__stat song-aside__stat--bpm">
|
||||
<span className="song-aside__label">BPM</span>
|
||||
<span className="song-aside__value">{song.bpm}</span>
|
||||
</div>
|
||||
<div className="song-aside__stat">
|
||||
<span className="song-aside__label">Duration</span>
|
||||
<span className="song-aside__value">{song.duration}</span>
|
||||
</div>
|
||||
<div className="song-aside__stat">
|
||||
<span className="song-aside__label">Genre</span>
|
||||
<span className="song-aside__value">{song.genre}</span>
|
||||
</div>
|
||||
<div className="song-aside__stat song-aside__stat--difficulty">
|
||||
<span className="song-aside__label">Difficulty</span>
|
||||
<span className="song-aside__value">{difficultyLabel}</span>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
{onSelect && (
|
||||
|
|
@ -63,3 +55,11 @@ export function SongAside({ song, onSelect }: Props) {
|
|||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
function getStepmaniaDifficultyLabel(level: number): string {
|
||||
if (level <= 3) return 'Beginner'
|
||||
if (level <= 5) return 'Easy'
|
||||
if (level <= 7) return 'Medium'
|
||||
if (level <= 12) return 'Hard'
|
||||
return 'Challenge'
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,7 @@
|
|||
.song-selection {
|
||||
--accent-glow: var(--effect-accent-glow);
|
||||
}
|
||||
|
||||
.song-card {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
|
@ -33,8 +37,7 @@
|
|||
.song-card--selected {
|
||||
box-shadow:
|
||||
inset 0 0 0 2px color-mix(in srgb, var(--color-accent) 75%, #ff6cd2),
|
||||
0 0 0 1px color-mix(in srgb, var(--color-accent) 45%, transparent),
|
||||
0 0 28px 6px color-mix(in srgb, var(--color-accent) 32%, transparent);
|
||||
var(--accent-glow);
|
||||
transform: translateY(-1px);
|
||||
}
|
||||
|
||||
|
|
@ -161,13 +164,11 @@
|
|||
.song-aside {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.song-aside__body {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 12px;
|
||||
gap: 14px;
|
||||
padding: 16px;
|
||||
border: 1px solid color-mix(in srgb, var(--color-accent) 58%, transparent);
|
||||
background: linear-gradient(180deg, color-mix(in srgb, var(--color-surface) 86%, #1a0c2d), color-mix(in srgb, var(--color-surface) 72%, #120a22));
|
||||
box-shadow: var(--accent-glow);
|
||||
}
|
||||
|
||||
.song-aside__banner {
|
||||
|
|
@ -180,6 +181,15 @@
|
|||
border-radius: 6px;
|
||||
}
|
||||
|
||||
.song-aside__kicker {
|
||||
margin: 0;
|
||||
margin-bottom: 5px;
|
||||
color: color-mix(in srgb, var(--color-accent) 86%, #9befff);
|
||||
font-size: 11px;
|
||||
letter-spacing: 0.14em;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.song-aside__banner-bg,
|
||||
.song-aside__banner-fg {
|
||||
position: absolute;
|
||||
|
|
@ -200,68 +210,60 @@
|
|||
|
||||
.song-aside__title {
|
||||
margin: 0;
|
||||
color: var(--color-text);
|
||||
font-size: 24px;
|
||||
line-height: 1.1;
|
||||
color: color-mix(in srgb, var(--color-text) 92%, #f1fbff);
|
||||
font-size: 36px;
|
||||
line-height: 0.92;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.03em;
|
||||
}
|
||||
|
||||
.song-aside__artist {
|
||||
color: var(--color-muted);
|
||||
font-size: 15px;
|
||||
color: color-mix(in srgb, var(--color-accent) 84%, #89ecff);
|
||||
font-size: 16px;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.04em;
|
||||
}
|
||||
|
||||
.song-aside__stats {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
gap: 10px;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.song-aside__stat {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 2px;
|
||||
gap: 6px;
|
||||
min-width: 0;
|
||||
padding: 10px 20px 12px;
|
||||
background: color-mix(in srgb, var(--color-accent) 8%, transparent);
|
||||
border-left: 3px solid color-mix(in srgb, var(--color-accent) 65%, transparent);
|
||||
}
|
||||
|
||||
.song-aside__stat--difficulty {
|
||||
justify-content: space-between;
|
||||
.song-aside__stat--bpm {
|
||||
border-left-color: color-mix(in srgb, #00d5ff 70%, transparent);
|
||||
}
|
||||
|
||||
.song-aside__label {
|
||||
color: var(--color-muted);
|
||||
font-size: 11px;
|
||||
letter-spacing: 0.08em;
|
||||
color: color-mix(in srgb, var(--color-muted) 84%, #9ec0cf);
|
||||
font-size: 10px;
|
||||
letter-spacing: 0.12em;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.song-aside__value {
|
||||
color: var(--color-text);
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.song-aside__difficulty {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.song-aside__difficulty-dot {
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
border-radius: 999px;
|
||||
border: 1px solid var(--color-accent);
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.song-aside__difficulty-dot--filled {
|
||||
background: var(--color-accent);
|
||||
color: color-mix(in srgb, var(--color-text) 94%, #f0fbff);
|
||||
font-size: 20px;
|
||||
line-height: 1;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.song-aside__select {
|
||||
margin-top: 4px;
|
||||
margin-top: 8px;
|
||||
width: 100%;
|
||||
padding: 12px 14px;
|
||||
padding: 14px 16px;
|
||||
letter-spacing: 0.1em;
|
||||
box-shadow: var(--accent-glow);
|
||||
}
|
||||
|
||||
@media (max-width: 840px) {
|
||||
|
|
@ -294,10 +296,16 @@
|
|||
.song-aside {
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
gap: 10px;
|
||||
padding: 10px;
|
||||
box-shadow: none;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.song-aside__kicker {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.song-aside__banner {
|
||||
flex: 0 0 84px;
|
||||
width: 84px;
|
||||
|
|
@ -320,7 +328,7 @@
|
|||
}
|
||||
|
||||
.song-aside__artist {
|
||||
font-size: 13px;
|
||||
font-size: 12px;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
|
|
@ -330,19 +338,6 @@
|
|||
display: none;
|
||||
}
|
||||
|
||||
.song-aside__value {
|
||||
font-size: 13px;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.song-aside__label {
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.song-aside__select {
|
||||
margin-top: 0;
|
||||
width: auto;
|
||||
|
|
|
|||
|
|
@ -74,8 +74,8 @@
|
|||
}
|
||||
|
||||
.song-selection__aside {
|
||||
width: 320px;
|
||||
flex: 0 0 320px;
|
||||
width: 400px;
|
||||
flex: 0 0 400px;
|
||||
border-left: 1px solid var(--studio-border);
|
||||
padding: 12px;
|
||||
box-sizing: border-box;
|
||||
|
|
|
|||
|
|
@ -71,10 +71,11 @@
|
|||
--color-button-bg: rgba(255, 255, 255, 0.1);
|
||||
--color-button-bg-hover: rgba(255, 255, 255, 0.18);
|
||||
--color-button-text: #ccc;
|
||||
--effect-accent-glow: 0 0 0 1px color-mix(in srgb, var(--color-accent) 45%, transparent), 0 0 28px 6px color-mix(in srgb, var(--color-accent) 32%, transparent);
|
||||
--color-button-accent-border: var(--color-accent);
|
||||
--color-button-accent-bg: rgba(217, 70, 239, 0.12);
|
||||
--color-button-accent-bg-hover: rgba(217, 70, 239, 0.18);
|
||||
--color-button-accent-text: var(--color-text);
|
||||
--color-button-accent-text: var(--color-accent);
|
||||
}
|
||||
|
||||
html {
|
||||
|
|
@ -156,6 +157,7 @@ body {
|
|||
border-color: var(--color-button-accent-border);
|
||||
background: var(--color-button-accent-bg);
|
||||
color: var(--color-button-accent-text);
|
||||
box-shadow: var(--effect-accent-glow);
|
||||
}
|
||||
|
||||
.ui-button--accent:hover {
|
||||
|
|
|
|||
Loading…
Reference in New Issue