Skip to content

Commit

Permalink
Navigation 사용성 개선 및 부가 기능 추가 (#191)
Browse files Browse the repository at this point in the history
* refactor(NavigationLink): separate data and views

* feat: refactor NavigationBar

* feat: create PostTitle on NavigationBar

* fix: content id duplication issues

* fix: google font error
  • Loading branch information
loopy-dev committed Jul 18, 2023
1 parent c422c5a commit 1272ecd
Show file tree
Hide file tree
Showing 7 changed files with 200 additions and 73 deletions.
222 changes: 168 additions & 54 deletions src/components/NavigationBar/NavigationBar.tsx
Original file line number Diff line number Diff line change
@@ -1,24 +1,16 @@
import { useState } from 'react';
import React, { useEffect, useState } from 'react';
import classNames from 'classnames';
import dynamic from 'next/dynamic';
import { Noto_Sans_KR } from 'next/font/google';
import Link from 'next/link';
import { useRouter } from 'next/router';
import { FaGithub } from 'react-icons/fa';
import Icon from '../icons';
import { Item } from './Item';
import styles from './NavigationBar.module.scss';

const ThemeToggleButton = dynamic(() => import('./ThemeToggleButton'), {
ssr: false,
});

const notoSans = Noto_Sans_KR({
weight: '500',
style: ['normal'],
subsets: ['latin'],
});

// TODO - show floating menu button when display size is under sm
const NavigationBar = () => {
const [isOpen, setIsOpen] = useState(false);
Expand Down Expand Up @@ -55,30 +47,10 @@ const NavigationBar = () => {
'mx-auto'
)}
>
<div
className={classNames(
'left',
'flex',
'items-center',
'gap-2',
'sm:gap-0'
)}
>
<Link
className={classNames(notoSans.className, styles.title)}
href="/"
>
BenLog
</Link>
</div>
<div className={classNames('hidden', 'sm:flex')}>
<ThemeToggleButton />
<NavigationLinks />
</div>
<div className={classNames('flex', 'sm:hidden')}>
<ThemeToggleButton />
<Icon type="hamburger" onClick={toggleHamburgerIcon} />
</div>
<Left />
<Middle />
<Right />
<Hidden onClick={toggleHamburgerIcon} />
</div>
{/** hidden part of NavigationBar */}
{isOpen ? (
Expand All @@ -92,32 +64,174 @@ const NavigationBar = () => {

export default NavigationBar;

const NavigationLinks = () => {
const Left = () => {
return (
<div
className={classNames(
'left',
'flex',
'items-center',
'gap-2',
'sm:gap-0'
)}
>
<Logo />
</div>
);
};

const Logo = () => {
return (
<Link
className={classNames(styles.title)}
href="/"
style={{ fontFamily: 'Noto Sans KR' }}
>
BenLog
</Link>
);
};

const Right = () => {
return (
<div className={classNames('hidden', 'sm:flex')}>
<ThemeToggleButton />
<NavigationLinks />
</div>
);
};

const Middle = () => {
const router = useRouter();
const [isShowing, setIsShowing] = useState(false);
const [postTitle, setPostTitle] = useState('');

useEffect(() => {
const isPostPath = getSubDomain(router.pathname) === 'posts';
setIsShowing(isPostPath);
}, [router.pathname]);

useEffect(() => {
const handler = () => {
const title = document.querySelector('.post-title');

if (!title) return;

setPostTitle(title.textContent || '');
};

handler();

router.events.on('routeChangeComplete', handler);

return () => {
router.events.off('routeChangeComplete', handler);
};
}, [router.events]);

return (
<>
<Link
className={classNames('w-full', 'text-center', 'flex', 'items-center')}
href="/posts"
>
<Item current={getSubDomain(router.pathname) === 'posts'}>Posts</Item>
</Link>
<Link
className={classNames('w-full', 'text-center', 'flex', 'items-center')}
href="/about"
>
<Item current={getSubDomain(router.pathname) === 'posts'}>About</Item>
</Link>
<div
className={classNames(
'hidden',
'md:flex',
'flex-col',
'justify-center',
'items-center',
'w-full',
'text-center'
)}
>
{postTitle}
</div>
);
};

interface HiddenComponentProps {
onClick?: React.MouseEventHandler<HTMLDivElement>;
}

const Hidden = ({ onClick }: HiddenComponentProps) => {
return (
<div className={classNames('flex', 'sm:hidden')}>
<ThemeToggleButton />
<Icon type="hamburger" onClick={onClick} />
</div>
);
};

interface NavigationLinkProps {
href: string;
children?: React.ReactNode;
}

const getPathname = (href: string) => {
if (href[0] !== '/') {
return href;
}

return href.slice(1);
};

const NavigationLink = ({ href, children }: NavigationLinkProps) => {
const router = useRouter();
const pathname = getPathname(href);
const isExternalLink = href === pathname;

return (
<li className={classNames('w-full', 'text-center', 'flex', 'items-center')}>
<Link
className={classNames('w-full', 'text-center', 'flex', 'items-center')}
href="https://github.com/mrbartrns"
rel="noopener noreferrer"
target="_blank"
href={href}
rel={isExternalLink ? 'noopener noreferrer' : undefined}
target={isExternalLink ? '_blank' : undefined}
title={typeof children === 'string' ? children : pathname}
className={classNames(
'flex',
'justify-center',
'items-center',
'w-full',
'select-none',
'transition-all',
'py-1',
'px-2',
'font-medium',
'text-zinc-600',
'dark:text-zinc-300',
{
'text-zinc-800': getSubDomain(router.pathname) === pathname,
'dark:text-zinc-100': getSubDomain(router.pathname) === pathname,
},
'hover:text-zinc-800',
'dark:hover:text-zinc-100'
)}
>
<Item>
<FaGithub className={classNames('text-xl')} />
</Item>
{children}
</Link>
</li>
);
};

const NavigationLinks = () => {
const links = [
{
href: '/posts',
children: 'Posts',
},
{
href: '/about',
children: 'About',
},
{
href: 'https://github.com/mrbartrns',
children: <FaGithub className={classNames('text-xl')} />,
},
];
return (
<>
{links.map((link) => (
<NavigationLink key={link.href} href={link.href}>
{link.children}
</NavigationLink>
))}
</>
);
};
Expand Down
23 changes: 20 additions & 3 deletions src/components/NavigationBar/ThemeToggleButton.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,33 @@
import classNames from 'classnames';
import { MdOutlineLightMode, MdOutlineDarkMode } from 'react-icons/md';
import useTheme from '~/lib/styles/useTheme';
import { Item } from './Item';
import type { Theme } from '~/lib/styles/types';

const ThemeToggleButton = () => {
const [theme, toggle] = useTheme();

return (
<Item onClick={toggle}>
<div
className={classNames(
'flex',
'justify-center',
'items-center',
'w-full',
'select-none',
'transition-all',
'cursor-pointer',
'font-medium',
'py-1',
'px-2',
'dark:text-zinc-300',
'dark:hover:text-zinc-100',
'text-zinc-600',
'hover:text-zinc-800'
)}
onClick={toggle}
>
<ThemeToggleIcon theme={theme} />
</Item>
</div>
);
};

Expand Down
4 changes: 2 additions & 2 deletions src/components/Post/PostDetail/PostAside.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ const PostAside = () => {
<ul className={classNames('w-full', 'text-[color:var(--primary-variant)]')}>
{heads.map((head) => (
<li
key={head.textContent}
key={`${head.textContent}-${head.dataset.index}`}
className={classNames('text-[90%]', 'leading-[1.7]', {
'font-bold': activeIndex === Number(head.dataset.index),
})}
Expand All @@ -70,7 +70,7 @@ const PostAside = () => {
>
<a
className={classNames('hover:underline')}
href={`#${setElementId(head.textContent)}`}
href={`#${setElementId(head.textContent)}-${head.dataset.index}`}
>
{head.textContent}
</a>
Expand Down
6 changes: 3 additions & 3 deletions src/components/Post/PostDetail/PostContent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -59,21 +59,21 @@ const Content = ({ content }: Props) => {
components={{
h1({ index, children }) {
return (
<h1 data-index={index} id={setElementId(children)}>
<h1 data-index={index} id={`${setElementId(children)}-${index}`}>
{children}
</h1>
);
},
h2({ index, children }) {
return (
<h2 data-index={index} id={setElementId(children)}>
<h2 data-index={index} id={`${setElementId(children)}-${index}`}>
{children}
</h2>
);
},
h3({ index, children }) {
return (
<h3 data-index={index} id={setElementId(children)}>
<h3 data-index={index} id={`${setElementId(children)}-${index}`}>
{children}
</h3>
);
Expand Down
3 changes: 2 additions & 1 deletion src/components/Post/PostDetail/PostHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@ const PostHeader = ({ postMetaData }: Props) => {
'font-bold',
'text-[3em]',
'leading-[1.3]',
'mt-[1em]'
'mt-[1em]',
'post-title'
)}
>
{postMetaData.title}
Expand Down
6 changes: 4 additions & 2 deletions src/components/Post/PostDetail/PostNavbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ const PostNavbar = ({ category = 'posts' }: Props) => {
<ul className={classNames('max-h-[280px]', 'overflow-auto')}>
{headings.map((heading) => (
<li
key={heading.textContent}
key={`${heading.textContent}-${heading.dataset.index}`}
className={classNames(
'w-full',
'px-4',
Expand All @@ -116,7 +116,9 @@ const PostNavbar = ({ category = 'posts' }: Props) => {
>
<a
className={classNames('hover:underline')}
href={`#${setElementId(heading.textContent)}`}
href={`#${setElementId(heading.textContent)}-${
heading.dataset.index
}`}
onClick={() => {
setIsOpen(false);
}}
Expand Down
Loading

0 comments on commit 1272ecd

Please sign in to comment.