Skip to content

Commit 943a37d

Browse files
authored
Merge pull request #34 from thedevdavid/feature/back-to-top
feat: added back to top component
2 parents 395405a + 194216d commit 943a37d

File tree

4 files changed

+54
-1
lines changed

4 files changed

+54
-1
lines changed

CHANGELOG.md

+4
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased]
99

10+
### Added
11+
12+
- Back to top button
13+
1014
## [0.5.0] - 2023-07-06
1115

1216
### Added

README.md

+4-1
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,7 @@ Note: DO NOT overdo it. You can easily make images look bad with lossy compressi
171171
- [x] Not found page
172172
- [x] contributing docs
173173
- [x] Docs refresh
174+
- [x] Back to top button
174175
- [ ] Social sharing buttons
175176
- [ ] newsletter integration (form, api route, keys, welcome page, previous issues)
176177
- [ ] Other analytics providers (fathom, simplelytics, plausible, etc)
@@ -183,7 +184,9 @@ Note: DO NOT overdo it. You can easily make images look bad with lossy compressi
183184
- [ ] Code preview component
184185
- [ ] Code highlight improvements (copy code, theme)
185186
- [ ] `manifest.json`
186-
- [ ] Hidden content (behind email subscription)
187+
- [ ] Rich project cards
188+
- [ ] CV template
189+
- [ ] Authenticated pages and/or hidden content (behind email address)
187190
- [ ] 100 lighthouse score
188191
- [ ] Command bar fuzzy search in content
189192
- [ ] Pagination

app/layout.tsx

+2
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { Inter, Space_Grotesk } from "next/font/google";
55
import siteMetadata from "@/lib/metadata";
66
import { Toaster } from "@/components/ui/toaster";
77
import { Analytics } from "@/components/analytics";
8+
import { BackTopButton } from "@/components/back-to-top";
89
import { ThemeProvider } from "@/components/theme-provider";
910

1011
const spaceGrotesk = Space_Grotesk({
@@ -30,6 +31,7 @@ export default function RootLayout({ children }: RootLayoutProps) {
3031
<body className="min-h-screen bg-gradient-to-b from-slate-100 to-white text-slate-900 antialiased dark:bg-gradient-to-b dark:from-gray-900 dark:to-gray-800 dark:text-slate-50">
3132
<ThemeProvider attribute="class" defaultTheme="system" enableSystem>
3233
{children}
34+
<BackTopButton />
3335
<Toaster />
3436
</ThemeProvider>
3537
</body>

components/back-to-top.tsx

+44
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
"use client";
2+
3+
import { useEffect, useState } from "react";
4+
import { ArrowUp } from "lucide-react";
5+
6+
import { cn } from "@/lib/utils";
7+
import { Button } from "@/components/ui/button";
8+
9+
const SCROLL_OFFSET: number = 1550;
10+
11+
export const BackTopButton = () => {
12+
let [show, setShow] = useState(false);
13+
14+
const handleClick = (e: React.MouseEvent<HTMLButtonElement, MouseEvent>) => {
15+
e.preventDefault();
16+
window.scrollTo({
17+
top: 0,
18+
behavior: "smooth",
19+
});
20+
};
21+
22+
useEffect(() => {
23+
let handleWindowScroll = () => {
24+
if (window.scrollY > SCROLL_OFFSET) setShow(true);
25+
else setShow(false);
26+
};
27+
28+
window.addEventListener("scroll", handleWindowScroll);
29+
return () => window.removeEventListener("scroll", handleWindowScroll);
30+
}, []);
31+
32+
return (
33+
<Button
34+
variant="default"
35+
size="icon"
36+
aria-label="Scroll To Top"
37+
type="button"
38+
onClick={handleClick}
39+
className={cn(show ? "flex" : "hidden", "fixed bottom-8 right-8 z-50")}
40+
>
41+
<ArrowUp />
42+
</Button>
43+
);
44+
};

0 commit comments

Comments
 (0)