-
Notifications
You must be signed in to change notification settings - Fork 6
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
Feat: 리스트 상세페이지 안쪽 레이아웃 퍼블리싱 #15
Changes from 37 commits
91eb607
918ec84
9f031bf
6c70a71
03328bf
5260285
ceca2ea
b89db45
7fde5f0
08b9252
292fbf7
250b759
4723e2e
f31b0b7
20971db
dea6474
3fcbad3
da2e056
aaa72c6
6da3a8c
f7b372a
8d60c1f
d5687d0
668609c
6101a8a
1fb34c0
332575e
eaa8444
30d5a43
c3a2490
2685880
2bd4c0c
584b6f1
20b7633
eba8ed8
b7794b3
6430315
f39effc
37b1606
e33c35c
89aa080
c90d561
5a3b3a8
4627d2d
dec085b
0462dd3
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,74 @@ | ||
import { keyframes, style } from '@vanilla-extract/css'; | ||
|
||
export const backGround = style({ | ||
position: 'fixed', | ||
top: 0, | ||
left: 0, | ||
bottom: 0, | ||
right: 0, | ||
background: 'rgba(0,0,0,0.3)', | ||
zIndex: 999, | ||
}); | ||
|
||
export const wrapper = style({ | ||
padding: '37px 0 43px', | ||
|
||
position: 'fixed', | ||
bottom: 0, | ||
left: 0, | ||
right: 0, | ||
|
||
display: 'flex', | ||
flexDirection: 'column', | ||
justifyContent: 'center', | ||
|
||
backgroundColor: '#ffffff', | ||
borderTopLeftRadius: '25px', | ||
borderTopRightRadius: '25px', | ||
|
||
transitionProperty: 'all', | ||
transitionDuration: '0.2s', | ||
}); | ||
|
||
const slideIn = keyframes({ | ||
from: { transform: 'translateY(100%)' }, | ||
to: { transform: 'translateY(0)' }, | ||
}); | ||
|
||
export const sheetActive = style({ | ||
animation: `${slideIn} 0.2s ease-in-out`, | ||
}); | ||
|
||
export const sheetItemWrapper = style({ | ||
display: 'flex', | ||
justifyContent: 'space-between', | ||
alignItems: 'center', | ||
|
||
':hover': { | ||
backgroundColor: '#EFEFF0', | ||
}, | ||
}); | ||
|
||
export const checkIcon = style({ | ||
display: 'none', | ||
marginRight: '28px', | ||
|
||
selectors: { | ||
[`${sheetItemWrapper}:hover &`]: { | ||
display: 'block', | ||
}, | ||
}, | ||
}); | ||
|
||
export const sheetItem = style({ | ||
width: '100%', | ||
fontSize: '1.4rem', | ||
cursor: 'pointer', | ||
padding: '2.5rem 2.8rem 2.5rem', | ||
|
||
selectors: { | ||
[`${sheetItemWrapper}:hover &`]: { | ||
color: '#FF5454', | ||
}, | ||
}, | ||
}); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
import { style } from '@vanilla-extract/css'; | ||
|
||
export const container = style({ | ||
width: '100%', | ||
|
||
display: 'flex', | ||
justifyContent: 'space-between', | ||
alignItems: 'center', | ||
}); | ||
|
||
export const shareAndOthers = style({ | ||
width: '100%', | ||
|
||
display: 'flex', | ||
flexDirection: 'row', | ||
justifyContent: 'right', | ||
alignItems: 'center', | ||
gap: '20px', | ||
}); | ||
|
||
export const buttonComponent = style({ | ||
cursor: 'pointer', | ||
}); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,143 @@ | ||
'use client'; | ||
|
||
import * as styles from './Footer.css'; | ||
import CollectIcon from '/public/icons/collect.svg'; | ||
import ShareIcon from '/public/icons/share.svg'; | ||
import EtcIcon from '/public/icons/etc.svg'; | ||
import BottomSheet from '@/app/[userNickname]/[listId]/_components/BottomSheet/BottomSheet'; | ||
import { MouseEvent, useState } from 'react'; | ||
import ModalPortal from '@/components/ModalPortal'; | ||
import copyUrl from '@/lib/utils/copyUrl'; | ||
import saveImageFromHtml from '@/lib/utils/saveImageFromHtml'; | ||
import kakaotalkShare from '@/components/KakaotalkShare/kakaotalkShare'; | ||
import { useParams, useRouter } from 'next/navigation'; | ||
import toasting from '@/lib/utils/toasting'; | ||
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. 코드리뷰로 리뷰드릴건 없고 많이 배워가기만해서 민망하네요 ㅎㅎㅎ
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. 앗 놓친게 역시 있었네용..!!ㅎㅎ 감사합니다 수정하겠습니다!!!! 👍 👍 👍 |
||
|
||
interface BottomSheetOptionsProps { | ||
key: string; | ||
title: string; | ||
onClick: () => void; | ||
} | ||
|
||
interface SheetTypeProps { | ||
type: 'share' | 'etc'; | ||
} | ||
|
||
interface FooterProps { | ||
category: string; | ||
listId: string; | ||
title: string; | ||
description: string; | ||
items: []; | ||
collaborators: []; | ||
ownerNickname: string; | ||
} | ||
|
||
function Footer({ data }: { data: FooterProps }) { | ||
const router = useRouter(); | ||
const params = useParams<{ userNickname: string; listId: string }>(); | ||
|
||
const [isSheetActive, setSheetActive] = useState<boolean>(false); | ||
const [sheetOptionList, setSheetOptionList] = useState<BottomSheetOptionsProps[]>([]); | ||
|
||
const handleSheetOptionList = ({ type }: SheetTypeProps) => { | ||
const listUrl = `${process.env.NEXT_PUBLIC_BASE_URL}/${params?.userNickname}/${params?.listId}`; | ||
|
||
if (type === 'share') { | ||
const optionList = [ | ||
{ | ||
key: 'copyLink', | ||
title: '리스트 링크 복사하기', | ||
onClick: () => { | ||
copyUrl(listUrl); | ||
setSheetActive(false); | ||
}, | ||
}, | ||
{ | ||
key: 'kakaoShare', | ||
title: '리스트 카카오톡으로 공유하기', | ||
onClick: () => { | ||
// TODO: image로 저장한다음에 해당 image를 보내줘야한다. | ||
kakaotalkShare({ | ||
title: data.title, | ||
description: data.description, | ||
image: | ||
'https://i.namu.wiki/i/-8Iah6PGZzzQuY1KtJIbj8_KBbX4whnbaq8AYShoqphdJOpfJDskZZ2Y3bU2I5Jpnx8aRi1LXTz1_e0v_fMrp172modjOmKRcxcME5dmM6IDAIgqktw5yIs75is2CgC1GrGoxZPwxpeTXudKIxWn2w.webp', | ||
listItem: data.items, | ||
collaborators: data.collaborators, | ||
listId: data.listId, | ||
userNickname: data.ownerNickname, | ||
}); | ||
setSheetActive(false); | ||
}, | ||
}, | ||
]; | ||
setSheetOptionList([...optionList]); | ||
return; | ||
} | ||
Comment on lines
+76
to
+77
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. if문-fast 리턴 패턴 너무 편안하고 좋아요 ㅎㅎ |
||
|
||
if (type === 'etc') { | ||
const optionList = [ | ||
{ | ||
key: 'saveToImg', | ||
title: '리스트 이미지로 저장하기', | ||
onClick: () => { | ||
setSheetActive(false); | ||
saveImageFromHtml({ filename: `${data.category}_${data.listId}` }); | ||
}, | ||
}, | ||
{ | ||
key: 'copyAndCreateList', | ||
title: '이 리스트 템플릿으로 바로 리스트 작성하기', | ||
onClick: () => { | ||
toasting({ type: 'default', txt: '리스트 작성 페이지로 이동합니다.' }); | ||
router.push(`/create?title=${data.title}&category=${data.category}`); | ||
}, | ||
}, | ||
]; | ||
setSheetOptionList([...optionList]); | ||
return; | ||
} | ||
}; | ||
|
||
const handleSheetActive = ({ type }: SheetTypeProps) => { | ||
handleSheetOptionList({ type }); | ||
setSheetActive((prev: boolean) => !prev); | ||
}; | ||
|
||
const handleOutsideClick = (e: MouseEvent) => { | ||
if (e.target === e.currentTarget) { | ||
setSheetActive(false); | ||
} | ||
}; | ||
|
||
// TODO: 콜렉트 API생성되면 요청보내고 UI변경시키기 | ||
const handleCollect = () => { | ||
console.log('콜렉트기능 미구현'); | ||
}; | ||
|
||
return ( | ||
<> | ||
{isSheetActive && ( | ||
<ModalPortal> | ||
<BottomSheet onClose={handleOutsideClick} isActive={isSheetActive} optionList={sheetOptionList} /> | ||
</ModalPortal> | ||
)} | ||
<div className={styles.container}> | ||
<div className={styles.buttonComponent}> | ||
<CollectIcon onClick={handleCollect} /> | ||
</div> | ||
<div className={styles.shareAndOthers}> | ||
<div className={styles.buttonComponent} onClick={() => handleSheetActive({ type: 'share' })}> | ||
<ShareIcon /> | ||
</div> | ||
<div className={styles.buttonComponent} onClick={() => handleSheetActive({ type: 'etc' })}> | ||
<EtcIcon /> | ||
</div> | ||
</div> | ||
</div> | ||
</> | ||
); | ||
} | ||
|
||
export default Footer; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
import { style } from '@vanilla-extract/css'; | ||
|
||
export const container = style({ | ||
width: '100%', | ||
|
||
display: 'flex', | ||
justifyContent: 'right', | ||
alignItems: 'center', | ||
}); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
import * as styles from './Header.css'; | ||
import SelectComponent from '@/components/SelectComponent/SelectComponent'; | ||
|
||
interface OptionsProps { | ||
value: string; | ||
label: string; | ||
} | ||
|
||
interface HeaderProps { | ||
handleChangeListType: (target: OptionsProps) => void | undefined; | ||
} | ||
|
||
const dropdownOptions = [ | ||
{ | ||
value: 'simple', | ||
label: '간단히', | ||
}, | ||
{ | ||
value: 'detail', | ||
label: '자세히', | ||
}, | ||
]; | ||
function Header({ handleChangeListType }: HeaderProps) { | ||
return ( | ||
<div className={styles.container}> | ||
<SelectComponent name="listType" options={dropdownOptions} isSearchable={false} onChange={handleChangeListType} /> | ||
</div> | ||
); | ||
} | ||
|
||
export default 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.
바닐라익스트랙 keyframe 이렇게 쓰는거였군요,,!!!
왜인지 제 드롭다운은 스르륵이 적용 안 됐는데 이제야 이유를 알아갑니다,,🩷
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.
나현님께서 구현하신 부분입니다!!! 컨플릭트 없애려고 전전긍긍하다보니 제꺼로 들어와버렸네요...ㅠㅠㅠㅠㅠ
나현님최고!