Big layout improvements, started on miniplayer
This commit is contained in:
@@ -0,0 +1,12 @@
|
||||
<footer class="sticky bottom-0 flex flex-col-reverse">
|
||||
<slot name="content" />
|
||||
</footer>
|
||||
|
||||
<style>
|
||||
footer {
|
||||
padding-top: 16px;
|
||||
padding-bottom: 16px;
|
||||
font-size: 20px;
|
||||
line-height: 28px;
|
||||
}
|
||||
</style>
|
||||
@@ -2,46 +2,35 @@
|
||||
import IconButton from './iconButton.svelte'
|
||||
import { goto } from '$app/navigation'
|
||||
import { page } from '$app/stores'
|
||||
|
||||
let windowY = 0
|
||||
</script>
|
||||
|
||||
<svelte:window bind:scrollY={windowY} />
|
||||
<nav class="sticky top-0 z-10 flex items-center justify-between px-8 duration-300" class:background-active={windowY > 0}>
|
||||
<nav class="sticky top-0 z-10 grid grid-cols-[1fr_auto_1fr] items-center duration-300">
|
||||
<section class="flex h-full">
|
||||
<IconButton>
|
||||
<i slot="icon" class="fa-solid fa-gear" />
|
||||
<IconButton on:click={() => goto('/settings')}>
|
||||
<i slot="icon" class="fa-solid fa-user-gear" />
|
||||
</IconButton>
|
||||
{#if $page.url.pathname !== '/'}
|
||||
<IconButton on:click={() => goto('/')}>
|
||||
<i slot="icon" class="fa-solid fa-house" />
|
||||
</IconButton>
|
||||
<IconButton on:click={() => history.back()}>
|
||||
<i slot="icon" class="fa-solid fa-arrow-left" />
|
||||
</IconButton>
|
||||
{/if}
|
||||
</section>
|
||||
<section class="flex h-full">
|
||||
<section class="flex h-full justify-center">
|
||||
<slot name="center-content" />
|
||||
</section>
|
||||
<section class="flex h-full justify-end">
|
||||
<IconButton>
|
||||
<i slot="icon" class="fa-solid fa-magnifying-glass" />
|
||||
</IconButton>
|
||||
<IconButton>
|
||||
<i slot="icon" class="fa-solid fa-user" />
|
||||
</IconButton>
|
||||
</section>
|
||||
</nav>
|
||||
|
||||
<style>
|
||||
nav {
|
||||
height: 64px;
|
||||
padding-top: 16px;
|
||||
padding-bottom: 16px;
|
||||
padding: 20px 2rem;
|
||||
font-size: 20px;
|
||||
line-height: 28px;
|
||||
}
|
||||
nav.background-active {
|
||||
background-color: rgb(10, 10, 10);
|
||||
}
|
||||
section {
|
||||
gap: 24px;
|
||||
}
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
<script>
|
||||
export let open = false
|
||||
|
||||
import IconButton from './iconButton.svelte'
|
||||
import { slide } from 'svelte/transition'
|
||||
|
||||
export const toggleOpen = () => (open = !open)
|
||||
|
||||
let sidebar
|
||||
</script>
|
||||
|
||||
<svelte:document
|
||||
on:mouseup={(event) => {
|
||||
if (sidebar && open) {
|
||||
if (!sidebar.contains(event.target)) open = false
|
||||
}
|
||||
}}
|
||||
/>
|
||||
{#if open}
|
||||
<section bind:this={sidebar} transition:slide={{ axis: 'x' }} class="fixed left-0 top-0 z-20 h-full w-full max-w-sm bg-slate-600 p-2" style="width: calc(100% - 4rem);">
|
||||
<div class="float-right h-8">
|
||||
<IconButton on:click={toggleOpen}>
|
||||
<i slot="icon" class="fa-solid fa-x" />
|
||||
</IconButton>
|
||||
</div>
|
||||
</section>
|
||||
{/if}
|
||||
@@ -0,0 +1,78 @@
|
||||
<script>
|
||||
import { onMount } from 'svelte'
|
||||
import { createEventDispatcher } from 'svelte'
|
||||
|
||||
export let initialValue = 0
|
||||
onMount(() => (sliderValue = Number(initialValue)))
|
||||
|
||||
export const setValue = (value) => (sliderValue = value)
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
|
||||
let sliderValue
|
||||
let sliderTrail, sliderThumb
|
||||
|
||||
const trackThumb = (sliderPos) => {
|
||||
if (sliderThumb) sliderThumb.style.left = `${sliderPos}%`
|
||||
if (sliderTrail) sliderTrail.style.right = `${100 - sliderPos}%`
|
||||
}
|
||||
|
||||
$: trackThumb(sliderValue)
|
||||
|
||||
const handleKeyPress = (key) => {
|
||||
if ((key === 'ArrowRight' || key === 'ArrowUp') && sliderValue < 100) {
|
||||
sliderValue += 1
|
||||
return dispatch('valuechange', { value: sliderValue })
|
||||
}
|
||||
if ((key === 'ArrowLeft' || key === 'ArrowDown') && sliderValue > 0) {
|
||||
sliderValue -= 1
|
||||
return dispatch('valuechange', { value: sliderValue })
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<div
|
||||
id="slider-track"
|
||||
class="relative isolate h-1 w-full rounded-full bg-neutral-600"
|
||||
role="slider"
|
||||
tabindex="0"
|
||||
aria-valuenow={sliderValue}
|
||||
aria-valuemin="0"
|
||||
aria-valuemax="100"
|
||||
on:keydown={(event) => handleKeyPress(event.key)}
|
||||
>
|
||||
<input
|
||||
type="range"
|
||||
class="absolute z-10 h-1 w-full"
|
||||
step="any"
|
||||
min="0"
|
||||
max="100"
|
||||
bind:value={sliderValue}
|
||||
tabindex="-1"
|
||||
aria-hidden="true"
|
||||
aria-disabled="true"
|
||||
on:mouseup={() => dispatch('valuechange', { value: sliderValue })}
|
||||
/>
|
||||
<span bind:this={sliderTrail} id="slider-trail" class="absolute left-0 h-1 rounded-full bg-white transition-colors" />
|
||||
<span bind:this={sliderThumb} id="slider-thumb" class="absolute top-1/2 aspect-square h-4 -translate-x-1/2 -translate-y-1/2 rounded-full bg-white opacity-0 transition-opacity duration-300" />
|
||||
</div>
|
||||
|
||||
<style>
|
||||
input[type='range'] {
|
||||
appearance: none;
|
||||
cursor: pointer;
|
||||
opacity: 0;
|
||||
}
|
||||
#slider-track:hover > #slider-trail {
|
||||
background-color: var(--lazuli-primary);
|
||||
}
|
||||
#slider-track:focus > #slider-trail {
|
||||
background-color: var(--lazuli-primary);
|
||||
}
|
||||
#slider-track:hover > #slider-thumb {
|
||||
opacity: 1;
|
||||
}
|
||||
#slider-track:focus > #slider-thumb {
|
||||
opacity: 1;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user