-
Notifications
You must be signed in to change notification settings - Fork 38
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
[김정현] Sprint9 #283
The head ref may contain hidden characters: "Next-\uAE40\uC815\uD604-sprint9"
[김정현] Sprint9 #283
Changes from all commits
21c3ea7
837acf5
633500f
5e97825
9646b44
5b8c0a3
65c162d
e5bd56b
bea8a6b
663f4b5
fdb8835
925ea24
f1b7a27
ccb701a
295d8f4
b84de6d
f089662
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
# 제목은 최대 50글자까지 아래에 작성: ex) Feat: Add Key mapping | ||
|
||
# 본문은 아래에 작성 | ||
|
||
# 꼬릿말은 아래에 작성: ex) Github issue #23 | ||
|
||
# --- COMMIT END --- | ||
# <타입> 리스트 | ||
# feat : 기능 (새로운 기능) | ||
# fix : 버그 (버그 수정) | ||
# refactor : 리팩토링 (기존 기능 개선, 구조 변경 하지만 외부 동작에는 변화 없음) | ||
# design : CSS 등 사용자 UI 디자인 변경 | ||
# comment : 필요한 주석 추가 및 변경 | ||
# style : 스타일 (코드 형식, 세미콜론 추가: 비즈니스 로직에 변경 없음) | ||
# docs : 문서 수정 (문서 추가, 수정, 삭제, README) | ||
# test : 테스트 (테스트 코드 추가, 수정, 삭제: 비즈니스 로직에 변경 없음) | ||
# chore : 기타 변경사항 (빌드 스크립트 수정, assets, 패키지 매니저 등) | ||
# init : 초기 생성 | ||
# rename : 파일 혹은 폴더명을 수정하거나 옮기는 작업만 한 경우 | ||
# remove : 파일을 삭제하는 작업만 수행한 경우 | ||
# ------------------ | ||
# 제목 첫 글자를 대문자로 | ||
# 제목은 명령문으로 | ||
# 제목 끝에 마침표(.) 금지 | ||
# 제목과 본문을 한 줄 띄워 분리하기 | ||
# 본문은 "어떻게" 보다 "무엇을", "왜"를 설명한다. | ||
# 본문에 여러줄의 메시지를 작성할 땐 "-"로 구분 | ||
# ------------------ | ||
# <꼬리말> | ||
# 필수가 아닌 optioanl | ||
# Fixes :이슈 수정중 (아직 해결되지 않은 경우) | ||
# Resolves : 이슈 해결했을 때 사용 | ||
# Ref : 참고할 이슈가 있을 때 사용 | ||
# Related to : 해당 커밋에 관련된 이슈번호 (아직 해결되지 않은 경우) | ||
# ex) Fixes: #47 Related to: #32, #21 |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
.btnContainer { | ||
overflow: hidden; | ||
border-radius: 8px; | ||
background-color: var(--color-blue); | ||
} | ||
|
||
.button { | ||
display: inline-block; | ||
padding: 11.5px 23px; | ||
font-size: 1.6rem; | ||
font-weight: 600; | ||
border-radius: 8px; | ||
background-color: var(--color-blue); | ||
color: #ffffff; | ||
cursor: pointer; | ||
} | ||
|
||
.button:disabled { | ||
cursor: default; | ||
background-color: var(--color-gray400); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
import { ReactNode } from 'react'; | ||
import Link from 'next/link'; | ||
import styles from './LinkButton.module.css'; | ||
|
||
type ButtonType = 'button' | 'submit' | 'reset'; | ||
|
||
interface LinkButtonProps { | ||
href?: string; | ||
type?: ButtonType; | ||
btnName?: ReactNode; | ||
isActive?: boolean; | ||
className?: string; | ||
} | ||
|
||
export default function LinkButton({ | ||
href, | ||
type, | ||
btnName, | ||
isActive, | ||
className, | ||
}: LinkButtonProps) { | ||
if (href) { | ||
return ( | ||
<div className={`${styles.btnContainer} ${className}`}> | ||
<Link className={styles.button} href={href}> | ||
{btnName} | ||
</Link> | ||
</div> | ||
); | ||
} | ||
|
||
return ( | ||
<> | ||
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. 이 빈 태그는 불필요해보이는데 제거해도 좋을 것 같아요! |
||
<button | ||
className={`${styles.button} ${className}`} | ||
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. classname을 부여하는데 조건식이 필요하다면 classnames라는 라이브러리를 사용해보세요! 아주 편하고 좋습니다 ㅎㅎ |
||
disabled={isActive} | ||
type={type} | ||
> | ||
{btnName} | ||
</button> | ||
</> | ||
); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
.sortContainer { | ||
position: relative; | ||
} | ||
.sortList { | ||
display: flex; | ||
align-items: center; | ||
width: 130px; | ||
padding: 8px 19px; | ||
border: 1px solid var(--color-gray200); | ||
border-radius: 12px; | ||
cursor: pointer; | ||
} | ||
.sortList > p { | ||
display: inline-block; | ||
width: 100%; | ||
font-size: 1.6rem; | ||
font-weight: 400; | ||
} | ||
.sortArrowIcon { | ||
display: block; | ||
width: 24px; | ||
height: 24px; | ||
background: url(/images/icon/ic_arrow_down.png) no-repeat center center; | ||
} | ||
.sortOptions { | ||
position: absolute; | ||
top: 45px; | ||
right: 0; | ||
} | ||
.sortOptions > ul { | ||
width: 130px; | ||
border: 1px solid var(--color-gray200); | ||
border-radius: 12px; | ||
background: #fff; | ||
} | ||
.sortOptions > ul > li { | ||
text-align: center; | ||
border-bottom: 1px solid var(--color-gray200); | ||
} | ||
.sortOptions > ul > li > button { | ||
width: 100%; | ||
padding: 9px 0; | ||
line-height: 24px; | ||
font-size: 1.6rem; | ||
cursor: pointer; | ||
} | ||
.sortOptions > ul > li:last-child { | ||
border-bottom: none; | ||
} | ||
@media (max-width: 1199px) { | ||
.sortList { | ||
width: 120px; | ||
} | ||
.sortOptions > ul { | ||
width: 120px; | ||
} | ||
} | ||
|
||
@media (max-width: 768px) { | ||
.sortList { | ||
width: 42px; | ||
height: 42px; | ||
padding: 9px; | ||
} | ||
.sortList > p { | ||
display: none; | ||
} | ||
|
||
.sortArrowIcon { | ||
display: block; | ||
background: url(/images/icon/ic_sort.png) no-repeat center center; | ||
} | ||
.sortOptions { | ||
top: 50px; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
import { MouseEvent } from 'react'; | ||
import styles from './SortOptions.module.css'; | ||
|
||
interface SortOptionProps { | ||
isOpen: boolean; | ||
sortText: string; | ||
sortHandler: (e: MouseEvent<HTMLButtonElement>) => void; | ||
showOptions: () => void; | ||
} | ||
|
||
export default function SortOptions({ | ||
isOpen, | ||
sortText, | ||
sortHandler, | ||
showOptions, | ||
}: SortOptionProps) { | ||
return ( | ||
<div className={styles.sortContainer}> | ||
<div className={styles.sortList} onClick={showOptions}> | ||
<p>{sortText}</p> | ||
<i className={styles.sortArrowIcon} /> | ||
</div> | ||
{isOpen && ( | ||
<div className={styles.sortOptions}> | ||
<ul> | ||
<li> | ||
<button data-type="recent" onClick={sortHandler}> | ||
최신순 | ||
</button> | ||
</li> | ||
<li> | ||
<button data-type="like" onClick={sortHandler}> | ||
좋아요순 | ||
</button> | ||
</li> | ||
</ul> | ||
</div> | ||
)} | ||
</div> | ||
); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
.header { | ||
position: fixed; | ||
top: 0; | ||
width: 100%; | ||
padding: 0 20rem; | ||
z-index: 999; | ||
background: #fff; | ||
border-bottom: 1px solid #dfdfdf; | ||
} | ||
|
||
.mainHeader { | ||
display: flex; | ||
align-items: center; | ||
justify-content: space-between; | ||
height: 70px; | ||
} | ||
.logoBox { | ||
margin-right: 32px; | ||
} | ||
.headerNav { | ||
display: flex; | ||
align-items: center; | ||
} | ||
.navList > ul { | ||
display: flex; | ||
align-items: center; | ||
font-size: 1.8rem; | ||
} | ||
.navList > ul > li { | ||
text-align: center; | ||
padding: 24px 15px; | ||
} | ||
.navList > ul > li > a { | ||
display: inline-block; | ||
width: 78px; | ||
font-weight: 700; | ||
} | ||
.navList > ul > li > a.active { | ||
color: var(--color-blue); | ||
} | ||
|
||
.logo { | ||
position: relative; | ||
display: block; | ||
width: 153px; | ||
height: 51px; | ||
} | ||
.mobileLogo { | ||
display: none; | ||
} | ||
.profile { | ||
position: relative; | ||
width: 40px; | ||
height: 40px; | ||
margin-right: 40px; | ||
} | ||
/* header */ | ||
|
||
@media (max-width: 1199px) { | ||
.header { | ||
padding: 0 2.4rem; | ||
} | ||
.profile { | ||
margin-right: 0; | ||
} | ||
} | ||
|
||
@media (max-width: 768px) { | ||
/* 메인 페이지 */ | ||
.header { | ||
padding: 0 1.6rem; | ||
} | ||
.logo { | ||
display: none; | ||
} | ||
.mobileLogo { | ||
position: relative; | ||
display: block; | ||
width: 81px; | ||
height: 40px; | ||
} | ||
.logoBox { | ||
margin-right: 16px; | ||
} | ||
.navList > ul { | ||
font-size: 1.6rem; | ||
} | ||
.navList > ul > li { | ||
padding: 0 8px 0 0; | ||
} | ||
.navList > ul > li:last-child { | ||
padding: 0; | ||
} | ||
.navList > ul > li > a { | ||
width: 100%; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
import Image from 'next/image'; | ||
import Link from 'next/link'; | ||
import NAVIGATION_LIST from '@/utils/NAVIGATION_LIST'; | ||
import styles from './Header.module.css'; | ||
|
||
const navList = NAVIGATION_LIST.map(list => ( | ||
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. 이 부분을 컴포넌트로 분리하면 좋을 것 같네요! |
||
<li key={list.name}> | ||
<Link href={list.path}>{list.name}</Link> | ||
</li> | ||
)); | ||
|
||
export default function Header() { | ||
return ( | ||
<header className={styles.header}> | ||
<div className={styles.mainHeader}> | ||
<div className={styles.headerNav}> | ||
<div className={styles.logoBox}> | ||
<Link href="/" className={styles.logo}> | ||
<Image fill src="/images/[email protected]" alt="판다마켓 로고" /> | ||
</Link> | ||
<Link href="/" className={styles.mobileLogo}> | ||
<Image | ||
fill | ||
src="/images/[email protected]" | ||
alt="판다마켓 모바일 로고" | ||
/> | ||
</Link> | ||
</div> | ||
<div className={styles.navList}> | ||
<ul>{navList}</ul> | ||
</div> | ||
</div> | ||
<Link href="/" className={styles.profile}> | ||
<Image fill src="/images/[email protected]" alt="사용자 프로필" /> | ||
</Link> | ||
</div> | ||
</header> | ||
); | ||
} |
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.
이런 props들의 기본 값을 설정해주면 동작을 명확히 하는데 도움을 줄거에요!