Skip to content
30 changes: 30 additions & 0 deletions app/entities/common/Button/IconButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { IconType } from 'react-icons';

interface IconButtonProps {
Icon: IconType;
text?: string;
size?: number;
className?: string;
onClick?: () => void;
}

const IconButton = ({
Icon,
text,
size,
className,
onClick,
}: IconButtonProps) => {
return (
<button
onClick={onClick}
className={
className || 'p-4 fill-current hover:bg-gray-200/50 rounded-md'
}
>
<Icon size={size || 20} />
{text && <span>{text}</span>}
</button>
);
};
export default IconButton;
18 changes: 17 additions & 1 deletion app/entities/common/NavBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,13 @@ import { useEffect, useState } from 'react';
import Profile from '@/app/entities/common/Profile';

import profile from '@/app/public/profile.jpg';
import IconButton from '@/app/entities/common/Button/IconButton';
import { FaRegMoon, FaRegSun } from 'react-icons/fa';
import useTheme from '@/app/hooks/useTheme';
import { IoMoonSharp, IoSunny, IoSunnySharp } from 'react-icons/io5';
const NavBar = () => {
const [isFixed, setIsFixed] = useState(false);
const { theme, toggleTheme } = useTheme();

useEffect(() => {
const handleScroll = () => {
Expand Down Expand Up @@ -36,7 +41,11 @@ const NavBar = () => {
<Profile profileThumbnail={profile} username={'Jeongwoo Seo'} />
</Link>
</div>
<ul className={'inline-flex max-w-5xl w-full justify-end gap-6 '}>
<ul
className={
'inline-flex max-w-5xl w-full justify-end gap-4 items-center'
}
>
<li>
<Link href="/posts">Blog</Link>
</li>
Expand All @@ -46,6 +55,13 @@ const NavBar = () => {
<li>
<Link href="/portfolio">Portfolio</Link>
</li>
<li>
<IconButton
onClick={toggleTheme}
Icon={theme === 'light' ? IoSunnySharp : IoMoonSharp}
size={20}
/>
</li>
</ul>
</div>
</nav>
Expand Down
4 changes: 3 additions & 1 deletion app/entities/post/detail/PostBody.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,15 @@
import LoadingIndicator from '@/app/entities/common/Loading/LoadingIndicator';
import MDEditor from '@uiw/react-md-editor';
import PostTOC from '@/app/entities/post/detail/PostTOC';
import useTheme from '@/app/hooks/useTheme';

interface Props {
content: string;
loading?: boolean;
}

const PostBody = ({ content, loading }: Props) => {
const { theme } = useTheme();
return (
<div
className={'max-w-full post-body px-4 py-16 min-h-[500px] relative '}
Expand All @@ -27,7 +29,7 @@ const PostBody = ({ content, loading }: Props) => {
className={''}
source={content}
wrapperElement={{
'data-color-mode': 'dark',
'data-color-mode': theme,
}}
/>
<PostTOC postContent={content || ''} />
Expand Down
2 changes: 1 addition & 1 deletion app/entities/post/detail/PostHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ const PostHeader = ({
return (
<div
className={
'post-header h-[220px] md:h-[292px] relative overflow-hidden w-full text-center bg-gray-400/50'
'post-header h-[220px] md:h-[292px] relative overflow-hidden w-full text-center bg-gray-400/40 text-white'
}
>
<h1 className={'font-bold mb-4 pt-10 md:pt-20 text-3xl md:text-5xl '}>
Expand Down
2 changes: 1 addition & 1 deletion app/entities/post/detail/PostTOC.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ const PostTOC = ({ postContent }: { postContent: string }) => {
};

return (
<div className="fixed post-toc hidden 2xl:block w-[280px] top-[calc(50%+100px)] -translate-y-1/2 left-[calc(50%+524px)] transition-all text-sm bg-gray-100/80 rounded-md p-4 text-black">
<div className="absolute post-toc hidden 2xl:block w-[280px] top-20 left-full ml-16 transition-all text-sm bg-gray-100/80 rounded-md p-4 text-black">
<h4 className={'text-xl font-bold mb-2'}>📌 Table of Contents</h4>
<ul className={'list-none'}>
{parseHeadings(postContent).map((heading) => {
Expand Down
21 changes: 21 additions & 0 deletions app/hooks/useTheme.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import useThemeStore from '@/app/stores/useThemeStore';
import { useEffect } from 'react';

const useTheme = () => {
const { theme, setTheme } = useThemeStore();
const toggleTheme = () => {
setTheme(theme === 'light' ? 'dark' : 'light');
};

useEffect(() => {
if (theme === 'dark') {
document.body.classList.add('dark');
} else {
document.body.classList.remove('dark');
}
}, [theme]);

return { theme, toggleTheme };
};

export default useTheme;
10 changes: 5 additions & 5 deletions app/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ export default function Home() {
Frontend Developer
</h1>
</div>
<p className="text-lg text-gray-200 max-w-2xl">
<p className="text-lg text-default max-w-2xl">
안녕하세요, 서정우입니다. 사용자 경험과 깔끔한 코드 작성에 중점을 두고
있으며, 멈추지 않는 기술의 변화를 즐깁니다.
</p>
Expand All @@ -60,22 +60,22 @@ export default function Home() {
</div>
<div className="grid gap-4">
<h2 className="text-2xl font-semibold">About Me</h2>
<p className="text-gray-200">
<p className="text-default">
프론트엔드 개발자로서 React, Next.js, TypeScript를 주로 사용합니다.
항상 사용자 입장에서 생각하고, 성능 최적화에 관심이 많으며, 지속적인
학습과 성장을 추구합니다.
</p>
<div className="flex gap-4">
<a href={'https://github.com/ShipFriend0516'} target={'_blank'}>
<FaGithub className="w-5 h-5 text-gray-200 hover:text-gray-100 hover:scale-125 transition cursor-pointer" />
<FaGithub className="w-5 h-5 text-default hover:text-gray-100 hover:scale-125 transition cursor-pointer" />
</a>
<a
href={
'https://www.linkedin.com/in/%EC%A0%95%EC%9A%B0-%EC%84%9C-9a0b79312/'
}
target={'_blank'}
>
<FaLinkedin className="w-5 h-5 text-gray-200 hover:text-gray-100 hover:scale-125 transition cursor-pointer" />
<FaLinkedin className="w-5 h-5 text-default hover:text-gray-100 hover:scale-125 transition cursor-pointer" />
</a>
</div>
</div>
Expand Down Expand Up @@ -107,7 +107,7 @@ export default function Home() {
/>
</div>
<h3 className="font-medium mb-2">{post.title}</h3>
<p className="text-sm text-gray-200">
<p className="text-sm text-default">
{post.subTitle && post.subTitle.slice(0, 80)}
</p>
</Link>
Expand Down
23 changes: 23 additions & 0 deletions app/stores/useThemeStore.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { create } from 'zustand';
import { persist } from 'zustand/middleware';

type Theme = 'light' | 'dark';

interface ThemeState {
theme: 'light' | 'dark';
setTheme: (theme: Theme) => void;
}

const useThemeStore = create(
persist<ThemeState>(
(set) => ({
theme: 'dark',
setTheme: (theme: Theme) => set({ theme }),
}),
{
name: 'theme-storage',
}
)
);

export default useThemeStore;
Loading