@react-ui-org/react-ui 0.47.0 → 0.48.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/lib.development.js +330 -54
- package/dist/lib.js +1 -1
- package/package.json +1 -1
- package/src/lib/components/Alert/README.mdx +4 -2
- package/src/lib/components/Alert/index.js +1 -1
- package/src/lib/components/Badge/README.mdx +1 -1
- package/src/lib/components/Badge/index.js +1 -1
- package/src/lib/components/Button/Button.jsx +31 -31
- package/src/lib/components/Button/README.mdx +4 -2
- package/src/lib/components/Button/index.js +1 -1
- package/src/lib/components/ButtonGroup/ButtonGroup.jsx +2 -1
- package/src/lib/components/ButtonGroup/README.mdx +4 -2
- package/src/lib/components/Card/README.mdx +7 -5
- package/src/lib/components/CheckboxField/CheckboxField.jsx +27 -28
- package/src/lib/components/CheckboxField/README.mdx +1 -1
- package/src/lib/components/CheckboxField/index.js +1 -1
- package/src/lib/components/FileInputField/FileInputField.jsx +27 -27
- package/src/lib/components/FileInputField/README.mdx +1 -1
- package/src/lib/components/FileInputField/index.js +1 -1
- package/src/lib/components/FormLayout/README.mdx +15 -13
- package/src/lib/components/Grid/Grid.jsx +31 -28
- package/src/lib/components/Grid/Grid.scss +10 -15
- package/src/lib/components/Grid/GridSpan.jsx +5 -4
- package/src/lib/components/Grid/README.mdx +34 -36
- package/src/lib/components/Grid/_helpers/generateResponsiveCustomProperties.js +11 -3
- package/src/lib/components/Grid/_settings.scss +18 -0
- package/src/lib/components/Grid/_tools.scss +5 -5
- package/src/lib/components/Modal/Modal.jsx +147 -250
- package/src/lib/components/Modal/Modal.scss +7 -55
- package/src/lib/components/Modal/ModalBody.jsx +64 -0
- package/src/lib/components/Modal/ModalBody.scss +18 -0
- package/src/lib/components/Modal/ModalCloseButton.jsx +61 -0
- package/src/lib/components/Modal/ModalCloseButton.scss +18 -0
- package/src/lib/components/Modal/ModalContent.jsx +43 -0
- package/src/lib/components/Modal/ModalContent.scss +5 -0
- package/src/lib/components/Modal/ModalFooter.jsx +46 -0
- package/src/lib/components/Modal/ModalFooter.scss +35 -0
- package/src/lib/components/Modal/ModalHeader.jsx +48 -0
- package/src/lib/components/Modal/ModalHeader.scss +30 -0
- package/src/lib/components/Modal/ModalTitle.jsx +45 -0
- package/src/lib/components/Modal/ModalTitle.scss +10 -0
- package/src/lib/components/Modal/README.mdx +842 -197
- package/src/lib/components/Modal/_helpers/getJustifyClassName.js +19 -0
- package/src/lib/components/Modal/_helpers/getScrollingClassName.js +11 -0
- package/src/lib/components/Modal/_settings.scss +1 -5
- package/src/lib/components/Modal/_theme.scss +6 -0
- package/src/lib/components/Modal/index.js +7 -1
- package/src/lib/components/Paper/README.mdx +1 -1
- package/src/lib/components/Paper/index.js +1 -1
- package/src/lib/components/Popover/Popover.jsx +24 -24
- package/src/lib/components/Popover/Popover.scss +7 -6
- package/src/lib/components/Popover/PopoverWrapper.jsx +5 -5
- package/src/lib/components/Popover/PopoverWrapper.scss +3 -0
- package/src/lib/components/Popover/README.mdx +13 -11
- package/src/lib/components/Popover/_theme.scss +1 -1
- package/src/lib/components/Radio/README.mdx +1 -1
- package/src/lib/components/Radio/Radio.jsx +37 -27
- package/src/lib/components/Radio/index.js +1 -1
- package/src/lib/components/ScrollView/README.mdx +146 -84
- package/src/lib/components/ScrollView/ScrollView.jsx +104 -113
- package/src/lib/components/ScrollView/ScrollView.scss +18 -16
- package/src/lib/components/ScrollView/index.js +1 -1
- package/src/lib/components/SelectField/README.mdx +66 -2
- package/src/lib/components/SelectField/SelectField.jsx +93 -49
- package/src/lib/components/SelectField/_components/Option/Option.jsx +46 -0
- package/src/lib/components/SelectField/_components/Option/index.js +1 -0
- package/src/lib/components/SelectField/index.js +1 -1
- package/src/lib/components/Table/README.mdx +4 -2
- package/src/lib/components/Table/Table.jsx +1 -1
- package/src/lib/components/Table/index.js +1 -1
- package/src/lib/components/Tabs/README.mdx +5 -3
- package/src/lib/components/Tabs/TabsItem.scss +1 -2
- package/src/lib/components/Text/README.mdx +9 -7
- package/src/lib/components/Text/index.js +1 -1
- package/src/lib/components/TextArea/README.mdx +1 -1
- package/src/lib/components/TextArea/TextArea.jsx +33 -33
- package/src/lib/components/TextArea/index.js +1 -1
- package/src/lib/components/TextField/README.mdx +3 -3
- package/src/lib/components/TextField/TextField.jsx +33 -34
- package/src/lib/components/TextField/index.js +1 -1
- package/src/lib/components/TextLink/README.mdx +1 -1
- package/src/lib/components/TextLink/index.js +1 -1
- package/src/lib/components/Toggle/README.mdx +1 -1
- package/src/lib/components/Toggle/Toggle.jsx +28 -28
- package/src/lib/components/Toggle/index.js +1 -1
- package/src/lib/components/Toolbar/README.mdx +8 -6
- package/src/lib/components/_helpers/transferProps.js +1 -1
- package/src/lib/index.js +24 -16
- package/src/lib/provider/withGlobalProps.jsx +20 -3
- package/src/lib/theme.scss +18 -26
- package/src/lib/translations/en.js +1 -1
- package/src/lib/components/Grid/_theme.scss +0 -11
- package/src/lib/components/ScrollView/_theme.scss +0 -2
- package/src/lib/components/withForwardedRef.jsx +0 -11
|
@@ -6,21 +6,44 @@ route: /components/modal
|
|
|
6
6
|
|
|
7
7
|
# Modal
|
|
8
8
|
|
|
9
|
-
Modal allows
|
|
9
|
+
Modal allows prompting users to take or complete an action.
|
|
10
10
|
|
|
11
11
|
import {
|
|
12
12
|
Playground,
|
|
13
13
|
Props,
|
|
14
14
|
} from 'docz'
|
|
15
|
-
import
|
|
16
|
-
|
|
15
|
+
import {
|
|
16
|
+
Button,
|
|
17
|
+
FormLayout,
|
|
18
|
+
Modal,
|
|
19
|
+
ModalBody,
|
|
20
|
+
ModalCloseButton,
|
|
21
|
+
ModalContent,
|
|
22
|
+
ModalFooter,
|
|
23
|
+
ModalHeader,
|
|
24
|
+
ModalTitle,
|
|
25
|
+
ScrollView,
|
|
26
|
+
TextField,
|
|
27
|
+
Toolbar,
|
|
28
|
+
ToolbarGroup,
|
|
29
|
+
ToolbarItem,
|
|
30
|
+
} from '../..'
|
|
31
|
+
import Icon from '../../../docs/_components/Icon'
|
|
17
32
|
|
|
18
33
|
## Basic Usage
|
|
19
34
|
|
|
20
35
|
To implement the Modal component, you need to import it first:
|
|
21
36
|
|
|
22
37
|
```js
|
|
23
|
-
import {
|
|
38
|
+
import {
|
|
39
|
+
Modal,
|
|
40
|
+
ModalHeader,
|
|
41
|
+
ModalBody,
|
|
42
|
+
ModalCloseButton,
|
|
43
|
+
ModalContent,
|
|
44
|
+
ModalFooter,
|
|
45
|
+
ModalTitle,
|
|
46
|
+
} from '@react-ui-org/react-ui';
|
|
24
47
|
```
|
|
25
48
|
|
|
26
49
|
And use it:
|
|
@@ -28,6 +51,8 @@ And use it:
|
|
|
28
51
|
<Playground>
|
|
29
52
|
{() => {
|
|
30
53
|
const [modalOpen, setModalOpen] = React.useState(false);
|
|
54
|
+
const modalPrimaryButtonRef = React.useRef();
|
|
55
|
+
const modalCloseButtonRef = React.useRef();
|
|
31
56
|
return (
|
|
32
57
|
<>
|
|
33
58
|
<Button
|
|
@@ -38,18 +63,35 @@ And use it:
|
|
|
38
63
|
<div>
|
|
39
64
|
{modalOpen && (
|
|
40
65
|
<Modal
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
label: 'Delete',
|
|
44
|
-
onClick: () => setModalOpen(false),
|
|
45
|
-
}]}
|
|
46
|
-
onClose={() => setModalOpen(false)}
|
|
47
|
-
title="Warning"
|
|
66
|
+
closeButtonRef={modalCloseButtonRef}
|
|
67
|
+
primaryButtonRef={modalPrimaryButtonRef}
|
|
48
68
|
>
|
|
49
|
-
<
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
</
|
|
69
|
+
<ModalHeader>
|
|
70
|
+
<ModalTitle>Delete the user?</ModalTitle>
|
|
71
|
+
<ModalCloseButton onClick={() => setModalOpen(false)} />
|
|
72
|
+
</ModalHeader>
|
|
73
|
+
<ModalBody>
|
|
74
|
+
<ModalContent>
|
|
75
|
+
<p>
|
|
76
|
+
Do you really want to delete the user <code>admin</code>?
|
|
77
|
+
This cannot be undone.
|
|
78
|
+
</p>
|
|
79
|
+
</ModalContent>
|
|
80
|
+
</ModalBody>
|
|
81
|
+
<ModalFooter>
|
|
82
|
+
<Button
|
|
83
|
+
color="danger"
|
|
84
|
+
label="Delete"
|
|
85
|
+
onClick={() => setModalOpen(false)}
|
|
86
|
+
ref={modalPrimaryButtonRef}
|
|
87
|
+
/>
|
|
88
|
+
<Button
|
|
89
|
+
label="Close"
|
|
90
|
+
onClick={() => setModalOpen(false)}
|
|
91
|
+
priority="outline"
|
|
92
|
+
ref={modalCloseButtonRef}
|
|
93
|
+
/>
|
|
94
|
+
</ModalFooter>
|
|
53
95
|
</Modal>
|
|
54
96
|
)}
|
|
55
97
|
</div>
|
|
@@ -62,25 +104,449 @@ See [API](#api) for all available options.
|
|
|
62
104
|
|
|
63
105
|
## General Guidelines
|
|
64
106
|
|
|
65
|
-
- Use modals to **confirm an action,** display a **blocking alert**, or
|
|
66
|
-
|
|
67
|
-
|
|
107
|
+
- Use modals to **confirm an action,** display a **blocking alert**, or reveal
|
|
108
|
+
**contextual options or settings** that cannot be displayed in line with the
|
|
109
|
+
parent content.
|
|
68
110
|
|
|
69
111
|
- **The title** should communicate the **purpose of the modal** rather than a
|
|
70
112
|
generic text. Eg. “Delete the user?” tells more than “Are you sure?” or
|
|
71
113
|
“Warning”.
|
|
72
114
|
|
|
73
|
-
- **Modal actions** should correspond to the modal purpose, too.
|
|
115
|
+
- **Modal actions** should correspond to the modal purpose, too. E.g. “Delete”
|
|
74
116
|
tells better what happens rather than “OK”.
|
|
75
117
|
|
|
76
118
|
- Modal **automatically focuses the first form field** by default which allows
|
|
77
|
-
users to confirm the modal by hitting enter key
|
|
78
|
-
|
|
79
|
-
|
|
119
|
+
users to confirm the modal by hitting the enter key. When no field is found
|
|
120
|
+
then the primary button (in the footer) is focused. To turn this feature off,
|
|
121
|
+
set the `autofocus` prop to `false`.
|
|
80
122
|
|
|
81
123
|
- **Avoid stacking** of modals. While it may technically work, the modal is just
|
|
82
124
|
not designed for that.
|
|
83
125
|
|
|
126
|
+
## Composition
|
|
127
|
+
|
|
128
|
+
Modal is decomposed into the following components:
|
|
129
|
+
|
|
130
|
+
- [Modal](#api)
|
|
131
|
+
- [ModalHeader](#modalheader-1)
|
|
132
|
+
- [ModalTitle](#modaltitle)
|
|
133
|
+
- [ModalCloseButton](#modalclosebutton)
|
|
134
|
+
- [ModalBody](#modalbody-1)
|
|
135
|
+
- [ModalContent](#modalcontent)
|
|
136
|
+
(may be wrapped with [ScrollView](/components/scroll-view))
|
|
137
|
+
- [ModalFooter](#modalfooter-1)
|
|
138
|
+
|
|
139
|
+
Using different combinations, you can compose different kinds of modals,
|
|
140
|
+
e.g. dialog modal, blocking modal, scrollable modal, etc.
|
|
141
|
+
|
|
142
|
+
<Playground>
|
|
143
|
+
{() => {
|
|
144
|
+
const [modalOpen, setModalOpen] = React.useState(null);
|
|
145
|
+
const modalPrimaryButtonRef = React.useRef();
|
|
146
|
+
const modalCloseButtonRef = React.useRef();
|
|
147
|
+
return (
|
|
148
|
+
<>
|
|
149
|
+
<Button
|
|
150
|
+
label="Launch blocking modal without title"
|
|
151
|
+
onClick={() => {
|
|
152
|
+
setModalOpen(1);
|
|
153
|
+
setTimeout(() => setModalOpen(null), 2500);
|
|
154
|
+
}}
|
|
155
|
+
priority="outline"
|
|
156
|
+
/>
|
|
157
|
+
<Button
|
|
158
|
+
label="Launch blocking modal with title"
|
|
159
|
+
onClick={() => {
|
|
160
|
+
setModalOpen(2);
|
|
161
|
+
setTimeout(() => setModalOpen(null), 3500);
|
|
162
|
+
}}
|
|
163
|
+
priority="outline"
|
|
164
|
+
/>
|
|
165
|
+
<Button
|
|
166
|
+
label="Launch modal as dialog"
|
|
167
|
+
onClick={() => setModalOpen(3)}
|
|
168
|
+
priority="outline"
|
|
169
|
+
/>
|
|
170
|
+
<Button
|
|
171
|
+
label="Launch modal as form"
|
|
172
|
+
onClick={() => setModalOpen(4)}
|
|
173
|
+
priority="outline"
|
|
174
|
+
/>
|
|
175
|
+
<div>
|
|
176
|
+
{modalOpen === 1 && (
|
|
177
|
+
<Modal>
|
|
178
|
+
<ModalBody>
|
|
179
|
+
<ModalContent>
|
|
180
|
+
<p className="text-center">
|
|
181
|
+
Application is being loaded.
|
|
182
|
+
<span className="d-inline-flex align-items-center animation-spin-counterclockwise">
|
|
183
|
+
<Icon icon="loading" />
|
|
184
|
+
</span>
|
|
185
|
+
</p>
|
|
186
|
+
</ModalContent>
|
|
187
|
+
</ModalBody>
|
|
188
|
+
</Modal>
|
|
189
|
+
)}
|
|
190
|
+
{modalOpen === 2 && (
|
|
191
|
+
<Modal>
|
|
192
|
+
<ModalHeader>
|
|
193
|
+
<ModalTitle>Action finished</ModalTitle>
|
|
194
|
+
</ModalHeader>
|
|
195
|
+
<ModalBody>
|
|
196
|
+
<ModalContent>
|
|
197
|
+
<p>
|
|
198
|
+
Action has been successfully finished.
|
|
199
|
+
You will be redirected within a few seconds.
|
|
200
|
+
</p>
|
|
201
|
+
</ModalContent>
|
|
202
|
+
</ModalBody>
|
|
203
|
+
</Modal>
|
|
204
|
+
)}
|
|
205
|
+
{modalOpen === 3 && (
|
|
206
|
+
<Modal
|
|
207
|
+
closeButtonRef={modalCloseButtonRef}
|
|
208
|
+
primaryButtonRef={modalPrimaryButtonRef}
|
|
209
|
+
>
|
|
210
|
+
<ModalHeader>
|
|
211
|
+
<ModalTitle>Delete the user?</ModalTitle>
|
|
212
|
+
<ModalCloseButton onClick={() => setModalOpen(false)} />
|
|
213
|
+
</ModalHeader>
|
|
214
|
+
<ModalBody>
|
|
215
|
+
<ModalContent>
|
|
216
|
+
<p>
|
|
217
|
+
Do you really want to delete the user <code>admin</code>?
|
|
218
|
+
This cannot be undone.
|
|
219
|
+
</p>
|
|
220
|
+
</ModalContent>
|
|
221
|
+
</ModalBody>
|
|
222
|
+
<ModalFooter>
|
|
223
|
+
<Button
|
|
224
|
+
color="danger"
|
|
225
|
+
label="Delete"
|
|
226
|
+
onClick={() => setModalOpen(false)}
|
|
227
|
+
ref={modalPrimaryButtonRef}
|
|
228
|
+
/>
|
|
229
|
+
<Button
|
|
230
|
+
label="Close"
|
|
231
|
+
onClick={() => setModalOpen(false)}
|
|
232
|
+
priority="outline"
|
|
233
|
+
ref={modalCloseButtonRef}
|
|
234
|
+
/>
|
|
235
|
+
</ModalFooter>
|
|
236
|
+
</Modal>
|
|
237
|
+
)}
|
|
238
|
+
{modalOpen === 4 && (
|
|
239
|
+
<Modal
|
|
240
|
+
closeButtonRef={modalCloseButtonRef}
|
|
241
|
+
primaryButtonRef={modalPrimaryButtonRef}
|
|
242
|
+
>
|
|
243
|
+
<ModalHeader>
|
|
244
|
+
<ModalTitle>Add new user</ModalTitle>
|
|
245
|
+
<ModalCloseButton onClick={() => setModalOpen(false)} />
|
|
246
|
+
</ModalHeader>
|
|
247
|
+
<ModalBody>
|
|
248
|
+
<ModalContent>
|
|
249
|
+
<FormLayout fieldLayout="horizontal">
|
|
250
|
+
<TextField label="Username" />
|
|
251
|
+
<TextField label="Password" type="password" />
|
|
252
|
+
</FormLayout>
|
|
253
|
+
</ModalContent>
|
|
254
|
+
</ModalBody>
|
|
255
|
+
<ModalFooter>
|
|
256
|
+
<Button
|
|
257
|
+
label="Save"
|
|
258
|
+
onClick={() => setModalOpen(false)}
|
|
259
|
+
ref={modalPrimaryButtonRef}
|
|
260
|
+
/>
|
|
261
|
+
<Button
|
|
262
|
+
label="Close"
|
|
263
|
+
onClick={() => setModalOpen(false)}
|
|
264
|
+
priority="outline"
|
|
265
|
+
ref={modalCloseButtonRef}
|
|
266
|
+
/>
|
|
267
|
+
</ModalFooter>
|
|
268
|
+
</Modal>
|
|
269
|
+
)}
|
|
270
|
+
</div>
|
|
271
|
+
</>
|
|
272
|
+
);
|
|
273
|
+
}}
|
|
274
|
+
</Playground>
|
|
275
|
+
|
|
276
|
+
### ModalHeader
|
|
277
|
+
|
|
278
|
+
ModalHeader is an optional part of the Modal which allows you to display the title
|
|
279
|
+
of the modal and its close button.
|
|
280
|
+
|
|
281
|
+
It is recommended to compose ModalHeader from the following elements. For title,
|
|
282
|
+
use ModalTitle. For the close button, use ModalCloseButton, however it can
|
|
283
|
+
be omitted if a close button is part of ModalFooter.
|
|
284
|
+
|
|
285
|
+
There are two ways how to position elements within the ModalHeader:
|
|
286
|
+
|
|
287
|
+
1. You can use provided positioning. Place previously mentioned elements into
|
|
288
|
+
the ModalHeader and use `justify` prop to set up the positioning of those
|
|
289
|
+
elements.
|
|
290
|
+
2. You can customize positioning using another component (e.g.
|
|
291
|
+
[Toolbar](/components/toolbar)). In that case, set `justify` to `stretch` and
|
|
292
|
+
position elements on your own.
|
|
293
|
+
|
|
294
|
+
<Playground>
|
|
295
|
+
{() => {
|
|
296
|
+
const [modalOpen, setModalOpen] = React.useState(false);
|
|
297
|
+
const [variant, setVariant] = React.useState(null);
|
|
298
|
+
const modalPrimaryButtonRef = React.useRef();
|
|
299
|
+
const modalCloseButtonRef = React.useRef();
|
|
300
|
+
return (
|
|
301
|
+
<>
|
|
302
|
+
<Button
|
|
303
|
+
label="Launch with close button"
|
|
304
|
+
onClick={() => {
|
|
305
|
+
setModalOpen(true);
|
|
306
|
+
setVariant(1);
|
|
307
|
+
}}
|
|
308
|
+
priority="outline"
|
|
309
|
+
/>
|
|
310
|
+
<Button
|
|
311
|
+
label="Launch without close button"
|
|
312
|
+
onClick={() => {
|
|
313
|
+
setModalOpen(true);
|
|
314
|
+
setVariant(2);
|
|
315
|
+
}}
|
|
316
|
+
priority="outline"
|
|
317
|
+
/>
|
|
318
|
+
<Button
|
|
319
|
+
label="Launch without close button and with centered title"
|
|
320
|
+
onClick={() => {
|
|
321
|
+
setModalOpen(true);
|
|
322
|
+
setVariant(3);
|
|
323
|
+
}}
|
|
324
|
+
priority="outline"
|
|
325
|
+
/>
|
|
326
|
+
<Button
|
|
327
|
+
label="Launch with custom layout"
|
|
328
|
+
onClick={() => {
|
|
329
|
+
setModalOpen(true);
|
|
330
|
+
setVariant(4);
|
|
331
|
+
}}
|
|
332
|
+
priority="outline"
|
|
333
|
+
/>
|
|
334
|
+
<div>
|
|
335
|
+
{modalOpen && (
|
|
336
|
+
<Modal
|
|
337
|
+
closeButtonRef={modalCloseButtonRef}
|
|
338
|
+
primaryButtonRef={modalPrimaryButtonRef}
|
|
339
|
+
>
|
|
340
|
+
{variant === 1 && (
|
|
341
|
+
<ModalHeader>
|
|
342
|
+
<ModalTitle>Delete the user?</ModalTitle>
|
|
343
|
+
<ModalCloseButton onClick={() => setModalOpen(false)} />
|
|
344
|
+
</ModalHeader>
|
|
345
|
+
)}
|
|
346
|
+
{variant === 2 && (
|
|
347
|
+
<ModalHeader>
|
|
348
|
+
<ModalTitle>Delete the user?</ModalTitle>
|
|
349
|
+
</ModalHeader>
|
|
350
|
+
)}
|
|
351
|
+
{variant === 3 && (
|
|
352
|
+
<ModalHeader justify="center">
|
|
353
|
+
<ModalTitle>Delete the user?</ModalTitle>
|
|
354
|
+
</ModalHeader>
|
|
355
|
+
)}
|
|
356
|
+
{variant === 4 && (
|
|
357
|
+
<ModalHeader justify="stretch">
|
|
358
|
+
<Toolbar justify="space-between">
|
|
359
|
+
<ToolbarItem>
|
|
360
|
+
{''}
|
|
361
|
+
</ToolbarItem>
|
|
362
|
+
<ToolbarItem>
|
|
363
|
+
<ModalTitle>Delete the user?</ModalTitle>
|
|
364
|
+
</ToolbarItem>
|
|
365
|
+
<ToolbarItem>
|
|
366
|
+
<ModalCloseButton onClick={() => setModalOpen(false)} />
|
|
367
|
+
</ToolbarItem>
|
|
368
|
+
</Toolbar>
|
|
369
|
+
</ModalHeader>
|
|
370
|
+
)}
|
|
371
|
+
<ModalBody>
|
|
372
|
+
<ModalContent>
|
|
373
|
+
<p>
|
|
374
|
+
Do you really want to delete the user <code>admin</code>?
|
|
375
|
+
This cannot be undone.
|
|
376
|
+
</p>
|
|
377
|
+
</ModalContent>
|
|
378
|
+
</ModalBody>
|
|
379
|
+
<ModalFooter>
|
|
380
|
+
<Button
|
|
381
|
+
color="danger"
|
|
382
|
+
label="Delete"
|
|
383
|
+
onClick={() => setModalOpen(false)}
|
|
384
|
+
ref={modalPrimaryButtonRef}
|
|
385
|
+
/>
|
|
386
|
+
<Button
|
|
387
|
+
label="Close"
|
|
388
|
+
onClick={() => setModalOpen(false)}
|
|
389
|
+
priority="outline"
|
|
390
|
+
ref={modalCloseButtonRef}
|
|
391
|
+
/>
|
|
392
|
+
</ModalFooter>
|
|
393
|
+
</Modal>
|
|
394
|
+
)}
|
|
395
|
+
</div>
|
|
396
|
+
</>
|
|
397
|
+
);
|
|
398
|
+
}}
|
|
399
|
+
</Playground>
|
|
400
|
+
|
|
401
|
+
### ModalBody
|
|
402
|
+
|
|
403
|
+
ModalBody is a mandatory part of the Modal which allows you to display the
|
|
404
|
+
content of the Modal.
|
|
405
|
+
|
|
406
|
+
Although the ModalBody allows you to display arbitrary content, you should not
|
|
407
|
+
place content directly into the ModalBody, but wrap it with ModalContent first.
|
|
408
|
+
|
|
409
|
+
In case your content is expected to be long, consider wrapping ModalContent
|
|
410
|
+
with ScrollView. Check [Scrolling Long Content](#scrolling-long-content) section
|
|
411
|
+
below.
|
|
412
|
+
|
|
413
|
+
### ModalFooter
|
|
414
|
+
|
|
415
|
+
ModalFooter is an optional part of the Modal which allows you to display
|
|
416
|
+
user actions.
|
|
417
|
+
|
|
418
|
+
There are two ways to position buttons within the ModalFooter:
|
|
419
|
+
|
|
420
|
+
1. You can use provided positioning. Place Button component (or any arbitrary
|
|
421
|
+
element) and use `justify` prop to set up the positioning of those elements.
|
|
422
|
+
2. You can customize positioning using another component (e.g.
|
|
423
|
+
[Toolbar](/components/toolbar)). In that case, set `justify` to `stretch`
|
|
424
|
+
and position elements on your own.
|
|
425
|
+
|
|
426
|
+
<Playground>
|
|
427
|
+
{() => {
|
|
428
|
+
const [modalOpen, setModalOpen] = React.useState(false);
|
|
429
|
+
const [modalJustify, setModalJustify] = React.useState('center');
|
|
430
|
+
const modalPrimaryButtonRef = React.useRef();
|
|
431
|
+
const modalCloseButtonRef = React.useRef();
|
|
432
|
+
return (
|
|
433
|
+
<>
|
|
434
|
+
<Button
|
|
435
|
+
label="Launch with footer justified to start"
|
|
436
|
+
onClick={() => {
|
|
437
|
+
setModalOpen(true);
|
|
438
|
+
setModalJustify('start');
|
|
439
|
+
}}
|
|
440
|
+
priority="outline"
|
|
441
|
+
/>
|
|
442
|
+
<Button
|
|
443
|
+
label="Launch with footer justified to center"
|
|
444
|
+
onClick={() => {
|
|
445
|
+
setModalOpen(true);
|
|
446
|
+
setModalJustify('center');
|
|
447
|
+
}}
|
|
448
|
+
priority="outline"
|
|
449
|
+
/>
|
|
450
|
+
<Button
|
|
451
|
+
label="Launch with footer justified to end"
|
|
452
|
+
onClick={() => {
|
|
453
|
+
setModalOpen(true);
|
|
454
|
+
setModalJustify('end');
|
|
455
|
+
}}
|
|
456
|
+
priority="outline"
|
|
457
|
+
/>
|
|
458
|
+
<Button
|
|
459
|
+
label="Launch with footer justified with space between"
|
|
460
|
+
onClick={() => {
|
|
461
|
+
setModalOpen(true);
|
|
462
|
+
setModalJustify('space-between');
|
|
463
|
+
}}
|
|
464
|
+
priority="outline"
|
|
465
|
+
/>
|
|
466
|
+
<Button
|
|
467
|
+
label="Launch with footer with custom layout"
|
|
468
|
+
onClick={() => {
|
|
469
|
+
setModalOpen(true);
|
|
470
|
+
setModalJustify('stretch');
|
|
471
|
+
}}
|
|
472
|
+
priority="outline"
|
|
473
|
+
/>
|
|
474
|
+
<div>
|
|
475
|
+
{modalOpen && (
|
|
476
|
+
<Modal
|
|
477
|
+
closeButtonRef={modalCloseButtonRef}
|
|
478
|
+
primaryButtonRef={modalPrimaryButtonRef}
|
|
479
|
+
>
|
|
480
|
+
<ModalHeader>
|
|
481
|
+
<ModalTitle>Delete the user?</ModalTitle>
|
|
482
|
+
<ModalCloseButton onClick={() => setModalOpen(false)} />
|
|
483
|
+
</ModalHeader>
|
|
484
|
+
<ModalBody>
|
|
485
|
+
<ModalContent>
|
|
486
|
+
<p>
|
|
487
|
+
Do you really want to delete the user <code>admin</code>?
|
|
488
|
+
This cannot be undone.
|
|
489
|
+
</p>
|
|
490
|
+
</ModalContent>
|
|
491
|
+
</ModalBody>
|
|
492
|
+
<ModalFooter justify={modalJustify}>
|
|
493
|
+
{
|
|
494
|
+
modalJustify === 'stretch'
|
|
495
|
+
? (
|
|
496
|
+
<Toolbar justify="space-between">
|
|
497
|
+
<ToolbarGroup>
|
|
498
|
+
<ToolbarItem>
|
|
499
|
+
<Button
|
|
500
|
+
color="danger"
|
|
501
|
+
label="Delete"
|
|
502
|
+
onClick={() => setModalOpen(false)}
|
|
503
|
+
ref={modalPrimaryButtonRef}
|
|
504
|
+
/>
|
|
505
|
+
</ToolbarItem>
|
|
506
|
+
<ToolbarItem>
|
|
507
|
+
<Button
|
|
508
|
+
color="warning"
|
|
509
|
+
label="Archive"
|
|
510
|
+
onClick={() => setModalOpen(false)}
|
|
511
|
+
ref={modalPrimaryButtonRef}
|
|
512
|
+
/>
|
|
513
|
+
</ToolbarItem>
|
|
514
|
+
</ToolbarGroup>
|
|
515
|
+
<ToolbarItem>
|
|
516
|
+
<Button
|
|
517
|
+
label="Close"
|
|
518
|
+
onClick={() => setModalOpen(false)}
|
|
519
|
+
priority="outline"
|
|
520
|
+
ref={modalCloseButtonRef}
|
|
521
|
+
/>
|
|
522
|
+
</ToolbarItem>
|
|
523
|
+
</Toolbar>
|
|
524
|
+
) : (
|
|
525
|
+
<>
|
|
526
|
+
<Button
|
|
527
|
+
color="danger"
|
|
528
|
+
label="Delete"
|
|
529
|
+
onClick={() => setModalOpen(false)}
|
|
530
|
+
ref={modalPrimaryButtonRef}
|
|
531
|
+
/>
|
|
532
|
+
<Button
|
|
533
|
+
label="Close"
|
|
534
|
+
onClick={() => setModalOpen(false)}
|
|
535
|
+
priority="outline"
|
|
536
|
+
ref={modalCloseButtonRef}
|
|
537
|
+
/>
|
|
538
|
+
</>
|
|
539
|
+
)
|
|
540
|
+
}
|
|
541
|
+
</ModalFooter>
|
|
542
|
+
</Modal>
|
|
543
|
+
)}
|
|
544
|
+
</div>
|
|
545
|
+
</>
|
|
546
|
+
);
|
|
547
|
+
}}
|
|
548
|
+
</Playground>
|
|
549
|
+
|
|
84
550
|
## Sizes
|
|
85
551
|
|
|
86
552
|
Modal is available in three fixed-width sizes: small, medium, large and fullscreen.
|
|
@@ -90,6 +556,8 @@ Modals of any size automatically shrink when they cannot fit the screen width.
|
|
|
90
556
|
{() => {
|
|
91
557
|
const [modalOpen, setModalOpen] = React.useState(false);
|
|
92
558
|
const [modalSize, setModalSize] = React.useState('small');
|
|
559
|
+
const modalPrimaryButtonRef = React.useRef();
|
|
560
|
+
const modalCloseButtonRef = React.useRef();
|
|
93
561
|
return (
|
|
94
562
|
<>
|
|
95
563
|
<Button
|
|
@@ -127,19 +595,36 @@ Modals of any size automatically shrink when they cannot fit the screen width.
|
|
|
127
595
|
<div>
|
|
128
596
|
{modalOpen && (
|
|
129
597
|
<Modal
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
label: 'Delete',
|
|
133
|
-
onClick: () => setModalOpen(false),
|
|
134
|
-
}]}
|
|
135
|
-
onClose={() => setModalOpen(false)}
|
|
598
|
+
closeButtonRef={modalCloseButtonRef}
|
|
599
|
+
primaryButtonRef={modalPrimaryButtonRef}
|
|
136
600
|
size={modalSize}
|
|
137
|
-
title="Delete the user?"
|
|
138
601
|
>
|
|
139
|
-
<
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
</
|
|
602
|
+
<ModalHeader>
|
|
603
|
+
<ModalTitle>Delete the user?</ModalTitle>
|
|
604
|
+
<ModalCloseButton onClick={() => setModalOpen(false)} />
|
|
605
|
+
</ModalHeader>
|
|
606
|
+
<ModalBody>
|
|
607
|
+
<ModalContent>
|
|
608
|
+
<p>
|
|
609
|
+
Do you really want to delete the user <code>admin</code>?
|
|
610
|
+
This cannot be undone.
|
|
611
|
+
</p>
|
|
612
|
+
</ModalContent>
|
|
613
|
+
</ModalBody>
|
|
614
|
+
<ModalFooter>
|
|
615
|
+
<Button
|
|
616
|
+
color="danger"
|
|
617
|
+
label="Delete"
|
|
618
|
+
onClick={() => setModalOpen(false)}
|
|
619
|
+
ref={modalPrimaryButtonRef}
|
|
620
|
+
/>
|
|
621
|
+
<Button
|
|
622
|
+
label="Close"
|
|
623
|
+
onClick={() => setModalOpen(false)}
|
|
624
|
+
priority="outline"
|
|
625
|
+
ref={modalCloseButtonRef}
|
|
626
|
+
/>
|
|
627
|
+
</ModalFooter>
|
|
143
628
|
</Modal>
|
|
144
629
|
)}
|
|
145
630
|
</div>
|
|
@@ -148,39 +633,117 @@ Modals of any size automatically shrink when they cannot fit the screen width.
|
|
|
148
633
|
}}
|
|
149
634
|
</Playground>
|
|
150
635
|
|
|
151
|
-
On top of that, the modal
|
|
636
|
+
On top of that, the modal can adjust to the width of its content.
|
|
637
|
+
|
|
638
|
+
<Playground>
|
|
639
|
+
{() => {
|
|
640
|
+
const [modalOpen, setModalOpen] = React.useState(false);
|
|
641
|
+
const modalPrimaryButtonRef = React.useRef();
|
|
642
|
+
const modalCloseButtonRef = React.useRef();
|
|
643
|
+
return (
|
|
644
|
+
<>
|
|
645
|
+
<Button
|
|
646
|
+
label="Launch auto-width modal"
|
|
647
|
+
onClick={() => setModalOpen(true)}
|
|
648
|
+
priority="outline"
|
|
649
|
+
/>
|
|
650
|
+
<div>
|
|
651
|
+
{modalOpen && (
|
|
652
|
+
<Modal
|
|
653
|
+
closeButtonRef={modalCloseButtonRef}
|
|
654
|
+
primaryButtonRef={modalPrimaryButtonRef}
|
|
655
|
+
size="auto"
|
|
656
|
+
>
|
|
657
|
+
<ModalHeader>
|
|
658
|
+
<ModalTitle>Delete the user?</ModalTitle>
|
|
659
|
+
<ModalCloseButton onClick={() => setModalOpen(false)} />
|
|
660
|
+
</ModalHeader>
|
|
661
|
+
<ModalBody>
|
|
662
|
+
<ModalContent>
|
|
663
|
+
<p>
|
|
664
|
+
Do you really want to delete the user <code>admin</code>?
|
|
665
|
+
This cannot be undone.
|
|
666
|
+
</p>
|
|
667
|
+
</ModalContent>
|
|
668
|
+
</ModalBody>
|
|
669
|
+
<ModalFooter>
|
|
670
|
+
<Button
|
|
671
|
+
color="danger"
|
|
672
|
+
label="Delete"
|
|
673
|
+
onClick={() => setModalOpen(false)}
|
|
674
|
+
ref={modalPrimaryButtonRef}
|
|
675
|
+
/>
|
|
676
|
+
<Button
|
|
677
|
+
label="Close"
|
|
678
|
+
onClick={() => setModalOpen(false)}
|
|
679
|
+
priority="outline"
|
|
680
|
+
ref={modalCloseButtonRef}
|
|
681
|
+
/>
|
|
682
|
+
</ModalFooter>
|
|
683
|
+
</Modal>
|
|
684
|
+
)}
|
|
685
|
+
</div>
|
|
686
|
+
</>
|
|
687
|
+
);
|
|
688
|
+
}}
|
|
689
|
+
</Playground>
|
|
152
690
|
|
|
153
691
|
👉 Please note the auto width may not function correctly in combination with
|
|
154
|
-
other auto
|
|
692
|
+
other auto-layout mechanisms, e.g. the auto-width
|
|
155
693
|
[FormLayout](/components/form-layout#label-width). It's just too much
|
|
156
|
-
magic that doesn't work together yet 🎩.
|
|
694
|
+
magic that doesn't work together (yet?) 🎩.
|
|
695
|
+
|
|
696
|
+
👉 Beware of horizontal FormLayout inside `small` modals. While automatic
|
|
697
|
+
overflow handling comes to the rescue in this kind of scenario, you will be
|
|
698
|
+
better off with the combination of auto-sized modal and horizontal FormLayout
|
|
699
|
+
with a fixed label width (i.e. any other than `auto`, see the previous note).
|
|
157
700
|
|
|
158
701
|
<Playground>
|
|
159
702
|
{() => {
|
|
160
703
|
const [modalOpen, setModalOpen] = React.useState(false);
|
|
704
|
+
const modalPrimaryButtonRef = React.useRef();
|
|
705
|
+
const modalCloseButtonRef = React.useRef();
|
|
161
706
|
return (
|
|
162
707
|
<>
|
|
163
708
|
<Button
|
|
164
|
-
label="Launch auto-
|
|
709
|
+
label="Launch auto-with modal with a form"
|
|
165
710
|
onClick={() => setModalOpen(true)}
|
|
166
711
|
priority="outline"
|
|
167
712
|
/>
|
|
168
713
|
<div>
|
|
169
714
|
{modalOpen && (
|
|
170
715
|
<Modal
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
label: 'Delete',
|
|
174
|
-
onClick: () => setModalOpen(false),
|
|
175
|
-
}]}
|
|
176
|
-
onClose={() => setModalOpen(false)}
|
|
716
|
+
closeButtonRef={modalCloseButtonRef}
|
|
717
|
+
primaryButtonRef={modalPrimaryButtonRef}
|
|
177
718
|
size="auto"
|
|
178
|
-
title="Delete the user?"
|
|
179
719
|
>
|
|
180
|
-
<
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
</
|
|
720
|
+
<ModalHeader>
|
|
721
|
+
<ModalTitle>Form inside modal</ModalTitle>
|
|
722
|
+
<ModalCloseButton onClick={() => setModalOpen(false)} />
|
|
723
|
+
</ModalHeader>
|
|
724
|
+
<ModalBody>
|
|
725
|
+
<ModalContent>
|
|
726
|
+
<FormLayout fieldLayout="horizontal">
|
|
727
|
+
<TextField label="A form element" />
|
|
728
|
+
<TextField label="Another form element" />
|
|
729
|
+
<TextField label="Yet another one" />
|
|
730
|
+
</FormLayout>
|
|
731
|
+
</ModalContent>
|
|
732
|
+
</ModalBody>
|
|
733
|
+
<ModalFooter>
|
|
734
|
+
<Button
|
|
735
|
+
color="primary"
|
|
736
|
+
label="Save"
|
|
737
|
+
onClick={() => setModalOpen(false)}
|
|
738
|
+
ref={modalPrimaryButtonRef}
|
|
739
|
+
/>
|
|
740
|
+
<Button
|
|
741
|
+
label="Cancel"
|
|
742
|
+
onClick={() => setModalOpen(false)}
|
|
743
|
+
priority="outline"
|
|
744
|
+
ref={modalCloseButtonRef}
|
|
745
|
+
/>
|
|
746
|
+
</ModalFooter>
|
|
184
747
|
</Modal>
|
|
185
748
|
)}
|
|
186
749
|
</div>
|
|
@@ -191,12 +754,14 @@ magic that doesn't work together yet 🎩.
|
|
|
191
754
|
|
|
192
755
|
## Position
|
|
193
756
|
|
|
194
|
-
Modal can be aligned either to top or center of the screen.
|
|
757
|
+
Modal can be aligned either to the top or center of the screen.
|
|
195
758
|
|
|
196
759
|
<Playground>
|
|
197
760
|
{() => {
|
|
198
761
|
const [modalOpen, setModalOpen] = React.useState(false);
|
|
199
762
|
const [modalPosition, setModalPosition] = React.useState('center');
|
|
763
|
+
const modalPrimaryButtonRef = React.useRef();
|
|
764
|
+
const modalCloseButtonRef = React.useRef();
|
|
200
765
|
return (
|
|
201
766
|
<>
|
|
202
767
|
<Button
|
|
@@ -218,19 +783,36 @@ Modal can be aligned either to top or center of the screen.
|
|
|
218
783
|
<div>
|
|
219
784
|
{modalOpen && (
|
|
220
785
|
<Modal
|
|
221
|
-
|
|
222
|
-
onClick: () => setModalOpen(false),
|
|
223
|
-
label: 'Delete',
|
|
224
|
-
color: 'danger',
|
|
225
|
-
}]}
|
|
226
|
-
onClose={() => setModalOpen(false)}
|
|
786
|
+
closeButtonRef={modalCloseButtonRef}
|
|
227
787
|
position={modalPosition}
|
|
228
|
-
|
|
788
|
+
primaryButtonRef={modalPrimaryButtonRef}
|
|
229
789
|
>
|
|
230
|
-
<
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
</
|
|
790
|
+
<ModalHeader>
|
|
791
|
+
<ModalTitle>Delete the user?</ModalTitle>
|
|
792
|
+
<ModalCloseButton onClick={() => setModalOpen(false)} />
|
|
793
|
+
</ModalHeader>
|
|
794
|
+
<ModalBody>
|
|
795
|
+
<ModalContent>
|
|
796
|
+
<p>
|
|
797
|
+
Do you really want to delete the user <code>admin</code>?
|
|
798
|
+
This cannot be undone.
|
|
799
|
+
</p>
|
|
800
|
+
</ModalContent>
|
|
801
|
+
</ModalBody>
|
|
802
|
+
<ModalFooter>
|
|
803
|
+
<Button
|
|
804
|
+
color="danger"
|
|
805
|
+
label="Delete"
|
|
806
|
+
onClick={() => setModalOpen(false)}
|
|
807
|
+
ref={modalPrimaryButtonRef}
|
|
808
|
+
/>
|
|
809
|
+
<Button
|
|
810
|
+
label="Close"
|
|
811
|
+
onClick={() => setModalOpen(false)}
|
|
812
|
+
priority="outline"
|
|
813
|
+
ref={modalCloseButtonRef}
|
|
814
|
+
/>
|
|
815
|
+
</ModalFooter>
|
|
234
816
|
</Modal>
|
|
235
817
|
)}
|
|
236
818
|
</div>
|
|
@@ -239,33 +821,146 @@ Modal can be aligned either to top or center of the screen.
|
|
|
239
821
|
}}
|
|
240
822
|
</Playground>
|
|
241
823
|
|
|
824
|
+
## Keyboard Control
|
|
825
|
+
|
|
826
|
+
Modal can be controlled either by mouse or keyboard. To enhance user
|
|
827
|
+
experience, primary action can be fired by pressing `Enter` key and the modal
|
|
828
|
+
can be closed by pressing the `Escape` key.
|
|
829
|
+
|
|
830
|
+
To enable it, you just need to pass a reference to the buttons using
|
|
831
|
+
`primaryButtonRef` and `closeButtonRef` props on Modal. The advantage of passing
|
|
832
|
+
a reference to the button is that if the button is disabled, the key press will
|
|
833
|
+
not fire the event.
|
|
834
|
+
|
|
835
|
+
👉 We strongly recommend using this feature together with Autofocus for a better
|
|
836
|
+
user experience.
|
|
837
|
+
|
|
838
|
+
## Autofocus
|
|
839
|
+
|
|
840
|
+
Autofocus is implemented to enhance the user experience by automatically
|
|
841
|
+
focussing an element within the modal.
|
|
842
|
+
|
|
843
|
+
How does it work? It tries to find `input`, `textarea`, and `select` elements
|
|
844
|
+
inside of Modal and moves focus into the first found. If none is found and the
|
|
845
|
+
`primaryButtonRef` prop on Modal is set, then the primary button is focused.
|
|
846
|
+
|
|
847
|
+
Autofocus is enabled by default, so if you want to control the focus of
|
|
848
|
+
elements manually, set the `autoFocus` prop on Modal to `false`.
|
|
849
|
+
|
|
242
850
|
## Scrolling Long Content
|
|
243
851
|
|
|
244
852
|
When modals become too long for the user's viewport or device, they scroll
|
|
245
|
-
independent of the page itself.
|
|
853
|
+
independent of the page itself. This can be done in three ways using the
|
|
854
|
+
`scrolling` option of the ModalBody component:
|
|
246
855
|
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
856
|
+
- `auto` (default) — ModalBody is responsible for scrolling,
|
|
857
|
+
- `custom` — you must provide a custom component to handle scrolling,
|
|
858
|
+
typically an instance of [ScrollView](/components/scroll-view) wrapping
|
|
859
|
+
ModalContent,
|
|
860
|
+
- `none` — entire Modal is responsible for scrolling.
|
|
250
861
|
|
|
251
862
|
<Playground>
|
|
252
863
|
{() => {
|
|
253
864
|
const [modalOpen, setModalOpen] = React.useState(false);
|
|
254
|
-
const [
|
|
865
|
+
const [modalScrolling, setModalScrolling] = React.useState('auto');
|
|
866
|
+
const modalCloseButtonRef = React.useRef();
|
|
867
|
+
const modalPrimaryButtonRef = React.useRef();
|
|
868
|
+
const modalContent = (
|
|
869
|
+
<ModalContent>
|
|
870
|
+
<p>
|
|
871
|
+
Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean
|
|
872
|
+
commodo ligula eget dolor. Aenean massa.
|
|
873
|
+
</p>
|
|
874
|
+
<p>
|
|
875
|
+
Cum sociis natoque penatibus et magnis dis parturient montes,
|
|
876
|
+
nascetur ridiculus mus. Donec quam felis, ultricies nec,
|
|
877
|
+
pellentesque eu, pretium quis, sem.
|
|
878
|
+
</p>
|
|
879
|
+
<p>
|
|
880
|
+
Nulla consequat massa quis enim. Donec pede justo, fringilla
|
|
881
|
+
vel, aliquet nec, vulputate eget, arcu. In enim justo, rhoncus
|
|
882
|
+
ut, imperdiet a, venenatis vitae, justo.
|
|
883
|
+
</p>
|
|
884
|
+
<p>
|
|
885
|
+
Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean
|
|
886
|
+
commodo ligula eget dolor. Aenean massa.
|
|
887
|
+
</p>
|
|
888
|
+
<p>
|
|
889
|
+
Cum sociis natoque penatibus et magnis dis parturient montes,
|
|
890
|
+
nascetur ridiculus mus. Donec quam felis, ultricies nec,
|
|
891
|
+
pellentesque eu, pretium quis, sem.
|
|
892
|
+
</p>
|
|
893
|
+
<p>
|
|
894
|
+
Nulla consequat massa quis enim. Donec pede justo, fringilla
|
|
895
|
+
vel, aliquet nec, vulputate eget, arcu. In enim justo, rhoncus
|
|
896
|
+
ut, imperdiet a, venenatis vitae, justo.
|
|
897
|
+
</p>
|
|
898
|
+
<p>
|
|
899
|
+
Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean
|
|
900
|
+
commodo ligula eget dolor. Aenean massa.
|
|
901
|
+
</p>
|
|
902
|
+
<p>
|
|
903
|
+
Cum sociis natoque penatibus et magnis dis parturient montes,
|
|
904
|
+
nascetur ridiculus mus. Donec quam felis, ultricies nec,
|
|
905
|
+
pellentesque eu, pretium quis, sem.
|
|
906
|
+
</p>
|
|
907
|
+
<p>
|
|
908
|
+
Nulla consequat massa quis enim. Donec pede justo, fringilla
|
|
909
|
+
vel, aliquet nec, vulputate eget, arcu. In enim justo, rhoncus
|
|
910
|
+
ut, imperdiet a, venenatis vitae, justo.
|
|
911
|
+
</p>
|
|
912
|
+
<p>
|
|
913
|
+
Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean
|
|
914
|
+
commodo ligula eget dolor. Aenean massa.
|
|
915
|
+
</p>
|
|
916
|
+
<p>
|
|
917
|
+
Cum sociis natoque penatibus et magnis dis parturient montes,
|
|
918
|
+
nascetur ridiculus mus. Donec quam felis, ultricies nec,
|
|
919
|
+
pellentesque eu, pretium quis, sem.
|
|
920
|
+
</p>
|
|
921
|
+
<p>
|
|
922
|
+
Nulla consequat massa quis enim. Donec pede justo, fringilla
|
|
923
|
+
vel, aliquet nec, vulputate eget, arcu. In enim justo, rhoncus
|
|
924
|
+
ut, imperdiet a, venenatis vitae, justo.
|
|
925
|
+
</p>
|
|
926
|
+
<p>
|
|
927
|
+
Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean
|
|
928
|
+
commodo ligula eget dolor. Aenean massa.
|
|
929
|
+
</p>
|
|
930
|
+
<p>
|
|
931
|
+
Cum sociis natoque penatibus et magnis dis parturient montes,
|
|
932
|
+
nascetur ridiculus mus. Donec quam felis, ultricies nec,
|
|
933
|
+
pellentesque eu, pretium quis, sem.
|
|
934
|
+
</p>
|
|
935
|
+
<p>
|
|
936
|
+
Nulla consequat massa quis enim. Donec pede justo, fringilla
|
|
937
|
+
vel, aliquet nec, vulputate eget, arcu. In enim justo, rhoncus
|
|
938
|
+
ut, imperdiet a, venenatis vitae, justo.
|
|
939
|
+
</p>
|
|
940
|
+
</ModalContent>
|
|
941
|
+
)
|
|
255
942
|
return (
|
|
256
943
|
<>
|
|
257
944
|
<Button
|
|
258
945
|
label="Launch modal with scrolling body"
|
|
259
946
|
onClick={() => {
|
|
260
|
-
|
|
947
|
+
setModalScrolling('auto');
|
|
261
948
|
setModalOpen(true);
|
|
262
949
|
}}
|
|
263
950
|
priority="outline"
|
|
264
951
|
/>
|
|
265
952
|
<Button
|
|
266
|
-
label="Launch
|
|
953
|
+
label="Launch modal with ScrollView"
|
|
267
954
|
onClick={() => {
|
|
268
|
-
|
|
955
|
+
setModalScrolling('custom');
|
|
956
|
+
setModalOpen(true);
|
|
957
|
+
}}
|
|
958
|
+
priority="outline"
|
|
959
|
+
/>
|
|
960
|
+
<Button
|
|
961
|
+
label="Launch modal with non-scrolling body"
|
|
962
|
+
onClick={() => {
|
|
963
|
+
setModalScrolling('none');
|
|
269
964
|
setModalOpen(true);
|
|
270
965
|
}}
|
|
271
966
|
priority="outline"
|
|
@@ -273,86 +968,39 @@ component.
|
|
|
273
968
|
<div>
|
|
274
969
|
{modalOpen && (
|
|
275
970
|
<Modal
|
|
276
|
-
actions={[{
|
|
277
|
-
label: 'OK',
|
|
278
|
-
onClick: () => setModalOpen(false),
|
|
279
|
-
}]}
|
|
280
971
|
autoFocus={false}
|
|
281
|
-
|
|
282
|
-
|
|
972
|
+
closeButtonRef={modalCloseButtonRef}
|
|
973
|
+
primaryButtonRef={modalPrimaryButtonRef}
|
|
283
974
|
size="small"
|
|
284
|
-
title="Modal with long content"
|
|
285
975
|
>
|
|
286
|
-
<
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
</
|
|
290
|
-
<
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
</
|
|
314
|
-
<p>
|
|
315
|
-
Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean
|
|
316
|
-
commodo ligula eget dolor. Aenean massa.
|
|
317
|
-
</p>
|
|
318
|
-
<p>
|
|
319
|
-
Cum sociis natoque penatibus et magnis dis parturient montes,
|
|
320
|
-
nascetur ridiculus mus. Donec quam felis, ultricies nec,
|
|
321
|
-
pellentesque eu, pretium quis, sem.
|
|
322
|
-
</p>
|
|
323
|
-
<p>
|
|
324
|
-
Nulla consequat massa quis enim. Donec pede justo, fringilla
|
|
325
|
-
vel, aliquet nec, vulputate eget, arcu. In enim justo, rhoncus
|
|
326
|
-
ut, imperdiet a, venenatis vitae, justo.
|
|
327
|
-
</p>
|
|
328
|
-
<p>
|
|
329
|
-
Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean
|
|
330
|
-
commodo ligula eget dolor. Aenean massa.
|
|
331
|
-
</p>
|
|
332
|
-
<p>
|
|
333
|
-
Cum sociis natoque penatibus et magnis dis parturient montes,
|
|
334
|
-
nascetur ridiculus mus. Donec quam felis, ultricies nec,
|
|
335
|
-
pellentesque eu, pretium quis, sem.
|
|
336
|
-
</p>
|
|
337
|
-
<p>
|
|
338
|
-
Nulla consequat massa quis enim. Donec pede justo, fringilla
|
|
339
|
-
vel, aliquet nec, vulputate eget, arcu. In enim justo, rhoncus
|
|
340
|
-
ut, imperdiet a, venenatis vitae, justo.
|
|
341
|
-
</p>
|
|
342
|
-
<p>
|
|
343
|
-
Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean
|
|
344
|
-
commodo ligula eget dolor. Aenean massa.
|
|
345
|
-
</p>
|
|
346
|
-
<p>
|
|
347
|
-
Cum sociis natoque penatibus et magnis dis parturient montes,
|
|
348
|
-
nascetur ridiculus mus. Donec quam felis, ultricies nec,
|
|
349
|
-
pellentesque eu, pretium quis, sem.
|
|
350
|
-
</p>
|
|
351
|
-
<p>
|
|
352
|
-
Nulla consequat massa quis enim. Donec pede justo, fringilla
|
|
353
|
-
vel, aliquet nec, vulputate eget, arcu. In enim justo, rhoncus
|
|
354
|
-
ut, imperdiet a, venenatis vitae, justo.
|
|
355
|
-
</p>
|
|
976
|
+
<ModalHeader>
|
|
977
|
+
<ModalTitle>Modal with long content</ModalTitle>
|
|
978
|
+
<ModalCloseButton onClick={() => setModalOpen(false)} />
|
|
979
|
+
</ModalHeader>
|
|
980
|
+
<ModalBody scrolling={modalScrolling}>
|
|
981
|
+
{
|
|
982
|
+
modalScrolling === 'custom'
|
|
983
|
+
? (
|
|
984
|
+
<ScrollView>
|
|
985
|
+
{modalContent}
|
|
986
|
+
</ScrollView>
|
|
987
|
+
)
|
|
988
|
+
: modalContent
|
|
989
|
+
}
|
|
990
|
+
</ModalBody>
|
|
991
|
+
<ModalFooter>
|
|
992
|
+
<Button
|
|
993
|
+
label="OK"
|
|
994
|
+
onClick={() => setModalOpen(false)}
|
|
995
|
+
ref={modalPrimaryButtonRef}
|
|
996
|
+
/>
|
|
997
|
+
<Button
|
|
998
|
+
label="Close"
|
|
999
|
+
onClick={() => setModalOpen(false)}
|
|
1000
|
+
priority="outline"
|
|
1001
|
+
ref={modalCloseButtonRef}
|
|
1002
|
+
/>
|
|
1003
|
+
</ModalFooter>
|
|
356
1004
|
</Modal>
|
|
357
1005
|
)}
|
|
358
1006
|
</div>
|
|
@@ -363,63 +1011,60 @@ component.
|
|
|
363
1011
|
|
|
364
1012
|
### Long Content and Autofocus
|
|
365
1013
|
|
|
366
|
-
👉 If you
|
|
367
|
-
to prevent the modal from scrolling to the end immediately after being
|
|
368
|
-
|
|
369
|
-
## Blocking Modals
|
|
370
|
-
|
|
371
|
-
There are situations when you need to interrupt user's flow and lock entire UI
|
|
372
|
-
to prevent interaction. That's where blocking modals may come handy.
|
|
1014
|
+
👉 If you wrap ModalContent with ScrollView, you may want to turn `autoFocus`
|
|
1015
|
+
off to prevent the modal from scrolling to the end immediately after being
|
|
1016
|
+
opened.
|
|
373
1017
|
|
|
374
|
-
|
|
375
|
-
{() => {
|
|
376
|
-
const [modalOpen, setModalOpen] = React.useState(false);
|
|
377
|
-
return (
|
|
378
|
-
<>
|
|
379
|
-
<Button
|
|
380
|
-
label="Launch blocking modal"
|
|
381
|
-
onClick={() => setModalOpen(true)}
|
|
382
|
-
priority="outline"
|
|
383
|
-
/>
|
|
384
|
-
<div>
|
|
385
|
-
{modalOpen && (
|
|
386
|
-
<Modal title="Update is in progress" size="auto">
|
|
387
|
-
<p>
|
|
388
|
-
<span role="img" aria-label="Warning">⚠️</span>
|
|
389
|
-
Please wait a few seconds until the firmware update is finished.
|
|
390
|
-
Don't turn off the device!
|
|
391
|
-
</p>
|
|
392
|
-
<Button
|
|
393
|
-
label="Close the demo"
|
|
394
|
-
onClick={() => setModalOpen(false)}
|
|
395
|
-
priority="flat"
|
|
396
|
-
/>
|
|
397
|
-
</Modal>
|
|
398
|
-
)}
|
|
399
|
-
</div>
|
|
400
|
-
</>
|
|
401
|
-
);
|
|
402
|
-
}}
|
|
403
|
-
</Playground>
|
|
1018
|
+
<!-- markdownlint-disable MD024 -->
|
|
404
1019
|
|
|
405
1020
|
## API
|
|
406
1021
|
|
|
407
1022
|
<Props table of={Modal} />
|
|
408
1023
|
|
|
1024
|
+
### ModalHeader
|
|
1025
|
+
|
|
1026
|
+
<Props table of={ModalHeader} />
|
|
1027
|
+
|
|
1028
|
+
### ModalTitle
|
|
1029
|
+
|
|
1030
|
+
<Props table of={ModalTitle} />
|
|
1031
|
+
|
|
1032
|
+
### ModalCloseButton
|
|
1033
|
+
|
|
1034
|
+
<Props table of={ModalCloseButton} />
|
|
1035
|
+
|
|
1036
|
+
### ModalBody
|
|
1037
|
+
|
|
1038
|
+
<Props table of={ModalBody} />
|
|
1039
|
+
|
|
1040
|
+
### ModalContent
|
|
1041
|
+
|
|
1042
|
+
<Props table of={ModalContent} />
|
|
1043
|
+
|
|
1044
|
+
### ModalFooter
|
|
1045
|
+
|
|
1046
|
+
<Props table of={ModalFooter} />
|
|
1047
|
+
|
|
409
1048
|
## Theming
|
|
410
1049
|
|
|
411
|
-
| Custom Property | Description
|
|
412
|
-
|
|
413
|
-
| `--rui-
|
|
414
|
-
| `--rui-
|
|
415
|
-
| `--rui-
|
|
416
|
-
| `--rui-
|
|
417
|
-
| `--rui-
|
|
418
|
-
| `--rui-
|
|
419
|
-
| `--rui-
|
|
420
|
-
| `--rui-
|
|
421
|
-
| `--rui-
|
|
422
|
-
| `--rui-
|
|
423
|
-
| `--rui-
|
|
424
|
-
| `--rui-
|
|
425
|
-
| `--rui-Modal--
|
|
1050
|
+
| Custom Property | Description |
|
|
1051
|
+
|------------------------------------------------------|---------------------------------------------------------------|
|
|
1052
|
+
| `--rui-Modal__padding-x` | Inline padding of individual modal components |
|
|
1053
|
+
| `--rui-Modal__padding-y` | Block padding of individual modal components |
|
|
1054
|
+
| `--rui-Modal__background` | Modal background (including `url()` or gradient) |
|
|
1055
|
+
| `--rui-Modal__box-shadow` | Modal box shadow |
|
|
1056
|
+
| `--rui-Modal__separator__width` | Width of separator between modal header, body, and footer |
|
|
1057
|
+
| `--rui-Modal__separator__color` | Color of separator between modal header, body, and footer |
|
|
1058
|
+
| `--rui-Modal__outer-spacing-xs` | Spacing around modal, `xs` screen size |
|
|
1059
|
+
| `--rui-Modal__outer-spacing-sm` | Spacing around modal, `sm` screen size and bigger |
|
|
1060
|
+
| `--rui-Modal__header__gap` | Modal header gap between children |
|
|
1061
|
+
| `--rui-Modal__footer__background` | Modal footer background (including `url()` or gradient) |
|
|
1062
|
+
| `--rui-Modal__footer__gap` | Modal footer gap between children |
|
|
1063
|
+
| `--rui-Modal__backdrop__background` | Modal backdrop background (including `url()` or gradient) |
|
|
1064
|
+
| `--rui-Modal--auto__min-width` | Min width of auto-sized modal (when enough screen estate) |
|
|
1065
|
+
| `--rui-Modal--auto__max-width` | Max width of auto-sized modal (when enough screen estate) |
|
|
1066
|
+
| `--rui-Modal--small__width` | Width of small modal |
|
|
1067
|
+
| `--rui-Modal--medium__width` | Width of medium modal |
|
|
1068
|
+
| `--rui-Modal--large__width` | Width of large modal |
|
|
1069
|
+
| `--rui-Modal--fullscreen__width` | Width of fullscreen modal |
|
|
1070
|
+
| `--rui-Modal--fullscreen__height` | Height of fullscreen modal |
|