mirror of
https://github.com/DefectingCat/DefectingCat.github.io
synced 2025-07-16 09:11:38 +00:00
Add dark mode state to global state.
* update mobile menu icon dark color * update post page dark mode
This commit is contained in:
@ -5,6 +5,7 @@ import UseAnimations from 'react-useanimations';
|
|||||||
import menu3 from 'react-useanimations/lib/menu3';
|
import menu3 from 'react-useanimations/lib/menu3';
|
||||||
import { IconType } from 'react-icons';
|
import { IconType } from 'react-icons';
|
||||||
import dynamic from 'next/dynamic';
|
import dynamic from 'next/dynamic';
|
||||||
|
import useDarkMode from 'lib/hooks/useDarkMode';
|
||||||
|
|
||||||
const NavAvatar = dynamic(() => import('components/nav/NavAvatar'));
|
const NavAvatar = dynamic(() => import('components/nav/NavAvatar'));
|
||||||
const NavMenuItem = dynamic(() => import('components/nav/NavMenuItem'));
|
const NavMenuItem = dynamic(() => import('components/nav/NavMenuItem'));
|
||||||
@ -44,13 +45,15 @@ export const menus: MenuItem[] = [
|
|||||||
];
|
];
|
||||||
|
|
||||||
const NavBar: FC = () => {
|
const NavBar: FC = () => {
|
||||||
|
const { isDark } = useDarkMode();
|
||||||
|
|
||||||
const [menuIsOpen, setMenuIsOpen] = useState(false);
|
const [menuIsOpen, setMenuIsOpen] = useState(false);
|
||||||
const iconRef = useRef<HTMLDivElement>(null);
|
const iconRef = useRef<HTMLDivElement>(null);
|
||||||
const onToggle = useCallback(() => {
|
const onToggle = useCallback(() => {
|
||||||
setMenuIsOpen((menuIsOpen) => !menuIsOpen);
|
setMenuIsOpen((menuIsOpen) => !menuIsOpen);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
// Mobile menu icon must manually clicked to colse when click the menu item.
|
// Mobile menu icon must manually click to colse when click the menu item.
|
||||||
const handleMenuClick = useCallback(() => {
|
const handleMenuClick = useCallback(() => {
|
||||||
(iconRef.current?.children[0] as HTMLDivElement).click();
|
(iconRef.current?.children[0] as HTMLDivElement).click();
|
||||||
}, []);
|
}, []);
|
||||||
@ -68,6 +71,7 @@ const NavBar: FC = () => {
|
|||||||
animation={menu3}
|
animation={menu3}
|
||||||
speed={2}
|
speed={2}
|
||||||
onClick={onToggle}
|
onClick={onToggle}
|
||||||
|
strokeColor={isDark ? 'white' : 'black'}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -78,10 +82,11 @@ const NavBar: FC = () => {
|
|||||||
{ 'max-h-[500px]': menuIsOpen },
|
{ 'max-h-[500px]': menuIsOpen },
|
||||||
{ 'py-4': menuIsOpen },
|
{ 'py-4': menuIsOpen },
|
||||||
{ 'max-h-0': !menuIsOpen },
|
{ 'max-h-0': !menuIsOpen },
|
||||||
'bg-white mx-[-1.5rem] px-6 mt-4 overflow-hidden',
|
'bg-white mx-[-1.5rem] px-6 mt-4 overflow-hidden',
|
||||||
'md:block md:bg-transparent md:mx-0 md:p-0',
|
'md:block md:bg-transparent md:mx-0 md:p-0',
|
||||||
'transition-all duration-500 h-auto ',
|
'transition-all duration-500 h-auto ',
|
||||||
'md:max-h-max'
|
'md:max-h-max',
|
||||||
|
'dark:bg-rua-gray-800 md:dark:bg-transparent'
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
{menus.map((menu) => (
|
{menus.map((menu) => (
|
||||||
|
@ -14,7 +14,12 @@ interface Props {
|
|||||||
const PostHeader: FC<Props> = ({ title, tags, date }) => {
|
const PostHeader: FC<Props> = ({ title, tags, date }) => {
|
||||||
return (
|
return (
|
||||||
<header className={'mb-6'}>
|
<header className={'mb-6'}>
|
||||||
<h1 className={'text-3xl md:text-4xl font-semibold text-gray-700 mb-4'}>
|
<h1
|
||||||
|
className={cn(
|
||||||
|
'text-3xl md:text-4xl font-semibold mb-4',
|
||||||
|
'text-gray-700 dark:text-gray-300'
|
||||||
|
)}
|
||||||
|
>
|
||||||
{title}
|
{title}
|
||||||
</h1>
|
</h1>
|
||||||
|
|
||||||
@ -26,7 +31,7 @@ const PostHeader: FC<Props> = ({ title, tags, date }) => {
|
|||||||
key={item}
|
key={item}
|
||||||
className={cn(
|
className={cn(
|
||||||
'rounded-md bg-gray-100 px-2 py-1 inline text-sm',
|
'rounded-md bg-gray-100 px-2 py-1 inline text-sm',
|
||||||
'text-gray-700 mr-3'
|
'text-gray-700 mr-3 '
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
{item}
|
{item}
|
||||||
@ -37,7 +42,7 @@ const PostHeader: FC<Props> = ({ title, tags, date }) => {
|
|||||||
<div
|
<div
|
||||||
className={cn(
|
className={cn(
|
||||||
'rounded-md bg-gray-100 px-2 py-1 inline text-sm',
|
'rounded-md bg-gray-100 px-2 py-1 inline text-sm',
|
||||||
'text-gray-700'
|
'text-gray-700 dark:text-gray-300 dark:bg-gray-500'
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
{tags}
|
{tags}
|
||||||
@ -45,7 +50,9 @@ const PostHeader: FC<Props> = ({ title, tags, date }) => {
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className={'flex items-center text-gray-600 text-sm'}>
|
<div
|
||||||
|
className={'flex items-center text-gray-600 dark:text-gray-400 text-sm'}
|
||||||
|
>
|
||||||
<FiCalendar className={'mr-2'} />
|
<FiCalendar className={'mr-2'} />
|
||||||
<DateFormater dateString={date} />
|
<DateFormater dateString={date} />
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,20 +1,24 @@
|
|||||||
import { useEffect, useState } from 'react';
|
import { ActionKind, useRUAContext } from '../store';
|
||||||
|
|
||||||
const useDarkMode = () => {
|
const useDarkMode = () => {
|
||||||
const [isDark, setIsDark] = useState(false);
|
const { state, dispatch } = useRUAContext();
|
||||||
useEffect(() => {
|
const { isDark } = state;
|
||||||
setIsDark(document.documentElement.classList.contains('dark'));
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const toggleDark = () => {
|
const toggleDark = () => {
|
||||||
if (isDark) {
|
if (isDark) {
|
||||||
document.documentElement.classList.remove('dark');
|
document.documentElement.classList.remove('dark');
|
||||||
localStorage.setItem('rua-theme', 'light');
|
localStorage.setItem('rua-theme', 'light');
|
||||||
setIsDark(document.documentElement.classList.contains('dark'));
|
dispatch({
|
||||||
|
type: ActionKind.SETTHEME,
|
||||||
|
payload: '',
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
document.documentElement.classList.add('dark');
|
document.documentElement.classList.add('dark');
|
||||||
localStorage.setItem('rua-theme', 'dark');
|
localStorage.setItem('rua-theme', 'dark');
|
||||||
setIsDark(document.documentElement.classList.contains('dark'));
|
dispatch({
|
||||||
|
type: ActionKind.SETTHEME,
|
||||||
|
payload: '',
|
||||||
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
import React, { FC, useReducer } from 'react';
|
import React, { FC, useEffect, useReducer } from 'react';
|
||||||
|
|
||||||
export enum ActionKind {
|
export enum ActionKind {
|
||||||
SETQUERY = 'SETQUERY',
|
SETQUERY = 'SETQUERY',
|
||||||
SETPATH = 'SETPATH',
|
SETPATH = 'SETPATH',
|
||||||
|
SETTHEME = 'SETTHEME',
|
||||||
}
|
}
|
||||||
|
|
||||||
type ReducerAction = {
|
type ReducerAction = {
|
||||||
@ -21,11 +22,17 @@ type State = {
|
|||||||
* Back path to record where to go back.
|
* Back path to record where to go back.
|
||||||
*/
|
*/
|
||||||
backPath: string;
|
backPath: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Use document.documentElement.classList
|
||||||
|
*/
|
||||||
|
isDark: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
const initialState: State = {
|
const initialState: State = {
|
||||||
searchQuery: '',
|
searchQuery: '',
|
||||||
backPath: '',
|
backPath: '',
|
||||||
|
isDark: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
const reducer = (state: State, action: ReducerAction): State => {
|
const reducer = (state: State, action: ReducerAction): State => {
|
||||||
@ -35,6 +42,11 @@ const reducer = (state: State, action: ReducerAction): State => {
|
|||||||
return { ...state, searchQuery: payload };
|
return { ...state, searchQuery: payload };
|
||||||
case ActionKind.SETPATH:
|
case ActionKind.SETPATH:
|
||||||
return { ...state, backPath: payload };
|
return { ...state, backPath: payload };
|
||||||
|
case ActionKind.SETTHEME:
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
isDark: document.documentElement.classList.contains('dark'),
|
||||||
|
};
|
||||||
default:
|
default:
|
||||||
throw new Error();
|
throw new Error();
|
||||||
}
|
}
|
||||||
@ -51,6 +63,13 @@ const RUAContext = React.createContext<{
|
|||||||
const RUAStore: FC = ({ children }) => {
|
const RUAStore: FC = ({ children }) => {
|
||||||
const [state, dispatch] = useReducer(reducer, initialState);
|
const [state, dispatch] = useReducer(reducer, initialState);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
dispatch({
|
||||||
|
type: ActionKind.SETTHEME,
|
||||||
|
payload: '',
|
||||||
|
});
|
||||||
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<RUAContext.Provider value={{ state, dispatch }}>
|
<RUAContext.Provider value={{ state, dispatch }}>
|
||||||
|
@ -69,7 +69,7 @@ const Post = ({ postData }: InferGetStaticPropsType<typeof getStaticProps>) => {
|
|||||||
|
|
||||||
<div
|
<div
|
||||||
className={cn(
|
className={cn(
|
||||||
'grid grid-cols-12 gap-4 p-2 container mx-auto',
|
'grid grid-cols-12 gap-4 px-2 py-4 container mx-auto',
|
||||||
'md:py-8'
|
'md:py-8'
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
@ -97,7 +97,11 @@ const Post = ({ postData }: InferGetStaticPropsType<typeof getStaticProps>) => {
|
|||||||
</aside>
|
</aside>
|
||||||
|
|
||||||
<main className={'md:col-span-10 col-span-12 lg:col-span-8'}>
|
<main className={'md:col-span-10 col-span-12 lg:col-span-8'}>
|
||||||
<div className={'bg-white shadow-md rounded-lg overflow-hidden'}>
|
<div
|
||||||
|
className={
|
||||||
|
'bg-white dark:bg-rua-gray-800 shadow-md rounded-lg overflow-hidden'
|
||||||
|
}
|
||||||
|
>
|
||||||
{index_img && (
|
{index_img && (
|
||||||
<div className="relative aspect-video">
|
<div className="relative aspect-video">
|
||||||
<Image
|
<Image
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
#write {
|
#write {
|
||||||
@apply text-gray-600;
|
@apply text-gray-600 dark:text-gray-300;
|
||||||
}
|
}
|
||||||
|
|
||||||
#table-of-contents {
|
#table-of-contents {
|
||||||
@ -247,7 +247,7 @@
|
|||||||
|
|
||||||
#write code,
|
#write code,
|
||||||
#write tt {
|
#write tt {
|
||||||
@apply bg-gray-100 rounded-md;
|
@apply bg-gray-100 dark:bg-gray-500 rounded-md;
|
||||||
padding: 0 4px;
|
padding: 0 4px;
|
||||||
font-size: 0.9em;
|
font-size: 0.9em;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user