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
|
|
@ -7,7 +7,7 @@
|
||||||
<div class="flex flex-col items-center justify-center w-full h-full">
|
<div class="flex flex-col items-center justify-center w-full h-full">
|
||||||
<div class="flex flex-col w-72">
|
<div class="flex flex-col w-72">
|
||||||
<div class="w-full h-72 bg-lime-200"></div>
|
<div class="w-full h-72 bg-lime-200"></div>
|
||||||
<CustomScrollBar overflowX="scroll" overflowY="hidden" Class="h-26">
|
<CustomScrollBar overflowX="scroll" overflowY="hidden" Class="">
|
||||||
<div class="flex w-full gap-4">
|
<div class="flex w-full gap-4">
|
||||||
{#each { length: 4 } as i}
|
{#each { length: 4 } as i}
|
||||||
<img
|
<img
|
||||||
|
|
|
||||||
|
|
@ -11,8 +11,8 @@
|
||||||
import DeprivedLogo from "$lib/images/DeprivedLogo.svelte";
|
import DeprivedLogo from "$lib/images/DeprivedLogo.svelte";
|
||||||
import HamburgerMenuIcon from "$lib/images/HamburgerMenuIcon.svelte";
|
import HamburgerMenuIcon from "$lib/images/HamburgerMenuIcon.svelte";
|
||||||
|
|
||||||
const footerCollapseThreshold: string = "1000px";
|
const footerCollapseThreshold: string = "40rem";
|
||||||
const headerCollapseThreshold: string = "1000px";
|
const headerCollapseThreshold: string = "40rem";
|
||||||
let footerCollapse: boolean;
|
let footerCollapse: boolean;
|
||||||
let isMobile: boolean = $state(false);
|
let isMobile: boolean = $state(false);
|
||||||
|
|
||||||
|
|
@ -31,6 +31,7 @@
|
||||||
|
|
||||||
import { onMount } from "svelte";
|
import { onMount } from "svelte";
|
||||||
import Zooter from "./comps/Zooter.svelte";
|
import Zooter from "./comps/Zooter.svelte";
|
||||||
|
import CustomScrollBar from "./comps/CustomScrollBar.svelte";
|
||||||
|
|
||||||
onMount(async () => {
|
onMount(async () => {
|
||||||
const lock = document.createElement("meta");
|
const lock = document.createElement("meta");
|
||||||
|
|
@ -82,6 +83,13 @@
|
||||||
bind:matches={isMobile}
|
bind:matches={isMobile}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<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">
|
<div class="flex flex-col justify-between min-h-screen bg-base-200 p-0">
|
||||||
<header class="{hideOnPrint ? 'hide-on-print' : ''} bg-base-300">
|
<header class="{hideOnPrint ? 'hide-on-print' : ''} bg-base-300">
|
||||||
<div class="nav-bar pr-4">
|
<div class="nav-bar pr-4">
|
||||||
|
|
@ -162,6 +170,7 @@
|
||||||
|
|
||||||
<Zooter bind:hideOnPrint />
|
<Zooter bind:hideOnPrint />
|
||||||
</div>
|
</div>
|
||||||
|
</CustomScrollBar>
|
||||||
|
|
||||||
{#if footerCollapse}
|
{#if footerCollapse}
|
||||||
<style>
|
<style>
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,18 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { onMount, onDestroy } from "svelte";
|
import { onMount, onDestroy } from "svelte";
|
||||||
|
import MediaQuery from "svelte-media-queries";
|
||||||
|
|
||||||
// Public props
|
// Public props
|
||||||
export let overflowX: "auto" | "scroll" | "hidden" = "hidden";
|
export let overflowX: "auto" | "scroll" | "hidden" = "hidden";
|
||||||
export let overflowY: "auto" | "scroll" | "hidden" = "auto";
|
export let overflowY: "auto" | "scroll" | "hidden" = "auto";
|
||||||
|
|
||||||
|
export let hideOnMobile = false; // True if hide scrollbar when mobile detected
|
||||||
|
|
||||||
// Visual tuning
|
// Visual tuning
|
||||||
export let thickness = 12; // px
|
export let thickness = 12; // px
|
||||||
export let padding = 0; // px, space around track inside the overlay
|
export let padding = 0; // px, space around track inside the overlay
|
||||||
export let minThumb = 24; // px
|
export let minThumb = 10; // px
|
||||||
export let contentPadding = 16; // px, inner padding for your content
|
export let contentPadding = 0; // px, inner padding for your content
|
||||||
export let Class = ""; // Extra classes for the scrollbar
|
export let Class = ""; // Extra classes for the scrollbar
|
||||||
|
|
||||||
// Styling (customize freely)
|
// Styling (customize freely)
|
||||||
|
|
@ -18,9 +21,11 @@
|
||||||
export let trackOpacity = 0.55;
|
export let trackOpacity = 0.55;
|
||||||
|
|
||||||
export let thumbClass =
|
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 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 viewport: HTMLDivElement;
|
||||||
let vBar: HTMLDivElement; // vertical bar container
|
let vBar: HTMLDivElement; // vertical bar container
|
||||||
let hBar: HTMLDivElement; // horizontal bar container
|
let hBar: HTMLDivElement; // horizontal bar container
|
||||||
|
|
@ -29,6 +34,7 @@
|
||||||
|
|
||||||
let showBarY = false;
|
let showBarY = false;
|
||||||
let showBarX = false;
|
let showBarX = false;
|
||||||
|
let isMobile = false;
|
||||||
|
|
||||||
// ——— utils
|
// ——— utils
|
||||||
const sMaxY = () =>
|
const sMaxY = () =>
|
||||||
|
|
@ -41,9 +47,13 @@
|
||||||
|
|
||||||
function updateVisibility() {
|
function updateVisibility() {
|
||||||
showBarY =
|
showBarY =
|
||||||
overflowY !== "hidden" && viewport.scrollHeight > viewport.clientHeight;
|
overflowY !== "hidden" &&
|
||||||
|
viewport.scrollHeight > viewport.clientHeight &&
|
||||||
|
!(hideOnMobile && isMobile);
|
||||||
showBarX =
|
showBarX =
|
||||||
overflowX !== "hidden" && viewport.scrollWidth > viewport.clientWidth;
|
overflowX !== "hidden" &&
|
||||||
|
viewport.scrollWidth > viewport.clientWidth &&
|
||||||
|
!(hideOnMobile && isMobile);
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateVerticalThumb() {
|
function updateVerticalThumb() {
|
||||||
|
|
@ -268,15 +278,25 @@
|
||||||
$: pb = contentPadding + (showBarX ? thickness + padding * 2 : 0);
|
$: pb = contentPadding + (showBarX ? thickness + padding * 2 : 0);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<MediaQuery query="(max-width: 40rem)" bind:matches={isMobile} />
|
||||||
|
|
||||||
<!-- svelte-ignore element_invalid_self_closing_tag -->
|
<!-- svelte-ignore element_invalid_self_closing_tag -->
|
||||||
<!-- svelte-ignore a11y_role_has_required_aria_props -->
|
<!-- svelte-ignore a11y_role_has_required_aria_props -->
|
||||||
|
|
||||||
<!-- Wrapper -->
|
<!-- 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) -->
|
<!-- The real, native scrolling area (we hide its native scrollbar) -->
|
||||||
<div
|
<div
|
||||||
bind:this={viewport}
|
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="
|
style="
|
||||||
padding: {contentPadding}px {pr}px {pb}px {contentPadding}px;
|
padding: {contentPadding}px {pr}px {pb}px {contentPadding}px;
|
||||||
overscroll-behavior: contain;
|
overscroll-behavior: contain;
|
||||||
|
|
@ -292,7 +312,7 @@
|
||||||
{#if showBarY}
|
{#if showBarY}
|
||||||
<div
|
<div
|
||||||
bind:this={vBar}
|
bind:this={vBar}
|
||||||
class="absolute"
|
class="absolute bg-base-200"
|
||||||
style="
|
style="
|
||||||
top: {padding}px;
|
top: {padding}px;
|
||||||
bottom: {padding}px;
|
bottom: {padding}px;
|
||||||
|
|
@ -304,7 +324,7 @@
|
||||||
>
|
>
|
||||||
<div class="absolute inset-0 corner-border-container">
|
<div class="absolute inset-0 corner-border-container">
|
||||||
<div
|
<div
|
||||||
class="transition-opacity {trackClass} w-full"
|
class="transition-opacity {trackClass} w-full h-full"
|
||||||
style="
|
style="
|
||||||
pointer-events: auto;
|
pointer-events: auto;
|
||||||
{trackStyle}
|
{trackStyle}
|
||||||
|
|
@ -318,14 +338,18 @@
|
||||||
role="scrollbar"
|
role="scrollbar"
|
||||||
aria-orientation="vertical"
|
aria-orientation="vertical"
|
||||||
tabindex="0"
|
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;"
|
style="height: {thumbLength}px; pointer-events: auto; touch-action: none;"
|
||||||
on:pointerdown={onVPointerDown}
|
on:pointerdown={onVPointerDown}
|
||||||
on:pointermove={onVPointerMove}
|
on:pointermove={onVPointerMove}
|
||||||
on:pointerup={endVDrag}
|
on:pointerup={endVDrag}
|
||||||
on:pointercancel={endVDrag}
|
on:pointercancel={endVDrag}
|
||||||
on:keydown={onVKeyDown}
|
on:keydown={onVKeyDown}
|
||||||
></div>
|
>
|
||||||
|
<span class="rotate-90">
|
||||||
|
-------------------------------------------------Scroll-------------------------------------------------
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
|
|
@ -358,7 +382,7 @@
|
||||||
role="scrollbar"
|
role="scrollbar"
|
||||||
aria-orientation="horizontal"
|
aria-orientation="horizontal"
|
||||||
tabindex="0"
|
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;"
|
style="width: {thumbLength}px; pointer-events: auto; touch-action: none;"
|
||||||
on:pointerdown={onHPointerDown}
|
on:pointerdown={onHPointerDown}
|
||||||
on:pointermove={onHPointerMove}
|
on:pointermove={onHPointerMove}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue