+54
-6
frontend/src/lib/components/Queue.svelte
+54
-6
frontend/src/lib/components/Queue.svelte
···
114
114
<div class="queue">
115
115
<div class="queue-header">
116
116
<h2>queue</h2>
117
-
{#if upcoming.length > 0}
117
+
<div class="queue-actions">
118
118
<button
119
-
class="clear-btn"
120
-
onclick={() => queue.clearUpNext()}
121
-
title="clear upcoming tracks"
119
+
class="shuffle-btn"
120
+
class:active={queue.shuffle}
121
+
onclick={() => queue.toggleShuffle()}
122
+
title={queue.shuffle ? 'disable shuffle' : 'enable shuffle'}
122
123
>
123
-
clear queue
124
+
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
125
+
<polyline points="16 3 21 3 21 8"></polyline>
126
+
<line x1="4" y1="20" x2="21" y2="3"></line>
127
+
<polyline points="21 16 21 21 16 21"></polyline>
128
+
<line x1="15" y1="15" x2="21" y2="21"></line>
129
+
<line x1="4" y1="4" x2="9" y2="9"></line>
130
+
</svg>
124
131
</button>
125
-
{/if}
132
+
{#if upcoming.length > 0}
133
+
<button
134
+
class="clear-btn"
135
+
onclick={() => queue.clearUpNext()}
136
+
title="clear upcoming tracks"
137
+
>
138
+
clear
139
+
</button>
140
+
{/if}
141
+
</div>
126
142
</div>
127
143
128
144
<div class="queue-body">
···
259
275
display: flex;
260
276
justify-content: space-between;
261
277
align-items: center;
278
+
}
279
+
280
+
.queue-actions {
281
+
display: flex;
282
+
align-items: center;
283
+
gap: 0.5rem;
284
+
}
285
+
286
+
.shuffle-btn {
287
+
display: flex;
288
+
align-items: center;
289
+
justify-content: center;
290
+
width: 32px;
291
+
height: 32px;
292
+
padding: 0;
293
+
background: transparent;
294
+
border: 1px solid var(--border-subtle);
295
+
color: var(--text-tertiary);
296
+
border-radius: var(--radius-sm);
297
+
cursor: pointer;
298
+
transition: all 0.15s ease;
299
+
}
300
+
301
+
.shuffle-btn:hover {
302
+
color: var(--text-secondary);
303
+
border-color: var(--border-default);
304
+
background: var(--bg-secondary);
305
+
}
306
+
307
+
.shuffle-btn.active {
308
+
color: var(--accent);
309
+
border-color: var(--accent);
262
310
}
263
311
264
312
.clear-btn {
+1
-69
frontend/src/lib/components/player/PlaybackControls.svelte
+1
-69
frontend/src/lib/components/player/PlaybackControls.svelte
···
151
151
</svg>
152
152
</button>
153
153
154
-
<div class="playback-options">
155
-
<button
156
-
class="option-btn"
157
-
class:active={queue.shuffle}
158
-
onclick={() => queue.toggleShuffle()}
159
-
title={queue.shuffle ? 'disable shuffle' : 'enable shuffle'}
160
-
>
161
-
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
162
-
<polyline points="16 3 21 3 21 8"></polyline>
163
-
<line x1="4" y1="20" x2="21" y2="3"></line>
164
-
<polyline points="21 16 21 21 16 21"></polyline>
165
-
<line x1="15" y1="15" x2="21" y2="21"></line>
166
-
<line x1="4" y1="4" x2="9" y2="9"></line>
167
-
</svg>
168
-
</button>
169
-
</div>
170
-
171
154
<div class="time-control">
172
155
<span class="time">{formattedCurrentTime}</span>
173
156
<input
···
264
247
.control-btn.disabled {
265
248
opacity: 0.4;
266
249
pointer-events: none;
267
-
}
268
-
269
-
.playback-options {
270
-
display: flex;
271
-
align-items: center;
272
-
gap: 0.5rem;
273
-
}
274
-
275
-
.option-btn {
276
-
background: transparent;
277
-
border: 1px solid var(--border-default);
278
-
color: var(--text-secondary);
279
-
cursor: pointer;
280
-
width: 40px;
281
-
height: 40px;
282
-
display: flex;
283
-
align-items: center;
284
-
justify-content: center;
285
-
border-radius: var(--radius-base);
286
-
transition: all 0.2s;
287
-
position: relative;
288
-
}
289
-
290
-
.option-btn svg {
291
-
width: 20px;
292
-
height: 20px;
293
-
}
294
-
295
-
.option-btn:hover {
296
-
color: var(--text-primary);
297
-
border-color: var(--accent);
298
-
}
299
-
300
-
.option-btn.active {
301
-
color: var(--accent);
302
-
border-color: var(--accent);
303
250
}
304
251
305
252
.time-control {
···
472
419
height: 32px;
473
420
}
474
421
475
-
.playback-options {
476
-
grid-row: 2;
477
-
grid-column: 1;
478
-
}
479
-
480
-
.option-btn {
481
-
width: 36px;
482
-
height: 36px;
483
-
}
484
-
485
-
.option-btn svg {
486
-
width: 18px;
487
-
height: 18px;
488
-
}
489
-
490
422
.time-control {
491
423
grid-row: 2;
492
-
grid-column: 2 / 7;
424
+
grid-column: 1 / 7;
493
425
}
494
426
495
427
.time {