36 |
37 | Simple, lightweight hook for Modals/Dialogs.
38 |
39 | This hook is also isomorphic, meaning it works with SSR (server side rendering).
40 |
41 |
46 |
47 | Features
48 | --------
49 | - SSR (server side rendering) support
50 | - TypeScript support
51 | - 2 dependencies ([use-ssr](https://github.com/alex-cory/use-ssr), [react-useportal](https://github.com/alex-cory/react-useportal))
52 | - Built in state
53 |
54 | ### Examples
55 | - [Example](https://codesandbox.io/s/usemodal-dj3du)
56 |
57 | Installation
58 | ------------
59 |
60 | ```shell
61 | yarn add use-react-modal or npm i -S use-react-modal
62 | ```
63 |
64 | Usage
65 | -----
66 |
67 | ### Basic Usage
68 |
69 | ```jsx
70 | import useModal from 'use-react-modal'
71 |
72 | const App = () => {
73 | const { isOpen, openModal, closeModal, Modal } = useModal()
74 |
75 | return (
76 | <>
77 |
78 | {isOpen && (
79 |
80 |
81 | Whatever you put here will be centered to the middle of the screen.
82 |
83 | )
84 | >
85 | )
86 | }
87 | ```
88 |
89 | ### With Provider
90 | ```jsx
91 | import useModal, { Provider } from 'use-react-modal'
92 |
93 | const MyComponent = () => {
94 | const { isOpen, openModal, Modal } = useModal()
95 |
96 | return (
97 | <>
98 |
99 | {isOpen && (
100 |
101 | Now, whatever you put here will be centered AND have a backdrop
102 | with the color specified in the Provider
103 |
104 | )
105 | >
106 | )
107 | }
108 |
109 |
110 | const App = () => (
111 |
112 |
113 |
114 | )
115 | ```
116 |
117 | **Make sure you are passing the html synthetic event to the `openModal` and `toggleModal` . i.e. `onClick={e => openModal(e)}`**
118 |
119 | ### Usage with a `ref`
120 | If for some reason, you don't want to pass around the `event` to `openModal` or `toggleModal`, you can use a `targetRef` like this.
121 | ```jsx
122 | import useModal from 'use-react-modal'
123 |
124 | const App = () => {
125 | const { targetRef, openModal, closeModal, isOpen, Modal } = useModal()
126 |
127 | return (
128 | <>
129 | {/* see below how I don't have to pass the event if I use the ref */}
130 |
133 | {isOpen && (
134 |
135 |
136 | , hit ESC or
137 | Cool Modal 😜
138 |
139 |
140 | )}
141 | >
142 | )
143 | }
144 | ```
145 |
146 | Options
147 | -----
148 | | Option | Description |
149 | | --------------------- | ---------------------------------------------------------------------------------------- |
150 | | `background` | sets the color of the backdrop, if nothing is set, there will be no backdrop |
151 | | `closeOnOutsideClick` | This will close the modal when not clicking within the modal. Default is `true` |
152 | | `closeOnEsc` | This will allow you to hit ESC and it will close the modal. Default is `true` |
153 | | `bindTo` | This is the DOM node you want to attach the modal to. By default it attaches to `document.body` |
154 | | `isOpen` | This will be the default for the modal being open or closed. Default is `false` |
155 | | `onOpen` | This is used to call something when the modal is opened |
156 | | `onClose` | This is used to call something when the modal is closed |
157 | | html event handlers (i.e. `onClick`) | These can be used instead of `onOpen`. |
158 |
159 | ### Option Usage
160 |
161 | ```js
162 | const {
163 | openModal,
164 | closeModal,
165 | toggleModal,
166 | isOpen,
167 | Modal,
168 | // if you don't pass an event to openModal, closeModal, or toggleModal, you will need to
169 | // put this on the element you want to interact with/click to open the modal
170 | targetRef,
171 | // this allows you to interact directly with the backdrop/overlay
172 | backdropRef,
173 | // this allows you to interact directly with the modal
174 | modalRef,
175 | } = useModal({
176 | // sets the color of the backdrop, if nothing is set, the backdrop will be transparent unless it's set in the Provider
177 | // setting to `null` removes any background set in the `Provider`
178 | background: 'rgba(0, 0, 0, 0.5)',
179 | closeOnOutsideClick: true,
180 | closeOnEsc: true,
181 | bindTo, // attach the portal to this node in the DOM
182 | isOpen: false,
183 | // `event` has all the fields that a normal `event` would have such as `event.target.value`, etc.
184 | // with the additional `portal` and `targetEl` added to it as seen in the examples below
185 | onOpen: (event) => {
186 | // can access: event.portal, event.targetEl, event.event, event.target, etc.
187 | },
188 | // `onClose` will not have an `event` unless you pass an `event` to `closePortal`
189 | onClose({ targetEl, event, portal }) {},
190 | // `targetEl` is the element that you either are attaching a `ref` to
191 | // or that you are putting `openPortal` or `togglePortal` or `closePortal` on
192 |
193 | // in addition, any event handler such as onClick, onMouseOver, etc will be handled the same
194 | onClick({ targetEl, event, portal }) {}
195 | })
196 | ```
197 | Can also do array destructuring
198 | ```js
199 | const [openModal, closeModal, isOpen, Modal, toggleModal, targetRef, portalRef, modalRef] = useModal()
200 | ```
201 |
202 | Todos
203 | ------
204 | - [ ] animations 😜
205 | - [ ] React Native support. [1](https://github.com/zenyr/react-native-portal) [2](https://github.com/cloudflare/react-gateway) [3](https://medium.com/@naorzruk/portals-in-react-native-22797ba8aa1b) [4](https://stackoverflow.com/questions/46505378/can-we-have-react-16-portal-functionality-react-native) [5](https://github.com/callstack/react-native-paper/blob/master/src/components/Portal/PortalManager.tsx) Probably going to have to add a `Provider`...
206 | - [ ] add correct return types
207 | - [ ] tests (priority)
208 | - [ ] potential syntax ideas
209 | ```
210 | // then you can change the order of the array destructuring syntax
211 |
212 |
213 | // CustomModal, CustomCloseButton
214 |
215 | const { Modal, CloseButton } = useProvider()
216 |
217 | // customize the modal animations
218 | const { Modal } = useModal({
219 | onOpen({ modal }) {
220 | modal.current.style.cssText = `
221 | /* do some animation in */
222 | `
223 | },
224 | onClose({ modal }) {
225 | modal.current.style.cssText = `
226 | /* do some animation out */
227 | `
228 | }
229 | })
230 |
231 | // customize the modal animations idea 2
232 | const { Modal } = useModal({
233 | animateIn: `
234 | /* css for animating in */
235 | `,
236 | animateOut: `
237 | /* css for animating out */
238 | `,
239 | })
240 |
241 | // customize the modal animations idea 3
242 | // maybe have some predefined options?
243 | const { Modal } = useModal({
244 | animate: 'fade-in-out', // 'slide-in-top', etc...
245 | })
246 |
247 | // check out http://reactcommunity.org/react-modal/styles/transitions.html
248 | ```
249 |
--------------------------------------------------------------------------------