-
Notifications
You must be signed in to change notification settings - Fork 0
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: ✨ LevelModal 컴포넌트 이관 #98
Changes from 6 commits
1a186b8
7cd59f6
556e269
611df31
0be80b7
53088cd
a292574
31ce12c
2c5a2c1
4a79cff
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,141 @@ | ||
import { ComponentStory, ComponentMeta } from '@storybook/react'; | ||
import React, { useState } from 'react'; | ||
import Button from '@/components/commons/Button'; | ||
|
||
import Modal from './Modal'; | ||
|
||
export default { | ||
title: 'Components/Modal', | ||
component: Modal, | ||
argTypes: { | ||
title: { control: 'text', name: 'title' }, | ||
description: { control: 'text', name: 'description' }, | ||
withCloseButton: { control: 'boolean' }, | ||
noMoreSee: { control: 'boolean' }, | ||
}, | ||
args: { withCloseButton: true, noMoreSee: true }, | ||
} as ComponentMeta<typeof Modal>; | ||
|
||
const Template: ComponentStory<typeof Modal> = (args) => { | ||
const [isModalOpen, setIsModalOpen] = useState(false); | ||
|
||
const openModal = () => setIsModalOpen(true); | ||
const closeModal = () => setIsModalOpen(false); | ||
|
||
return <Modal openModal={openModal} closeModal={closeModal} {...args} />; | ||
}; | ||
|
||
export const Default = Template.bind({}); | ||
Default.args = { | ||
open: true, | ||
header: '헤더입니다', | ||
title: '타이틀입니다', | ||
withCloseButton: true, | ||
noMoreSee: true, | ||
description: '설명설명설명설명설명설명설명설명', | ||
buttons: ( | ||
<Button type="primary" width="large"> | ||
기록할 맥주 검색하러 가기 | ||
</Button> | ||
), | ||
}; | ||
|
||
export const 로그아웃: ComponentStory<typeof Modal> = () => { | ||
const [isModalOpen, setIsModalOpen] = useState(true); | ||
|
||
const openModal = () => setIsModalOpen(true); | ||
const closeModal = () => setIsModalOpen(false); | ||
|
||
return ( | ||
<Modal | ||
open={isModalOpen} | ||
openModal={openModal} | ||
closeModal={closeModal} | ||
buttons={ | ||
<> | ||
<Button type="grey" onClick={closeModal}> | ||
취소 | ||
</Button> | ||
<Button type="primary" onClick={closeModal}> | ||
확인 | ||
</Button> | ||
</> | ||
} | ||
title="로그아웃 하시겠어요?" | ||
/> | ||
); | ||
}; | ||
|
||
export const 회원탈퇴: ComponentStory<typeof Modal> = () => { | ||
const [isModalOpen, setIsModalOpen] = useState(true); | ||
|
||
const openModal = () => setIsModalOpen(true); | ||
const closeModal = () => setIsModalOpen(false); | ||
|
||
return ( | ||
<Modal | ||
open={isModalOpen} | ||
openModal={openModal} | ||
closeModal={closeModal} | ||
buttons={ | ||
<> | ||
<Button type="grey" onClick={closeModal}> | ||
취소 | ||
</Button> | ||
<Button type="primary" onClick={closeModal}> | ||
확인 | ||
</Button> | ||
</> | ||
} | ||
title="정말 회원 탈퇴 하시겠어요?" | ||
description="회원 탈퇴 시 저장된 모든 정보가 삭제됩니다." | ||
/> | ||
); | ||
}; | ||
|
||
export const 닉네임_수정: ComponentStory<typeof Modal> = () => { | ||
const [isModalOpen, setIsModalOpen] = useState(true); | ||
|
||
const openModal = () => setIsModalOpen(true); | ||
const closeModal = () => setIsModalOpen(false); | ||
|
||
return ( | ||
<Modal | ||
open={isModalOpen} | ||
openModal={openModal} | ||
closeModal={closeModal} | ||
withCloseButton | ||
header="닉네임 수정하기" | ||
buttons={ | ||
<Button type="primary" width="large" onClick={closeModal}> | ||
완료 | ||
</Button> | ||
} | ||
/> | ||
); | ||
}; | ||
|
||
export const 기록할_맥주_검색_하러가기: ComponentStory<typeof Modal> = () => { | ||
const [isModalOpen, setIsModalOpen] = useState(true); | ||
|
||
const openModal = () => setIsModalOpen(true); | ||
const closeModal = () => setIsModalOpen(false); | ||
|
||
return ( | ||
<Modal | ||
open={isModalOpen} | ||
openModal={openModal} | ||
closeModal={closeModal} | ||
title="어떤 맥주를 기록하시겠어요?" | ||
description="맥주를 선택하면 기록을 시작할 수 있어요." | ||
withCloseButton | ||
buttons={ | ||
<Button type="primary" width="large" onClick={closeModal}> | ||
기록할 맥주 검색하러 가기 | ||
</Button> | ||
} | ||
noMoreSee | ||
/> | ||
); | ||
}; | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,122 @@ | ||
import styled from '@emotion/styled'; | ||
import React, { ReactNode } from 'react'; | ||
|
||
import ModalLayout from '@/components/layouts/ModalLayout'; | ||
import Icon from '@/components/commons/Icon'; | ||
|
||
interface ModalProps { | ||
openModal?: () => void; | ||
closeModal?: () => void; | ||
open: boolean; | ||
setOpen?: () => void; | ||
buttons?: ReactNode; | ||
header?: string; | ||
title?: string; | ||
description?: string | ReactNode; | ||
withCloseButton?: boolean; | ||
noMoreSee?: boolean; | ||
disabledDimClick?: boolean; | ||
} | ||
|
||
const Modal = (props: ModalProps) => { | ||
const { | ||
closeModal, | ||
open, | ||
buttons, | ||
header, | ||
title, | ||
description, | ||
withCloseButton, | ||
noMoreSee, | ||
disabledDimClick, | ||
} = props; | ||
|
||
return ( | ||
<ModalLayout open={open} {...(!disabledDimClick && { onClose: closeModal })}> | ||
<StyledModal open={open}> | ||
<Header> | ||
{withCloseButton ? ( | ||
<button type="button" aria-label="닫기"> | ||
<Icon name="Close" size={24} onClick={closeModal} /> | ||
</button> | ||
) : ( | ||
<Icon name="Close" size={24} color="white" /> | ||
)} | ||
{header} | ||
<Icon name="Close" size={24} color="white" /> | ||
</Header> | ||
{title && <Title>{title}</Title>} | ||
{description && <Description>{description}</Description>} | ||
{buttons && <ButtonContainer>{buttons}</ButtonContainer>} | ||
{noMoreSee && <NoMoreSee onClick={closeModal}>다시 보지 않기</NoMoreSee>} | ||
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. 다시보지 않기의 onClick 이벤트가 closeModal만 들어가는것이 맞을까용..? 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. 넵 noMoreSee prop은 공통 Modal에 있기에 적합하지 않다는 의견에 동의합니다 이 PR은 LevelModal 컴포넌트를 만들면서 필요한 Modal 컴포넌트를 이관한 것이니, 홈 화면 전용 모달을 만들때 NoMoreSee 부분을 리팩토링하면 좋을 것 같아요 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. #104 (comment) 추가했어요! |
||
</StyledModal> | ||
</ModalLayout> | ||
); | ||
}; | ||
|
||
export default Modal; | ||
|
||
const StyledModal = styled.div<{ open: boolean }>` | ||
position: absolute; | ||
top: 50%; | ||
left: 50%; | ||
transform: translate(-50%, -50%); | ||
display: flex; | ||
flex-direction: column; | ||
align-items: center; | ||
justify-content: space-between; | ||
width: calc(100% - 76px); | ||
padding: 16px 16px 20px 16px; | ||
border-radius: 12px; | ||
background-color: ${(p) => p.theme.color.white}; | ||
|
||
${(p) => !p.open && `display:none;`} | ||
`; | ||
|
||
const Header = styled.div` | ||
position: absolute; | ||
top: 0; | ||
left: 0; | ||
width: 100%; | ||
padding: 14px; | ||
font-weight: 700; | ||
font-size: 16px; | ||
line-height: 19px; | ||
color: #323232; | ||
display: flex; | ||
justify-content: space-between; | ||
`; | ||
|
||
const Title = styled.p` | ||
width: 100%; | ||
margin: 46px 0 8px 0; | ||
text-align: center; | ||
color: #323232; | ||
${(p) => p.theme.fonts.SubTitle2}; | ||
`; | ||
|
||
const Description = styled.p` | ||
width: 100%; | ||
text-align: center; | ||
color: ${({ theme }) => theme.color.grey4}; | ||
${(p) => p.theme.fonts.Body1}; | ||
`; | ||
|
||
const ButtonContainer = styled.div` | ||
width: 100%; | ||
display: flex; | ||
justify-content: center; | ||
gap: 13px; | ||
margin: 30px 0 10px 0; | ||
`; | ||
|
||
const NoMoreSee = styled.div` | ||
font-weight: 600; | ||
font-size: 13px; | ||
line-height: 16px; | ||
border-bottom: 1px solid #c7c7c7; | ||
color: ${({ theme }) => theme.color.grey3}; | ||
height: fit-content; | ||
margin-top: 10px; | ||
cursor: pointer; | ||
`; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export { default } from './Modal'; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
import { ILevel } from '@/types'; | ||
import { ComponentStory, ComponentMeta } from '@storybook/react'; | ||
import { useState } from 'react'; | ||
|
||
import LevelModal from './LevelModal'; | ||
|
||
const LEVEL_DATA: ILevel[] = [ | ||
{ | ||
id: 1, | ||
tier: 1, | ||
imageUrl: 'https://cdn.pixabay.com/photo/2016/04/24/14/19/paper-1349664_1280.png', | ||
req: 0, | ||
}, | ||
{ | ||
id: 2, | ||
tier: 2, | ||
imageUrl: 'https://cdn.pixabay.com/photo/2016/04/24/14/19/paper-1349664_1280.png', | ||
req: 1, | ||
}, | ||
{ | ||
id: 3, | ||
tier: 3, | ||
imageUrl: 'https://cdn.pixabay.com/photo/2016/04/24/14/19/paper-1349664_1280.png', | ||
req: 5, | ||
}, | ||
{ | ||
id: 4, | ||
tier: 4, | ||
imageUrl: 'https://cdn.pixabay.com/photo/2016/04/24/14/19/paper-1349664_1280.png', | ||
req: 12, | ||
}, | ||
{ | ||
id: 5, | ||
tier: 5, | ||
imageUrl: 'https://cdn.pixabay.com/photo/2016/04/24/14/19/paper-1349664_1280.png', | ||
req: 20, | ||
}, | ||
]; | ||
|
||
export default { | ||
title: 'Components/mypage/LevelModal', | ||
component: LevelModal, | ||
} as ComponentMeta<typeof LevelModal>; | ||
|
||
const Template: ComponentStory<typeof LevelModal> = () => { | ||
const [isOpen, setIsOpen] = useState(true); | ||
|
||
return ( | ||
<LevelModal | ||
isLevelModalOpen={isOpen} | ||
openLevelModal={() => setIsOpen(true)} | ||
closeLevelModal={() => setIsOpen(false)} | ||
levels={LEVEL_DATA} | ||
/> | ||
); | ||
}; | ||
|
||
export const Default = Template.bind({}); |
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.
openModal과 setOpen은 불필요한 prop인 것 같고, 코드상에 사용되는 부분이 없어보이는데
전달받아야하는 이유가 있나요??
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.
Modal 컴포넌트를 옮기는 과정에서 중복되는 prop이 생긴것 같아 정리하였습니다!
불필요하게 중복되는 prop은 제거하고, 네이밍을 통일했습니다
a292574