fix(player): volume slider fill
This commit is contained in:
@@ -1,14 +1,5 @@
|
||||
<script lang="ts">
|
||||
import {
|
||||
Play,
|
||||
Pause,
|
||||
SkipBack,
|
||||
SkipForward,
|
||||
VolumeX,
|
||||
Volume1,
|
||||
Volume2,
|
||||
List
|
||||
} from 'lucide-svelte';
|
||||
import { Play, Pause, SkipBack, SkipForward, List } from 'lucide-svelte';
|
||||
import { Button } from '$lib/components/ui/button';
|
||||
import { Progress } from '$lib/components/ui/progress';
|
||||
import dayjs from 'dayjs';
|
||||
@@ -18,6 +9,7 @@
|
||||
import { getPlayerState } from '$lib/player.svelte';
|
||||
import { enhance } from '$app/forms';
|
||||
import { getCoverUrl } from '$lib/covers';
|
||||
import VolumeSlider from '$lib/components/groove/VolumeSlider.svelte';
|
||||
import type { SubmitFunction } from '../../../routes/player/$types';
|
||||
|
||||
dayjs.extend(duration);
|
||||
@@ -34,7 +26,6 @@
|
||||
});
|
||||
|
||||
let progressBar = $state<HTMLElement | null>(null);
|
||||
let volumeForm = $state<HTMLFormElement | null>(null);
|
||||
|
||||
const seekProgressValue: SubmitFunction = ({ formData, cancel }) => {
|
||||
if (!player.currentlyPlaying || !progressBar) {
|
||||
@@ -76,20 +67,6 @@
|
||||
};
|
||||
};
|
||||
|
||||
const submitVolumeForm: SubmitFunction = async ({ formData }) => {
|
||||
formData.set('volume', player.volume.toString());
|
||||
|
||||
return async ({ update, result }) => {
|
||||
await update({
|
||||
invalidateAll: false
|
||||
});
|
||||
|
||||
if (result.type === 'success' && result.data && 'volume' in result.data) {
|
||||
player.volume = result.data.volume;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
function onMouseMove(e: MouseEvent) {
|
||||
mouse.offsetX = e.offsetX;
|
||||
mouse.offsetY = e.offsetY;
|
||||
@@ -179,47 +156,7 @@
|
||||
</Popover.Content>
|
||||
</Popover.Root>
|
||||
|
||||
<div class="flex grow flex-row items-center gap-4">
|
||||
<div class="min-w-6 text-muted-foreground">
|
||||
{#if player.volume <= 0.0}
|
||||
<VolumeX class="size-full" />
|
||||
{:else if player.volume < 0.5}
|
||||
<Volume1 class="size-full" />
|
||||
{:else}
|
||||
<Volume2 class="size-full" />
|
||||
{/if}
|
||||
</div>
|
||||
<form
|
||||
bind:this={volumeForm}
|
||||
class="volume-form flex-1"
|
||||
method="POST"
|
||||
action="/player?/volume"
|
||||
use:enhance={submitVolumeForm}
|
||||
>
|
||||
<input
|
||||
class="volume-slider min-w-40"
|
||||
type="range"
|
||||
min={0.0}
|
||||
max={1.0}
|
||||
step={0.01}
|
||||
bind:value={player.volume}
|
||||
oninput={() => {
|
||||
volumeForm?.requestSubmit();
|
||||
}}
|
||||
onmousedown={() => {
|
||||
player.adjustingVolume = true;
|
||||
}}
|
||||
onmouseup={() => {
|
||||
player.adjustingVolume = false;
|
||||
}}
|
||||
/>
|
||||
</form>
|
||||
<div class="min-w-10 self-center">
|
||||
<p class="text-sm text-muted-foreground">
|
||||
{Math.round(player.volume * 100.0)}%
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<VolumeSlider />
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
@@ -249,36 +186,3 @@
|
||||
</footer>
|
||||
|
||||
<svelte:window onmousemove={onMouseMove} />
|
||||
|
||||
<style>
|
||||
.volume-slider {
|
||||
-webkit-appearance: none !important; /* Override default CSS styles */
|
||||
appearance: none !important;
|
||||
width: 100%; /* Full-width */
|
||||
height: 8px; /* Specified height */
|
||||
border-radius: 0.5rem;
|
||||
background: hsl(var(--secondary));
|
||||
outline: none; /* Remove outline */
|
||||
opacity: 0.7; /* Set transparency (for mouse-over effects on hover) */
|
||||
-webkit-transition: 0.2s; /* 0.2 seconds transition on hover */
|
||||
transition: opacity 0.2s;
|
||||
-webkit-user-drag: none;
|
||||
}
|
||||
|
||||
.volume-slider::-webkit-slider-thumb {
|
||||
@apply size-4 bg-background ring ring-secondary ring-offset-0 ring-offset-transparent transition-colors;
|
||||
|
||||
-webkit-user-drag: none;
|
||||
appearance: none;
|
||||
background-color: hsl(var(--primary));
|
||||
border-radius: 100%;
|
||||
}
|
||||
|
||||
.volume-slider::-webkit-slider-thumb:active {
|
||||
@apply ring-offset-2 ring-offset-background;
|
||||
}
|
||||
|
||||
.volume-form {
|
||||
-webkit-user-drag: none;
|
||||
}
|
||||
</style>
|
||||
|
||||
102
src/lib/components/groove/VolumeSlider.svelte
Normal file
102
src/lib/components/groove/VolumeSlider.svelte
Normal file
@@ -0,0 +1,102 @@
|
||||
<script lang="ts">
|
||||
import { enhance } from '$app/forms';
|
||||
import { getPlayerState } from '$lib/player.svelte';
|
||||
import { Volume1, Volume2, VolumeX } from 'lucide-svelte';
|
||||
import type { SubmitFunction } from '../../../routes/player/$types';
|
||||
|
||||
const player = getPlayerState();
|
||||
|
||||
let volumeForm = $state<HTMLFormElement | null>(null);
|
||||
|
||||
const submitVolumeForm: SubmitFunction = async ({ formData }) => {
|
||||
formData.set('volume', player.volume.toString());
|
||||
|
||||
return async ({ update, result }) => {
|
||||
await update({
|
||||
invalidateAll: false
|
||||
});
|
||||
|
||||
if (result.type === 'success' && result.data && 'volume' in result.data) {
|
||||
player.volume = result.data.volume;
|
||||
}
|
||||
};
|
||||
};
|
||||
</script>
|
||||
|
||||
<div class="flex grow flex-row items-center gap-4">
|
||||
<div class="min-w-6 text-muted-foreground">
|
||||
{#if player.volume <= 0.0}
|
||||
<VolumeX class="size-full" />
|
||||
{:else if player.volume < 0.5}
|
||||
<Volume1 class="size-full" />
|
||||
{:else}
|
||||
<Volume2 class="size-full" />
|
||||
{/if}
|
||||
</div>
|
||||
<form
|
||||
bind:this={volumeForm}
|
||||
class="volume-form flex-1"
|
||||
method="POST"
|
||||
action="/player?/volume"
|
||||
use:enhance={submitVolumeForm}
|
||||
>
|
||||
<input
|
||||
class="volume-slider min-w-40"
|
||||
type="range"
|
||||
min={0.0}
|
||||
max={1.0}
|
||||
step={0.01}
|
||||
bind:value={player.volume}
|
||||
oninput={() => {
|
||||
volumeForm?.requestSubmit();
|
||||
}}
|
||||
onmousedown={() => {
|
||||
player.adjustingVolume = true;
|
||||
}}
|
||||
onmouseup={() => {
|
||||
player.adjustingVolume = false;
|
||||
}}
|
||||
style="background-size: {(player.volume / 1.0) * 100}% 100%"
|
||||
/>
|
||||
</form>
|
||||
<div class="min-w-10 self-center">
|
||||
<p class="text-sm text-muted-foreground">
|
||||
{Math.round(player.volume * 100.0)}%
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.volume-slider {
|
||||
-webkit-user-drag: none;
|
||||
appearance: none;
|
||||
|
||||
width: 100%;
|
||||
height: 8px;
|
||||
outline: none;
|
||||
background: hsl(var(--secondary));
|
||||
background-image: linear-gradient(hsl(var(--primary)), hsl(var(--primary)));
|
||||
/* background-size: 50% 100%; */
|
||||
background-repeat: no-repeat;
|
||||
border-radius: 0.5rem;
|
||||
-webkit-user-drag: none;
|
||||
}
|
||||
|
||||
.volume-slider::-webkit-slider-thumb {
|
||||
@apply size-4 bg-background ring ring-secondary ring-offset-0 ring-offset-transparent transition-colors;
|
||||
|
||||
-webkit-user-drag: none;
|
||||
appearance: none;
|
||||
|
||||
background-color: hsl(var(--primary));
|
||||
border-radius: 100%;
|
||||
}
|
||||
|
||||
.volume-slider::-webkit-slider-thumb:active {
|
||||
@apply ring-offset-2 ring-offset-background;
|
||||
}
|
||||
|
||||
.volume-form {
|
||||
-webkit-user-drag: none;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user