-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
15 changed files
with
247 additions
and
56 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -56,6 +56,12 @@ | |
} | ||
] | ||
} | ||
}, | ||
{ | ||
"files": ["*.ts", "*.tsx"], | ||
"rules": { | ||
"no-undef": "off" | ||
} | ||
} | ||
] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
import type { Meta, StoryObj } from '@storybook/react'; | ||
|
||
import { useModalStore } from '@/src/stores/modalStore'; | ||
|
||
import Modal from '.'; | ||
|
||
const meta: Meta<typeof Modal> = { | ||
title: 'Components/Modal', | ||
component: Modal, | ||
decorators: [ | ||
(Story) => ( | ||
<div style={{ height: '500px' }}> | ||
<Story /> | ||
</div> | ||
), | ||
], | ||
}; | ||
|
||
export default meta; | ||
|
||
type Story = StoryObj<typeof Modal>; | ||
|
||
export const DeleteArticle: Story = { | ||
render: function Render() { | ||
const { openModal } = useModalStore(); | ||
|
||
openModal('deleteArticle'); | ||
|
||
return <Modal />; | ||
}, | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
import type { PropsWithChildren } from 'react'; | ||
|
||
import Portal from '../Portal'; | ||
import * as styles from './style.css'; | ||
|
||
const ModalContainer = ({ children }: PropsWithChildren<unknown>) => { | ||
return ( | ||
<Portal id="modal-root"> | ||
<div className={styles.dimmed} /> | ||
<div className={styles.modalStyle}>{children}</div> | ||
</Portal> | ||
); | ||
}; | ||
|
||
export default ModalContainer; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
import { assignInlineVars } from '@vanilla-extract/dynamic'; | ||
|
||
import { useModalStore } from '@/src/stores/modalStore'; | ||
import { COLORS } from '@/src/styles/tokens'; | ||
|
||
import ModalContainer from '../ModalContainer'; | ||
import * as styles from '../style.css'; | ||
|
||
const DeleteArticle = () => { | ||
const { closeModal } = useModalStore(); | ||
|
||
return ( | ||
<ModalContainer> | ||
<strong className={styles.title}>해당 글을 삭제할까요?</strong> | ||
<p className={styles.body}> | ||
{'삭제한 글은 복구할 수 없어요!\n삭제하시겠어요'} | ||
</p> | ||
<div> | ||
<button | ||
type="button" | ||
className={styles.button} | ||
style={assignInlineVars({ | ||
[styles.buttonColor]: COLORS['Grey/600'], | ||
[styles.buttonBackgroundColor]: COLORS['Grey/150'], | ||
})} | ||
onClick={closeModal} | ||
> | ||
취소 | ||
</button> | ||
<button | ||
type="button" | ||
className={styles.button} | ||
style={assignInlineVars({ | ||
[styles.buttonColor]: COLORS['Grey/White'], | ||
[styles.buttonBackgroundColor]: COLORS['Blue/Default'], | ||
})} | ||
> | ||
만들기 | ||
</button> | ||
</div> | ||
</ModalContainer> | ||
); | ||
}; | ||
|
||
export default DeleteArticle; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
import { useModalStore } from '@/src/stores/modalStore'; | ||
|
||
import DeleteArticle from './components/DeleteArticle'; | ||
|
||
const Modal = () => { | ||
const { type } = useModalStore(); | ||
|
||
if (type === 'deleteArticle') return <DeleteArticle />; | ||
|
||
return null; | ||
}; | ||
|
||
export default Modal; |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
import { createVar, style } from '@vanilla-extract/css'; | ||
|
||
import { sprinkles } from '@/src/styles/sprinkles.css'; | ||
import { COLORS } from '@/src/styles/tokens'; | ||
import { middleLayer, positionCenter, topLayer } from '@/src/styles/utils.css'; | ||
|
||
export const modalStyle = style([ | ||
positionCenter, | ||
topLayer, | ||
{ | ||
padding: '32px', | ||
width: '400px', | ||
borderRadius: '16px', | ||
backgroundColor: COLORS['Grey/White'], | ||
}, | ||
]); | ||
|
||
export const dimmed = style([ | ||
middleLayer, | ||
{ | ||
backgroundColor: COLORS['Dim/50'], | ||
position: 'fixed', | ||
left: '0', | ||
top: '0', | ||
right: '0', | ||
bottom: '0', | ||
}, | ||
]); | ||
|
||
export const title = style([ | ||
sprinkles({ | ||
typography: '20/Title/Semibold', | ||
}), | ||
{ | ||
display: 'block', | ||
marginBottom: '18px', | ||
}, | ||
]); | ||
|
||
export const body = style([ | ||
sprinkles({ | ||
typography: '15/Body/Regular', | ||
}), | ||
{ | ||
display: 'block', | ||
}, | ||
]); | ||
|
||
export const buttonColor = createVar(); | ||
export const buttonBackgroundColor = createVar(); | ||
|
||
export const button = style([ | ||
sprinkles({ | ||
typography: '15/Title/Medium', | ||
}), | ||
{ | ||
width: '164px', | ||
color: buttonColor, | ||
backgroundColor: buttonBackgroundColor, | ||
padding: '16px 40px', | ||
borderRadius: '8px', | ||
marginTop: '24px', | ||
selectors: { | ||
'& + &': { | ||
marginLeft: '8px', | ||
}, | ||
}, | ||
}, | ||
]); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
import type { PropsWithChildren } from 'react'; | ||
import { useEffect } from 'react'; | ||
import ReactDOM from 'react-dom'; | ||
|
||
interface PortalProps { | ||
id: 'modal-root'; | ||
tag?: keyof HTMLElementTagNameMap; | ||
} | ||
|
||
const Portal = ({ | ||
children, | ||
id, | ||
tag = 'div', | ||
}: PropsWithChildren<PortalProps>) => { | ||
const root = document.createElement(tag); | ||
root.id = id; | ||
|
||
useEffect(() => { | ||
if (root) { | ||
document.body.appendChild(root); | ||
} | ||
|
||
return () => { | ||
document.body.removeChild(root); | ||
}; | ||
}, [root]); | ||
|
||
return ReactDOM.createPortal(children, root); | ||
}; | ||
|
||
export default Portal; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
import { createStore } from 'zustand'; | ||
import { shallow } from 'zustand/shallow'; | ||
import { useStoreWithEqualityFn as useStore } from 'zustand/traditional'; | ||
|
||
type ModalType = 'deleteArticle'; | ||
|
||
interface State { | ||
type: ModalType | null; | ||
} | ||
|
||
interface Action { | ||
openModal: (type: ModalType) => void; | ||
closeModal: () => void; | ||
} | ||
|
||
export const modalStore = createStore<State & Action>((set) => ({ | ||
type: null, | ||
openModal: (type) => set({ type }), | ||
closeModal: () => set({ type: null }), | ||
})); | ||
|
||
export const useModalStore = () => | ||
useStore(modalStore, (state) => state, shallow); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters