-
Notifications
You must be signed in to change notification settings - Fork 2
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
1 parent
f553dd5
commit 07b7247
Showing
30 changed files
with
612 additions
and
38 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
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,97 @@ | ||
import { useState } from 'react'; | ||
import Unit from '../Unit'; | ||
import { Button, Modal } from '@/packages'; | ||
|
||
export function DemoModalDefault() { | ||
const [visible, setVisible] = useState(false); | ||
|
||
const openModal = () => setVisible(true); | ||
|
||
const closeModal = () => { | ||
setVisible(false); | ||
}; | ||
|
||
return ( | ||
<Unit layout="row"> | ||
<> | ||
<Button onClick={openModal}>Open Modal</Button> | ||
<Modal visible={visible} onClose={closeModal}> | ||
<Modal.Header>Modal Title</Modal.Header> | ||
<Modal.Body> | ||
<div>This is a modal.</div> | ||
</Modal.Body> | ||
<Modal.Footer> | ||
<Button onClick={closeModal}>Cancel</Button> | ||
<Button type="primary" onClick={closeModal}> | ||
Confirm | ||
</Button> | ||
</Modal.Footer> | ||
</Modal> | ||
</> | ||
</Unit> | ||
); | ||
} | ||
|
||
export function DemoModalNotCloseOnOverlayClick() { | ||
const [visible, setVisible] = useState(false); | ||
|
||
const openModal = () => setVisible(true); | ||
|
||
const closeModal = () => { | ||
setVisible(false); | ||
}; | ||
|
||
return ( | ||
<Unit layout="row"> | ||
<> | ||
<Button onClick={openModal}>Open Modal</Button> | ||
<Modal | ||
visible={visible} | ||
onClose={closeModal} | ||
closeOnOverlayClick={false} | ||
> | ||
<Modal.Header>Modal Title</Modal.Header> | ||
<Modal.Body> | ||
<div>This is a modal.</div> | ||
</Modal.Body> | ||
<Modal.Footer> | ||
<Button onClick={closeModal}>Cancel</Button> | ||
<Button type="primary" onClick={closeModal}> | ||
Confirm | ||
</Button> | ||
</Modal.Footer> | ||
</Modal> | ||
</> | ||
</Unit> | ||
); | ||
} | ||
|
||
export function DemoModalWidth() { | ||
const [visible, setVisible] = useState(false); | ||
|
||
const openModal = () => setVisible(true); | ||
|
||
const closeModal = () => { | ||
setVisible(false); | ||
}; | ||
|
||
return ( | ||
<Unit layout="row"> | ||
<> | ||
<Button onClick={openModal}>Open Modal</Button> | ||
<Modal visible={visible} onClose={closeModal} width="400px"> | ||
<Modal.Header>Modal Title</Modal.Header> | ||
<Modal.Body> | ||
<div>This is a modal.</div> | ||
</Modal.Body> | ||
<Modal.Footer> | ||
<Button onClick={closeModal}>Cancel</Button> | ||
<Button type="primary" onClick={closeModal}> | ||
Confirm | ||
</Button> | ||
</Modal.Footer> | ||
</Modal> | ||
</> | ||
</Unit> | ||
); | ||
} |
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,53 @@ | ||
import React, { FC, PropsWithChildren, useCallback, useMemo } from 'react'; | ||
import { createPortal } from 'react-dom'; | ||
import { ModalProps } from './Modal.types'; | ||
import { useControlled, usePortal } from '../utils/hooks'; | ||
import Overlay from '../Overlay'; | ||
import ModalWrapper from './ModalWrapper'; | ||
import { ModalConfig, ModalContext } from './modal-context'; | ||
import ModalCloseButton from './ModalCloseButton'; | ||
|
||
const Modal: FC<PropsWithChildren<ModalProps>> = ({ | ||
visible, | ||
width = '540px', | ||
closeOnOverlayClick = true, | ||
onClose, | ||
children, | ||
...restProps | ||
}) => { | ||
const portal = usePortal('modal'); | ||
const [internalValue, setInternalValue] = useControlled<boolean>({ | ||
defaultValue: false, | ||
value: visible, | ||
}); | ||
|
||
const closeModal = useCallback(() => { | ||
setInternalValue(false); | ||
onClose?.(); | ||
}, [onClose, setInternalValue]); | ||
|
||
const modalConfig: ModalConfig = useMemo( | ||
() => ({ | ||
width, | ||
closeOnOverlayClick, | ||
closeModal, | ||
}), | ||
[closeModal, width, closeOnOverlayClick] | ||
); | ||
|
||
if (!portal) return null; | ||
|
||
return createPortal( | ||
<ModalContext.Provider value={modalConfig}> | ||
<Overlay visible={internalValue}> | ||
<ModalWrapper visible={internalValue} {...restProps}> | ||
<ModalCloseButton /> | ||
{children} | ||
</ModalWrapper> | ||
</Overlay> | ||
</ModalContext.Provider>, | ||
portal | ||
); | ||
}; | ||
|
||
export default 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 { HTMLAttributes } from 'react'; | ||
|
||
interface BaseModalProps { | ||
visible?: boolean; | ||
width?: string; | ||
closeOnOverlayClick?: boolean; | ||
onClose?: () => void; | ||
} | ||
|
||
type NativeModalProps = Omit< | ||
HTMLAttributes<HTMLDivElement>, | ||
keyof BaseModalProps | ||
>; | ||
|
||
export type ModalProps = BaseModalProps & NativeModalProps; |
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,18 @@ | ||
import React, { FC, PropsWithChildren } from 'react'; | ||
|
||
const ModalBody: FC<PropsWithChildren> = ({ children, ...restProps }) => { | ||
return ( | ||
<div className="raw-modal-body" {...restProps}> | ||
{children} | ||
<style jsx>{` | ||
.raw-modal-body { | ||
flex: 1 1 0%; | ||
padding: 8px 24px; | ||
font-size: 16px; | ||
} | ||
`}</style> | ||
</div> | ||
); | ||
}; | ||
|
||
export default ModalBody; |
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,41 @@ | ||
import React from 'react'; | ||
import { X } from 'react-feather'; | ||
import { useTheme } from '../Theme'; | ||
import { useModalContext } from './modal-context'; | ||
|
||
const ModalCloseButton = () => { | ||
const theme = useTheme(); | ||
const { closeModal } = useModalContext(); | ||
|
||
return ( | ||
<button className="raw-modal-close-button" onClick={closeModal}> | ||
<X size={20} /> | ||
<style jsx>{` | ||
.raw-modal-close-button { | ||
position: absolute; | ||
top: 16px; | ||
right: 16px; | ||
display: flex; | ||
align-items: center; | ||
justify-content: center; | ||
cursor: pointer; | ||
color: ${theme.palette.accents7}; | ||
transition-property: color; | ||
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); | ||
transition-duration: 0.15s; | ||
flex-shrink: 0; | ||
padding: 0; | ||
background: transparent; | ||
appearance: none; | ||
border: none; | ||
outline: none; | ||
} | ||
.raw-modal-close-button:hover { | ||
color: ${theme.palette.foreground}; | ||
} | ||
`}</style> | ||
</button> | ||
); | ||
}; | ||
|
||
export default ModalCloseButton; |
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,20 @@ | ||
import React, { FC, PropsWithChildren } from 'react'; | ||
|
||
const ModalFooter: FC<PropsWithChildren> = ({ children, ...restProps }) => { | ||
return ( | ||
<footer className="raw-modal-footer" {...restProps}> | ||
{children} | ||
<style jsx>{` | ||
.raw-modal-footer { | ||
display: flex; | ||
align-items: center; | ||
justify-content: flex-end; | ||
padding: 16px 24px; | ||
gap: 16px; | ||
} | ||
`}</style> | ||
</footer> | ||
); | ||
}; | ||
|
||
export default ModalFooter; |
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,19 @@ | ||
import React, { FC, PropsWithChildren } from 'react'; | ||
|
||
const ModalHeader: FC<PropsWithChildren> = ({ children, ...restProps }) => { | ||
return ( | ||
<header className="raw-modal-header" {...restProps}> | ||
{children} | ||
<style jsx>{` | ||
.raw-modal-header { | ||
flex: 0 1 0%; | ||
padding: 16px 24px; | ||
font-weight: 600; | ||
font-size: 24px; | ||
} | ||
`}</style> | ||
</header> | ||
); | ||
}; | ||
|
||
export default ModalHeader; |
Oops, something went wrong.