From 3d2056c3d9685f0a86f4d4281e4bcbc392298e30 Mon Sep 17 00:00:00 2001 From: GauthierWebDev Date: Mon, 21 Apr 2025 16:20:17 +0200 Subject: [PATCH] feat: Add ReadProgressBar component to DefaultLayout --- app/layouts/DocsLayout.tsx | 6 ++--- app/layouts/LayoutDefault.tsx | 6 +++++ app/partials/ReadProgressBar.tsx | 44 ++++++++++++++++++++++++++++++++ 3 files changed, 53 insertions(+), 3 deletions(-) create mode 100644 app/partials/ReadProgressBar.tsx diff --git a/app/layouts/DocsLayout.tsx b/app/layouts/DocsLayout.tsx index 30ca027..42b2ee9 100644 --- a/app/layouts/DocsLayout.tsx +++ b/app/layouts/DocsLayout.tsx @@ -22,8 +22,8 @@ export function DocsLayout(props: DocsLayoutProps) { return ( <> -
-
+
+
{props.children}
-
+ diff --git a/app/layouts/LayoutDefault.tsx b/app/layouts/LayoutDefault.tsx index bc0ef30..7032c31 100755 --- a/app/layouts/LayoutDefault.tsx +++ b/app/layouts/LayoutDefault.tsx @@ -3,6 +3,7 @@ import type { JSXElement } from "solid-js"; import { usePageContext } from "vike-solid/usePageContext"; import { HeroSection } from "@/partials/HeroSection"; import { Navigation } from "@/partials/Navigation"; +import { clientOnly } from "vike-solid/clientOnly"; import { Header } from "@/partials/Header"; import { Footer } from "@/partials/Footer"; import { DocsLayout } from "./DocsLayout"; @@ -10,6 +11,10 @@ import { Toaster } from "solid-toast"; import "./tailwind.css"; +const ReadProgressBar = clientOnly( + async () => (await import("@/partials/ReadProgressBar")).ReadProgressBar, +); + type DefaultLayoutProps = { children: JSXElement; }; @@ -21,6 +26,7 @@ export default function DefaultLayout(props: DefaultLayoutProps) { <>
+ {pageContext.urlPathname === "/" && } diff --git a/app/partials/ReadProgressBar.tsx b/app/partials/ReadProgressBar.tsx new file mode 100644 index 0000000..5f51ba4 --- /dev/null +++ b/app/partials/ReadProgressBar.tsx @@ -0,0 +1,44 @@ +import { createEffect, createSignal } from "solid-js"; + +export function ReadProgressBar() { + const articleContentElement: HTMLElement | null = + document.getElementById("article-content"); + if (!articleContentElement) return null; + + const [width, setWidth] = createSignal("0%"); + + const handleScroll = () => { + const scrollTop = window.scrollY; + const pageHeight = document.documentElement.scrollHeight; + const scrollHeight = articleContentElement.scrollHeight; + + const gapWithBottom = pageHeight - scrollHeight; + const scrollableHeight = pageHeight - gapWithBottom; + + const scrollPercentage = Math.round((scrollTop / scrollableHeight) * 100); + + setWidth(`${scrollPercentage}%`); + }; + + createEffect(() => { + window.addEventListener("scroll", handleScroll); + + handleScroll(); + + return () => { + window.removeEventListener("scroll", handleScroll); + }; + }); + + return ( +
+
+
+ ); +}