This commit is contained in:
parent
f859a12d2c
commit
9dc9225591
5 changed files with 137 additions and 34 deletions
|
@ -11,6 +11,8 @@ import * as $post_slug_ from "./routes/post/[slug].tsx";
|
||||||
import * as $posts from "./routes/posts.tsx";
|
import * as $posts from "./routes/posts.tsx";
|
||||||
import * as $projects from "./routes/projects.tsx";
|
import * as $projects from "./routes/projects.tsx";
|
||||||
import * as $Example from "./islands/Example.tsx";
|
import * as $Example from "./islands/Example.tsx";
|
||||||
|
import * as $NavigationBar from "./islands/NavigationBar.tsx";
|
||||||
|
import * as $ScrollUpButton from "./islands/ScrollUpButton.tsx";
|
||||||
import type { Manifest } from "$fresh/server.ts";
|
import type { Manifest } from "$fresh/server.ts";
|
||||||
|
|
||||||
const manifest = {
|
const manifest = {
|
||||||
|
@ -26,6 +28,8 @@ const manifest = {
|
||||||
},
|
},
|
||||||
islands: {
|
islands: {
|
||||||
"./islands/Example.tsx": $Example,
|
"./islands/Example.tsx": $Example,
|
||||||
|
"./islands/NavigationBar.tsx": $NavigationBar,
|
||||||
|
"./islands/ScrollUpButton.tsx": $ScrollUpButton,
|
||||||
},
|
},
|
||||||
baseUrl: import.meta.url,
|
baseUrl: import.meta.url,
|
||||||
} satisfies Manifest;
|
} satisfies Manifest;
|
||||||
|
|
83
islands/NavigationBar.tsx
Normal file
83
islands/NavigationBar.tsx
Normal file
|
@ -0,0 +1,83 @@
|
||||||
|
// islands/NavigationBar.tsx
|
||||||
|
import { useComputed, useSignal } from "@preact/signals";
|
||||||
|
import { useEffect } from "preact/hooks";
|
||||||
|
import { LuCodeXml, LuHouse, LuNotebookPen } from "@preact-icons/lu";
|
||||||
|
|
||||||
|
interface NavigationBarProps {
|
||||||
|
currentPath: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function NavigationBar({ currentPath }: NavigationBarProps) {
|
||||||
|
const isScrolling = useSignal(false);
|
||||||
|
const prevScrollPos = useSignal(0);
|
||||||
|
const isVisible = useComputed(() => {
|
||||||
|
if (prevScrollPos.value < 50) return true;
|
||||||
|
|
||||||
|
const currentPos = typeof window !== "undefined" ? globalThis.scrollY : 0;
|
||||||
|
return prevScrollPos.value > currentPos;
|
||||||
|
});
|
||||||
|
|
||||||
|
const isPostsPath = (path: string) => {
|
||||||
|
return path.startsWith("/posts") || path.startsWith("/post/");
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
let scrollTimer: number | undefined;
|
||||||
|
|
||||||
|
const handleScroll = () => {
|
||||||
|
isScrolling.value = true;
|
||||||
|
prevScrollPos.value = globalThis.scrollY;
|
||||||
|
|
||||||
|
if (scrollTimer) clearTimeout(scrollTimer);
|
||||||
|
|
||||||
|
scrollTimer = setTimeout(() => {
|
||||||
|
isScrolling.value = false;
|
||||||
|
}, 200);
|
||||||
|
};
|
||||||
|
|
||||||
|
globalThis.addEventListener("scroll", handleScroll);
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
globalThis.removeEventListener("scroll", handleScroll);
|
||||||
|
if (scrollTimer) clearTimeout(scrollTimer);
|
||||||
|
};
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
class={`fixed bottom-4 left-1/2 transform -translate-x-1/2 z-20 transition-all duration-300 ${
|
||||||
|
isScrolling.value ? "opacity-30" : "opacity-100"
|
||||||
|
} ${isVisible.value ? "translate-y-0" : "translate-y-20"}`}
|
||||||
|
>
|
||||||
|
<ul class="menu menu-horizontal bg-base-200 rounded-box p-2 shadow-lg gap-2">
|
||||||
|
<li>
|
||||||
|
<a href="/" class={currentPath === "/" ? "menu-active" : ""}>
|
||||||
|
<div class="tooltip" data-tip="Home">
|
||||||
|
<LuHouse class="text-xl" />
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a
|
||||||
|
href="/posts"
|
||||||
|
class={isPostsPath(currentPath) ? "menu-active" : ""}
|
||||||
|
>
|
||||||
|
<div class="tooltip" data-tip="Posts">
|
||||||
|
<LuNotebookPen class="text-xl" />
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a
|
||||||
|
href="/projects"
|
||||||
|
class={currentPath.startsWith("/projects") ? "menu-active" : ""}
|
||||||
|
>
|
||||||
|
<div class="tooltip" data-tip="Projects">
|
||||||
|
<LuCodeXml class="text-xl" />
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
45
islands/ScrollUpButton.tsx
Normal file
45
islands/ScrollUpButton.tsx
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
import { useSignal } from "@preact/signals";
|
||||||
|
import { useEffect } from "preact/hooks";
|
||||||
|
import { LuArrowUp } from "@preact-icons/lu";
|
||||||
|
|
||||||
|
export default function ScrollUpButton() {
|
||||||
|
const isVisible = useSignal(false);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const checkScroll = () => {
|
||||||
|
isVisible.value = globalThis.scrollY > 300;
|
||||||
|
};
|
||||||
|
|
||||||
|
checkScroll();
|
||||||
|
|
||||||
|
globalThis.addEventListener("scroll", checkScroll);
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
globalThis.removeEventListener("scroll", checkScroll);
|
||||||
|
};
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const scrollToTop = () => {
|
||||||
|
globalThis.scrollTo({
|
||||||
|
top: 0,
|
||||||
|
behavior: "smooth",
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={scrollToTop}
|
||||||
|
class={`fixed bottom-20 right-4 z-20 bg-secondary hover:bg-primary
|
||||||
|
p-3 rounded-full shadow-lg transition-all duration-300
|
||||||
|
${
|
||||||
|
isVisible.value
|
||||||
|
? "opacity-70 translate-y-0"
|
||||||
|
: "opacity-0 translate-y-10 pointer-events-none"
|
||||||
|
}`}
|
||||||
|
aria-label="Scroll to top"
|
||||||
|
>
|
||||||
|
<LuArrowUp class="text-lg" />
|
||||||
|
</button>
|
||||||
|
);
|
||||||
|
}
|
|
@ -7,7 +7,7 @@ export default function App({ Component }: PageProps) {
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<title>Atridad Lahiji</title>
|
<title>Atridad Lahiji</title>
|
||||||
<link rel="stylesheet" href="/styles.css" />
|
<link rel="stylesheet" href="/styles.css" />
|
||||||
<link rel="icon" type="image/x-icon" href="favicon.ico"></link>
|
<link rel="icon" type="image/x-icon" href="/favicon.ico"></link>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<Component />
|
<Component />
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
// routes/_layout.tsx
|
|
||||||
import { PageProps } from "$fresh/server.ts";
|
import { PageProps } from "$fresh/server.ts";
|
||||||
import { Head } from "$fresh/runtime.ts";
|
import { Head } from "$fresh/runtime.ts";
|
||||||
import { LuCodeXml, LuHouse, LuNotebookPen } from "@preact-icons/lu";
|
import NavigationBar from "../islands/NavigationBar.tsx";
|
||||||
|
import ScrollUpButton from "../islands/ScrollUpButton.tsx";
|
||||||
|
|
||||||
export default function Layout({ Component, url }: PageProps) {
|
export default function Layout({ Component, url }: PageProps) {
|
||||||
const currentPath = url.pathname;
|
const currentPath = url.pathname;
|
||||||
|
@ -19,37 +19,8 @@ export default function Layout({ Component, url }: PageProps) {
|
||||||
<Component />
|
<Component />
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
<div class="fixed bottom-4 left-1/2 transform -translate-x-1/2 z-20">
|
<NavigationBar currentPath={currentPath} />
|
||||||
<ul class="menu menu-horizontal bg-base-200 rounded-box p-2 shadow-lg gap-2">
|
<ScrollUpButton />
|
||||||
<li>
|
|
||||||
<a href="/" class={currentPath === "/" ? "menu-active" : ""}>
|
|
||||||
<div class="tooltip" data-tip="Home">
|
|
||||||
<LuHouse class="text-xl" />
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<a
|
|
||||||
href="/posts"
|
|
||||||
class={currentPath.startsWith("/posts") ? "menu-active" : ""}
|
|
||||||
>
|
|
||||||
<div class="tooltip" data-tip="Posts">
|
|
||||||
<LuNotebookPen class="text-xl" />
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<a
|
|
||||||
href="/projects"
|
|
||||||
class={currentPath.startsWith("/projects") ? "menu-active" : ""}
|
|
||||||
>
|
|
||||||
<div class="tooltip" data-tip="Projects">
|
|
||||||
<LuCodeXml class="text-xl" />
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</body>
|
</body>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|
Loading…
Add table
Reference in a new issue