diff --git a/src/components/GNB/GNB.tsx b/src/components/GNB/GNB.tsx index 749c6cf2..255cc59d 100644 --- a/src/components/GNB/GNB.tsx +++ b/src/components/GNB/GNB.tsx @@ -1,12 +1,14 @@ +import { useState } from 'react'; import Image from 'next/image'; import Link from 'next/link'; import { useRouter } from 'next/router'; import { css, Theme } from '@emotion/react'; +import { AnimatePresence } from 'framer-motion'; import { Button } from '~/components/Button'; -import { MenuIcon } from '~/components/Icons'; +import { MobileMenu } from '~/components/GNB/MobileMenu'; +import { MobileMenuIcon } from '~/components/GNB/MobileMenuIcon'; import { GNB_MENU_NAME, GNBMenu } from '~/constant/gnb'; -import { colors } from '~/styles/colors'; import { mediaQuery } from '~/styles/media'; const LOGO_IMAGE = `/images/logo.png`; @@ -23,12 +25,14 @@ function ApplyButton({ menu }: { menu: GNBMenu }) { export function GNB() { const { pathname } = useRouter(); + const [isMenuOpen, setIsMenuOpen] = useState(false); const getActiveLinkcss = (menu: GNBMenu) => { if (pathname.startsWith(menu.href)) { return activeLinkCss; } return inActiveLinkCss; }; + return ( <> +
); } -const navCss = css` - background-color: ${colors.black800}; +const navCommonCss = (theme: Theme) => css` + background-color: ${theme.colors.black800}; position: fixed; - padding: 20px 32px; top: 0; left: 0; z-index: 9998; width: 100vw; `; +const navCss = (theme: Theme) => css` + ${navCommonCss(theme)}; + padding: 20px 32px; + + ${mediaQuery('mobile')} { + display: none; + } +`; + const blankCss = css` width: 100vw; height: 82px; + + ${mediaQuery('mobile')} { + height: 72px; + } `; const navWrapperCss = css` @@ -85,13 +107,9 @@ const navWrapperCss = css` const menuContainerCss = css` display: flex; gap: 32px; - - ${mediaQuery('mobile')} { - display: none; - } `; -const mobileMenuContainerCss = css` +const mobileNavCss = css` display: none; ${mediaQuery('mobile')} { @@ -114,3 +132,15 @@ const inActiveLinkCss = (theme: Theme) => css` const linkCss = (theme: Theme) => css` ${theme.typos.pretendard.body1}; `; + +const mobileMenuGNBCss = (theme: Theme) => css` + ${navCommonCss(theme)}; + padding: 20px 32px; + display: flex; + align-items: center; + justify-content: space-between; + + & > a { + margin-top: 6px; + } +`; diff --git a/src/components/GNB/MobileMenu.tsx b/src/components/GNB/MobileMenu.tsx new file mode 100644 index 00000000..e217c691 --- /dev/null +++ b/src/components/GNB/MobileMenu.tsx @@ -0,0 +1,62 @@ +import Link from 'next/link'; +import { css, Theme } from '@emotion/react'; +import { m } from 'framer-motion'; + +import { GNB_MENU_NAME } from '~/constant/gnb'; + +export function MobileMenu({}) { + return ( + + + + ); +} + +const mobileMenuCss = (theme: Theme) => css` + z-index: 9997; + + width: 100vw; + height: fit-content; + position: fixed; + top: 0; + left: 0; + margin: auto; + background-color: ${theme.colors.black800}; + padding-top: 72px; + + overflow: hidden; + li { + padding: 12px 32px; + } +`; + +const activeLinkCss = (theme: Theme) => css` + color: ${theme.colors.yellow500}; +`; + +const inActiveLinkCss = (theme: Theme) => css` + color: ${theme.colors.white}; +`; + +const linkCss = (theme: Theme) => css` + ${theme.typos.pretendard.body1}; +`; diff --git a/src/components/GNB/MobileMenuIcon.tsx b/src/components/GNB/MobileMenuIcon.tsx new file mode 100644 index 00000000..5983146c --- /dev/null +++ b/src/components/GNB/MobileMenuIcon.tsx @@ -0,0 +1,101 @@ +import { css } from '@emotion/react'; + +interface Props { + onClick?: () => void; + isChecked?: boolean; +} +export function MobileMenuIcon({ onClick, isChecked }: Props) { + return ( +
+ + +
+ ); +} + +const containerCss = css` + position: relative; + width: 32px; + height: 32px; + + .menu { + position: absolute; + top: 0; + right: 0; + height: 100%; + max-width: 0; + min-width: 100px; + transition: 0.5s ease; + z-index: 1; + background-color: #eee; + } + + .burger-icon { + cursor: pointer; + display: inline-block; + position: absolute; + z-index: 2; + padding: 8px 0; + top: 8px; + right: 4px; + user-select: none; + width: auto; + + .burger-sticks { + background: #d9d9d9; + display: block; + height: 3px; + position: relative; + transition: background 0.2s ease-out; + width: 24px; + + &:before, + &:after { + background: #d9d9d9; + content: ''; + display: block; + height: 100%; + position: absolute; + transition: all 0.2s ease-out; + width: 100%; + } + + &:before { + top: 8px; + } + + &:after { + top: -8px; + } + } + } + + .burger-check { + display: none; + } + + .burger-check:checked ~ .burger-icon .burger-sticks { + background: transparent; + &:before { + transform: rotate(-45deg); + } + &:after { + transform: rotate(45deg); + } + } + + .burger-check:checked ~ .burger-icon:not(.steps) .burger-sticks { + &:before, + &:after { + top: 0; + } + } +`;