Skip to content

Commit 4918222

Browse files
committed
feat: implement ScrollToTop component and update layout and fix README categories typo
1 parent 5c26b9f commit 4918222

6 files changed

Lines changed: 57 additions & 17 deletions

File tree

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ bun dev
3232
- [x] Add Header navigation
3333
- [x] Add posts reading time
3434
- [x] Add Mobile responsive
35-
- [x] Add categories / tags
35+
- [x] Add categories / tag
3636
- [ ] Add search
3737
- [ ] Add comment system
3838
- [x] Add dark mode

app/components/NavBar.tsx

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,21 +5,9 @@ import Image from "next/image";
55
import { ThemeToggle } from "./ThemeToggle";
66

77
const NavBar = () => {
8-
const toTop = () => {
9-
return window.scrollTo({ top: 0, behavior: 'smooth' })
10-
}
11-
128
return (
139
<header>
1410
<Link href="/" className="absolute"><Image src="/logo.png" width={32} height={32} alt="logo" /></Link>
15-
<button title="scroll to top"
16-
className="fixed bottom-8 right-8 rounded-full p-1 shadow-lg shadow-zinc-950/50 hover:bg-zinc-800 transition-colors duration-200"
17-
onClick={toTop}
18-
>
19-
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth={1.5} stroke="currentColor" className="w-10 h-10">
20-
<path strokeLinecap="round" strokeLinejoin="round" d="M15 11.25l-3-3-3 3" />
21-
</svg>
22-
</button>
2311
<nav className="grid grid-cols-[auto_max-content] gap-4 w-full py-2">
2412
<div></div>
2513
<div className="grid grid-cols-[repeat(7,auto)] gap-4">

app/components/ScrollToTop.tsx

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
"use client"
2+
3+
import { useEffect, useState } from "react";
4+
5+
function ScrollToTop() {
6+
const [showToTop, setShowToTop] = useState(false);
7+
8+
const toTop = () => {
9+
return window.scrollTo({ top: 0, behavior: 'smooth' })
10+
}
11+
12+
useEffect(() => {
13+
const checkScrollable = () => document.documentElement.scrollHeight > window.innerHeight;
14+
const onScroll = () => {
15+
const scrolledDown = window.scrollY > 100; // only show after user scrolled a bit
16+
setShowToTop(checkScrollable() && scrolledDown);
17+
};
18+
const onResize = () => {
19+
if (!checkScrollable()) setShowToTop(false);
20+
else onScroll();
21+
};
22+
23+
window.addEventListener('scroll', onScroll);
24+
window.addEventListener('resize', onResize);
25+
// initial check
26+
onResize();
27+
28+
return () => {
29+
window.removeEventListener('scroll', onScroll);
30+
window.removeEventListener('resize', onResize);
31+
};
32+
}, []);
33+
34+
return (
35+
<>
36+
{showToTop && (
37+
<button title="scroll to top"
38+
className="fixed bottom-8 right-8 rounded-full p-1 shadow-lg hover:cursor-pointer hover:bg-zinc-100 dark:hover:bg-zinc-800 transition-colors duration-200"
39+
onClick={toTop}
40+
>
41+
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth={1.5} stroke="currentColor" className="w-10 h-10">
42+
<path strokeLinecap="round" strokeLinejoin="round" d="M15 11.25l-3-3-3 3" />
43+
</svg>
44+
</button>
45+
)}
46+
</>
47+
)
48+
}
49+
50+
export { ScrollToTop }

app/layout.tsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { Analytics } from "@vercel/analytics/next";
44
import { SpeedInsights } from "@vercel/speed-insights/next";
55
import "./globals.css";
66
import { NavBar } from "./components/NavBar";
7+
import { ScrollToTop } from "./components/ScrollToTop";
78

89
const geistSans = Geist({
910
variable: "--font-geist-sans",
@@ -20,11 +21,11 @@ export const metadata: Metadata = {
2021
default: "杨金 (Yang Jin)",
2122
template: "%s | Yang Jin",
2223
},
23-
description: "杨金的个人博客,分享关于生活、技术和阅读的见解 | Yang Jin's personal blog, sharing insights on life, technology, and reading.",
24+
description: "杨金的个人博客,分享生活、技术和阅读 | Yang Jin's personal blog, sharing insights on life, technology, and reading.",
2425
keywords: ["杨金", "Yang Jin", "前端工程师", "个人博客", "技术分享", "Front-end Engineer", "Personal Blog", "Technology"],
2526
openGraph: {
2627
title: "杨金 (Yang Jin)'s Blog",
27-
description: "杨金的个人博客,分享关于生活、技术和阅读的见解 | Yang Jin's personal blog, sharing insights on life, technology, and reading.",
28+
description: "杨金的个人博客,分享生活、技术和阅读 | Yang Jin's personal blog, sharing insights on life, technology, and reading.",
2829
url: "https://yangjin.dev",
2930
siteName: "杨金 (Yang Jin)'s Blog",
3031
images: [
@@ -98,6 +99,7 @@ function Footer() {
9899
</a>
99100
))}
100101
</div>
102+
<ScrollToTop />
101103
</footer>
102104
);
103105
}

app/page.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<img src="/avatar.jpg" className='mt-10 rounded-full' alt="avatar" width={50} height={50}/>
22

3-
### Yang Jin
3+
### About Me
44
This is my portfolio, blog, and personal website where I share insights about life, technology, and reading.
55

66
👋 Hello! I'm Yang Jin(杨金), a front-end engineer based in Shenzhen. I'm excited to share my professional journey and experiences here. Currently, I work on the TikTok Ads Interface team.

app/posts/think/elon-musk/page.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
export const metadata = {
22
title: '🚀 《埃隆·马斯克传》阅读笔记',
33
description: '《埃隆·马斯克传》是《乔布斯传》作者沃尔特·艾萨克森的新作,记录了马斯克在电动车、太空、AI、能源等领域的多线作战。',
4-
tags: ['思考', '马斯克', '阅读笔记'],
4+
tag: ['思考', '马斯克', '阅读笔记'],
55
date: '2025-10-17',
66
duration: '10 min',
77
}

0 commit comments

Comments
 (0)