From 7685b44257ebaeb4ccfa2d972892192b93cfd4e3 Mon Sep 17 00:00:00 2001 From: YAPPgit Date: Sun, 27 Feb 2022 16:50:47 +0000 Subject: [PATCH] =?UTF-8?q?fix:=20Recruit=20Banner,=20Way=20=EB=B0=98?= =?UTF-8?q?=EC=9D=91=ED=98=95=20=EC=88=98=EC=A0=95,=20BreakPoint=20xsmall?= =?UTF-8?q?=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- __mocks__/next/image.js | 4 + __mocks__/next/link.js | 4 + __mocks__/next/router.js | 9 + build.sh | 5 + components/AnimatedBox/index.stories.tsx | 26 + components/AnimatedBox/index.tsx | 89 + components/Box.tsx | 50 + components/Button/index.stories.tsx | 47 + components/Button/index.tsx | 71 + components/Carousel/index.stories.tsx | 29 + components/Carousel/index.tsx | 185 + components/FloatingButton/index.stories.tsx | 20 + components/FloatingButton/index.tsx | 166 + components/Footer/index.tsx | 118 + components/HamburgerMenu/index.tsx | 88 + components/Header/index.stories.tsx | 20 + components/Header/index.tsx | 107 + components/LayoutWrapper.tsx | 25 + components/NewsCard/index.stories.tsx | 21 + components/NewsCard/index.tsx | 82 + components/SEO.tsx | 15 + components/index.ts | 10 + constants/breakpoints.ts | 9 + constants/headerMenus.ts | 20 + constants/path.ts | 8 + constants/yapp.ts | 8 + database/home.ts | 89 + database/recruit.ts | 233 + hooks/useDragScroll.ts | 35 + hooks/useToggle.ts | 9 + hooks/useWindowDimensions.ts | 27 + next-env.d.ts | 5 + next.config.js | 14 + package.json | 46 + pages/_app.tsx | 36 + pages/_document.tsx | 21 + .../components/AnimatedTextSection/index.tsx | 25 + pages/components/GridSection/index.tsx | 45 + pages/components/IntroSection/index.tsx | 136 + pages/components/NewsSection/index.tsx | 39 + pages/components/ProjectSection/index.tsx | 30 + pages/components/SectionTemplate/index.tsx | 28 + pages/components/SectionTitle/index.tsx | 28 + pages/components/SponsorSection/index.tsx | 73 + pages/components/index.ts | 8 + pages/index.stories.tsx | 29 + pages/index.tsx | 28 + pages/recruit/components/ApplyWay/index.tsx | 114 + pages/recruit/components/Enquiry/index.tsx | 90 + .../FrequentlyAskedQuestions/index.tsx | 103 + .../components/RecruitBanner/index.tsx | 163 + .../RecruitField/RecruitDesigner.tsx | 16 + .../RecruitField/RecruitDeveloper.tsx | 87 + .../RecruitField/RecruitFieldExplain.tsx | 135 + .../RecruitField/RecruitProjectManager.tsx | 14 + .../recruit/components/RecruitField/index.tsx | 122 + .../components/RecruitSchedule/index.tsx | 95 + .../components/SectionTemplate/index.tsx | 34 + .../recruit/components/SectionTitle/index.tsx | 25 + pages/recruit/components/index.ts | 8 + pages/recruit/index.tsx | 27 + public/assets/icons/YAPP_Logo.svg | 9 + public/assets/icons/arrow_down.svg | 3 + public/assets/icons/arrow_left.svg | 4 + public/assets/icons/arrow_right.svg | 4 + public/assets/icons/facebook.svg | 3 + public/assets/icons/hamburger.svg | 3 + public/assets/icons/index.ts | 9 + public/assets/icons/kakao.svg | 3 + public/assets/icons/mail.svg | 3 + public/assets/icons/plus.svg | 4 + public/assets/images/facebook1.png | Bin 0 -> 156032 bytes public/assets/images/facebook2.png | Bin 0 -> 162298 bytes public/assets/images/facebook3.png | Bin 0 -> 139264 bytes public/assets/images/naverD2.png | Bin 0 -> 5420 bytes public/assets/images/project1.png | Bin 0 -> 89018 bytes public/assets/images/project2.png | Bin 0 -> 11471 bytes public/assets/images/project3.png | Bin 0 -> 8476 bytes public/favicon.ico | Bin 0 -> 25931 bytes public/vercel.svg | 4 + styles/global-styles.ts | 38 + styles/media.ts | 16 + styles/styled.d.ts | 26 + styles/theme.ts | 278 + styles/utils-styles.ts | 27 + tsconfig.json | 21 + utils/getDeveloperFieldExplain.ts | 22 + yarn.lock | 10861 ++++++++++++++++ 89 files changed, 14592 insertions(+), 1 deletion(-) create mode 100644 __mocks__/next/image.js create mode 100644 __mocks__/next/link.js create mode 100644 __mocks__/next/router.js create mode 100644 build.sh create mode 100644 components/AnimatedBox/index.stories.tsx create mode 100644 components/AnimatedBox/index.tsx create mode 100644 components/Box.tsx create mode 100644 components/Button/index.stories.tsx create mode 100644 components/Button/index.tsx create mode 100644 components/Carousel/index.stories.tsx create mode 100644 components/Carousel/index.tsx create mode 100644 components/FloatingButton/index.stories.tsx create mode 100644 components/FloatingButton/index.tsx create mode 100644 components/Footer/index.tsx create mode 100644 components/HamburgerMenu/index.tsx create mode 100644 components/Header/index.stories.tsx create mode 100644 components/Header/index.tsx create mode 100644 components/LayoutWrapper.tsx create mode 100644 components/NewsCard/index.stories.tsx create mode 100644 components/NewsCard/index.tsx create mode 100644 components/SEO.tsx create mode 100644 components/index.ts create mode 100644 constants/breakpoints.ts create mode 100644 constants/headerMenus.ts create mode 100644 constants/path.ts create mode 100644 constants/yapp.ts create mode 100644 database/home.ts create mode 100644 database/recruit.ts create mode 100644 hooks/useDragScroll.ts create mode 100644 hooks/useToggle.ts create mode 100644 hooks/useWindowDimensions.ts create mode 100644 next-env.d.ts create mode 100644 next.config.js create mode 100644 package.json create mode 100644 pages/_app.tsx create mode 100644 pages/_document.tsx create mode 100644 pages/components/AnimatedTextSection/index.tsx create mode 100644 pages/components/GridSection/index.tsx create mode 100644 pages/components/IntroSection/index.tsx create mode 100644 pages/components/NewsSection/index.tsx create mode 100644 pages/components/ProjectSection/index.tsx create mode 100644 pages/components/SectionTemplate/index.tsx create mode 100644 pages/components/SectionTitle/index.tsx create mode 100644 pages/components/SponsorSection/index.tsx create mode 100644 pages/components/index.ts create mode 100644 pages/index.stories.tsx create mode 100644 pages/index.tsx create mode 100644 pages/recruit/components/ApplyWay/index.tsx create mode 100644 pages/recruit/components/Enquiry/index.tsx create mode 100644 pages/recruit/components/FrequentlyAskedQuestions/index.tsx create mode 100644 pages/recruit/components/RecruitBanner/index.tsx create mode 100644 pages/recruit/components/RecruitField/RecruitDesigner.tsx create mode 100644 pages/recruit/components/RecruitField/RecruitDeveloper.tsx create mode 100644 pages/recruit/components/RecruitField/RecruitFieldExplain.tsx create mode 100644 pages/recruit/components/RecruitField/RecruitProjectManager.tsx create mode 100644 pages/recruit/components/RecruitField/index.tsx create mode 100644 pages/recruit/components/RecruitSchedule/index.tsx create mode 100644 pages/recruit/components/SectionTemplate/index.tsx create mode 100644 pages/recruit/components/SectionTitle/index.tsx create mode 100644 pages/recruit/components/index.ts create mode 100644 pages/recruit/index.tsx create mode 100644 public/assets/icons/YAPP_Logo.svg create mode 100644 public/assets/icons/arrow_down.svg create mode 100644 public/assets/icons/arrow_left.svg create mode 100644 public/assets/icons/arrow_right.svg create mode 100644 public/assets/icons/facebook.svg create mode 100644 public/assets/icons/hamburger.svg create mode 100644 public/assets/icons/index.ts create mode 100644 public/assets/icons/kakao.svg create mode 100644 public/assets/icons/mail.svg create mode 100644 public/assets/icons/plus.svg create mode 100644 public/assets/images/facebook1.png create mode 100644 public/assets/images/facebook2.png create mode 100644 public/assets/images/facebook3.png create mode 100644 public/assets/images/naverD2.png create mode 100644 public/assets/images/project1.png create mode 100644 public/assets/images/project2.png create mode 100644 public/assets/images/project3.png create mode 100644 public/favicon.ico create mode 100644 public/vercel.svg create mode 100644 styles/global-styles.ts create mode 100644 styles/media.ts create mode 100644 styles/styled.d.ts create mode 100644 styles/theme.ts create mode 100644 styles/utils-styles.ts create mode 100644 tsconfig.json create mode 100644 utils/getDeveloperFieldExplain.ts create mode 100644 yarn.lock diff --git a/README.md b/README.md index caacc0f..ec5b0ec 100644 --- a/README.md +++ b/README.md @@ -1 +1 @@ -# yapp-web \ No newline at end of file +# YAPP Web diff --git a/__mocks__/next/image.js b/__mocks__/next/image.js new file mode 100644 index 0000000..4407753 --- /dev/null +++ b/__mocks__/next/image.js @@ -0,0 +1,4 @@ + import React from 'react'; + export default function (props) { + return + } \ No newline at end of file diff --git a/__mocks__/next/link.js b/__mocks__/next/link.js new file mode 100644 index 0000000..0f4b678 --- /dev/null +++ b/__mocks__/next/link.js @@ -0,0 +1,4 @@ +import React from 'react'; +export default function ({ children }) { + return {children}; +} diff --git a/__mocks__/next/router.js b/__mocks__/next/router.js new file mode 100644 index 0000000..17b8214 --- /dev/null +++ b/__mocks__/next/router.js @@ -0,0 +1,9 @@ +export const useRouter = () => ({ + route: '/', + pathname: '', + query: '', + asPath: '', + prefetch: () => {}, + push: () => {}, +}); +export default { useRouter }; diff --git a/build.sh b/build.sh new file mode 100644 index 0000000..f06b379 --- /dev/null +++ b/build.sh @@ -0,0 +1,5 @@ +#!/bin/sh +cd ../ +mkdir output +cp -R ./yapp-web/* ./output +cp -R ./output ./yapp-web/ \ No newline at end of file diff --git a/components/AnimatedBox/index.stories.tsx b/components/AnimatedBox/index.stories.tsx new file mode 100644 index 0000000..9c874d6 --- /dev/null +++ b/components/AnimatedBox/index.stories.tsx @@ -0,0 +1,26 @@ +import { Story, Meta } from '@storybook/react'; +import GridSection from 'pages/components/GridSection'; + +export default { + title: 'YAPP Design System/Component/AnimatedBox', + component: GridSection, + parameters: { + docs: { + description: { + component: 'AnimatedBox', + }, + }, + }, + argTypes: { + data: { + table: { + disable: true, + }, + }, + }, +} as Meta; + +const Template: Story = (args) => ; + +export const defaultAnimatedBox = Template.bind({}); +defaultAnimatedBox.args = {}; diff --git a/components/AnimatedBox/index.tsx b/components/AnimatedBox/index.tsx new file mode 100644 index 0000000..82b82c9 --- /dev/null +++ b/components/AnimatedBox/index.tsx @@ -0,0 +1,89 @@ +import { useEffect, useCallback, useRef, useState } from 'react'; +import type { ReactElement, ReactNode } from 'react'; +import { useSpring, animated } from '@react-spring/web'; +import { Box } from 'components'; +import styled from 'styled-components'; +import media from 'styles/media'; + +interface AnimatedBox { + children: ReactNode; + className?: string; +} + +function AnimatedBox({ children, className }: AnimatedBox): ReactElement { + const animatedDivRef = useRef(null); + const [isIntersect, setIsIntersect] = useState(false); + + const handleIntersect: IntersectionObserverCallback = useCallback( + ([entry], observer) => { + if (entry.isIntersecting && animatedDivRef.current) { + observer.unobserve(animatedDivRef.current); // 한번 observe된 ref 풀기 + setIsIntersect(true); + } + }, + [], + ); + + const styles = useSpring({ + config: { mass: 200, tension: 1500, friction: 1000 }, // 질량, 장력, 마찰력 + from: { opacity: 0, y: 50 }, // 처음 위치 + to: isIntersect && { opacity: 1, y: 0 }, // 이벤트 시작시 해당 값까지 애니메이션 + }); + + useEffect(() => { + let observer: IntersectionObserver; + if (animatedDivRef.current) { + observer = new IntersectionObserver(handleIntersect, { threshold: 0.3 }); // 이벤트 부여 + observer.observe(animatedDivRef.current); // observe 시작 + } + + return () => observer && observer.disconnect(); + }, [handleIntersect]); + + return ( + + + {children} + + + ); +} + +export default AnimatedBox; + +const StyledBox = styled(Box)` + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + padding: 0; + filter: drop-shadow( + 0px 5px 40px ${({ theme }) => theme.palette.grey_850 + '3'} + ); + + .title-text { + color: ${({ theme }) => theme.palette.grey_500}; + ${({ theme }) => theme.textStyle.web.Subtitle}; + } + .content-text { + ${({ theme }) => theme.textStyle.web.Head} + } + + ${media.mobile} { + width: 335px; + height: 220px; + + .title-text { + ${({ theme }) => theme.textStyle.mobile.Subtitle} + } + .content-text { + ${({ theme }) => theme.textStyle.mobile.Head} + } + } +`; diff --git a/components/Box.tsx b/components/Box.tsx new file mode 100644 index 0000000..43d07fd --- /dev/null +++ b/components/Box.tsx @@ -0,0 +1,50 @@ +import React, { ReactElement, ReactNode } from 'react'; +import styled from 'styled-components'; +import theme, { PaletteKeyTypes } from 'styles/theme'; + +interface IBoxStyle { + backgroundColor?: PaletteKeyTypes; + width?: number; + height?: number; + borderRadius?: number; + isFullWidth?: boolean; +} + +interface BoxProps extends IBoxStyle { + children: ReactNode; + className?: string; +} + +function Box({ + children, + className, + width = 0, + height, + backgroundColor = 'grey', + borderRadius = 20, + ...rest +}: BoxProps): ReactElement { + return ( + + {children} + + ); +} + +const StyledBox = styled.div` + padding: 10px; + width: ${({ isFullWidth, width }) => (isFullWidth ? '100%' : `${width}px`)}; + height: ${({ height }) => height}px; + border-radius: ${({ borderRadius }) => borderRadius}px; + background-color: ${({ backgroundColor }) => + backgroundColor && theme.palette[backgroundColor]}; +`; + +export default Box; diff --git a/components/Button/index.stories.tsx b/components/Button/index.stories.tsx new file mode 100644 index 0000000..ff67c0c --- /dev/null +++ b/components/Button/index.stories.tsx @@ -0,0 +1,47 @@ +import { Story, Meta } from '@storybook/react'; +import Button, { ButtonProps } from 'components/Button'; + +export default { + title: 'YAPP Design System/Component/Button', + component: Button, + parameters: { + docs: { + description: { + component: '홈페이지에 사용되는 모든 버튼', + }, + }, + }, + argTypes: { + width: { + type: 'number', + }, + height: { + type: 'number', + }, + hasBorder: { type: 'boolean' }, + borderRadius: { type: 'number' }, + className: { + table: { + disable: true, + }, + }, + onClick: { + table: { + disable: true, + }, + }, + }, +} as Meta; + +const Template: Story = (args) => + + + + + + ); +} + +const TriggerButton = styled(Button)<{ visible: boolean }>` + position: fixed; + bottom: 48px; + right: 48px; + z-index: 1000; + background: ${({ theme }) => + `linear-gradient(208.15deg, ${theme.palette.orange_300} 12.08%, ${theme.palette.orange_500} 86.71%)`}; + + ${media.mobile} { + bottom: 24px; + right: 24px; + } + + svg { + // plus 버튼 각도 조절 transition + transition: transform 0.5s; + } + + ${({ visible }) => + visible && + css` + background: ${({ theme }) => theme.palette.grey_800}; + svg { + transform: rotate(45deg); + } + `}; +`; + +const FixedFloatingContainer = styled.div<{ visible: boolean }>` + position: fixed; + overflow: hidden; + bottom: 48px; + right: 48px; + z-index: 900; + opacity: 0; + visibility: 'hidden'; + pointer-events: none; + + ${media.mobile} { + bottom: 24px; + right: 24px; + } + + /* floating container transition + 해당 transition을 통해 버튼이 Plus 버튼에서 자연스럽게 올라와지는 것 처럼 보임 */ + transition: all 1.2s; + ${({ visible }) => + visible && + css` + bottom: 117px; + opacity: 1; + visibility: visible; + pointer-events: auto; + + ${media.mobile} { + bottom: 93px; + } + `}; +`; + +const AnimatedFloatingContainer = styled.div<{ visible: boolean }>` + position: relative; + display: flex; + flex-direction: column; + align-items: flex-end; + bottom: -150px; + + // floating 버튼 등장 transition + transition: all 1s; + ${({ visible }) => + visible && + css` + bottom: 0; + `}; + + .floating-button { + display: flex; + justify-content: space-around; + margin: 5px 0; + + .text { + display: none; + flex-grow: 0; + flex-shrink: 0; + ${({ theme }) => theme.textStyle.web.Category} + + &.facebook, &.mail { + color: ${({ theme }) => theme.palette.white}; + } + } + + // floating 버튼 길이 transition + transition: all 0.5s; + :hover { + width: 188px; + padding: 0 20px 0 5px; + .text { + display: inline-block; + } + } + } +`; + +export default FloatingButton; diff --git a/components/Footer/index.tsx b/components/Footer/index.tsx new file mode 100644 index 0000000..9093e85 --- /dev/null +++ b/components/Footer/index.tsx @@ -0,0 +1,118 @@ +import Breakpoints from 'constants/breakpoints'; +import Yapp from 'constants/yapp'; +import React, { ReactElement } from 'react'; +import styled from 'styled-components'; +import media from 'styles/media'; + +function Footer(): ReactElement { + const { YAPP_NAME, YAPP_OFFICIAL_EMAIL } = Yapp; + + return ( + <> + + + + {YAPP_NAME} + {YAPP_OFFICIAL_EMAIL} + + + Your own idea can change the{' '} + Actual world at +
anytime with Passion and{' '} + Potential. +
+ + {/* @Todo 임시 버튼들, 나중에 소셜 버튼 나오면 추가 예정 */} + + + + +
+
+ Copyright © YAPP All Rights Reserved. + + ); +} + +const FooterBlock = styled.div` + width: 100%; + height: 336px; + background-color: ${({ theme }) => theme.palette.grey_900}; + color: ${({ theme }) => theme.palette.white}; +`; + +const FooterInner = styled.div` + width: ${Breakpoints.large}px; + margin: 0 auto; + padding-top: 72px; + display: flex; + flex-direction: column; + ${media.tablet} { + width: auto; + padding: 48px 81px 40px; + } + ${media.mobile} { + padding: 48px 36px 50px; + min-width: auto; + } +`; + +const YappInfo = styled.div` + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 16px; + ${media.mobile} { + flex-direction: column; + align-items: flex-start; + } +`; + +const InfoText = styled.div` + ${({ theme }) => theme.textStyle.web.Footer_Text}; + margin-bottom: 60px; +`; + +const TextPoint = styled.span` + color: ${({ theme }) => theme.palette.yellow_400}; + font-weight: ${({ theme }) => theme.fontWeight.semibold}; +`; + +const YappName = styled.span` + ${({ theme }) => theme.textStyle.web.Footer_Logo} + ${media.mobile} { + margin-bottom: 8px; + ${({ theme }) => theme.textStyle.mobile.Footer_Logo} + } +`; + +const YappEmail = styled.span` + ${({ theme }) => theme.textStyle.web.Body_1} +`; + +const YappSocialButtonGroup = styled.div` + width: 160px; + display: flex; + align-items: center; + justify-content: space-between; +`; + +// @Todo 임시 소셜 버튼 +const SocialButton = styled.div` + width: 32px; + height: 32px; + background-color: #c9c9c9; + border-radius: 50%; +`; + +const Copyright = styled.div` + background-color: ${({ theme }) => theme.palette.grey_1000}; + color: ${({ theme }) => theme.palette.grey_700}; + height: 49px; + ${({ theme }) => theme.textStyle.web.Copyright_Text} + display: flex; + align-items: center; + justify-content: center; +`; + +export default Footer; diff --git a/components/HamburgerMenu/index.tsx b/components/HamburgerMenu/index.tsx new file mode 100644 index 0000000..520ba7f --- /dev/null +++ b/components/HamburgerMenu/index.tsx @@ -0,0 +1,88 @@ +import { ReactElement, useEffect } from 'react'; +import { HEADER_MENUS } from 'constants/headerMenus'; +import styled from 'styled-components'; +import { fadeIn } from 'styles/utils-styles'; +import { useRouter } from 'next/router'; +import Link from 'next/link'; + +interface HamburgerMenuProps { + handleOpenMenu: () => void; +} + +function HamburgerMenu({ handleOpenMenu }: HamburgerMenuProps): ReactElement { + const { asPath } = useRouter(); + + useEffect(() => { + document.body.style.overflow = 'hidden'; + return () => { + document.body.style.overflow = 'unset'; + }; + }, []); + + return ( + + + + {HEADER_MENUS.map(({ name, path }) => ( + + + {name} + + + ))} + + + + + ); +} + +const HamburgerMenuContainer = styled.div` + position: fixed; + top: 0; + width: 100%; + height: 100%; + z-index: 1500; +`; + +const InnerMenu = styled.div` + position: absolute; + top: 0; + left: 0; + bottom: 0; + right: 0; + color: #fff; + display: flex; + align-items: center; + justify-content: center; + height: 100%; + z-index: 2000; + animation: ${fadeIn} 0.5s ease-in-out; +`; + +const MenuList = styled.div` + height: 356px; + display: flex; + flex-direction: column; + align-items: center; + justify-content: space-between; +`; + +const MenuItem = styled.a<{ active: boolean }>` + cursor: pointer; + ${({ theme }) => theme.textStyle.mobile.Title_1} + color: ${({ theme, active }) => + active ? theme.palette.orange_400 : theme.palette.white}; +`; + +const Background = styled.div` + display: block; + width: 100%; + height: 100%; + background-color: rgba(7, 9, 11, 0.75); + position: absolute; + left: 0; + top: 0; +`; + +export default HamburgerMenu; diff --git a/components/Header/index.stories.tsx b/components/Header/index.stories.tsx new file mode 100644 index 0000000..cdd6856 --- /dev/null +++ b/components/Header/index.stories.tsx @@ -0,0 +1,20 @@ +import { Meta, Story } from '@storybook/react'; +import Header from 'components/Header'; + +export default { + title: 'YAPP Design System/Component/Header', + component: Header, + parameters: { + docs: { + description: { + component: 'Header', + }, + }, + }, + argTypes: {}, +} as Meta; + +const Template: Story = (args) =>
; + +export const defaultHeader = Template.bind({}); +defaultHeader.args = {}; diff --git a/components/Header/index.tsx b/components/Header/index.tsx new file mode 100644 index 0000000..ce51258 --- /dev/null +++ b/components/Header/index.tsx @@ -0,0 +1,107 @@ +import Breakpoints from 'constants/breakpoints'; +import { HEADER_MENUS } from 'constants/headerMenus'; +import Link from 'next/link'; +import { useRouter } from 'next/router'; +import { Hamburger, YappLogo } from 'public/assets/icons'; +import React, { ReactElement, useEffect, useRef } from 'react'; +import styled from 'styled-components'; +import media from 'styles/media'; +import useToggle from 'hooks/useToggle'; +import HamburgerMenu from 'components/HamburgerMenu'; +import useWindowDimensions from 'hooks/useWindowDimensions'; + +function Header(): ReactElement { + const { asPath } = useRouter(); + const [isOpenMenu, handleOpenMenu, setOpenMenu] = useToggle(false); + const { windowWidth } = useWindowDimensions(); + + useEffect(() => { + if (windowWidth > Breakpoints.medium) { + setOpenMenu(false); + } + }, [windowWidth]); + + const ref = useRef(null); + + const handleToggleMenu = () => { + if (!ref.current) return; + ref.current.scrollIntoView({ + behavior: 'smooth', + block: 'start', + inline: 'nearest', + }); + handleOpenMenu(); + }; + + return ( + <> + + + + + {HEADER_MENUS.map(({ name, path }) => ( + + {name} + + ))} + + + + + {isOpenMenu && } + + ); +} + +const HeaderBlock = styled.header` + width: 100%; + background-color: ${({ theme }) => theme.palette.grey_900}; + color: ${({ theme }) => theme.palette.white}; + position: sticky; + top: 0; + z-index: 5000; +`; + +const HeaderInner = styled.div` + width: ${Breakpoints.large}px; + height: 80px; + margin: 0 auto; + display: flex; + justify-content: space-between; + align-items: center; + ${media.tablet} { + width: auto; + padding: 0 81px; + } + ${media.mobile} { + padding: 0 20px; + height: 64px; + } +`; + +const HeaderMenu = styled.div` + width: 470px; + display: flex; + align-items: center; + justify-content: space-between; + ${media.mobile} { + display: none; + } +`; + +const MenuText = styled.a<{ active: boolean }>` + cursor: pointer; + color: ${({ theme, active }) => + active ? theme.palette.orange_400 : theme.palette.white}; + ${({ theme }) => theme.textStyle.web.Category}; +`; + +const MobileHeaderMenu = styled(Hamburger)` + display: none; + ${media.mobile} { + display: block; + cursor: pointer; + } +`; + +export default Header; diff --git a/components/LayoutWrapper.tsx b/components/LayoutWrapper.tsx new file mode 100644 index 0000000..f72338a --- /dev/null +++ b/components/LayoutWrapper.tsx @@ -0,0 +1,25 @@ +import React, { ReactNode } from 'react'; +import { Header, Footer, FloatingButton } from 'components'; +import { useRouter } from 'next/router'; +import IntroSection from 'pages/components/IntroSection'; +import PATH from 'constants/path'; + +interface LayoutWrapperProps { + children: ReactNode; +} + +function LayoutWrapper({ children }: LayoutWrapperProps) { + const { asPath } = useRouter(); + + return ( + <> + {asPath === PATH.Home && } +
+ {children} +