-
Notifications
You must be signed in to change notification settings - Fork 2
[Feat]: 헤더, 푸터 구현 #66
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 8 commits
d6fc328
5678857
318b745
a10e090
d003ec3
e182a68
fac621d
8cd053a
73384c6
2ac85cc
8dfb97b
696edac
8cf6c61
11a69bb
58b2728
340da68
eb3c641
9907e94
e8066ae
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
This file was deleted.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,13 +1,19 @@ | ||
| import { style } from '@vanilla-extract/css'; | ||
|
|
||
| export const layoutContainer = style({ | ||
| height: '100vh', | ||
| display: 'flex', | ||
| flexDirection: 'column', | ||
| height: '100vh', | ||
| overflow: 'hidden', | ||
| overflow: 'auto', | ||
| scrollbarWidth: 'none', | ||
| msOverflowStyle: 'none', | ||
| selectors: { | ||
| '&::-webkit-scrollbar': { | ||
| display: 'none', | ||
| }, | ||
| }, | ||
| }); | ||
|
|
||
| export const layoutMain = style({ | ||
| flex: 1, | ||
| overflow: 'hidden', | ||
| }); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,37 @@ | ||
| import { style } from '@vanilla-extract/css'; | ||
|
|
||
| import { colors } from '@/style/token'; | ||
| import { fonts } from '@/style/token/typography.css'; | ||
|
|
||
| export const footerContainer = style({ | ||
| display: 'flex', | ||
| flexDirection: 'column', | ||
| height: '15.1rem', | ||
| padding: '4rem 0', | ||
| justifyContent: 'center', | ||
| alignItems: 'center', | ||
| borderTop: `2px solid ${colors.grey1}`, | ||
| background: colors.black01, | ||
| }); | ||
|
|
||
| export const linkWrapper = style({ | ||
| display: 'flex', | ||
| gap: '2.7rem', | ||
| marginBottom: '2rem', | ||
| }); | ||
|
|
||
| export const linkText = style({ | ||
| color: colors.grey11, | ||
| ...fonts.caption01, | ||
| cursor: 'pointer', | ||
| textDecoration: 'none', | ||
| }); | ||
|
|
||
| export const infoWrapper = style({ | ||
| textAlign: 'center', | ||
| }); | ||
|
|
||
| export const infoText = style({ | ||
| color: colors.grey11, | ||
| ...fonts.caption02, | ||
| }); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,26 @@ | ||
| import { Link } from 'react-router-dom'; | ||
|
|
||
| import * as styles from './Footer.css'; | ||
|
|
||
| import { PATH } from '@/route'; | ||
|
|
||
| const Footer = () => { | ||
| return ( | ||
| <footer className={styles.footerContainer}> | ||
| <nav className={styles.linkWrapper}> | ||
| <Link to={PATH.TERMS} className={styles.linkText}> | ||
| 이용약관 | ||
| </Link> | ||
| <Link to={PATH.PRIVACY} className={styles.linkText}> | ||
| 개인정보처리방침 | ||
| </Link> | ||
| </nav> | ||
| <div className={styles.infoWrapper}> | ||
| <p className={styles.infoText}>대표: 이현준</p> | ||
| <p className={styles.infoText}>이메일: 999inedot@gmail.com</p> | ||
| </div> | ||
| </footer> | ||
| ); | ||
| }; | ||
|
|
||
| export default Footer; | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -4,6 +4,9 @@ import { colors } from '@/style/token/color.css'; | |
| import { fonts } from '@/style/token/typography.css'; | ||
|
|
||
| export const header = style({ | ||
| position: 'sticky', | ||
| top: 0, | ||
| zIndex: 100, | ||
|
||
| width: '100%', | ||
| backgroundColor: colors.bg_black01, | ||
| display: 'flex', | ||
|
|
@@ -12,8 +15,8 @@ export const header = style({ | |
|
|
||
| export const headerInner = style({ | ||
| width: '100%', | ||
| maxWidth: '90rem', | ||
| padding: '0.94rem 5rem', | ||
| maxWidth: '128rem', | ||
| padding: '1.5rem 8rem', | ||
| display: 'flex', | ||
| justifyContent: 'space-between', | ||
| alignItems: 'center', | ||
|
|
@@ -26,33 +29,62 @@ export const logo = style({ | |
|
|
||
| export const navWrapper = style({ | ||
| display: 'flex', | ||
| gap: '1.25rem', | ||
| gap: '2rem', | ||
| }); | ||
|
|
||
| export const navItem = style({ | ||
| display: 'flex', | ||
| padding: '0.75rem 1.25rem', | ||
| padding: '1.2rem 2rem', | ||
| justifyContent: 'center', | ||
| alignItems: 'center', | ||
| flexShrink: 0, | ||
| color: '#5A5E66', // 추후 토큰 색상으로 변경 | ||
| color: colors.grey6, | ||
| textAlign: 'center', | ||
| ...fonts.subtitle05, | ||
| background: 'transparent', | ||
| border: 'none', | ||
| cursor: 'pointer', | ||
| whiteSpace: 'nowrap', | ||
| transition: 'color 0.2s', | ||
| selectors: { | ||
| '&:hover': { | ||
| color: colors.grey7, | ||
| }, | ||
| }, | ||
| }); | ||
|
|
||
| export const navItemActive = style({ | ||
| color: `${colors.grey11} !important`, | ||
|
||
| selectors: { | ||
| '&:hover': { | ||
| color: `${colors.grey11} !important`, | ||
| }, | ||
| }, | ||
| }); | ||
|
|
||
| export const active = style({ | ||
| color: '#FDFDFD', | ||
| color: colors.grey11, | ||
| }); | ||
|
|
||
| export const profilePlaceholder = style({ | ||
| width: '3.125rem', | ||
| height: '3.125rem', | ||
| width: '5rem', | ||
| height: '5rem', | ||
| borderRadius: '50%', | ||
| backgroundColor: '#5A5E66', // 추후 토큰 색상으로 변경 | ||
| backgroundColor: colors.grey6, | ||
| flexShrink: 0, | ||
| }); | ||
|
|
||
| export const loginButton = style({ | ||
| color: colors.grey11, | ||
| textAlign: 'center', | ||
| ...fonts.subtitle05, | ||
| background: 'transparent', | ||
| border: 'none', | ||
| cursor: 'pointer', | ||
| transition: 'color 0.2s', | ||
| selectors: { | ||
| '&:hover': { | ||
| color: colors.grey7, | ||
| }, | ||
| }, | ||
| }); | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,59 @@ | ||
| import { useState } from 'react'; | ||
| import { useNavigate } from 'react-router-dom'; | ||
|
|
||
| import * as styles from './Header.css'; | ||
|
|
||
| import { PATH } from '@/route/path'; | ||
|
|
||
| const MENUS = [ | ||
| { label: '나의 할 일', path: PATH.TODO }, | ||
| { label: '나의 만다르트', path: PATH.MANDAL }, | ||
| { label: '나의 히스토리', path: PATH.HISTORY }, | ||
| ]; | ||
|
|
||
| const Header = () => { | ||
| const [activeMenu, setActiveMenu] = useState<string>(MENUS[0].label); | ||
| const [isLoggedIn, setIsLoggedIn] = useState<boolean>(false); | ||
| const navigate = useNavigate(); | ||
|
|
||
| const handleLogin = () => { | ||
| // 로그인 로직 추가하기 | ||
| setIsLoggedIn(true); | ||
| }; | ||
|
|
||
| const handleMenuClick = (menuLabel: string, path: string) => { | ||
| setActiveMenu(menuLabel); | ||
| navigate(path); | ||
| }; | ||
|
|
||
| return ( | ||
| <header className={styles.header}> | ||
| <div className={styles.headerInner}> | ||
| <h1 className={styles.logo}>NINEDOT</h1> | ||
|
|
||
| <nav className={styles.navWrapper}> | ||
| {MENUS.map((menu) => ( | ||
| <button | ||
| key={menu.label} | ||
| className={`${styles.navItem} ${activeMenu === menu.label ? styles.navItemActive : ''}`} | ||
| onClick={() => handleMenuClick(menu.label, menu.path)} | ||
| aria-current={activeMenu === menu.label ? 'page' : undefined} | ||
| > | ||
|
Comment on lines
+40
to
+41
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. p5) aria-current 속성 사용 좋아요 🙊 |
||
| {menu.label} | ||
| </button> | ||
| ))} | ||
| </nav> | ||
|
|
||
| {isLoggedIn ? ( | ||
| <div className={styles.profilePlaceholder} /> | ||
| ) : ( | ||
| <button className={styles.loginButton} onClick={handleLogin}> | ||
| 로그인 | ||
| </button> | ||
| )} | ||
| </div> | ||
| </header> | ||
| ); | ||
| }; | ||
|
|
||
| export default Header; | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,90 @@ | ||
| import { style } from '@vanilla-extract/css'; | ||
|
|
||
| import { colors } from '@/style/token/color.css'; | ||
| import { fonts } from '@/style/token/typography.css'; | ||
|
|
||
| export const header = style({ | ||
| position: 'sticky', | ||
| top: 0, | ||
| zIndex: 100, | ||
| width: '100%', | ||
| backgroundColor: colors.bg_black01, | ||
| display: 'flex', | ||
| justifyContent: 'center', | ||
| }); | ||
|
|
||
| export const headerInner = style({ | ||
| width: '100%', | ||
| maxWidth: '128rem', | ||
| padding: '1.5rem 8rem', | ||
| display: 'flex', | ||
| justifyContent: 'space-between', | ||
| alignItems: 'center', | ||
| }); | ||
|
|
||
| export const logo = style({ | ||
| color: colors.white01, | ||
| ...fonts.subtitle05, | ||
| }); | ||
|
|
||
| export const navWrapper = style({ | ||
| display: 'flex', | ||
| gap: '2rem', | ||
| }); | ||
|
|
||
| export const navItem = style({ | ||
| display: 'flex', | ||
| padding: '1.2rem 2rem', | ||
| justifyContent: 'center', | ||
| alignItems: 'center', | ||
| flexShrink: 0, | ||
| color: colors.grey6, | ||
| textAlign: 'center', | ||
| ...fonts.subtitle05, | ||
| background: 'transparent', | ||
| border: 'none', | ||
| cursor: 'pointer', | ||
| whiteSpace: 'nowrap', | ||
| transition: 'color 0.2s', | ||
| selectors: { | ||
| '&:hover': { | ||
| color: colors.grey7, | ||
| }, | ||
| }, | ||
| }); | ||
|
|
||
| export const navItemActive = style({ | ||
| color: `${colors.grey11} !important`, | ||
| selectors: { | ||
| '&:hover': { | ||
| color: `${colors.grey11} !important`, | ||
| }, | ||
| }, | ||
| }); | ||
|
|
||
| export const active = style({ | ||
| color: colors.grey11, | ||
| }); | ||
|
|
||
| export const profilePlaceholder = style({ | ||
| width: '5rem', | ||
| height: '5rem', | ||
| borderRadius: '50%', | ||
| backgroundColor: colors.grey6, | ||
| flexShrink: 0, | ||
| }); | ||
|
|
||
| export const loginButton = style({ | ||
| color: colors.grey11, | ||
| textAlign: 'center', | ||
| ...fonts.subtitle05, | ||
| background: 'transparent', | ||
| border: 'none', | ||
| cursor: 'pointer', | ||
| transition: 'color 0.2s', | ||
| selectors: { | ||
| '&:hover': { | ||
| color: colors.grey7, | ||
| }, | ||
| }, | ||
| }); |
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
p3) 사이트 제작자의 이름이나 제작자의 웹 페이지 또는 피드백을 위한 연락처 정보는
<address>태그 활용해 보는 것도 좋을 것 같아요 !!There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
수정해버릴게요