custom scrollbar implemented
Some checks failed
Rebuild signaller for deprived.dev to rebuild site / test_service (push) Failing after 0s
Some checks failed
Rebuild signaller for deprived.dev to rebuild site / test_service (push) Failing after 0s
This commit is contained in:
parent
c099b9ce9f
commit
7a8d61d598
3 changed files with 116 additions and 83 deletions
|
|
@ -11,8 +11,8 @@
|
|||
import DeprivedLogo from "$lib/images/DeprivedLogo.svelte";
|
||||
import HamburgerMenuIcon from "$lib/images/HamburgerMenuIcon.svelte";
|
||||
|
||||
const footerCollapseThreshold: string = "1000px";
|
||||
const headerCollapseThreshold: string = "1000px";
|
||||
const footerCollapseThreshold: string = "40rem";
|
||||
const headerCollapseThreshold: string = "40rem";
|
||||
let footerCollapse: boolean;
|
||||
let isMobile: boolean = $state(false);
|
||||
|
||||
|
|
@ -31,6 +31,7 @@
|
|||
|
||||
import { onMount } from "svelte";
|
||||
import Zooter from "./comps/Zooter.svelte";
|
||||
import CustomScrollBar from "./comps/CustomScrollBar.svelte";
|
||||
|
||||
onMount(async () => {
|
||||
const lock = document.createElement("meta");
|
||||
|
|
@ -82,86 +83,94 @@
|
|||
bind:matches={isMobile}
|
||||
/>
|
||||
|
||||
<div class="flex flex-col justify-between min-h-screen bg-base-200 p-0">
|
||||
<header class="{hideOnPrint ? 'hide-on-print' : ''} bg-base-300">
|
||||
<div class="nav-bar pr-4">
|
||||
{#if !isMobile}
|
||||
<div class="desktop items-center">
|
||||
<a href="/" class="nav-head">
|
||||
<DeprivedLogo
|
||||
Class="fill-base-content p-2"
|
||||
Style="width: 3.5rem; height: auto;"
|
||||
/>
|
||||
<!-- <h3 id="logo-text">The Deprived Devs</h3> -->
|
||||
</a>
|
||||
<div class="nav-spacer" />
|
||||
<CustomScrollBar
|
||||
overflowX="hidden"
|
||||
overflowY="auto"
|
||||
Class="h-screen"
|
||||
requireAbsolute={true}
|
||||
hideOnMobile={true}
|
||||
>
|
||||
<div class="flex flex-col justify-between min-h-screen bg-base-200 p-0">
|
||||
<header class="{hideOnPrint ? 'hide-on-print' : ''} bg-base-300">
|
||||
<div class="nav-bar pr-4">
|
||||
{#if !isMobile}
|
||||
<div class="desktop items-center">
|
||||
<a href="/" class="nav-head">
|
||||
<DeprivedLogo
|
||||
Class="fill-base-content p-2"
|
||||
Style="width: 3.5rem; height: auto;"
|
||||
/>
|
||||
<!-- <h3 id="logo-text">The Deprived Devs</h3> -->
|
||||
</a>
|
||||
<div class="nav-spacer" />
|
||||
|
||||
<!-- <a href="/">Home</a> -->
|
||||
<!-- <a href="/zhen/notes/physics/1?hideOnPrint=1" target="_blank" style="width: 7.5rem;">Notes</a> -->
|
||||
<!-- <a href="/">Home</a> -->
|
||||
<!-- <a href="/zhen/notes/physics/1?hideOnPrint=1" target="_blank" style="width: 7.5rem;">Notes</a> -->
|
||||
|
||||
{@render SwitchThemeButton()}
|
||||
{@render SwitchThemeButton()}
|
||||
|
||||
<a
|
||||
href="/zhen/cv/rev3?hideOnPrint=1"
|
||||
target="_blank"
|
||||
style="width: 7.5rem;"
|
||||
class="text-center justify-center">Zhen CV</a
|
||||
>
|
||||
<!-- <a href="/tools" style="width: 7.5rem;" class="text-center">Tools</a> -->
|
||||
<a href="https://botalex.itch.io/" target="_blank">Games</a>
|
||||
<!-- <a href="/posts">Blog</a>
|
||||
<a href="/about">About</a> -->
|
||||
</div>
|
||||
{:else}
|
||||
<div class="collapsed shadow-xl">
|
||||
<a onclick={resetNavBar} href="/" class="nav-head">
|
||||
<DeprivedLogo
|
||||
Class="fill-base-content p-2"
|
||||
Style="width: 3.5rem; height: auto;"
|
||||
/>
|
||||
<!-- <h3 id="logo-text">The Deprived Devs</h3> -->
|
||||
</a>
|
||||
<div class="nav-spacer" />
|
||||
{@render SwitchThemeButton()}
|
||||
<div class="px-1"></div>
|
||||
<button
|
||||
id="toggle-nav"
|
||||
onclick={() => {
|
||||
navbarHidden = !navbarHidden;
|
||||
console.log(navbarHidden);
|
||||
}}
|
||||
>
|
||||
<HamburgerMenuIcon Class="fill-base-content" />
|
||||
</button>
|
||||
</div>
|
||||
{#if !navbarHidden}
|
||||
<div class="nav-list" transition:fly={{ y: -25, duration: 350 }}>
|
||||
<!-- <a onclick={resetNavBar} href="/">Home</a> -->
|
||||
<a
|
||||
onclick={resetNavBar}
|
||||
href="https://botalex.itch.io/"
|
||||
target="_blank">Games</a
|
||||
>
|
||||
<a
|
||||
href="/zhen/cv/rev3?hideOnPrint=1"
|
||||
target="_blank"
|
||||
class="justify-center">Zhen's CV</a
|
||||
style="width: 7.5rem;"
|
||||
class="text-center justify-center">Zhen CV</a
|
||||
>
|
||||
<!-- <a onclick={resetNavBar} href="/posts">Blog</a>
|
||||
<a onclick={resetNavBar} href="/about">About</a> -->
|
||||
<!-- <a href="/tools" style="width: 7.5rem;" class="text-center">Tools</a> -->
|
||||
<a href="https://botalex.itch.io/" target="_blank">Games</a>
|
||||
<!-- <a href="/posts">Blog</a>
|
||||
<a href="/about">About</a> -->
|
||||
</div>
|
||||
{:else}
|
||||
<div class="collapsed shadow-xl">
|
||||
<a onclick={resetNavBar} href="/" class="nav-head">
|
||||
<DeprivedLogo
|
||||
Class="fill-base-content p-2"
|
||||
Style="width: 3.5rem; height: auto;"
|
||||
/>
|
||||
<!-- <h3 id="logo-text">The Deprived Devs</h3> -->
|
||||
</a>
|
||||
<div class="nav-spacer" />
|
||||
{@render SwitchThemeButton()}
|
||||
<div class="px-1"></div>
|
||||
<button
|
||||
id="toggle-nav"
|
||||
onclick={() => {
|
||||
navbarHidden = !navbarHidden;
|
||||
console.log(navbarHidden);
|
||||
}}
|
||||
>
|
||||
<HamburgerMenuIcon Class="fill-base-content" />
|
||||
</button>
|
||||
</div>
|
||||
{#if !navbarHidden}
|
||||
<div class="nav-list" transition:fly={{ y: -25, duration: 350 }}>
|
||||
<!-- <a onclick={resetNavBar} href="/">Home</a> -->
|
||||
<a
|
||||
onclick={resetNavBar}
|
||||
href="https://botalex.itch.io/"
|
||||
target="_blank">Games</a
|
||||
>
|
||||
<a
|
||||
href="/zhen/cv/rev3?hideOnPrint=1"
|
||||
target="_blank"
|
||||
class="justify-center">Zhen's CV</a
|
||||
>
|
||||
<!-- <a onclick={resetNavBar} href="/posts">Blog</a>
|
||||
<a onclick={resetNavBar} href="/about">About</a> -->
|
||||
</div>
|
||||
{/if}
|
||||
{/if}
|
||||
{/if}
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<div class="flex-1">
|
||||
<!-- Page content -->
|
||||
{@render children?.()}
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<div class="flex-1">
|
||||
<!-- Page content -->
|
||||
{@render children?.()}
|
||||
<Zooter bind:hideOnPrint />
|
||||
</div>
|
||||
|
||||
<Zooter bind:hideOnPrint />
|
||||
</div>
|
||||
</CustomScrollBar>
|
||||
|
||||
{#if footerCollapse}
|
||||
<style>
|
||||
|
|
|
|||
|
|
@ -1,15 +1,18 @@
|
|||
<script lang="ts">
|
||||
import { onMount, onDestroy } from "svelte";
|
||||
import MediaQuery from "svelte-media-queries";
|
||||
|
||||
// Public props
|
||||
export let overflowX: "auto" | "scroll" | "hidden" = "hidden";
|
||||
export let overflowY: "auto" | "scroll" | "hidden" = "auto";
|
||||
|
||||
export let hideOnMobile = false; // True if hide scrollbar when mobile detected
|
||||
|
||||
// Visual tuning
|
||||
export let thickness = 12; // px
|
||||
export let padding = 0; // px, space around track inside the overlay
|
||||
export let minThumb = 24; // px
|
||||
export let contentPadding = 16; // px, inner padding for your content
|
||||
export let minThumb = 10; // px
|
||||
export let contentPadding = 0; // px, inner padding for your content
|
||||
export let Class = ""; // Extra classes for the scrollbar
|
||||
|
||||
// Styling (customize freely)
|
||||
|
|
@ -18,9 +21,11 @@
|
|||
export let trackOpacity = 0.55;
|
||||
|
||||
export let thumbClass =
|
||||
"bg-black border-x-1 opacity-50 border-white text-xs text-center text-opacity-50 overflow-hidden flex items-center text-nowrap justify-center";
|
||||
"bg-black opacity-50 border-white text-xs text-center text-opacity-50 overflow-hidden flex items-center text-nowrap justify-center";
|
||||
export let thumbLength = 20; // px. doesn't work for some reason, idk
|
||||
|
||||
export let requireAbsolute = false; // Some needs absolute for some reason. idk
|
||||
|
||||
let viewport: HTMLDivElement;
|
||||
let vBar: HTMLDivElement; // vertical bar container
|
||||
let hBar: HTMLDivElement; // horizontal bar container
|
||||
|
|
@ -29,6 +34,7 @@
|
|||
|
||||
let showBarY = false;
|
||||
let showBarX = false;
|
||||
let isMobile = false;
|
||||
|
||||
// ——— utils
|
||||
const sMaxY = () =>
|
||||
|
|
@ -41,9 +47,13 @@
|
|||
|
||||
function updateVisibility() {
|
||||
showBarY =
|
||||
overflowY !== "hidden" && viewport.scrollHeight > viewport.clientHeight;
|
||||
overflowY !== "hidden" &&
|
||||
viewport.scrollHeight > viewport.clientHeight &&
|
||||
!(hideOnMobile && isMobile);
|
||||
showBarX =
|
||||
overflowX !== "hidden" && viewport.scrollWidth > viewport.clientWidth;
|
||||
overflowX !== "hidden" &&
|
||||
viewport.scrollWidth > viewport.clientWidth &&
|
||||
!(hideOnMobile && isMobile);
|
||||
}
|
||||
|
||||
function updateVerticalThumb() {
|
||||
|
|
@ -268,15 +278,25 @@
|
|||
$: pb = contentPadding + (showBarX ? thickness + padding * 2 : 0);
|
||||
</script>
|
||||
|
||||
<MediaQuery query="(max-width: 40rem)" bind:matches={isMobile} />
|
||||
|
||||
<!-- svelte-ignore element_invalid_self_closing_tag -->
|
||||
<!-- svelte-ignore a11y_role_has_required_aria_props -->
|
||||
|
||||
<!-- Wrapper -->
|
||||
<div class="relative overflow-hidden {Class}">
|
||||
<div
|
||||
class="relative {overflowY == 'hidden'
|
||||
? ''
|
||||
: 'overflow-y-hidden'} {overflowX == 'hidden'
|
||||
? ''
|
||||
: 'overflow-x-hidden'} {Class}"
|
||||
>
|
||||
<!-- The real, native scrolling area (we hide its native scrollbar) -->
|
||||
<div
|
||||
bind:this={viewport}
|
||||
class="csb-viewport absolute inset-0 overflow-auto focus:outline-none"
|
||||
class="csb-viewport {requireAbsolute
|
||||
? 'absolute'
|
||||
: ''} inset-0 overflow-auto focus:outline-none"
|
||||
style="
|
||||
padding: {contentPadding}px {pr}px {pb}px {contentPadding}px;
|
||||
overscroll-behavior: contain;
|
||||
|
|
@ -292,7 +312,7 @@
|
|||
{#if showBarY}
|
||||
<div
|
||||
bind:this={vBar}
|
||||
class="absolute"
|
||||
class="absolute bg-base-200"
|
||||
style="
|
||||
top: {padding}px;
|
||||
bottom: {padding}px;
|
||||
|
|
@ -304,7 +324,7 @@
|
|||
>
|
||||
<div class="absolute inset-0 corner-border-container">
|
||||
<div
|
||||
class="transition-opacity {trackClass} w-full"
|
||||
class="transition-opacity {trackClass} w-full h-full"
|
||||
style="
|
||||
pointer-events: auto;
|
||||
{trackStyle}
|
||||
|
|
@ -318,14 +338,18 @@
|
|||
role="scrollbar"
|
||||
aria-orientation="vertical"
|
||||
tabindex="0"
|
||||
class={`absolute left-[2px] right-[2px] rounded-full cursor-grab active:cursor-grabbing focus-visible:outline focus-visible:outline-2 focus-visible:outline-sky-500 ${thumbClass}`}
|
||||
class={`absolute border-y-2 left-0 right-0 rounded-none cursor-grab active:cursor-grabbing focus-visible:outline focus-visible:outline-2 focus-visible:outline-sky-500 ${thumbClass}`}
|
||||
style="height: {thumbLength}px; pointer-events: auto; touch-action: none;"
|
||||
on:pointerdown={onVPointerDown}
|
||||
on:pointermove={onVPointerMove}
|
||||
on:pointerup={endVDrag}
|
||||
on:pointercancel={endVDrag}
|
||||
on:keydown={onVKeyDown}
|
||||
></div>
|
||||
>
|
||||
<span class="rotate-90">
|
||||
-------------------------------------------------Scroll-------------------------------------------------
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
|
|
@ -358,7 +382,7 @@
|
|||
role="scrollbar"
|
||||
aria-orientation="horizontal"
|
||||
tabindex="0"
|
||||
class={`absolute top-0 bottom-0 rounded-none cursor-grab active:cursor-grabbing focus-visible:outline focus-visible:outline-2 focus-visible:outline-sky-500 ${thumbClass}`}
|
||||
class={`absolute border-x-2 top-0 bottom-0 rounded-none cursor-grab active:cursor-grabbing focus-visible:outline focus-visible:outline-2 focus-visible:outline-sky-500 ${thumbClass}`}
|
||||
style="width: {thumbLength}px; pointer-events: auto; touch-action: none;"
|
||||
on:pointerdown={onHPointerDown}
|
||||
on:pointermove={onHPointerMove}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue