diff --git a/frontend/app/blog/BlogPostCard.tsx b/frontend/app/blog/BlogPostCard.tsx index 49247e9..3829fd2 100644 --- a/frontend/app/blog/BlogPostCard.tsx +++ b/frontend/app/blog/BlogPostCard.tsx @@ -33,19 +33,23 @@ function BlogPostCard({ post }: Props) { { + { }
-
- + { category }

{ title }

{ sub_title }

@@ -54,13 +58,7 @@ function BlogPostCard({ post }: Props) {
- {/* */ } - - +
    diff --git a/frontend/app/blog/Pagination.tsx b/frontend/app/blog/Pagination.tsx index 6b53dac..c3b8033 100644 --- a/frontend/app/blog/Pagination.tsx +++ b/frontend/app/blog/Pagination.tsx @@ -1,8 +1,9 @@ 'use client'; -import React, { useEffect, useState } from 'react'; +import React from 'react'; import { Pagination as NextUIPagination } from '@nextui-org/react'; import { useRouter, useSearchParams } from 'next/navigation'; +import { useScreenSizeTrigger } from '@/app/public/screenSizeTrigger'; const Pagination = ({ total }: { total: number, @@ -12,23 +13,7 @@ const Pagination = ({ total }: { const router = useRouter(); - const maxMobileWidth: number = 768; - const [ isMobile, setIsMobile ] = useState(false); - useEffect(() => { - const updateMobileWidth = () => { - if (window.innerWidth <= maxMobileWidth) { - setIsMobile(true); - } else { - setIsMobile(false); - } - }; - updateMobileWidth(); - window.addEventListener('resize', updateMobileWidth); - return () => { - window.removeEventListener('resize', updateMobileWidth); - }; - - }, []); + const isMobile = useScreenSizeTrigger('md'); return (
    diff --git a/frontend/app/blog/post/[id]/Footer.tsx b/frontend/app/blog/post/[id]/Footer.tsx index ecc02d5..3c71bc2 100644 --- a/frontend/app/blog/post/[id]/Footer.tsx +++ b/frontend/app/blog/post/[id]/Footer.tsx @@ -25,7 +25,14 @@ const Footer = (props: Props) => {
    -
    +
    +
    + +
    +

    { post['meta']['title'] }

    @@ -63,8 +70,6 @@ const Footer = (props: Props) => {
    -
    diff --git a/frontend/app/blog/post/[id]/Headers.tsx b/frontend/app/blog/post/[id]/Headers.tsx index 48c9b9e..cb44322 100644 --- a/frontend/app/blog/post/[id]/Headers.tsx +++ b/frontend/app/blog/post/[id]/Headers.tsx @@ -42,7 +42,7 @@ const Headers = (props: Props) => { 'mx-8 -mt-16 backdrop-blur transition bg-zinc-300/80 dark:bg-gray-600/25 rounded-2xl z-30' : 'mx-6 mt-6' }> -
    +
    { category }

    { title }

    diff --git a/frontend/app/layout.tsx b/frontend/app/layout.tsx index 699c751..3e71f6c 100644 --- a/frontend/app/layout.tsx +++ b/frontend/app/layout.tsx @@ -7,8 +7,8 @@ import Footer from '@/components/Footer'; export const metadata: Metadata = { - title: 'Lumither\'s site', - description: 'a small corner on internet' + title: 'Lumitherの酒馆', + description: '一间位于时间夹缝中的旅馆,静候下一位旅者的到来...' }; export default function RootLayout({ @@ -19,7 +19,7 @@ export default function RootLayout({ return ( - +
    diff --git a/frontend/app/public/screenSizeTrigger.ts b/frontend/app/public/screenSizeTrigger.ts new file mode 100644 index 0000000..7a25074 --- /dev/null +++ b/frontend/app/public/screenSizeTrigger.ts @@ -0,0 +1,35 @@ +import { useEffect, useState } from 'react'; + +const screenSize = new Map( + [ + [ 'sm', 640 ], + [ 'md', 768 ], + [ 'lg', 1024 ], + [ 'xl', 1280 ], + [ '2xl', 2536 ] + ] +); + +export const useScreenSizeTrigger = (size: number | string) => { + const criticalSize = (typeof size === 'string') ? (screenSize.get(size) ?? 768) : size; + + const [ isCritical, setIsCritical ] = useState(false); + useEffect(() => { + const updateMobileWidth = () => { + if (window.innerWidth < criticalSize) { + setIsCritical(true); + } else { + setIsCritical(false); + } + }; + updateMobileWidth(); + window.addEventListener('resize', updateMobileWidth); + return () => { + window.removeEventListener('resize', updateMobileWidth); + }; + + }); + + return isCritical; + +}; diff --git a/frontend/components/Navbar.tsx b/frontend/components/Navbar.tsx index a310640..b0381b0 100644 --- a/frontend/components/Navbar.tsx +++ b/frontend/components/Navbar.tsx @@ -2,11 +2,12 @@ import React, { useEffect, useState } from 'react'; import { Button } from '@nextui-org/react'; -import NextImage from 'next/image'; +import Image from 'next/image'; import { IoHome, IoInformationCircle, IoLink, IoLogoGithub, IoMail, IoPencil, IoSearch } from 'react-icons/io5'; import Link from 'next/link'; import ThemeSwitcher from '@/components/ThemeSwitcher'; import { usePathname } from 'next/navigation'; +import { useScreenSizeTrigger } from '@/app/public/screenSizeTrigger'; const entries: { display_name: string; href: string; icon: React.ReactNode }[] = [ { @@ -50,17 +51,17 @@ const connections: { label: string, href: string, icon: React.ReactNode }[] = [ ]; function Navbar() { - const [ scrolled, setScrolled ] = useState(false); - useEffect(() => { - const handleScroll = () => { - const isScrolled = window.scrollY > 0; - setScrolled(isScrolled); - }; - window.addEventListener('scroll', handleScroll); - return () => { - window.removeEventListener('scroll', handleScroll); - }; - }, []); + // const [ scrolled, setScrolled ] = useState(false); + // useEffect(() => { + // const handleScroll = () => { + // const isScrolled = window.scrollY > 0; + // setScrolled(isScrolled); + // }; + // window.addEventListener('scroll', handleScroll); + // return () => { + // window.removeEventListener('scroll', handleScroll); + // }; + // }, []); const path = usePathname(); @@ -74,41 +75,24 @@ function Navbar() { } }, [ path ]); - - const maxMobileWidth: number = 1024; - const [ isMobile, setIsMobile ] = useState(false); - useEffect(() => { - const updateMobileWidth = () => { - if (window.innerWidth <= maxMobileWidth) { - setIsMobile(true); - } else { - setIsMobile(false); - } - }; - updateMobileWidth(); - window.addEventListener('resize', updateMobileWidth); - return () => { - window.removeEventListener('resize', updateMobileWidth); - }; - - }, []); - + const isMobile = useScreenSizeTrigger('lg'); return ( <>
    + className={ `flex flex-col min-w-[50px] lg:min-w-[200px] ml-2 mr-0 lg:ml-8 lg:mr-6 min-h-screen pt-8 sticky` }>
    -
    - +
    +
    + { +
    @@ -153,7 +137,8 @@ function Navbar() { isIconOnly={ isMobile } className={ 'flex lg:justify-start w-fit lg:w-full' } aria-label={ `navbar: ${ meta.display_name }` } - href={ meta.href }> + href={ meta.href } + > { meta.icon } @@ -170,7 +155,7 @@ function Navbar() {
    diff --git a/frontend/components/ThemeSwitcher.tsx b/frontend/components/ThemeSwitcher.tsx index eda2c48..07f6f15 100644 --- a/frontend/components/ThemeSwitcher.tsx +++ b/frontend/components/ThemeSwitcher.tsx @@ -2,12 +2,34 @@ import React, { useEffect, useState } from 'react'; import { useTheme } from 'next-themes'; -import { Switch } from '@nextui-org/react'; -import { MdOutlineDarkMode, MdOutlineLightMode } from 'react-icons/md'; +import { Button, Dropdown, DropdownItem, DropdownMenu, DropdownTrigger } from '@nextui-org/react'; +import { MdOutlineDarkMode, MdOutlineDesktopWindows, MdOutlineLightMode } from 'react-icons/md'; +import { useScreenSizeTrigger } from '@/app/public/screenSizeTrigger'; + +const switcherElements = new Map( + [ + [ 'dark', { + 'display_name': 'Dark Mode', + 'icon': + } ], + [ 'light', { + 'display_name': 'Light Mode', + 'icon': + } ], + [ 'system', { + 'display_name': 'Follow System', + 'icon': + } ] + ] +); function ThemeSwitcher() { const [ mounted, setMounted ] = useState(false); - const { setTheme } = useTheme(); + const { theme, setTheme } = useTheme(); + + const [ currTheme, setCurrTheme ] = useState(new Set([ theme as string ])); + + const isMobile = useScreenSizeTrigger('lg'); useEffect(() => { setMounted(true); @@ -19,22 +41,51 @@ function ThemeSwitcher() { return (
    -
    - } - endContent={ } - onValueChange={ (isSelected) => { - if (isSelected) { - setTheme('light'); - } else { - setTheme('dark'); - } + + + + + + { + setCurrTheme(new Set([ anchorKey as string ])); + setTheme(anchorKey as string); } } - > - -
    + + > + }> + Light Mode + + } + > + Dark Mode + + } + > + Follow System + + +
    ); }