From 7145e8a32fd113ba706cc6509600439284b91a3a Mon Sep 17 00:00:00 2001 From: f0ever0 Date: Wed, 18 Oct 2023 11:32:57 +0900 Subject: [PATCH 01/14] =?UTF-8?q?feat=20:=20blog=20=ED=83=AD=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Header/Desktop/DesktopHeader.tsx | 135 +----------------- src/components/Header/Mobile/HeaderMenu.tsx | 16 +-- src/components/Header/menuTapList.ts | 15 +- src/components/Header/types.ts | 10 +- src/pages/blog.tsx | 1 + src/views/BlogPage/BlogPage.tsx | 7 + src/views/BlogPage/index.tsx | 1 + 7 files changed, 20 insertions(+), 165 deletions(-) create mode 100644 src/pages/blog.tsx create mode 100644 src/views/BlogPage/BlogPage.tsx create mode 100644 src/views/BlogPage/index.tsx diff --git a/src/components/Header/Desktop/DesktopHeader.tsx b/src/components/Header/Desktop/DesktopHeader.tsx index f996103f..fe3b90bf 100644 --- a/src/components/Header/Desktop/DesktopHeader.tsx +++ b/src/components/Header/Desktop/DesktopHeader.tsx @@ -1,16 +1,14 @@ import styled from '@emotion/styled'; import Link from 'next/link'; import { css } from '@emotion/react'; -import { useCallback, useEffect, useState } from 'react'; import { LOGO_IMAGE_URL } from '@src/assets/mainLogo/base64_logo'; import useHeader from '@src/hooks/useHeader'; import { GrowDown } from '@src/lib/styles/animation'; import { menuTapList } from '../menuTapList'; -import { BaseMenuTap, MenuTapType, ParentMenuTap } from '../types'; +import { MenuTapType, SingleMenuTap } from '../types'; function DesktopHeader() { const { handleClickLogo, handleIsSelected } = useHeader(); - const [isSubTapOpened, setIsSubTapOpened] = useState(false); return ( <> @@ -20,138 +18,36 @@ function DesktopHeader() { {menuTapList.map((menuTap) => ( - + ))} - {isSubTapOpened && } ); } type MenuTapProps = { - menuTap: BaseMenuTap; + menuTap: SingleMenuTap; handleIsSelected: (path: string | string[]) => boolean; - isSubTapOpened: boolean; - setIsSubTapOpened: (isOpened: boolean) => void; }; -function MenuTap({ menuTap, handleIsSelected, isSubTapOpened, setIsSubTapOpened }: MenuTapProps) { +function MenuTap({ menuTap, handleIsSelected }: MenuTapProps) { switch (menuTap.type) { case MenuTapType.Anchor: return ( - setIsSubTapOpened(false)} - onMouseEnter={() => setIsSubTapOpened(false)} - > + {menuTap.title} ); case MenuTapType.Router: return ( - setIsSubTapOpened(false)} - onMouseEnter={() => setIsSubTapOpened(false)} - > + {menuTap.title} ); - case MenuTapType.Parent: - return ( - - ); } } -type ParentMenuProps = { - menuTap: ParentMenuTap; - handleIsSelected: (path: string | string[]) => boolean; - isSubTapOpened: boolean; - setIsSubTapOpened: (isOpened: boolean) => void; -}; - -function ParentMenu({ - menuTap, - handleIsSelected, - isSubTapOpened, - setIsSubTapOpened, -}: ParentMenuProps) { - const [isOpened, setIsOpened] = useState(false); - - const closeSubTap = useCallback(() => { - setIsSubTapOpened(false); - setIsOpened(false); - }, [setIsSubTapOpened, setIsOpened]); - - const onMouseIn = () => { - setIsSubTapOpened(true); - setIsOpened(true); - }; - - useEffect(() => { - if (!isSubTapOpened) { - setIsOpened(false); - } - }, [isSubTapOpened]); - - useEffect(() => { - if (isSubTapOpened) { - document.addEventListener('click', closeSubTap); - } - return () => { - document.removeEventListener('click', closeSubTap); - }; - }, [closeSubTap, isSubTapOpened]); - - return ( - t.href))} - isOpened={isOpened} - onMouseEnter={onMouseIn} - onClick={(e) => e.stopPropagation()} - > - {menuTap.title} - {isOpened && ( - - {menuTap.children.map((c) => { - switch (c.type) { - case MenuTapType.Anchor: - return ( - - - {c.title} - - - ); - case MenuTapType.Router: - return ( - - {c.title} - - ); - } - })} - - )} - - ); -} - interface MenuTitleProps { isSelected?: boolean; isOpened?: boolean; @@ -175,21 +71,6 @@ export const SubMenuWrapper = styled.div` animation: growdown 0.4s forwards; `; -const SubMenu = styled.div` - position: absolute; - z-index: 1; - display: flex; - align-items: center; - justify-content: center; - - width: 300px; - top: 80px; - left: 25%; /* it is bad practice */ - transform: translateX(-50%); - - cursor: default; -`; - export const CenterAligner = styled.div` display: flex; align-items: center; @@ -272,8 +153,4 @@ export const MenuTitle = styled.div` } `; -const ParentMenuTitle = styled(MenuTitle)` - position: relative; -`; - export default DesktopHeader; diff --git a/src/components/Header/Mobile/HeaderMenu.tsx b/src/components/Header/Mobile/HeaderMenu.tsx index cff9138a..e5880e01 100644 --- a/src/components/Header/Mobile/HeaderMenu.tsx +++ b/src/components/Header/Mobile/HeaderMenu.tsx @@ -2,7 +2,7 @@ import Link from 'next/link'; import { useEffect } from 'react'; import useHeader from '@src/hooks/useHeader'; import { menuTapList } from '../menuTapList'; -import { BaseMenuTap, MenuState, MenuTapType } from '../types'; +import { MenuState, MenuTapType, SingleMenuTap } from '../types'; import * as S from './HeaderMenu.style'; function useNoScroll(isMenuShown: MenuState) { @@ -27,7 +27,7 @@ interface HeaderMenuProps { } type MenuTapProps = { - menuTap: BaseMenuTap; + menuTap: SingleMenuTap; handleIsSelected: (path: string) => boolean; }; @@ -47,18 +47,6 @@ function MenuTap({ menuTap, handleIsSelected }: MenuTapProps) { {menuTap.title} ); - case MenuTapType.Parent: - return ( - <> - {menuTap.children.map((childMenuTap) => ( - - ))} - - ); } } diff --git a/src/components/Header/menuTapList.ts b/src/components/Header/menuTapList.ts index 98ee20dd..a8bb1663 100644 --- a/src/components/Header/menuTapList.ts +++ b/src/components/Header/menuTapList.ts @@ -12,20 +12,9 @@ export const menuTapList: MenuTapList = [ href: '/project', }, { - type: MenuTapType.Parent, + type: MenuTapType.Router, title: '블로그', - children: [ - { - type: MenuTapType.Router, - title: '활동후기', - href: '/review', - }, - { - type: MenuTapType.Router, - title: '솝티클', - href: '/sopticle', - }, - ], + href: '/blog', }, { type: MenuTapType.Router, diff --git a/src/components/Header/types.ts b/src/components/Header/types.ts index 55a813b8..b1783b91 100644 --- a/src/components/Header/types.ts +++ b/src/components/Header/types.ts @@ -6,18 +6,10 @@ export const enum MenuTapType { Parent = 'PARENT', } -export type ParentMenuTap = { - type: MenuTapType.Parent; - title: string; - children: SingleMenuTap[]; -}; - export type SingleMenuTap = { type: MenuTapType.Router | MenuTapType.Anchor; title: string; href: string; }; -export type BaseMenuTap = SingleMenuTap | ParentMenuTap; - -export type MenuTapList = BaseMenuTap[]; +export type MenuTapList = SingleMenuTap[]; diff --git a/src/pages/blog.tsx b/src/pages/blog.tsx new file mode 100644 index 00000000..29da1c6a --- /dev/null +++ b/src/pages/blog.tsx @@ -0,0 +1 @@ +export { default } from '@src/views/BlogPage'; diff --git a/src/views/BlogPage/BlogPage.tsx b/src/views/BlogPage/BlogPage.tsx new file mode 100644 index 00000000..f4eca1e9 --- /dev/null +++ b/src/views/BlogPage/BlogPage.tsx @@ -0,0 +1,7 @@ +import PageLayout from '@src/components/common/PageLayout'; + +function BlogPage() { + return ; +} + +export default BlogPage; diff --git a/src/views/BlogPage/index.tsx b/src/views/BlogPage/index.tsx new file mode 100644 index 00000000..75531ca0 --- /dev/null +++ b/src/views/BlogPage/index.tsx @@ -0,0 +1 @@ +export { default } from './BlogPage'; From 8bbcfe58c8ee0e8dc30c94295e3f047d94a27a50 Mon Sep 17 00:00:00 2001 From: f0ever0 Date: Wed, 18 Oct 2023 12:21:32 +0900 Subject: [PATCH 02/14] style : change header style --- src/components/Header/Desktop/DesktopHeader.tsx | 4 ++-- src/components/Header/Header.tsx | 4 ++-- src/components/Header/header.module.scss | 5 +++-- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/components/Header/Desktop/DesktopHeader.tsx b/src/components/Header/Desktop/DesktopHeader.tsx index fe3b90bf..dfb62fd4 100644 --- a/src/components/Header/Desktop/DesktopHeader.tsx +++ b/src/components/Header/Desktop/DesktopHeader.tsx @@ -55,8 +55,8 @@ interface MenuTitleProps { } export const Wrapper = styled.div` - max-width: 1280px; - width: 90%; + max-width: 1200px; + width: 100%; display: flex; justify-content: space-between; `; diff --git a/src/components/Header/Header.tsx b/src/components/Header/Header.tsx index 3e2a3fe9..3ee1be16 100644 --- a/src/components/Header/Header.tsx +++ b/src/components/Header/Header.tsx @@ -4,8 +4,8 @@ import MobileHeader from './Mobile/MobileHeader'; import styles from './header.module.scss'; export function Header() { - const isDesktop = useIsDesktop('992px'); - const isTablet = useIsTablet('766px', '991.9px'); + const isDesktop = useIsDesktop('940px'); + const isTablet = useIsTablet('768px', '939px'); const isMobile = useIsMobile(); return ( diff --git a/src/components/Header/header.module.scss b/src/components/Header/header.module.scss index 9f717033..2baded36 100644 --- a/src/components/Header/header.module.scss +++ b/src/components/Header/header.module.scss @@ -11,16 +11,17 @@ background-color: rgba(22, 22, 28, 0.9); backdrop-filter: blur(20px); z-index: 100; + padding: 0 20px; + top: 0; @include tablet { height: 48px; - padding: 0 48px; } @include mobile { height: 48px; min-height: 48px; - padding: 0 20px; + justify-content: space-between; } } From 94a89eeec8052355480837775976e9797e3bf053 Mon Sep 17 00:00:00 2001 From: f0ever0 Date: Wed, 18 Oct 2023 15:19:28 +0900 Subject: [PATCH 03/14] =?UTF-8?q?feat=20:=20=EB=B8=94=EB=A1=9C=EA=B7=B8=20?= =?UTF-8?q?=ED=83=AD=20=EB=84=A4=EB=B9=84=EA=B2=8C=EC=9D=B4=EC=85=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/views/BlogPage/BlogPage.tsx | 7 +- .../BlogPage/components/navigation/index.tsx | 35 ++++++ .../BlogPage/components/navigation/style.ts | 101 ++++++++++++++++++ .../BlogPage/components/navigation/types.ts | 10 ++ 4 files changed, 152 insertions(+), 1 deletion(-) create mode 100644 src/views/BlogPage/components/navigation/index.tsx create mode 100644 src/views/BlogPage/components/navigation/style.ts create mode 100644 src/views/BlogPage/components/navigation/types.ts diff --git a/src/views/BlogPage/BlogPage.tsx b/src/views/BlogPage/BlogPage.tsx index f4eca1e9..7ea77c88 100644 --- a/src/views/BlogPage/BlogPage.tsx +++ b/src/views/BlogPage/BlogPage.tsx @@ -1,7 +1,12 @@ import PageLayout from '@src/components/common/PageLayout'; +import Navigation from './components/navigation'; function BlogPage() { - return ; + return ( + + + + ); } export default BlogPage; diff --git a/src/views/BlogPage/components/navigation/index.tsx b/src/views/BlogPage/components/navigation/index.tsx new file mode 100644 index 00000000..e6646163 --- /dev/null +++ b/src/views/BlogPage/components/navigation/index.tsx @@ -0,0 +1,35 @@ +import { useState } from 'react'; +import * as S from './style'; +import { BlogTabList } from './types'; + +function Navigation() { + const [selectTab, setSelectTab] = useState('REVIEW'); + const blogTabList: BlogTabList = { + REVIEW: { title: '활동후기', description: 'SOPT 회원들의 생생한 활동 후기 마치 생생정보통' }, + ARTICLE: { title: '아티클', description: 'SOPT 회원들의 멋있는 아티클들' }, + }; + + return ( + + + + {Object.entries(blogTabList).map(([blogTab, tabInfo]) => { + return ( + setSelectTab(blogTab as keyof BlogTabList)} + isSelected={selectTab === blogTab} + > + {tabInfo.title} + + ); + })} + + {blogTabList[selectTab]?.description} +

드롭다운 들어가는 부분

+
+
+ ); +} + +export default Navigation; diff --git a/src/views/BlogPage/components/navigation/style.ts b/src/views/BlogPage/components/navigation/style.ts new file mode 100644 index 00000000..d8fad6a4 --- /dev/null +++ b/src/views/BlogPage/components/navigation/style.ts @@ -0,0 +1,101 @@ +import styled from '@emotion/styled'; + +export const Wrapper = styled.section` + width: 100%; + margin-top: 188px; + display: flex; + align-items: center; + justify-content: center; + + /* 태블릿 뷰 */ + @media (max-width: 939px) and (min-width: 768px) { + margin-top: 188px; + } + /* 모바일 뷰 */ + @media (max-width: 767px) { + margin-top: 76px; + } +`; + +export const Container = styled.main` + width: 900px; + display: flex; + align-items: flex-start; + flex-direction: column; + + /* 태블릿 뷰 */ + @media (max-width: 939px) and (min-width: 768px) { + margin-left: 20px; + margin-right: 20px; + width: 100%; + } + /* 모바일 뷰 */ + @media (max-width: 767px) { + margin-left: 20px; + margin-right: 20px; + width: 100%; + } +`; + +export const TabContainer = styled.section` + display: flex; + align-items: center; +`; + +interface MenuTitleProps { + isSelected: boolean; +} + +export const TabTitle = styled.article` + font-size: 24px; + height: 100%; + line-height: 36px; + font-weight: 700; + letter-spacing: -0.48px; + + color: ${({ isSelected }) => (isSelected ? '#F7F8FA' : '#66666D')}; + + cursor: pointer; + position: relative; + border-bottom: ${({ isSelected }) => isSelected && '2px solid #c0c5c9'}; + + padding-bottom: 16px; + margin-right: 20px; + + /* 모바일 뷰 */ + @media (max-width: 767px) { + margin-right: 12px; + } +`; + +export const TabDescription = styled.h1` + margin-top: 24px; + margin-bottom: 48px; + + font-size: 20px; + font-weight: 600; + line-height: 30px; + letter-spacing: -0.4px; + color: #c3c3c6; + width: 100%; + + /* 모바일 뷰 */ + @media (max-width: 767px) { + margin-top: 14px; + margin-bottom: 16px; + display: flex; + + padding: 16px; + flex-direction: column; + align-items: flex-start; + gap: 10px; + border-radius: 12px; + background: #17171c; + + font-size: 14px; + font-weight: 500; + line-height: 23.1px; + letter-spacing: -0.21px; + color: #f0f0f0; + } +`; diff --git a/src/views/BlogPage/components/navigation/types.ts b/src/views/BlogPage/components/navigation/types.ts new file mode 100644 index 00000000..b14bb9ac --- /dev/null +++ b/src/views/BlogPage/components/navigation/types.ts @@ -0,0 +1,10 @@ +export interface BlogTabList { + REVIEW: { + title: string; + description: string; + }; + ARTICLE: { + title: string; + description: string; + }; +} From 12efe7d81fe4e0cad0c3d2916a70f7f0c8063cc6 Mon Sep 17 00:00:00 2001 From: f0ever0 Date: Wed, 18 Oct 2023 15:19:44 +0900 Subject: [PATCH 04/14] =?UTF-8?q?style=20:=20=EC=A0=84=EC=B2=B4=EC=A0=81?= =?UTF-8?q?=EC=9D=B8=20=EC=BB=AC=EB=9F=AC=20=EC=BD=94=EB=93=9C=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/Footer/OriginFooter/style.ts | 2 +- src/components/Header/header.module.scss | 2 +- src/styles/global.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/components/Footer/OriginFooter/style.ts b/src/components/Footer/OriginFooter/style.ts index 2d278648..be4164f9 100644 --- a/src/components/Footer/OriginFooter/style.ts +++ b/src/components/Footer/OriginFooter/style.ts @@ -3,7 +3,7 @@ import styled from '@emotion/styled'; export const Root = styled.footer` width: 100%; min-height: 162px; - background-color: #2a2a2a; + background-color: #17171c; /* 태블릿 + 데스크탑 뷰 */ @media (min-width: 766px) { diff --git a/src/components/Header/header.module.scss b/src/components/Header/header.module.scss index 2baded36..8b13095a 100644 --- a/src/components/Header/header.module.scss +++ b/src/components/Header/header.module.scss @@ -8,7 +8,7 @@ justify-content: center; align-items: center; position: fixed; - background-color: rgba(22, 22, 28, 0.9); + background-color: #0f0f12; backdrop-filter: blur(20px); z-index: 100; padding: 0 20px; diff --git a/src/styles/global.ts b/src/styles/global.ts index f38426db..3a89d308 100644 --- a/src/styles/global.ts +++ b/src/styles/global.ts @@ -80,7 +80,7 @@ export const global = css` } body { - background-color: #16161c; + background-color: #0f0f12; line-height: 1; } From 78c27172525b4ce9c2892abc1159088fe169a82c Mon Sep 17 00:00:00 2001 From: f0ever0 Date: Wed, 18 Oct 2023 11:32:57 +0900 Subject: [PATCH 05/14] =?UTF-8?q?feat=20:=20blog=20=ED=83=AD=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Header/Desktop/DesktopHeader.tsx | 135 +----------------- src/components/Header/Mobile/HeaderMenu.tsx | 16 +-- src/components/Header/menuTapList.ts | 15 +- src/components/Header/types.ts | 10 +- src/pages/blog.tsx | 1 + src/views/BlogPage/BlogPage.tsx | 7 + src/views/BlogPage/index.tsx | 1 + 7 files changed, 20 insertions(+), 165 deletions(-) create mode 100644 src/pages/blog.tsx create mode 100644 src/views/BlogPage/BlogPage.tsx create mode 100644 src/views/BlogPage/index.tsx diff --git a/src/components/Header/Desktop/DesktopHeader.tsx b/src/components/Header/Desktop/DesktopHeader.tsx index f996103f..fe3b90bf 100644 --- a/src/components/Header/Desktop/DesktopHeader.tsx +++ b/src/components/Header/Desktop/DesktopHeader.tsx @@ -1,16 +1,14 @@ import styled from '@emotion/styled'; import Link from 'next/link'; import { css } from '@emotion/react'; -import { useCallback, useEffect, useState } from 'react'; import { LOGO_IMAGE_URL } from '@src/assets/mainLogo/base64_logo'; import useHeader from '@src/hooks/useHeader'; import { GrowDown } from '@src/lib/styles/animation'; import { menuTapList } from '../menuTapList'; -import { BaseMenuTap, MenuTapType, ParentMenuTap } from '../types'; +import { MenuTapType, SingleMenuTap } from '../types'; function DesktopHeader() { const { handleClickLogo, handleIsSelected } = useHeader(); - const [isSubTapOpened, setIsSubTapOpened] = useState(false); return ( <> @@ -20,138 +18,36 @@ function DesktopHeader() { {menuTapList.map((menuTap) => ( - + ))} - {isSubTapOpened && } ); } type MenuTapProps = { - menuTap: BaseMenuTap; + menuTap: SingleMenuTap; handleIsSelected: (path: string | string[]) => boolean; - isSubTapOpened: boolean; - setIsSubTapOpened: (isOpened: boolean) => void; }; -function MenuTap({ menuTap, handleIsSelected, isSubTapOpened, setIsSubTapOpened }: MenuTapProps) { +function MenuTap({ menuTap, handleIsSelected }: MenuTapProps) { switch (menuTap.type) { case MenuTapType.Anchor: return ( - setIsSubTapOpened(false)} - onMouseEnter={() => setIsSubTapOpened(false)} - > + {menuTap.title} ); case MenuTapType.Router: return ( - setIsSubTapOpened(false)} - onMouseEnter={() => setIsSubTapOpened(false)} - > + {menuTap.title} ); - case MenuTapType.Parent: - return ( - - ); } } -type ParentMenuProps = { - menuTap: ParentMenuTap; - handleIsSelected: (path: string | string[]) => boolean; - isSubTapOpened: boolean; - setIsSubTapOpened: (isOpened: boolean) => void; -}; - -function ParentMenu({ - menuTap, - handleIsSelected, - isSubTapOpened, - setIsSubTapOpened, -}: ParentMenuProps) { - const [isOpened, setIsOpened] = useState(false); - - const closeSubTap = useCallback(() => { - setIsSubTapOpened(false); - setIsOpened(false); - }, [setIsSubTapOpened, setIsOpened]); - - const onMouseIn = () => { - setIsSubTapOpened(true); - setIsOpened(true); - }; - - useEffect(() => { - if (!isSubTapOpened) { - setIsOpened(false); - } - }, [isSubTapOpened]); - - useEffect(() => { - if (isSubTapOpened) { - document.addEventListener('click', closeSubTap); - } - return () => { - document.removeEventListener('click', closeSubTap); - }; - }, [closeSubTap, isSubTapOpened]); - - return ( - t.href))} - isOpened={isOpened} - onMouseEnter={onMouseIn} - onClick={(e) => e.stopPropagation()} - > - {menuTap.title} - {isOpened && ( - - {menuTap.children.map((c) => { - switch (c.type) { - case MenuTapType.Anchor: - return ( - - - {c.title} - - - ); - case MenuTapType.Router: - return ( - - {c.title} - - ); - } - })} - - )} - - ); -} - interface MenuTitleProps { isSelected?: boolean; isOpened?: boolean; @@ -175,21 +71,6 @@ export const SubMenuWrapper = styled.div` animation: growdown 0.4s forwards; `; -const SubMenu = styled.div` - position: absolute; - z-index: 1; - display: flex; - align-items: center; - justify-content: center; - - width: 300px; - top: 80px; - left: 25%; /* it is bad practice */ - transform: translateX(-50%); - - cursor: default; -`; - export const CenterAligner = styled.div` display: flex; align-items: center; @@ -272,8 +153,4 @@ export const MenuTitle = styled.div` } `; -const ParentMenuTitle = styled(MenuTitle)` - position: relative; -`; - export default DesktopHeader; diff --git a/src/components/Header/Mobile/HeaderMenu.tsx b/src/components/Header/Mobile/HeaderMenu.tsx index cff9138a..e5880e01 100644 --- a/src/components/Header/Mobile/HeaderMenu.tsx +++ b/src/components/Header/Mobile/HeaderMenu.tsx @@ -2,7 +2,7 @@ import Link from 'next/link'; import { useEffect } from 'react'; import useHeader from '@src/hooks/useHeader'; import { menuTapList } from '../menuTapList'; -import { BaseMenuTap, MenuState, MenuTapType } from '../types'; +import { MenuState, MenuTapType, SingleMenuTap } from '../types'; import * as S from './HeaderMenu.style'; function useNoScroll(isMenuShown: MenuState) { @@ -27,7 +27,7 @@ interface HeaderMenuProps { } type MenuTapProps = { - menuTap: BaseMenuTap; + menuTap: SingleMenuTap; handleIsSelected: (path: string) => boolean; }; @@ -47,18 +47,6 @@ function MenuTap({ menuTap, handleIsSelected }: MenuTapProps) { {menuTap.title} ); - case MenuTapType.Parent: - return ( - <> - {menuTap.children.map((childMenuTap) => ( - - ))} - - ); } } diff --git a/src/components/Header/menuTapList.ts b/src/components/Header/menuTapList.ts index 98ee20dd..a8bb1663 100644 --- a/src/components/Header/menuTapList.ts +++ b/src/components/Header/menuTapList.ts @@ -12,20 +12,9 @@ export const menuTapList: MenuTapList = [ href: '/project', }, { - type: MenuTapType.Parent, + type: MenuTapType.Router, title: '블로그', - children: [ - { - type: MenuTapType.Router, - title: '활동후기', - href: '/review', - }, - { - type: MenuTapType.Router, - title: '솝티클', - href: '/sopticle', - }, - ], + href: '/blog', }, { type: MenuTapType.Router, diff --git a/src/components/Header/types.ts b/src/components/Header/types.ts index 55a813b8..b1783b91 100644 --- a/src/components/Header/types.ts +++ b/src/components/Header/types.ts @@ -6,18 +6,10 @@ export const enum MenuTapType { Parent = 'PARENT', } -export type ParentMenuTap = { - type: MenuTapType.Parent; - title: string; - children: SingleMenuTap[]; -}; - export type SingleMenuTap = { type: MenuTapType.Router | MenuTapType.Anchor; title: string; href: string; }; -export type BaseMenuTap = SingleMenuTap | ParentMenuTap; - -export type MenuTapList = BaseMenuTap[]; +export type MenuTapList = SingleMenuTap[]; diff --git a/src/pages/blog.tsx b/src/pages/blog.tsx new file mode 100644 index 00000000..29da1c6a --- /dev/null +++ b/src/pages/blog.tsx @@ -0,0 +1 @@ +export { default } from '@src/views/BlogPage'; diff --git a/src/views/BlogPage/BlogPage.tsx b/src/views/BlogPage/BlogPage.tsx new file mode 100644 index 00000000..f4eca1e9 --- /dev/null +++ b/src/views/BlogPage/BlogPage.tsx @@ -0,0 +1,7 @@ +import PageLayout from '@src/components/common/PageLayout'; + +function BlogPage() { + return ; +} + +export default BlogPage; diff --git a/src/views/BlogPage/index.tsx b/src/views/BlogPage/index.tsx new file mode 100644 index 00000000..75531ca0 --- /dev/null +++ b/src/views/BlogPage/index.tsx @@ -0,0 +1 @@ +export { default } from './BlogPage'; From 80adbca25606a3b3905ca4a45ae7d00427552d15 Mon Sep 17 00:00:00 2001 From: f0ever0 Date: Wed, 18 Oct 2023 12:21:32 +0900 Subject: [PATCH 06/14] style : change header style --- src/components/Header/Desktop/DesktopHeader.tsx | 4 ++-- src/components/Header/Header.tsx | 4 ++-- src/components/Header/header.module.scss | 5 +++-- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/components/Header/Desktop/DesktopHeader.tsx b/src/components/Header/Desktop/DesktopHeader.tsx index fe3b90bf..dfb62fd4 100644 --- a/src/components/Header/Desktop/DesktopHeader.tsx +++ b/src/components/Header/Desktop/DesktopHeader.tsx @@ -55,8 +55,8 @@ interface MenuTitleProps { } export const Wrapper = styled.div` - max-width: 1280px; - width: 90%; + max-width: 1200px; + width: 100%; display: flex; justify-content: space-between; `; diff --git a/src/components/Header/Header.tsx b/src/components/Header/Header.tsx index 3e2a3fe9..3ee1be16 100644 --- a/src/components/Header/Header.tsx +++ b/src/components/Header/Header.tsx @@ -4,8 +4,8 @@ import MobileHeader from './Mobile/MobileHeader'; import styles from './header.module.scss'; export function Header() { - const isDesktop = useIsDesktop('992px'); - const isTablet = useIsTablet('766px', '991.9px'); + const isDesktop = useIsDesktop('940px'); + const isTablet = useIsTablet('768px', '939px'); const isMobile = useIsMobile(); return ( diff --git a/src/components/Header/header.module.scss b/src/components/Header/header.module.scss index a4a41259..ecd22026 100644 --- a/src/components/Header/header.module.scss +++ b/src/components/Header/header.module.scss @@ -11,16 +11,17 @@ background-color: rgba(22, 22, 28, 0.9); backdrop-filter: blur(20px); z-index: 100; + padding: 0 20px; + top: 0; @include tablet { height: 48px; - padding: 0 48px; } @include mobile { height: 48px; min-height: 48px; - padding: 0 20px; + justify-content: space-between; } } From c10ea979257994f15ebe736f58776010bd45e5a6 Mon Sep 17 00:00:00 2001 From: f0ever0 Date: Wed, 18 Oct 2023 15:19:28 +0900 Subject: [PATCH 07/14] =?UTF-8?q?feat=20:=20=EB=B8=94=EB=A1=9C=EA=B7=B8=20?= =?UTF-8?q?=ED=83=AD=20=EB=84=A4=EB=B9=84=EA=B2=8C=EC=9D=B4=EC=85=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/views/BlogPage/BlogPage.tsx | 7 +- .../BlogPage/components/navigation/index.tsx | 35 ++++++ .../BlogPage/components/navigation/style.ts | 101 ++++++++++++++++++ .../BlogPage/components/navigation/types.ts | 10 ++ 4 files changed, 152 insertions(+), 1 deletion(-) create mode 100644 src/views/BlogPage/components/navigation/index.tsx create mode 100644 src/views/BlogPage/components/navigation/style.ts create mode 100644 src/views/BlogPage/components/navigation/types.ts diff --git a/src/views/BlogPage/BlogPage.tsx b/src/views/BlogPage/BlogPage.tsx index f4eca1e9..7ea77c88 100644 --- a/src/views/BlogPage/BlogPage.tsx +++ b/src/views/BlogPage/BlogPage.tsx @@ -1,7 +1,12 @@ import PageLayout from '@src/components/common/PageLayout'; +import Navigation from './components/navigation'; function BlogPage() { - return ; + return ( + + + + ); } export default BlogPage; diff --git a/src/views/BlogPage/components/navigation/index.tsx b/src/views/BlogPage/components/navigation/index.tsx new file mode 100644 index 00000000..e6646163 --- /dev/null +++ b/src/views/BlogPage/components/navigation/index.tsx @@ -0,0 +1,35 @@ +import { useState } from 'react'; +import * as S from './style'; +import { BlogTabList } from './types'; + +function Navigation() { + const [selectTab, setSelectTab] = useState('REVIEW'); + const blogTabList: BlogTabList = { + REVIEW: { title: '활동후기', description: 'SOPT 회원들의 생생한 활동 후기 마치 생생정보통' }, + ARTICLE: { title: '아티클', description: 'SOPT 회원들의 멋있는 아티클들' }, + }; + + return ( + + + + {Object.entries(blogTabList).map(([blogTab, tabInfo]) => { + return ( + setSelectTab(blogTab as keyof BlogTabList)} + isSelected={selectTab === blogTab} + > + {tabInfo.title} + + ); + })} + + {blogTabList[selectTab]?.description} +

드롭다운 들어가는 부분

+
+
+ ); +} + +export default Navigation; diff --git a/src/views/BlogPage/components/navigation/style.ts b/src/views/BlogPage/components/navigation/style.ts new file mode 100644 index 00000000..d8fad6a4 --- /dev/null +++ b/src/views/BlogPage/components/navigation/style.ts @@ -0,0 +1,101 @@ +import styled from '@emotion/styled'; + +export const Wrapper = styled.section` + width: 100%; + margin-top: 188px; + display: flex; + align-items: center; + justify-content: center; + + /* 태블릿 뷰 */ + @media (max-width: 939px) and (min-width: 768px) { + margin-top: 188px; + } + /* 모바일 뷰 */ + @media (max-width: 767px) { + margin-top: 76px; + } +`; + +export const Container = styled.main` + width: 900px; + display: flex; + align-items: flex-start; + flex-direction: column; + + /* 태블릿 뷰 */ + @media (max-width: 939px) and (min-width: 768px) { + margin-left: 20px; + margin-right: 20px; + width: 100%; + } + /* 모바일 뷰 */ + @media (max-width: 767px) { + margin-left: 20px; + margin-right: 20px; + width: 100%; + } +`; + +export const TabContainer = styled.section` + display: flex; + align-items: center; +`; + +interface MenuTitleProps { + isSelected: boolean; +} + +export const TabTitle = styled.article` + font-size: 24px; + height: 100%; + line-height: 36px; + font-weight: 700; + letter-spacing: -0.48px; + + color: ${({ isSelected }) => (isSelected ? '#F7F8FA' : '#66666D')}; + + cursor: pointer; + position: relative; + border-bottom: ${({ isSelected }) => isSelected && '2px solid #c0c5c9'}; + + padding-bottom: 16px; + margin-right: 20px; + + /* 모바일 뷰 */ + @media (max-width: 767px) { + margin-right: 12px; + } +`; + +export const TabDescription = styled.h1` + margin-top: 24px; + margin-bottom: 48px; + + font-size: 20px; + font-weight: 600; + line-height: 30px; + letter-spacing: -0.4px; + color: #c3c3c6; + width: 100%; + + /* 모바일 뷰 */ + @media (max-width: 767px) { + margin-top: 14px; + margin-bottom: 16px; + display: flex; + + padding: 16px; + flex-direction: column; + align-items: flex-start; + gap: 10px; + border-radius: 12px; + background: #17171c; + + font-size: 14px; + font-weight: 500; + line-height: 23.1px; + letter-spacing: -0.21px; + color: #f0f0f0; + } +`; diff --git a/src/views/BlogPage/components/navigation/types.ts b/src/views/BlogPage/components/navigation/types.ts new file mode 100644 index 00000000..b14bb9ac --- /dev/null +++ b/src/views/BlogPage/components/navigation/types.ts @@ -0,0 +1,10 @@ +export interface BlogTabList { + REVIEW: { + title: string; + description: string; + }; + ARTICLE: { + title: string; + description: string; + }; +} From 9c116aabb679be0f4c524cd1a2f4a0fb59853a71 Mon Sep 17 00:00:00 2001 From: f0ever0 Date: Wed, 18 Oct 2023 15:19:44 +0900 Subject: [PATCH 08/14] =?UTF-8?q?style=20:=20=EC=A0=84=EC=B2=B4=EC=A0=81?= =?UTF-8?q?=EC=9D=B8=20=EC=BB=AC=EB=9F=AC=20=EC=BD=94=EB=93=9C=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/Footer/OriginFooter/style.ts | 2 +- src/components/Header/header.module.scss | 2 +- src/lib/styles/global.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/components/Footer/OriginFooter/style.ts b/src/components/Footer/OriginFooter/style.ts index 36002259..e49c0e61 100644 --- a/src/components/Footer/OriginFooter/style.ts +++ b/src/components/Footer/OriginFooter/style.ts @@ -4,7 +4,7 @@ import { mainColor } from '@src/lib/styles/colors'; export const Root = styled.footer` width: 100%; min-height: 162px; - background-color: #2a2a2a; + background-color: #17171c; /* 태블릿 + 데스크탑 뷰 */ @media (min-width: 766px) { diff --git a/src/components/Header/header.module.scss b/src/components/Header/header.module.scss index ecd22026..2d96014a 100644 --- a/src/components/Header/header.module.scss +++ b/src/components/Header/header.module.scss @@ -8,7 +8,7 @@ justify-content: center; align-items: center; position: fixed; - background-color: rgba(22, 22, 28, 0.9); + background-color: #0f0f12; backdrop-filter: blur(20px); z-index: 100; padding: 0 20px; diff --git a/src/lib/styles/global.ts b/src/lib/styles/global.ts index f38426db..3a89d308 100644 --- a/src/lib/styles/global.ts +++ b/src/lib/styles/global.ts @@ -80,7 +80,7 @@ export const global = css` } body { - background-color: #16161c; + background-color: #0f0f12; line-height: 1; } From 88ae4c1906e45a4e8ad149f185a3e66a2cd5d617 Mon Sep 17 00:00:00 2001 From: f0ever0 Date: Thu, 19 Oct 2023 21:10:30 +0900 Subject: [PATCH 09/14] refactor : change to inline export --- src/views/BlogPage/BlogPage.tsx | 4 +--- src/views/BlogPage/components/navigation/index.tsx | 4 +--- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/src/views/BlogPage/BlogPage.tsx b/src/views/BlogPage/BlogPage.tsx index 7ea77c88..5c3da795 100644 --- a/src/views/BlogPage/BlogPage.tsx +++ b/src/views/BlogPage/BlogPage.tsx @@ -1,12 +1,10 @@ import PageLayout from '@src/components/common/PageLayout'; import Navigation from './components/navigation'; -function BlogPage() { +export default function BlogPage() { return ( ); } - -export default BlogPage; diff --git a/src/views/BlogPage/components/navigation/index.tsx b/src/views/BlogPage/components/navigation/index.tsx index e6646163..79d24906 100644 --- a/src/views/BlogPage/components/navigation/index.tsx +++ b/src/views/BlogPage/components/navigation/index.tsx @@ -2,7 +2,7 @@ import { useState } from 'react'; import * as S from './style'; import { BlogTabList } from './types'; -function Navigation() { +export default function Navigation() { const [selectTab, setSelectTab] = useState('REVIEW'); const blogTabList: BlogTabList = { REVIEW: { title: '활동후기', description: 'SOPT 회원들의 생생한 활동 후기 마치 생생정보통' }, @@ -31,5 +31,3 @@ function Navigation() { ); } - -export default Navigation; From 4c2e5f6ca7e00f38e5a0473f1054d70eefb7844d Mon Sep 17 00:00:00 2001 From: f0ever0 Date: Thu, 19 Oct 2023 21:11:04 +0900 Subject: [PATCH 10/14] refactor: apply color systems --- src/lib/styles/colors.ts | 1 + src/views/BlogPage/components/navigation/style.ts | 11 ++++++----- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/lib/styles/colors.ts b/src/lib/styles/colors.ts index 06eeadc9..b710de1a 100644 --- a/src/lib/styles/colors.ts +++ b/src/lib/styles/colors.ts @@ -10,6 +10,7 @@ export const colors = { gray10: '#F0F0F0', gray30: '#E4E4E5', + gray40: '#C0C5C9', gray50: '#C3C3C6', gray100: '#9D9DA4', gray200: '#808087', diff --git a/src/views/BlogPage/components/navigation/style.ts b/src/views/BlogPage/components/navigation/style.ts index d8fad6a4..5a4a1cbf 100644 --- a/src/views/BlogPage/components/navigation/style.ts +++ b/src/views/BlogPage/components/navigation/style.ts @@ -1,4 +1,5 @@ import styled from '@emotion/styled'; +import { colors } from '@src/lib/styles/colors'; export const Wrapper = styled.section` width: 100%; @@ -53,11 +54,11 @@ export const TabTitle = styled.article` font-weight: 700; letter-spacing: -0.48px; - color: ${({ isSelected }) => (isSelected ? '#F7F8FA' : '#66666D')}; + color: ${({ isSelected }) => (isSelected ? `${colors.gray10}` : `${colors.gray300}`)}; cursor: pointer; position: relative; - border-bottom: ${({ isSelected }) => isSelected && '2px solid #c0c5c9'}; + border-bottom: ${({ isSelected }) => isSelected && `2px solid ${colors.gray40}`}; padding-bottom: 16px; margin-right: 20px; @@ -76,7 +77,7 @@ export const TabDescription = styled.h1` font-weight: 600; line-height: 30px; letter-spacing: -0.4px; - color: #c3c3c6; + color: ${colors.gray50}; width: 100%; /* 모바일 뷰 */ @@ -90,12 +91,12 @@ export const TabDescription = styled.h1` align-items: flex-start; gap: 10px; border-radius: 12px; - background: #17171c; + background: ${colors.gray800}; font-size: 14px; font-weight: 500; line-height: 23.1px; letter-spacing: -0.21px; - color: #f0f0f0; + color: ${colors.gray10}; } `; From babab4f023a78a880a0fdcaab0600fc70cfb0738 Mon Sep 17 00:00:00 2001 From: f0ever0 Date: Thu, 19 Oct 2023 21:20:34 +0900 Subject: [PATCH 11/14] =?UTF-8?q?style=20:=20header=20=EC=84=A0=ED=83=9D?= =?UTF-8?q?=ED=95=9C=20=ED=83=AD=EC=97=90=20=EB=B0=91=EC=A4=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/Header/Desktop/DesktopHeader.tsx | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/src/components/Header/Desktop/DesktopHeader.tsx b/src/components/Header/Desktop/DesktopHeader.tsx index dfb62fd4..9dfc4aba 100644 --- a/src/components/Header/Desktop/DesktopHeader.tsx +++ b/src/components/Header/Desktop/DesktopHeader.tsx @@ -51,7 +51,6 @@ function MenuTap({ menuTap, handleIsSelected }: MenuTapProps) { interface MenuTitleProps { isSelected?: boolean; isOpened?: boolean; - type?: 'main' | 'sub'; } export const Wrapper = styled.div` @@ -137,20 +136,14 @@ export const MenuTitle = styled.div` line-height: 36px; font-weight: ${({ isSelected }) => (isSelected ? '700' : '500')}; - color: ${({ type, isSelected }) => - type === 'sub' ? (isSelected ? '#fff' : 'rgba(255, 255, 255, 0.5)') : '#fff'}; + color: ${({ isSelected }) => (isSelected ? '#fff' : 'rgba(255, 255, 255, 0.5)')}; cursor: pointer; position: relative; - ${({ isOpened }) => isOpened && menuTitleUnderline}; + ${({ isSelected }) => isSelected && menuTitleUnderline} &:not(:last-child) { padding-right: 40px; } - - &:hover { - color: #fff; - ${({ type }) => type !== 'sub' && menuTitleUnderline} - } `; export default DesktopHeader; From 85aa5ef1b932e07ea217538240f25b3c3acc608b Mon Sep 17 00:00:00 2001 From: f0ever0 Date: Thu, 19 Oct 2023 22:55:55 +0900 Subject: [PATCH 12/14] fix : change constant color --- src/lib/styles/colors.ts | 23 +++++++++---------- .../BlogPage/components/navigation/style.ts | 8 +++---- 2 files changed, 15 insertions(+), 16 deletions(-) diff --git a/src/lib/styles/colors.ts b/src/lib/styles/colors.ts index b710de1a..8f29a143 100644 --- a/src/lib/styles/colors.ts +++ b/src/lib/styles/colors.ts @@ -8,18 +8,17 @@ export const colors = { white: '#FFFFFF', black: '#000000', - gray10: '#F0F0F0', - gray30: '#E4E4E5', - gray40: '#C0C5C9', - gray50: '#C3C3C6', - gray100: '#9D9DA4', - gray200: '#808087', - gray300: '#66666D', - gray400: '#515159', - gray500: '#3F3F47', - gray600: '#2E2E35', - gray700: '#202025', - gray800: '#17171C', + gray10: '#FCFCFC', + gray30: '#F0F0F0', + gray50: '#E4E4E5', + gray100: '#C3C3C6', + gray200: '#9D9DA4', + gray300: '#808087', + gray400: '#66666D', + gray500: '#515159', + gray600: '#3F3F47', + gray700: '#2E2E35', + gray800: '#202025', gray900: '#0F0F12', blue50: '#C8E1FF', diff --git a/src/views/BlogPage/components/navigation/style.ts b/src/views/BlogPage/components/navigation/style.ts index 5a4a1cbf..5cd43e22 100644 --- a/src/views/BlogPage/components/navigation/style.ts +++ b/src/views/BlogPage/components/navigation/style.ts @@ -54,11 +54,11 @@ export const TabTitle = styled.article` font-weight: 700; letter-spacing: -0.48px; - color: ${({ isSelected }) => (isSelected ? `${colors.gray10}` : `${colors.gray300}`)}; + color: ${({ isSelected }) => (isSelected ? `${colors.gray30}` : `${colors.gray400}`)}; cursor: pointer; position: relative; - border-bottom: ${({ isSelected }) => isSelected && `2px solid ${colors.gray40}`}; + border-bottom: ${({ isSelected }) => isSelected && `2px solid ${colors.gray200}`}; padding-bottom: 16px; margin-right: 20px; @@ -77,7 +77,7 @@ export const TabDescription = styled.h1` font-weight: 600; line-height: 30px; letter-spacing: -0.4px; - color: ${colors.gray50}; + color: ${colors.gray100}; width: 100%; /* 모바일 뷰 */ @@ -97,6 +97,6 @@ export const TabDescription = styled.h1` font-weight: 500; line-height: 23.1px; letter-spacing: -0.21px; - color: ${colors.gray10}; + color: ${colors.gray30}; } `; From 5c178a187e1ade0546fd49c35729e800113d9076 Mon Sep 17 00:00:00 2001 From: f0ever0 Date: Fri, 20 Oct 2023 13:41:50 +0900 Subject: [PATCH 13/14] fix : blog tab mobile boder style --- src/views/BlogPage/components/navigation/style.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/views/BlogPage/components/navigation/style.ts b/src/views/BlogPage/components/navigation/style.ts index 5cd43e22..d4381ad9 100644 --- a/src/views/BlogPage/components/navigation/style.ts +++ b/src/views/BlogPage/components/navigation/style.ts @@ -65,6 +65,7 @@ export const TabTitle = styled.article` /* 모바일 뷰 */ @media (max-width: 767px) { + border-bottom: ${({ isSelected }) => isSelected && `1px solid ${colors.gray200}`}; margin-right: 12px; } `; From 8966d63b256c0a820ece4261950aaa5547288a67 Mon Sep 17 00:00:00 2001 From: f0ever0 Date: Fri, 20 Oct 2023 13:44:23 +0900 Subject: [PATCH 14/14] fix : blog tab description --- src/views/BlogPage/components/navigation/index.tsx | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/views/BlogPage/components/navigation/index.tsx b/src/views/BlogPage/components/navigation/index.tsx index 79d24906..eeade166 100644 --- a/src/views/BlogPage/components/navigation/index.tsx +++ b/src/views/BlogPage/components/navigation/index.tsx @@ -5,8 +5,14 @@ import { BlogTabList } from './types'; export default function Navigation() { const [selectTab, setSelectTab] = useState('REVIEW'); const blogTabList: BlogTabList = { - REVIEW: { title: '활동후기', description: 'SOPT 회원들의 생생한 활동 후기 마치 생생정보통' }, - ARTICLE: { title: '아티클', description: 'SOPT 회원들의 멋있는 아티클들' }, + REVIEW: { + title: '활동후기', + description: '회원들의 진솔한 후기를 통해 SOPT를 미리 만나보세요. ', + }, + ARTICLE: { + title: '아티클', + description: '회원들의 아티클을 통해 SOPT에서 얻은 인사이트를 확인해보세요.', + }, }; return (