@react-ui-org/react-ui 0.52.1 → 0.54.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/README.md +10 -7
- package/dist/react-ui.css +5 -3
- package/dist/react-ui.development.css +11302 -0
- package/dist/react-ui.development.js +1588 -0
- package/dist/react-ui.js +1 -1
- package/package.json +66 -77
- package/src/{lib/components → components}/Alert/Alert.jsx +1 -1
- package/src/{lib/components/Alert/README.mdx → components/Alert/README.md} +84 -100
- package/src/{lib/components → components}/Badge/Badge.jsx +1 -1
- package/src/{lib/components → components}/Badge/Badge.scss +1 -1
- package/src/components/Badge/README.md +103 -0
- package/src/{lib/components → components}/Button/Button.jsx +1 -1
- package/src/components/Button/README.md +580 -0
- package/src/{lib/components → components}/ButtonGroup/ButtonGroup.jsx +11 -9
- package/src/{lib/components/ButtonGroup/README.mdx → components/ButtonGroup/README.md} +128 -134
- package/src/{lib/components → components}/Card/Card.jsx +1 -1
- package/src/components/Card/README.md +314 -0
- package/src/{lib/components/CheckboxField/README.mdx → components/CheckboxField/README.md} +96 -108
- package/src/{lib/components/FileInputField/README.mdx → components/FileInputField/README.md} +83 -95
- package/src/{lib/components → components}/FormLayout/FormLayout.jsx +4 -4
- package/src/components/FormLayout/README.md +462 -0
- package/src/{lib/components → components}/Grid/Grid.jsx +2 -2
- package/src/components/Grid/README.md +281 -0
- package/src/{lib/components → components}/InputGroup/InputGroup.jsx +28 -19
- package/src/{lib/components → components}/InputGroup/InputGroup.scss +4 -5
- package/src/{lib/components/InputGroup/README.mdx → components/InputGroup/README.md} +162 -165
- package/src/{lib/components → components}/Modal/Modal.jsx +6 -6
- package/src/components/Modal/README.md +1090 -0
- package/src/components/Modal/_hooks/useModalScrollPrevention.js +37 -0
- package/src/{lib/components/Paper/README.mdx → components/Paper/README.md} +18 -30
- package/src/{lib/components/Popover/README.mdx → components/Popover/README.md} +102 -132
- package/src/{lib/components/Radio/README.mdx → components/Radio/README.md} +122 -134
- package/src/{lib/components → components}/Radio/Radio.jsx +11 -12
- package/src/{lib/components → components}/Radio/Radio.scss +0 -5
- package/src/components/ScrollView/README.md +503 -0
- package/src/{lib/components → components}/ScrollView/ScrollView.jsx +12 -3
- package/src/components/SelectField/README.md +681 -0
- package/src/components/Table/README.md +259 -0
- package/src/{lib/components → components}/Table/Table.jsx +4 -1
- package/src/{lib/components → components}/Table/_components/TableHeaderCell/TableHeaderCell.jsx +1 -1
- package/src/{lib/components/Tabs/README.mdx → components/Tabs/README.md} +117 -134
- package/src/{lib/components → components}/Tabs/TabsItem.jsx +3 -3
- package/src/components/Text/README.md +220 -0
- package/src/components/TextArea/README.md +359 -0
- package/src/{lib/components/TextField/README.mdx → components/TextField/README.md} +336 -342
- package/src/{lib/components/TextLink/README.mdx → components/TextLink/README.md} +19 -31
- package/src/{lib/components/Toggle/README.mdx → components/Toggle/README.md} +98 -110
- package/src/components/Toolbar/README.md +359 -0
- package/src/{lib/components → components}/Toolbar/_helpers/getAlignClassName.js +12 -4
- package/src/components/_helpers/getRootPriorityClassName.js +15 -0
- package/src/{lib/index.js → index.js} +6 -0
- package/src/{lib/provider → provider}/RUIProvider.jsx +17 -11
- package/src/{lib/styles → styles}/tools/_caret.scss +1 -1
- package/src/{lib/styles → styles}/tools/form-fields/_box-field-elements.scss +1 -1
- package/src/{lib/styles → styles}/tools/form-fields/_inline-field-elements.scss +2 -2
- package/src/{lib/theme.scss → theme.scss} +4 -3
- package/CONTRIBUTING.md +0 -137
- package/dist/lib.development.js +0 -3179
- package/dist/lib.js +0 -1
- package/public/racom.svg +0 -11
- package/src/lib/components/Badge/README.mdx +0 -126
- package/src/lib/components/Button/README.mdx +0 -581
- package/src/lib/components/Card/README.mdx +0 -326
- package/src/lib/components/FormLayout/README.mdx +0 -501
- package/src/lib/components/Grid/README.mdx +0 -299
- package/src/lib/components/Modal/README.mdx +0 -1360
- package/src/lib/components/Modal/_hooks/useModalScrollPrevention.js +0 -35
- package/src/lib/components/ScrollView/README.mdx +0 -521
- package/src/lib/components/SelectField/README.mdx +0 -693
- package/src/lib/components/Table/README.mdx +0 -275
- package/src/lib/components/Text/README.mdx +0 -241
- package/src/lib/components/TextArea/README.mdx +0 -366
- package/src/lib/components/Toolbar/README.mdx +0 -386
- package/src/{lib/components → components}/Alert/Alert.scss +0 -0
- package/src/{lib/components → components}/Alert/_settings.scss +0 -0
- package/src/{lib/components → components}/Alert/_theme.scss +0 -0
- package/src/{lib/components → components}/Alert/_tools.scss +0 -0
- package/src/{lib/components → components}/Alert/index.js +0 -0
- package/src/{lib/components → components}/Badge/index.js +0 -0
- package/src/{lib/components → components}/Button/Button.scss +0 -0
- package/src/{lib/components → components}/Button/_base.scss +0 -0
- package/src/{lib/components → components}/Button/_priorities.scss +0 -0
- package/src/{lib/components → components}/Button/_settings.scss +0 -0
- package/src/{lib/components → components}/Button/_theme.scss +0 -0
- package/src/{lib/components → components}/Button/_tools.scss +0 -0
- package/src/{lib/components → components}/Button/helpers/getRootLabelVisibilityClassName.js +0 -0
- package/src/{lib/components/_helpers → components/Button/helpers}/getRootPriorityClassName.js +0 -0
- package/src/{lib/components → components}/Button/index.js +0 -0
- package/src/{lib/components → components}/ButtonGroup/ButtonGroup.scss +0 -0
- package/src/{lib/components → components}/ButtonGroup/ButtonGroupContext.js +0 -0
- package/src/{lib/components → components}/ButtonGroup/_theme.scss +0 -0
- package/src/{lib/components → components}/ButtonGroup/index.js +0 -0
- package/src/{lib/components → components}/Card/Card.scss +0 -0
- package/src/{lib/components → components}/Card/CardBody.jsx +0 -0
- package/src/{lib/components → components}/Card/CardFooter.jsx +0 -0
- package/src/{lib/components → components}/Card/_theme.scss +0 -0
- package/src/{lib/components → components}/Card/_tools.scss +0 -0
- package/src/{lib/components → components}/Card/index.js +0 -0
- package/src/{lib/components → components}/CheckboxField/CheckboxField.jsx +0 -0
- package/src/{lib/components → components}/CheckboxField/CheckboxField.scss +0 -0
- package/src/{lib/components → components}/CheckboxField/index.js +0 -0
- package/src/{lib/components → components}/FileInputField/FileInputField.jsx +0 -0
- package/src/{lib/components → components}/FileInputField/FileInputField.scss +0 -0
- package/src/{lib/components → components}/FileInputField/index.js +0 -0
- package/src/{lib/components → components}/FormLayout/FormLayout.scss +0 -0
- package/src/{lib/components → components}/FormLayout/FormLayoutContext.js +0 -0
- package/src/{lib/components → components}/FormLayout/FormLayoutCustomField.jsx +4 -4
- package/src/{lib/components → components}/FormLayout/FormLayoutCustomField.scss +0 -0
- package/src/{lib/components → components}/FormLayout/_theme.scss +0 -0
- package/src/{lib/components → components}/FormLayout/index.js +0 -0
- package/src/{lib/components → components}/Grid/Grid.scss +0 -0
- package/src/{lib/components → components}/Grid/GridSpan.jsx +0 -0
- package/src/{lib/components → components}/Grid/_helpers/generateResponsiveCustomProperties.js +0 -0
- package/src/{lib/components → components}/Grid/_settings.scss +0 -0
- package/src/{lib/components → components}/Grid/_tools.scss +0 -0
- package/src/{lib/components → components}/Grid/index.js +0 -0
- package/src/{lib/components → components}/InputGroup/InputGroupContext.js +0 -0
- package/src/{lib/components → components}/InputGroup/_theme.scss +0 -0
- package/src/{lib/components → components}/InputGroup/index.js +0 -0
- package/src/{lib/components → components}/Modal/Modal.scss +0 -0
- package/src/{lib/components → components}/Modal/ModalBody.jsx +0 -0
- package/src/{lib/components → components}/Modal/ModalBody.scss +0 -0
- package/src/{lib/components → components}/Modal/ModalCloseButton.jsx +1 -1
- package/src/{lib/components → components}/Modal/ModalCloseButton.scss +0 -0
- package/src/{lib/components → components}/Modal/ModalContent.jsx +0 -0
- package/src/{lib/components → components}/Modal/ModalContent.scss +0 -0
- package/src/{lib/components → components}/Modal/ModalFooter.jsx +0 -0
- package/src/{lib/components → components}/Modal/ModalFooter.scss +0 -0
- package/src/{lib/components → components}/Modal/ModalHeader.jsx +0 -0
- package/src/{lib/components → components}/Modal/ModalHeader.scss +0 -0
- package/src/{lib/components → components}/Modal/ModalTitle.jsx +0 -0
- package/src/{lib/components → components}/Modal/ModalTitle.scss +0 -0
- package/src/{lib/components → components}/Modal/_helpers/getJustifyClassName.js +0 -0
- package/src/{lib/components → components}/Modal/_helpers/getPositionClassName.js +0 -0
- package/src/{lib/components → components}/Modal/_helpers/getScrollingClassName.js +0 -0
- package/src/{lib/components → components}/Modal/_helpers/getSizeClassName.js +0 -0
- package/src/{lib/components → components}/Modal/_hooks/useModalFocus.js +0 -0
- package/src/{lib/components → components}/Modal/_settings.scss +0 -0
- package/src/{lib/components → components}/Modal/_theme.scss +0 -0
- package/src/{lib/components → components}/Modal/index.js +0 -0
- package/src/{lib/components → components}/Paper/Paper.jsx +0 -0
- package/src/{lib/components → components}/Paper/Paper.scss +0 -0
- package/src/{lib/components → components}/Paper/_theme.scss +0 -0
- package/src/{lib/components → components}/Paper/index.js +0 -0
- package/src/{lib/components → components}/Popover/Popover.jsx +0 -0
- package/src/{lib/components → components}/Popover/Popover.scss +0 -0
- package/src/{lib/components → components}/Popover/PopoverWrapper.jsx +0 -0
- package/src/{lib/components → components}/Popover/PopoverWrapper.scss +0 -0
- package/src/{lib/components → components}/Popover/_helpers/getRootAlignmentClassName.js +0 -0
- package/src/{lib/components → components}/Popover/_helpers/getRootSideClassName.js +0 -0
- package/src/{lib/components → components}/Popover/_theme.scss +0 -0
- package/src/{lib/components → components}/Popover/index.js +0 -0
- package/src/{lib/components → components}/Radio/index.js +0 -0
- package/src/{lib/components → components}/ScrollView/ScrollView.scss +0 -0
- package/src/{lib/components → components}/ScrollView/_helpers/getElementsPositionDifference.js +0 -0
- package/src/{lib/components → components}/ScrollView/_hooks/useLoadResizeHook.js +0 -0
- package/src/{lib/components → components}/ScrollView/_hooks/useScrollPositionHook.js +0 -0
- package/src/{lib/components → components}/ScrollView/index.js +0 -0
- package/src/{lib/components → components}/SelectField/SelectField.jsx +0 -0
- package/src/{lib/components → components}/SelectField/SelectField.scss +0 -0
- package/src/{lib/components → components}/SelectField/_components/Option/Option.jsx +0 -0
- package/src/{lib/components → components}/SelectField/_components/Option/index.js +0 -0
- package/src/{lib/components → components}/SelectField/index.js +0 -0
- package/src/{lib/components → components}/Table/Table.scss +0 -0
- package/src/{lib/components → components}/Table/_components/TableBodyCell/TableBodyCell.jsx +0 -0
- package/src/{lib/components → components}/Table/_components/TableBodyCell/index.js +0 -0
- package/src/{lib/components → components}/Table/_components/TableCell.scss +0 -0
- package/src/{lib/components → components}/Table/_components/TableHeaderCell/index.js +0 -0
- package/src/{lib/components → components}/Table/_settings.scss +0 -0
- package/src/{lib/components → components}/Table/index.js +0 -0
- package/src/{lib/components → components}/Tabs/Tabs.jsx +0 -0
- package/src/{lib/components → components}/Tabs/Tabs.scss +0 -0
- package/src/{lib/components → components}/Tabs/TabsItem.scss +0 -0
- package/src/{lib/components → components}/Tabs/_theme.scss +0 -0
- package/src/{lib/components → components}/Tabs/index.js +0 -0
- package/src/{lib/components → components}/Text/Text.jsx +0 -0
- package/src/{lib/components → components}/Text/Text.scss +0 -0
- package/src/{lib/components → components}/Text/_helpers/getRootClampClassName.js +0 -0
- package/src/{lib/components → components}/Text/_helpers/getRootHyphensClassName.js +0 -0
- package/src/{lib/components → components}/Text/_helpers/getRootWordWrappingClassName.js +0 -0
- package/src/{lib/components → components}/Text/index.js +0 -0
- package/src/{lib/components → components}/TextArea/TextArea.jsx +0 -0
- package/src/{lib/components → components}/TextArea/TextArea.scss +0 -0
- package/src/{lib/components → components}/TextArea/index.js +0 -0
- package/src/{lib/components → components}/TextField/TextField.jsx +0 -0
- package/src/{lib/components → components}/TextField/TextField.scss +0 -0
- package/src/{lib/components → components}/TextField/index.js +0 -0
- package/src/{lib/components → components}/TextLink/TextLink.jsx +1 -1
- /package/src/{lib/components → components}/TextLink/TextLink.scss +0 -0
- /package/src/{lib/components → components}/TextLink/_theme.scss +0 -0
- /package/src/{lib/components → components}/TextLink/index.js +0 -0
- /package/src/{lib/components → components}/Toggle/Toggle.jsx +0 -0
- /package/src/{lib/components → components}/Toggle/Toggle.scss +0 -0
- /package/src/{lib/components → components}/Toggle/index.js +0 -0
- /package/src/{lib/components → components}/Toolbar/Toolbar.jsx +0 -0
- /package/src/{lib/components → components}/Toolbar/Toolbar.scss +0 -0
- /package/src/{lib/components → components}/Toolbar/ToolbarGroup.jsx +0 -0
- /package/src/{lib/components → components}/Toolbar/ToolbarItem.jsx +0 -0
- /package/src/{lib/components → components}/Toolbar/_helpers/getJustifyClassName.js +0 -0
- /package/src/{lib/components → components}/Toolbar/_theme.scss +0 -0
- /package/src/{lib/components → components}/Toolbar/index.js +0 -0
- /package/src/{lib/components → components}/_helpers/getRootColorClassName.js +0 -0
- /package/src/{lib/components → components}/_helpers/getRootSizeClassName.js +0 -0
- /package/src/{lib/components → components}/_helpers/getRootValidationStateClassName.js +0 -0
- /package/src/{lib/components → components}/_helpers/isChildrenEmpty.js +0 -0
- /package/src/{lib/components → components}/_helpers/resolveContextOrProp.js +0 -0
- /package/src/{lib/components → components}/_helpers/transferProps.js +0 -0
- /package/src/{lib/foundation.scss → foundation.scss} +0 -0
- /package/src/{lib/helpers.scss → helpers.scss} +0 -0
- /package/src/{lib/provider → provider}/RUIContext.jsx +0 -0
- /package/src/{lib/provider → provider}/index.js +0 -0
- /package/src/{lib/provider → provider}/withGlobalProps.jsx +0 -0
- /package/src/{lib/styles → styles}/_utilities.scss +0 -0
- /package/src/{lib/styles → styles}/elements/_code.scss +0 -0
- /package/src/{lib/styles → styles}/elements/_links.scss +0 -0
- /package/src/{lib/styles → styles}/elements/_lists.scss +0 -0
- /package/src/{lib/styles → styles}/elements/_page.scss +0 -0
- /package/src/{lib/styles → styles}/elements/_rulers.scss +0 -0
- /package/src/{lib/styles → styles}/elements/_small.scss +0 -0
- /package/src/{lib/styles → styles}/generic/_box-sizing.scss +0 -0
- /package/src/{lib/styles → styles}/generic/_focus.scss +0 -0
- /package/src/{lib/styles → styles}/generic/_forms.scss +0 -0
- /package/src/{lib/styles → styles}/generic/_reset.scss +0 -0
- /package/src/{lib/styles → styles}/generic/_shared.scss +0 -0
- /package/src/{lib/styles → styles}/helpers/_animation.scss +0 -0
- /package/src/{lib/styles → styles}/settings/_animations.scss +0 -0
- /package/src/{lib/styles → styles}/settings/_breakpoints.scss +0 -0
- /package/src/{lib/styles → styles}/settings/_escaped-characters.scss +0 -0
- /package/src/{lib/styles → styles}/settings/_form-fields.scss +0 -0
- /package/src/{lib/styles → styles}/settings/_forms.scss +0 -0
- /package/src/{lib/styles → styles}/settings/_utilities.scss +0 -0
- /package/src/{lib/styles → styles}/settings/_z-indexes.scss +0 -0
- /package/src/{lib/styles → styles}/theme/_accessibility.scss +0 -0
- /package/src/{lib/styles → styles}/theme/_borders.scss +0 -0
- /package/src/{lib/styles → styles}/theme/_code.scss +0 -0
- /package/src/{lib/styles → styles}/theme/_form-fields.scss +0 -0
- /package/src/{lib/styles → styles}/theme/_links.scss +0 -0
- /package/src/{lib/styles → styles}/theme/_lists.scss +0 -0
- /package/src/{lib/styles → styles}/theme/_page.scss +0 -0
- /package/src/{lib/styles → styles}/theme/_spacing.scss +0 -0
- /package/src/{lib/styles → styles}/theme/_typography.scss +0 -0
- /package/src/{lib/styles → styles}/theme-constants/_breakpoints.scss +0 -0
- /package/src/{lib/styles → styles}/theme-constants/_colors.scss +0 -0
- /package/src/{lib/styles → styles}/theme-constants/_svg.scss +0 -0
- /package/src/{lib/styles → styles}/tools/_accessibility.scss +0 -0
- /package/src/{lib/styles → styles}/tools/_breakpoint.scss +0 -0
- /package/src/{lib/styles → styles}/tools/_colors.scss +0 -0
- /package/src/{lib/styles → styles}/tools/_reset.scss +0 -0
- /package/src/{lib/styles → styles}/tools/_scrollbar.scss +0 -0
- /package/src/{lib/styles → styles}/tools/_spacing.scss +0 -0
- /package/src/{lib/styles → styles}/tools/_string.scss +0 -0
- /package/src/{lib/styles → styles}/tools/_svg.scss +0 -0
- /package/src/{lib/styles → styles}/tools/_transition.scss +0 -0
- /package/src/{lib/styles → styles}/tools/_utilities.scss +0 -0
- /package/src/{lib/styles → styles}/tools/form-fields/_box-field-layout.scss +0 -0
- /package/src/{lib/styles → styles}/tools/form-fields/_box-field-sizes.scss +0 -0
- /package/src/{lib/styles → styles}/tools/form-fields/_foundation.scss +0 -0
- /package/src/{lib/styles → styles}/tools/form-fields/_inline-field-layout.scss +0 -0
- /package/src/{lib/styles → styles}/tools/form-fields/_variants.scss +0 -0
- /package/src/{lib/translations → translations}/en.js +0 -0
- /package/src/{lib/utils → utils}/classNames.js +0 -0
|
@@ -1,1360 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: Modal
|
|
3
|
-
menu: 'Miscellaneous'
|
|
4
|
-
route: /components/modal
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
# Modal
|
|
8
|
-
|
|
9
|
-
Modal allows prompting users to take or complete an action.
|
|
10
|
-
|
|
11
|
-
import {
|
|
12
|
-
Playground,
|
|
13
|
-
Props,
|
|
14
|
-
} from 'docz'
|
|
15
|
-
import {
|
|
16
|
-
Button,
|
|
17
|
-
CheckboxField,
|
|
18
|
-
FormLayout,
|
|
19
|
-
Modal,
|
|
20
|
-
ModalBody,
|
|
21
|
-
ModalCloseButton,
|
|
22
|
-
ModalContent,
|
|
23
|
-
ModalFooter,
|
|
24
|
-
ModalHeader,
|
|
25
|
-
ModalTitle,
|
|
26
|
-
Radio,
|
|
27
|
-
ScrollView,
|
|
28
|
-
TextArea,
|
|
29
|
-
TextField,
|
|
30
|
-
Toolbar,
|
|
31
|
-
ToolbarGroup,
|
|
32
|
-
ToolbarItem,
|
|
33
|
-
} from '../..'
|
|
34
|
-
import Icon from '../../../docs/_components/Icon'
|
|
35
|
-
|
|
36
|
-
## Basic Usage
|
|
37
|
-
|
|
38
|
-
To implement the Modal component, you need to import it first:
|
|
39
|
-
|
|
40
|
-
```js
|
|
41
|
-
import {
|
|
42
|
-
Modal,
|
|
43
|
-
ModalHeader,
|
|
44
|
-
ModalBody,
|
|
45
|
-
ModalCloseButton,
|
|
46
|
-
ModalContent,
|
|
47
|
-
ModalFooter,
|
|
48
|
-
ModalTitle,
|
|
49
|
-
} from '@react-ui-org/react-ui';
|
|
50
|
-
```
|
|
51
|
-
|
|
52
|
-
And use it:
|
|
53
|
-
|
|
54
|
-
<Playground>
|
|
55
|
-
{() => {
|
|
56
|
-
const [modalOpen, setModalOpen] = React.useState(false);
|
|
57
|
-
const modalPrimaryButtonRef = React.useRef();
|
|
58
|
-
const modalCloseButtonRef = React.useRef();
|
|
59
|
-
return (
|
|
60
|
-
<>
|
|
61
|
-
<Button label="Launch modal" onClick={() => setModalOpen(true)} />
|
|
62
|
-
<div>
|
|
63
|
-
{modalOpen && (
|
|
64
|
-
<Modal
|
|
65
|
-
closeButtonRef={modalCloseButtonRef}
|
|
66
|
-
primaryButtonRef={modalPrimaryButtonRef}
|
|
67
|
-
>
|
|
68
|
-
<ModalHeader>
|
|
69
|
-
<ModalTitle>Delete the user?</ModalTitle>
|
|
70
|
-
<ModalCloseButton onClick={() => setModalOpen(false)} />
|
|
71
|
-
</ModalHeader>
|
|
72
|
-
<ModalBody>
|
|
73
|
-
<ModalContent>
|
|
74
|
-
<p>
|
|
75
|
-
Do you really want to delete the user <code>admin</code>?
|
|
76
|
-
This cannot be undone.
|
|
77
|
-
</p>
|
|
78
|
-
</ModalContent>
|
|
79
|
-
</ModalBody>
|
|
80
|
-
<ModalFooter>
|
|
81
|
-
<Button
|
|
82
|
-
color="danger"
|
|
83
|
-
label="Delete"
|
|
84
|
-
onClick={() => setModalOpen(false)}
|
|
85
|
-
ref={modalPrimaryButtonRef}
|
|
86
|
-
/>
|
|
87
|
-
<Button
|
|
88
|
-
color="secondary"
|
|
89
|
-
label="Close"
|
|
90
|
-
onClick={() => setModalOpen(false)}
|
|
91
|
-
priority="outline"
|
|
92
|
-
ref={modalCloseButtonRef}
|
|
93
|
-
/>
|
|
94
|
-
</ModalFooter>
|
|
95
|
-
</Modal>
|
|
96
|
-
)}
|
|
97
|
-
</div>
|
|
98
|
-
</>
|
|
99
|
-
);
|
|
100
|
-
}}
|
|
101
|
-
</Playground>
|
|
102
|
-
|
|
103
|
-
See [API](#api) for all available options.
|
|
104
|
-
|
|
105
|
-
## General Guidelines
|
|
106
|
-
|
|
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.
|
|
110
|
-
|
|
111
|
-
- **The title** should communicate the **purpose of the modal** rather than a
|
|
112
|
-
generic text. Eg. “Delete the user?” tells more than “Are you sure?” or
|
|
113
|
-
“Warning”.
|
|
114
|
-
|
|
115
|
-
- **Modal actions** should correspond to the modal purpose, too. E.g. “Delete”
|
|
116
|
-
tells better what happens rather than “OK”.
|
|
117
|
-
|
|
118
|
-
- Modal **automatically focuses the first non-disabled form field** by default
|
|
119
|
-
which allows users to confirm the modal by hitting the enter key. When no
|
|
120
|
-
field is found then the primary button (in the footer) is focused. If there
|
|
121
|
-
are neither, it tries to focus any other focusable elements. In case there
|
|
122
|
-
are none, or [autoFocus](#autoFocus) is disabled, Modal itself is focused.
|
|
123
|
-
|
|
124
|
-
- **Avoid stacking** of modals. While it may technically work, the modal is just
|
|
125
|
-
not designed for that.
|
|
126
|
-
|
|
127
|
-
📖 [Read more about modals at Nielsen Norman Group.][nng-modal]
|
|
128
|
-
|
|
129
|
-
## Composition
|
|
130
|
-
|
|
131
|
-
Modal is decomposed into the following components:
|
|
132
|
-
|
|
133
|
-
- [Modal](#api)
|
|
134
|
-
- [ModalHeader](#modalheader-1)
|
|
135
|
-
- [ModalTitle](#modaltitle)
|
|
136
|
-
- [ModalCloseButton](#modalclosebutton)
|
|
137
|
-
- [ModalBody](#modalbody-1)
|
|
138
|
-
- [ModalContent](#modalcontent)
|
|
139
|
-
(may be wrapped with [ScrollView](/components/scroll-view))
|
|
140
|
-
- [ModalFooter](#modalfooter-1)
|
|
141
|
-
|
|
142
|
-
Using different combinations, you can compose different kinds of modals,
|
|
143
|
-
e.g. dialog modal, blocking modal, scrollable modal, etc.
|
|
144
|
-
|
|
145
|
-
<Playground>
|
|
146
|
-
{() => {
|
|
147
|
-
const [modalOpen, setModalOpen] = React.useState(null);
|
|
148
|
-
const modalPrimaryButtonRef = React.useRef();
|
|
149
|
-
const modalCloseButtonRef = React.useRef();
|
|
150
|
-
return (
|
|
151
|
-
<>
|
|
152
|
-
<Button
|
|
153
|
-
label="Launch blocking modal without title"
|
|
154
|
-
onClick={() => {
|
|
155
|
-
setModalOpen(1);
|
|
156
|
-
setTimeout(() => setModalOpen(null), 2500);
|
|
157
|
-
}}
|
|
158
|
-
/>
|
|
159
|
-
<Button
|
|
160
|
-
label="Launch blocking modal with title"
|
|
161
|
-
onClick={() => {
|
|
162
|
-
setModalOpen(2);
|
|
163
|
-
setTimeout(() => setModalOpen(null), 3500);
|
|
164
|
-
}}
|
|
165
|
-
/>
|
|
166
|
-
<Button
|
|
167
|
-
label="Launch modal as dialog"
|
|
168
|
-
onClick={() => setModalOpen(3)}
|
|
169
|
-
/>
|
|
170
|
-
<Button
|
|
171
|
-
label="Launch modal as form"
|
|
172
|
-
onClick={() => setModalOpen(4)}
|
|
173
|
-
/>
|
|
174
|
-
<div>
|
|
175
|
-
{modalOpen === 1 && (
|
|
176
|
-
<Modal>
|
|
177
|
-
<ModalBody>
|
|
178
|
-
<ModalContent>
|
|
179
|
-
<p className="text-center">
|
|
180
|
-
Application is being loaded.
|
|
181
|
-
<span className="d-inline-flex align-items-center animation-spin-counterclockwise">
|
|
182
|
-
<Icon icon="loading" />
|
|
183
|
-
</span>
|
|
184
|
-
</p>
|
|
185
|
-
</ModalContent>
|
|
186
|
-
</ModalBody>
|
|
187
|
-
</Modal>
|
|
188
|
-
)}
|
|
189
|
-
{modalOpen === 2 && (
|
|
190
|
-
<Modal>
|
|
191
|
-
<ModalHeader>
|
|
192
|
-
<ModalTitle>Action finished</ModalTitle>
|
|
193
|
-
</ModalHeader>
|
|
194
|
-
<ModalBody>
|
|
195
|
-
<ModalContent>
|
|
196
|
-
<p>
|
|
197
|
-
Action has been successfully finished.
|
|
198
|
-
You will be redirected within a few seconds.
|
|
199
|
-
</p>
|
|
200
|
-
</ModalContent>
|
|
201
|
-
</ModalBody>
|
|
202
|
-
</Modal>
|
|
203
|
-
)}
|
|
204
|
-
{modalOpen === 3 && (
|
|
205
|
-
<Modal
|
|
206
|
-
closeButtonRef={modalCloseButtonRef}
|
|
207
|
-
primaryButtonRef={modalPrimaryButtonRef}
|
|
208
|
-
>
|
|
209
|
-
<ModalHeader>
|
|
210
|
-
<ModalTitle>Delete the user?</ModalTitle>
|
|
211
|
-
<ModalCloseButton onClick={() => setModalOpen(false)} />
|
|
212
|
-
</ModalHeader>
|
|
213
|
-
<ModalBody>
|
|
214
|
-
<ModalContent>
|
|
215
|
-
<p>
|
|
216
|
-
Do you really want to delete the user <code>admin</code>?
|
|
217
|
-
This cannot be undone.
|
|
218
|
-
</p>
|
|
219
|
-
</ModalContent>
|
|
220
|
-
</ModalBody>
|
|
221
|
-
<ModalFooter>
|
|
222
|
-
<Button
|
|
223
|
-
color="danger"
|
|
224
|
-
label="Delete"
|
|
225
|
-
onClick={() => setModalOpen(false)}
|
|
226
|
-
ref={modalPrimaryButtonRef}
|
|
227
|
-
/>
|
|
228
|
-
<Button
|
|
229
|
-
color="secondary"
|
|
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
|
-
color="secondary"
|
|
263
|
-
label="Close"
|
|
264
|
-
onClick={() => setModalOpen(false)}
|
|
265
|
-
priority="outline"
|
|
266
|
-
ref={modalCloseButtonRef}
|
|
267
|
-
/>
|
|
268
|
-
</ModalFooter>
|
|
269
|
-
</Modal>
|
|
270
|
-
)}
|
|
271
|
-
</div>
|
|
272
|
-
</>
|
|
273
|
-
);
|
|
274
|
-
}}
|
|
275
|
-
</Playground>
|
|
276
|
-
|
|
277
|
-
### ModalHeader
|
|
278
|
-
|
|
279
|
-
ModalHeader is an optional part of the Modal which allows you to display the title
|
|
280
|
-
of the modal and its close button.
|
|
281
|
-
|
|
282
|
-
It is recommended to compose ModalHeader from the following elements. For title,
|
|
283
|
-
use ModalTitle. For the close button, use ModalCloseButton, however it can
|
|
284
|
-
be omitted if a close button is part of ModalFooter.
|
|
285
|
-
|
|
286
|
-
There are two ways how to position elements within the ModalHeader:
|
|
287
|
-
|
|
288
|
-
1. You can use provided positioning. Place previously mentioned elements into
|
|
289
|
-
the ModalHeader and use `justify` prop to set up the positioning of those
|
|
290
|
-
elements.
|
|
291
|
-
2. You can customize positioning using another component (e.g.
|
|
292
|
-
[Toolbar](/components/toolbar)). In that case, set `justify` to `stretch` and
|
|
293
|
-
position elements on your own.
|
|
294
|
-
|
|
295
|
-
<Playground>
|
|
296
|
-
{() => {
|
|
297
|
-
const [modalOpen, setModalOpen] = React.useState(false);
|
|
298
|
-
const [variant, setVariant] = React.useState(null);
|
|
299
|
-
const modalPrimaryButtonRef = React.useRef();
|
|
300
|
-
const modalCloseButtonRef = React.useRef();
|
|
301
|
-
return (
|
|
302
|
-
<>
|
|
303
|
-
<Button
|
|
304
|
-
label="Launch with close button"
|
|
305
|
-
onClick={() => {
|
|
306
|
-
setModalOpen(true);
|
|
307
|
-
setVariant(1);
|
|
308
|
-
}}
|
|
309
|
-
/>
|
|
310
|
-
<Button
|
|
311
|
-
label="Launch without close button"
|
|
312
|
-
onClick={() => {
|
|
313
|
-
setModalOpen(true);
|
|
314
|
-
setVariant(2);
|
|
315
|
-
}}
|
|
316
|
-
/>
|
|
317
|
-
<Button
|
|
318
|
-
label="Launch without close button and with centered title"
|
|
319
|
-
onClick={() => {
|
|
320
|
-
setModalOpen(true);
|
|
321
|
-
setVariant(3);
|
|
322
|
-
}}
|
|
323
|
-
/>
|
|
324
|
-
<Button
|
|
325
|
-
label="Launch with custom layout"
|
|
326
|
-
onClick={() => {
|
|
327
|
-
setModalOpen(true);
|
|
328
|
-
setVariant(4);
|
|
329
|
-
}}
|
|
330
|
-
/>
|
|
331
|
-
<div>
|
|
332
|
-
{modalOpen && (
|
|
333
|
-
<Modal
|
|
334
|
-
closeButtonRef={modalCloseButtonRef}
|
|
335
|
-
primaryButtonRef={modalPrimaryButtonRef}
|
|
336
|
-
>
|
|
337
|
-
{variant === 1 && (
|
|
338
|
-
<ModalHeader>
|
|
339
|
-
<ModalTitle>Delete the user?</ModalTitle>
|
|
340
|
-
<ModalCloseButton onClick={() => setModalOpen(false)} />
|
|
341
|
-
</ModalHeader>
|
|
342
|
-
)}
|
|
343
|
-
{variant === 2 && (
|
|
344
|
-
<ModalHeader>
|
|
345
|
-
<ModalTitle>Delete the user?</ModalTitle>
|
|
346
|
-
</ModalHeader>
|
|
347
|
-
)}
|
|
348
|
-
{variant === 3 && (
|
|
349
|
-
<ModalHeader justify="center">
|
|
350
|
-
<ModalTitle>Delete the user?</ModalTitle>
|
|
351
|
-
</ModalHeader>
|
|
352
|
-
)}
|
|
353
|
-
{variant === 4 && (
|
|
354
|
-
<ModalHeader justify="stretch">
|
|
355
|
-
<Toolbar justify="space-between">
|
|
356
|
-
<ToolbarItem>
|
|
357
|
-
{''}
|
|
358
|
-
</ToolbarItem>
|
|
359
|
-
<ToolbarItem>
|
|
360
|
-
<ModalTitle>Delete the user?</ModalTitle>
|
|
361
|
-
</ToolbarItem>
|
|
362
|
-
<ToolbarItem>
|
|
363
|
-
<ModalCloseButton onClick={() => setModalOpen(false)} />
|
|
364
|
-
</ToolbarItem>
|
|
365
|
-
</Toolbar>
|
|
366
|
-
</ModalHeader>
|
|
367
|
-
)}
|
|
368
|
-
<ModalBody>
|
|
369
|
-
<ModalContent>
|
|
370
|
-
<p>
|
|
371
|
-
Do you really want to delete the user <code>admin</code>?
|
|
372
|
-
This cannot be undone.
|
|
373
|
-
</p>
|
|
374
|
-
</ModalContent>
|
|
375
|
-
</ModalBody>
|
|
376
|
-
<ModalFooter>
|
|
377
|
-
<Button
|
|
378
|
-
color="danger"
|
|
379
|
-
label="Delete"
|
|
380
|
-
onClick={() => setModalOpen(false)}
|
|
381
|
-
ref={modalPrimaryButtonRef}
|
|
382
|
-
/>
|
|
383
|
-
<Button
|
|
384
|
-
color="secondary"
|
|
385
|
-
label="Close"
|
|
386
|
-
onClick={() => setModalOpen(false)}
|
|
387
|
-
priority="outline"
|
|
388
|
-
ref={modalCloseButtonRef}
|
|
389
|
-
/>
|
|
390
|
-
</ModalFooter>
|
|
391
|
-
</Modal>
|
|
392
|
-
)}
|
|
393
|
-
</div>
|
|
394
|
-
</>
|
|
395
|
-
);
|
|
396
|
-
}}
|
|
397
|
-
</Playground>
|
|
398
|
-
|
|
399
|
-
### ModalBody
|
|
400
|
-
|
|
401
|
-
ModalBody is a mandatory part of the Modal which allows you to display the
|
|
402
|
-
content of the Modal.
|
|
403
|
-
|
|
404
|
-
Although the ModalBody allows you to display arbitrary content, you should not
|
|
405
|
-
place content directly into the ModalBody, but wrap it with ModalContent first.
|
|
406
|
-
|
|
407
|
-
In case your content is expected to be long, consider wrapping ModalContent
|
|
408
|
-
with ScrollView. Check [Scrolling Long Content](#scrolling-long-content) section
|
|
409
|
-
below.
|
|
410
|
-
|
|
411
|
-
### ModalFooter
|
|
412
|
-
|
|
413
|
-
ModalFooter is an optional part of the Modal which allows you to display
|
|
414
|
-
user actions.
|
|
415
|
-
|
|
416
|
-
There are two ways to position buttons within the ModalFooter:
|
|
417
|
-
|
|
418
|
-
1. You can use provided positioning. Place Button component (or any arbitrary
|
|
419
|
-
element) and use `justify` prop to set up the positioning of those elements.
|
|
420
|
-
2. You can customize positioning using another component (e.g.
|
|
421
|
-
[Toolbar](/components/toolbar)). In that case, set `justify` to `stretch`
|
|
422
|
-
and position elements on your own.
|
|
423
|
-
|
|
424
|
-
<Playground>
|
|
425
|
-
{() => {
|
|
426
|
-
const [modalOpen, setModalOpen] = React.useState(false);
|
|
427
|
-
const [modalJustify, setModalJustify] = React.useState('center');
|
|
428
|
-
const modalPrimaryButtonRef = React.useRef();
|
|
429
|
-
const modalCloseButtonRef = React.useRef();
|
|
430
|
-
return (
|
|
431
|
-
<>
|
|
432
|
-
<Button
|
|
433
|
-
label="Launch modal with footer variants"
|
|
434
|
-
onClick={() => setModalOpen(true)}
|
|
435
|
-
/>
|
|
436
|
-
<div>
|
|
437
|
-
{modalOpen && (
|
|
438
|
-
<Modal
|
|
439
|
-
closeButtonRef={modalCloseButtonRef}
|
|
440
|
-
primaryButtonRef={modalPrimaryButtonRef}
|
|
441
|
-
>
|
|
442
|
-
<ModalHeader>
|
|
443
|
-
<ModalTitle>Footer justification</ModalTitle>
|
|
444
|
-
<ModalCloseButton onClick={() => setModalOpen(false)} />
|
|
445
|
-
</ModalHeader>
|
|
446
|
-
<ModalBody>
|
|
447
|
-
<ModalContent>
|
|
448
|
-
<Radio
|
|
449
|
-
label="Footer justification"
|
|
450
|
-
onChange={(e) => setModalJustify(e.target.value)}
|
|
451
|
-
options={[
|
|
452
|
-
{
|
|
453
|
-
label: 'start',
|
|
454
|
-
value: 'start',
|
|
455
|
-
},
|
|
456
|
-
{
|
|
457
|
-
label: 'center',
|
|
458
|
-
value: 'center',
|
|
459
|
-
},
|
|
460
|
-
{
|
|
461
|
-
label: 'end',
|
|
462
|
-
value: 'end',
|
|
463
|
-
},
|
|
464
|
-
{
|
|
465
|
-
label: 'space-between',
|
|
466
|
-
value: 'space-between',
|
|
467
|
-
},
|
|
468
|
-
{
|
|
469
|
-
label: 'stretch (with a custom layout)',
|
|
470
|
-
value: 'stretch',
|
|
471
|
-
},
|
|
472
|
-
]}
|
|
473
|
-
value={modalJustify}
|
|
474
|
-
/>
|
|
475
|
-
</ModalContent>
|
|
476
|
-
</ModalBody>
|
|
477
|
-
<ModalFooter justify={modalJustify}>
|
|
478
|
-
{
|
|
479
|
-
modalJustify === 'stretch'
|
|
480
|
-
? (
|
|
481
|
-
<Toolbar justify="space-between">
|
|
482
|
-
<ToolbarGroup>
|
|
483
|
-
<ToolbarItem>
|
|
484
|
-
<Button
|
|
485
|
-
color="danger"
|
|
486
|
-
label="Delete"
|
|
487
|
-
onClick={() => setModalOpen(false)}
|
|
488
|
-
ref={modalPrimaryButtonRef}
|
|
489
|
-
/>
|
|
490
|
-
</ToolbarItem>
|
|
491
|
-
<ToolbarItem>
|
|
492
|
-
<Button
|
|
493
|
-
color="warning"
|
|
494
|
-
label="Archive"
|
|
495
|
-
onClick={() => setModalOpen(false)}
|
|
496
|
-
ref={modalPrimaryButtonRef}
|
|
497
|
-
/>
|
|
498
|
-
</ToolbarItem>
|
|
499
|
-
</ToolbarGroup>
|
|
500
|
-
<ToolbarItem>
|
|
501
|
-
<Button
|
|
502
|
-
color="secondary"
|
|
503
|
-
label="Close"
|
|
504
|
-
onClick={() => setModalOpen(false)}
|
|
505
|
-
priority="outline"
|
|
506
|
-
ref={modalCloseButtonRef}
|
|
507
|
-
/>
|
|
508
|
-
</ToolbarItem>
|
|
509
|
-
</Toolbar>
|
|
510
|
-
) : (
|
|
511
|
-
<>
|
|
512
|
-
<Button
|
|
513
|
-
label="OK"
|
|
514
|
-
onClick={() => setModalOpen(false)}
|
|
515
|
-
ref={modalPrimaryButtonRef}
|
|
516
|
-
/>
|
|
517
|
-
<Button
|
|
518
|
-
color="secondary"
|
|
519
|
-
label="Close"
|
|
520
|
-
onClick={() => setModalOpen(false)}
|
|
521
|
-
priority="outline"
|
|
522
|
-
ref={modalCloseButtonRef}
|
|
523
|
-
/>
|
|
524
|
-
</>
|
|
525
|
-
)
|
|
526
|
-
}
|
|
527
|
-
</ModalFooter>
|
|
528
|
-
</Modal>
|
|
529
|
-
)}
|
|
530
|
-
</div>
|
|
531
|
-
</>
|
|
532
|
-
);
|
|
533
|
-
}}
|
|
534
|
-
</Playground>
|
|
535
|
-
|
|
536
|
-
## Sizes
|
|
537
|
-
|
|
538
|
-
Modal is available in three fixed-width sizes: small, medium, large and fullscreen.
|
|
539
|
-
Modals of any size automatically shrink when they cannot fit the screen width.
|
|
540
|
-
|
|
541
|
-
<Playground>
|
|
542
|
-
{() => {
|
|
543
|
-
const [modalOpen, setModalOpen] = React.useState(false);
|
|
544
|
-
const [modalSize, setModalSize] = React.useState('small');
|
|
545
|
-
const modalPrimaryButtonRef = React.useRef();
|
|
546
|
-
const modalCloseButtonRef = React.useRef();
|
|
547
|
-
return (
|
|
548
|
-
<>
|
|
549
|
-
<Button
|
|
550
|
-
label="Launch small modal"
|
|
551
|
-
onClick={() => {
|
|
552
|
-
setModalSize('small');
|
|
553
|
-
setModalOpen(true);
|
|
554
|
-
}}
|
|
555
|
-
/>
|
|
556
|
-
<Button
|
|
557
|
-
label="Launch medium modal"
|
|
558
|
-
onClick={() => {
|
|
559
|
-
setModalSize('medium');
|
|
560
|
-
setModalOpen(true);
|
|
561
|
-
}}
|
|
562
|
-
/>
|
|
563
|
-
<Button
|
|
564
|
-
label="Launch large modal"
|
|
565
|
-
onClick={() => {
|
|
566
|
-
setModalSize('large');
|
|
567
|
-
setModalOpen(true);
|
|
568
|
-
}}
|
|
569
|
-
/>
|
|
570
|
-
<Button
|
|
571
|
-
label="Launch fullscreen modal"
|
|
572
|
-
onClick={() => {
|
|
573
|
-
setModalSize('fullscreen');
|
|
574
|
-
setModalOpen(true);
|
|
575
|
-
}}
|
|
576
|
-
/>
|
|
577
|
-
<div>
|
|
578
|
-
{modalOpen && (
|
|
579
|
-
<Modal
|
|
580
|
-
closeButtonRef={modalCloseButtonRef}
|
|
581
|
-
primaryButtonRef={modalPrimaryButtonRef}
|
|
582
|
-
size={modalSize}
|
|
583
|
-
>
|
|
584
|
-
<ModalHeader>
|
|
585
|
-
<ModalTitle>Delete the user?</ModalTitle>
|
|
586
|
-
<ModalCloseButton onClick={() => setModalOpen(false)} />
|
|
587
|
-
</ModalHeader>
|
|
588
|
-
<ModalBody>
|
|
589
|
-
<ModalContent>
|
|
590
|
-
<p>
|
|
591
|
-
Do you really want to delete the user <code>admin</code>?
|
|
592
|
-
This cannot be undone.
|
|
593
|
-
</p>
|
|
594
|
-
</ModalContent>
|
|
595
|
-
</ModalBody>
|
|
596
|
-
<ModalFooter>
|
|
597
|
-
<Button
|
|
598
|
-
color="danger"
|
|
599
|
-
label="Delete"
|
|
600
|
-
onClick={() => setModalOpen(false)}
|
|
601
|
-
ref={modalPrimaryButtonRef}
|
|
602
|
-
/>
|
|
603
|
-
<Button
|
|
604
|
-
color="secondary"
|
|
605
|
-
label="Close"
|
|
606
|
-
onClick={() => setModalOpen(false)}
|
|
607
|
-
priority="outline"
|
|
608
|
-
ref={modalCloseButtonRef}
|
|
609
|
-
/>
|
|
610
|
-
</ModalFooter>
|
|
611
|
-
</Modal>
|
|
612
|
-
)}
|
|
613
|
-
</div>
|
|
614
|
-
</>
|
|
615
|
-
);
|
|
616
|
-
}}
|
|
617
|
-
</Playground>
|
|
618
|
-
|
|
619
|
-
On top of that, the modal can adjust to the width of its content.
|
|
620
|
-
|
|
621
|
-
<Playground>
|
|
622
|
-
{() => {
|
|
623
|
-
const [modalOpen, setModalOpen] = React.useState(false);
|
|
624
|
-
const modalPrimaryButtonRef = React.useRef();
|
|
625
|
-
const modalCloseButtonRef = React.useRef();
|
|
626
|
-
return (
|
|
627
|
-
<>
|
|
628
|
-
<Button
|
|
629
|
-
label="Launch auto-width modal"
|
|
630
|
-
onClick={() => setModalOpen(true)}
|
|
631
|
-
/>
|
|
632
|
-
<div>
|
|
633
|
-
{modalOpen && (
|
|
634
|
-
<Modal
|
|
635
|
-
closeButtonRef={modalCloseButtonRef}
|
|
636
|
-
primaryButtonRef={modalPrimaryButtonRef}
|
|
637
|
-
size="auto"
|
|
638
|
-
>
|
|
639
|
-
<ModalHeader>
|
|
640
|
-
<ModalTitle>Delete the user?</ModalTitle>
|
|
641
|
-
<ModalCloseButton onClick={() => setModalOpen(false)} />
|
|
642
|
-
</ModalHeader>
|
|
643
|
-
<ModalBody>
|
|
644
|
-
<ModalContent>
|
|
645
|
-
<p>
|
|
646
|
-
Do you really want to delete the user <code>admin</code>?
|
|
647
|
-
This cannot be undone.
|
|
648
|
-
</p>
|
|
649
|
-
</ModalContent>
|
|
650
|
-
</ModalBody>
|
|
651
|
-
<ModalFooter>
|
|
652
|
-
<Button
|
|
653
|
-
color="danger"
|
|
654
|
-
label="Delete"
|
|
655
|
-
onClick={() => setModalOpen(false)}
|
|
656
|
-
ref={modalPrimaryButtonRef}
|
|
657
|
-
/>
|
|
658
|
-
<Button
|
|
659
|
-
color="secondary"
|
|
660
|
-
label="Close"
|
|
661
|
-
onClick={() => setModalOpen(false)}
|
|
662
|
-
priority="outline"
|
|
663
|
-
ref={modalCloseButtonRef}
|
|
664
|
-
/>
|
|
665
|
-
</ModalFooter>
|
|
666
|
-
</Modal>
|
|
667
|
-
)}
|
|
668
|
-
</div>
|
|
669
|
-
</>
|
|
670
|
-
);
|
|
671
|
-
}}
|
|
672
|
-
</Playground>
|
|
673
|
-
|
|
674
|
-
## Position
|
|
675
|
-
|
|
676
|
-
Modal can be aligned either to the top or center of the screen.
|
|
677
|
-
|
|
678
|
-
<Playground>
|
|
679
|
-
{() => {
|
|
680
|
-
const [modalOpen, setModalOpen] = React.useState(false);
|
|
681
|
-
const [modalPosition, setModalPosition] = React.useState('center');
|
|
682
|
-
const modalPrimaryButtonRef = React.useRef();
|
|
683
|
-
const modalCloseButtonRef = React.useRef();
|
|
684
|
-
return (
|
|
685
|
-
<>
|
|
686
|
-
<Button
|
|
687
|
-
label="Launch modal at center"
|
|
688
|
-
onClick={() => {
|
|
689
|
-
setModalPosition('center');
|
|
690
|
-
setModalOpen(true);
|
|
691
|
-
}}
|
|
692
|
-
/>
|
|
693
|
-
<Button
|
|
694
|
-
label="Launch modal at top"
|
|
695
|
-
onClick={() => {
|
|
696
|
-
setModalPosition('top');
|
|
697
|
-
setModalOpen(true);
|
|
698
|
-
}}
|
|
699
|
-
/>
|
|
700
|
-
<div>
|
|
701
|
-
{modalOpen && (
|
|
702
|
-
<Modal
|
|
703
|
-
closeButtonRef={modalCloseButtonRef}
|
|
704
|
-
position={modalPosition}
|
|
705
|
-
primaryButtonRef={modalPrimaryButtonRef}
|
|
706
|
-
>
|
|
707
|
-
<ModalHeader>
|
|
708
|
-
<ModalTitle>Delete the user?</ModalTitle>
|
|
709
|
-
<ModalCloseButton onClick={() => setModalOpen(false)} />
|
|
710
|
-
</ModalHeader>
|
|
711
|
-
<ModalBody>
|
|
712
|
-
<ModalContent>
|
|
713
|
-
<p>
|
|
714
|
-
Do you really want to delete the user <code>admin</code>?
|
|
715
|
-
This cannot be undone.
|
|
716
|
-
</p>
|
|
717
|
-
</ModalContent>
|
|
718
|
-
</ModalBody>
|
|
719
|
-
<ModalFooter>
|
|
720
|
-
<Button
|
|
721
|
-
color="danger"
|
|
722
|
-
label="Delete"
|
|
723
|
-
onClick={() => setModalOpen(false)}
|
|
724
|
-
ref={modalPrimaryButtonRef}
|
|
725
|
-
/>
|
|
726
|
-
<Button
|
|
727
|
-
color="secondary"
|
|
728
|
-
label="Close"
|
|
729
|
-
onClick={() => setModalOpen(false)}
|
|
730
|
-
priority="outline"
|
|
731
|
-
ref={modalCloseButtonRef}
|
|
732
|
-
/>
|
|
733
|
-
</ModalFooter>
|
|
734
|
-
</Modal>
|
|
735
|
-
)}
|
|
736
|
-
</div>
|
|
737
|
-
</>
|
|
738
|
-
);
|
|
739
|
-
}}
|
|
740
|
-
</Playground>
|
|
741
|
-
|
|
742
|
-
## Forms in Modals
|
|
743
|
-
|
|
744
|
-
You can safely place a FormLayout into a Modal of any size, including the
|
|
745
|
-
auto-width Modal.
|
|
746
|
-
|
|
747
|
-
<Playground>
|
|
748
|
-
{() => {
|
|
749
|
-
const [modalOpen, setModalOpen] = React.useState(false);
|
|
750
|
-
const [agree, setAgree] = React.useState(true);
|
|
751
|
-
const modalPrimaryButtonRef = React.useRef();
|
|
752
|
-
const modalCloseButtonRef = React.useRef();
|
|
753
|
-
return (
|
|
754
|
-
<>
|
|
755
|
-
<Button
|
|
756
|
-
label="Launch auto-width modal with auto-width form"
|
|
757
|
-
onClick={() => setModalOpen(true)}
|
|
758
|
-
/>
|
|
759
|
-
<div>
|
|
760
|
-
{modalOpen && (
|
|
761
|
-
<Modal
|
|
762
|
-
closeButtonRef={modalCloseButtonRef}
|
|
763
|
-
primaryButtonRef={modalPrimaryButtonRef}
|
|
764
|
-
size="auto"
|
|
765
|
-
>
|
|
766
|
-
<ModalHeader>
|
|
767
|
-
<ModalTitle>Auto-width form inside auto-width modal</ModalTitle>
|
|
768
|
-
<ModalCloseButton onClick={() => setModalOpen(false)} />
|
|
769
|
-
</ModalHeader>
|
|
770
|
-
<ModalBody>
|
|
771
|
-
<ModalContent>
|
|
772
|
-
<FormLayout autoWidth fieldLayout="horizontal">
|
|
773
|
-
<TextField
|
|
774
|
-
label="A form element"
|
|
775
|
-
validationState="warning"
|
|
776
|
-
validationText={`Account with this name already exists,
|
|
777
|
-
pick a different one.`
|
|
778
|
-
}
|
|
779
|
-
/>
|
|
780
|
-
<TextField label="Another form element" />
|
|
781
|
-
<TextField label="Yet another one" />
|
|
782
|
-
<CheckboxField
|
|
783
|
-
checked={agree}
|
|
784
|
-
label="I agree"
|
|
785
|
-
onChange={() => setAgree(!agree)}
|
|
786
|
-
/>
|
|
787
|
-
</FormLayout>
|
|
788
|
-
</ModalContent>
|
|
789
|
-
</ModalBody>
|
|
790
|
-
<ModalFooter>
|
|
791
|
-
<Button
|
|
792
|
-
color="primary"
|
|
793
|
-
label="Save"
|
|
794
|
-
onClick={() => setModalOpen(false)}
|
|
795
|
-
ref={modalPrimaryButtonRef}
|
|
796
|
-
/>
|
|
797
|
-
<Button
|
|
798
|
-
color="secondary"
|
|
799
|
-
label="Cancel"
|
|
800
|
-
onClick={() => setModalOpen(false)}
|
|
801
|
-
priority="outline"
|
|
802
|
-
ref={modalCloseButtonRef}
|
|
803
|
-
/>
|
|
804
|
-
</ModalFooter>
|
|
805
|
-
</Modal>
|
|
806
|
-
)}
|
|
807
|
-
</div>
|
|
808
|
-
</>
|
|
809
|
-
);
|
|
810
|
-
}}
|
|
811
|
-
</Playground>
|
|
812
|
-
|
|
813
|
-
👉 Inside Modal, we recommend using the `autoWidth` option of FormLayout. This
|
|
814
|
-
prevents the Modal from unwanted horizontal expansion when a long validation
|
|
815
|
-
text pops up during user's interaction with the form.
|
|
816
|
-
|
|
817
|
-
👉 Beware of horizontal FormLayout inside `small` modals. While automatic
|
|
818
|
-
overflow handling comes to the rescue in this kind of scenario, you will be
|
|
819
|
-
better off with the combination of auto-sized modal and horizontal FormLayout.
|
|
820
|
-
|
|
821
|
-
## Keyboard Control
|
|
822
|
-
|
|
823
|
-
Modal can be controlled either by mouse or keyboard. To enhance user
|
|
824
|
-
experience, primary action can be fired by pressing `Enter` key and the modal
|
|
825
|
-
can be closed by pressing the `Escape` key.
|
|
826
|
-
|
|
827
|
-
To enable it, you just need to pass a reference to the buttons using
|
|
828
|
-
`primaryButtonRef` and `closeButtonRef` props on Modal. The advantage of passing
|
|
829
|
-
the reference to the button is that if the button is disabled, the key press
|
|
830
|
-
will not fire the event.
|
|
831
|
-
|
|
832
|
-
## Autofocus
|
|
833
|
-
|
|
834
|
-
Autofocus is implemented to enhance the user experience by automatically
|
|
835
|
-
focusing an element within the Modal.
|
|
836
|
-
|
|
837
|
-
How does it work? It tries to find `input`, `textarea`, and `select` elements
|
|
838
|
-
inside of Modal and moves focus onto the first non-disabled one. If none is
|
|
839
|
-
found and the `primaryButtonRef` prop on Modal is set, then the primary button
|
|
840
|
-
is focused. If there are neither, it tries to focus any other focusable elements.
|
|
841
|
-
In case there are none or `autoFocus` is disabled, Modal itself is focused.
|
|
842
|
-
|
|
843
|
-
<Playground>
|
|
844
|
-
{() => {
|
|
845
|
-
const [modalOpen, setModalOpen] = React.useState(null);
|
|
846
|
-
const modalPrimaryButtonRef = React.useRef();
|
|
847
|
-
const modalCloseButtonRef = React.useRef();
|
|
848
|
-
return (
|
|
849
|
-
<>
|
|
850
|
-
<Button
|
|
851
|
-
label="Launch modal with autofocus and form"
|
|
852
|
-
onClick={() => setModalOpen(1)}
|
|
853
|
-
/>
|
|
854
|
-
<Button
|
|
855
|
-
label="Launch modal with autofocus"
|
|
856
|
-
onClick={() => setModalOpen(2)}
|
|
857
|
-
/>
|
|
858
|
-
<Button
|
|
859
|
-
label="Launch modal with autofocus disabled"
|
|
860
|
-
onClick={() => setModalOpen(3)}
|
|
861
|
-
/>
|
|
862
|
-
<div>
|
|
863
|
-
{modalOpen === 1 && (
|
|
864
|
-
<Modal
|
|
865
|
-
closeButtonRef={modalCloseButtonRef}
|
|
866
|
-
primaryButtonRef={modalPrimaryButtonRef}
|
|
867
|
-
>
|
|
868
|
-
<ModalHeader>
|
|
869
|
-
<ModalTitle>Modal with autoFocus and form</ModalTitle>
|
|
870
|
-
<ModalCloseButton onClick={() => setModalOpen(null)} />
|
|
871
|
-
</ModalHeader>
|
|
872
|
-
<ModalBody>
|
|
873
|
-
<ModalContent>
|
|
874
|
-
<FormLayout autoWidth fieldLayout="horizontal">
|
|
875
|
-
<TextField
|
|
876
|
-
disabled
|
|
877
|
-
label="A form element"
|
|
878
|
-
/>
|
|
879
|
-
<TextField label="Another form element" />
|
|
880
|
-
<TextArea label="Yet another one" />
|
|
881
|
-
</FormLayout>
|
|
882
|
-
</ModalContent>
|
|
883
|
-
</ModalBody>
|
|
884
|
-
<ModalFooter>
|
|
885
|
-
<Button
|
|
886
|
-
label="Submit"
|
|
887
|
-
onClick={() => setModalOpen(null)}
|
|
888
|
-
ref={modalPrimaryButtonRef}
|
|
889
|
-
/>
|
|
890
|
-
<Button
|
|
891
|
-
color="secondary"
|
|
892
|
-
label="Close"
|
|
893
|
-
onClick={() => setModalOpen(null)}
|
|
894
|
-
priority="outline"
|
|
895
|
-
ref={modalCloseButtonRef}
|
|
896
|
-
/>
|
|
897
|
-
</ModalFooter>
|
|
898
|
-
</Modal>
|
|
899
|
-
)}
|
|
900
|
-
{modalOpen === 2 && (
|
|
901
|
-
<Modal
|
|
902
|
-
closeButtonRef={modalCloseButtonRef}
|
|
903
|
-
primaryButtonRef={modalPrimaryButtonRef}
|
|
904
|
-
>
|
|
905
|
-
<ModalHeader>
|
|
906
|
-
<ModalTitle>Modal with autoFocus enabled with no form</ModalTitle>
|
|
907
|
-
<ModalCloseButton onClick={() => setModalOpen(null)} />
|
|
908
|
-
</ModalHeader>
|
|
909
|
-
<ModalBody>
|
|
910
|
-
<ModalContent>
|
|
911
|
-
<p>
|
|
912
|
-
This Modal autofocuses the primary button or any other
|
|
913
|
-
focusable element.
|
|
914
|
-
</p>
|
|
915
|
-
</ModalContent>
|
|
916
|
-
</ModalBody>
|
|
917
|
-
<ModalFooter>
|
|
918
|
-
<Button
|
|
919
|
-
label="Acknowledge"
|
|
920
|
-
onClick={() => setModalOpen(null)}
|
|
921
|
-
ref={modalPrimaryButtonRef}
|
|
922
|
-
/>
|
|
923
|
-
<Button
|
|
924
|
-
color="secondary"
|
|
925
|
-
label="Close"
|
|
926
|
-
onClick={() => setModalOpen(null)}
|
|
927
|
-
priority="outline"
|
|
928
|
-
ref={modalCloseButtonRef}
|
|
929
|
-
/>
|
|
930
|
-
</ModalFooter>
|
|
931
|
-
</Modal>
|
|
932
|
-
)}
|
|
933
|
-
{modalOpen === 3 && (
|
|
934
|
-
<Modal
|
|
935
|
-
autoFocus={false}
|
|
936
|
-
closeButtonRef={modalCloseButtonRef}
|
|
937
|
-
primaryButtonRef={modalPrimaryButtonRef}
|
|
938
|
-
>
|
|
939
|
-
<ModalHeader>
|
|
940
|
-
<ModalTitle>Modal with autoFocus disabled</ModalTitle>
|
|
941
|
-
</ModalHeader>
|
|
942
|
-
<ModalBody>
|
|
943
|
-
<ModalContent>
|
|
944
|
-
<p>
|
|
945
|
-
This Modal focuses the Modal element itself.
|
|
946
|
-
</p>
|
|
947
|
-
</ModalContent>
|
|
948
|
-
</ModalBody>
|
|
949
|
-
<ModalFooter>
|
|
950
|
-
<Button
|
|
951
|
-
label="Acknowledge"
|
|
952
|
-
onClick={() => setModalOpen(null)}
|
|
953
|
-
ref={modalPrimaryButtonRef}
|
|
954
|
-
/>
|
|
955
|
-
<Button
|
|
956
|
-
color="secondary"
|
|
957
|
-
label="Close"
|
|
958
|
-
onClick={() => setModalOpen(null)}
|
|
959
|
-
priority="outline"
|
|
960
|
-
ref={modalCloseButtonRef}
|
|
961
|
-
/>
|
|
962
|
-
</ModalFooter>
|
|
963
|
-
</Modal>
|
|
964
|
-
)}
|
|
965
|
-
</div>
|
|
966
|
-
</>
|
|
967
|
-
);
|
|
968
|
-
}}
|
|
969
|
-
</Playground>
|
|
970
|
-
|
|
971
|
-
## Scrolling Long Content
|
|
972
|
-
|
|
973
|
-
When modals become too long for the user's viewport or device, they scroll
|
|
974
|
-
independent of the page itself. This can be done in three ways using the
|
|
975
|
-
`scrolling` option of the ModalBody component:
|
|
976
|
-
|
|
977
|
-
- `auto` (default) — ModalBody is responsible for scrolling,
|
|
978
|
-
- `custom` — you must provide a custom component to handle scrolling,
|
|
979
|
-
typically an instance of [ScrollView](/components/scroll-view) wrapping
|
|
980
|
-
ModalContent,
|
|
981
|
-
- `none` — entire Modal is responsible for scrolling.
|
|
982
|
-
|
|
983
|
-
<Playground>
|
|
984
|
-
{() => {
|
|
985
|
-
const [modalOpen, setModalOpen] = React.useState(false);
|
|
986
|
-
const [modalScrolling, setModalScrolling] = React.useState('auto');
|
|
987
|
-
const modalCloseButtonRef = React.useRef();
|
|
988
|
-
const modalPrimaryButtonRef = React.useRef();
|
|
989
|
-
const modalContent = (
|
|
990
|
-
<ModalContent>
|
|
991
|
-
<p>
|
|
992
|
-
Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean
|
|
993
|
-
commodo ligula eget dolor. Aenean massa.
|
|
994
|
-
</p>
|
|
995
|
-
<p>
|
|
996
|
-
Cum sociis natoque penatibus et magnis dis parturient montes,
|
|
997
|
-
nascetur ridiculus mus. Donec quam felis, ultricies nec,
|
|
998
|
-
pellentesque eu, pretium quis, sem.
|
|
999
|
-
</p>
|
|
1000
|
-
<p>
|
|
1001
|
-
Nulla consequat massa quis enim. Donec pede justo, fringilla
|
|
1002
|
-
vel, aliquet nec, vulputate eget, arcu. In enim justo, rhoncus
|
|
1003
|
-
ut, imperdiet a, venenatis vitae, justo.
|
|
1004
|
-
</p>
|
|
1005
|
-
<p>
|
|
1006
|
-
Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean
|
|
1007
|
-
commodo ligula eget dolor. Aenean massa.
|
|
1008
|
-
</p>
|
|
1009
|
-
<p>
|
|
1010
|
-
Cum sociis natoque penatibus et magnis dis parturient montes,
|
|
1011
|
-
nascetur ridiculus mus. Donec quam felis, ultricies nec,
|
|
1012
|
-
pellentesque eu, pretium quis, sem.
|
|
1013
|
-
</p>
|
|
1014
|
-
<p>
|
|
1015
|
-
Nulla consequat massa quis enim. Donec pede justo, fringilla
|
|
1016
|
-
vel, aliquet nec, vulputate eget, arcu. In enim justo, rhoncus
|
|
1017
|
-
ut, imperdiet a, venenatis vitae, justo.
|
|
1018
|
-
</p>
|
|
1019
|
-
<p>
|
|
1020
|
-
Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean
|
|
1021
|
-
commodo ligula eget dolor. Aenean massa.
|
|
1022
|
-
</p>
|
|
1023
|
-
<p>
|
|
1024
|
-
Cum sociis natoque penatibus et magnis dis parturient montes,
|
|
1025
|
-
nascetur ridiculus mus. Donec quam felis, ultricies nec,
|
|
1026
|
-
pellentesque eu, pretium quis, sem.
|
|
1027
|
-
</p>
|
|
1028
|
-
<p>
|
|
1029
|
-
Nulla consequat massa quis enim. Donec pede justo, fringilla
|
|
1030
|
-
vel, aliquet nec, vulputate eget, arcu. In enim justo, rhoncus
|
|
1031
|
-
ut, imperdiet a, venenatis vitae, justo.
|
|
1032
|
-
</p>
|
|
1033
|
-
<p>
|
|
1034
|
-
Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean
|
|
1035
|
-
commodo ligula eget dolor. Aenean massa.
|
|
1036
|
-
</p>
|
|
1037
|
-
<p>
|
|
1038
|
-
Cum sociis natoque penatibus et magnis dis parturient montes,
|
|
1039
|
-
nascetur ridiculus mus. Donec quam felis, ultricies nec,
|
|
1040
|
-
pellentesque eu, pretium quis, sem.
|
|
1041
|
-
</p>
|
|
1042
|
-
<p>
|
|
1043
|
-
Nulla consequat massa quis enim. Donec pede justo, fringilla
|
|
1044
|
-
vel, aliquet nec, vulputate eget, arcu. In enim justo, rhoncus
|
|
1045
|
-
ut, imperdiet a, venenatis vitae, justo.
|
|
1046
|
-
</p>
|
|
1047
|
-
<p>
|
|
1048
|
-
Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean
|
|
1049
|
-
commodo ligula eget dolor. Aenean massa.
|
|
1050
|
-
</p>
|
|
1051
|
-
<p>
|
|
1052
|
-
Cum sociis natoque penatibus et magnis dis parturient montes,
|
|
1053
|
-
nascetur ridiculus mus. Donec quam felis, ultricies nec,
|
|
1054
|
-
pellentesque eu, pretium quis, sem.
|
|
1055
|
-
</p>
|
|
1056
|
-
<p>
|
|
1057
|
-
Nulla consequat massa quis enim. Donec pede justo, fringilla
|
|
1058
|
-
vel, aliquet nec, vulputate eget, arcu. In enim justo, rhoncus
|
|
1059
|
-
ut, imperdiet a, venenatis vitae, justo.
|
|
1060
|
-
</p>
|
|
1061
|
-
</ModalContent>
|
|
1062
|
-
)
|
|
1063
|
-
return (
|
|
1064
|
-
<>
|
|
1065
|
-
<Button
|
|
1066
|
-
label="Launch modal with scrolling body"
|
|
1067
|
-
onClick={() => {
|
|
1068
|
-
setModalScrolling('auto');
|
|
1069
|
-
setModalOpen(true);
|
|
1070
|
-
}}
|
|
1071
|
-
/>
|
|
1072
|
-
<Button
|
|
1073
|
-
label="Launch modal with ScrollView"
|
|
1074
|
-
onClick={() => {
|
|
1075
|
-
setModalScrolling('custom');
|
|
1076
|
-
setModalOpen(true);
|
|
1077
|
-
}}
|
|
1078
|
-
/>
|
|
1079
|
-
<Button
|
|
1080
|
-
label="Launch modal with non-scrolling body"
|
|
1081
|
-
onClick={() => {
|
|
1082
|
-
setModalScrolling('none');
|
|
1083
|
-
setModalOpen(true);
|
|
1084
|
-
}}
|
|
1085
|
-
/>
|
|
1086
|
-
<div>
|
|
1087
|
-
{modalOpen && (
|
|
1088
|
-
<Modal
|
|
1089
|
-
autoFocus={modalScrolling !== 'none'}
|
|
1090
|
-
closeButtonRef={modalCloseButtonRef}
|
|
1091
|
-
primaryButtonRef={modalPrimaryButtonRef}
|
|
1092
|
-
size="small"
|
|
1093
|
-
>
|
|
1094
|
-
<ModalHeader>
|
|
1095
|
-
<ModalTitle>Modal with long content</ModalTitle>
|
|
1096
|
-
<ModalCloseButton onClick={() => setModalOpen(false)} />
|
|
1097
|
-
</ModalHeader>
|
|
1098
|
-
<ModalBody scrolling={modalScrolling}>
|
|
1099
|
-
{
|
|
1100
|
-
modalScrolling === 'custom'
|
|
1101
|
-
? (
|
|
1102
|
-
<ScrollView>
|
|
1103
|
-
{modalContent}
|
|
1104
|
-
</ScrollView>
|
|
1105
|
-
)
|
|
1106
|
-
: modalContent
|
|
1107
|
-
}
|
|
1108
|
-
</ModalBody>
|
|
1109
|
-
<ModalFooter>
|
|
1110
|
-
<Button
|
|
1111
|
-
label="OK"
|
|
1112
|
-
onClick={() => setModalOpen(false)}
|
|
1113
|
-
ref={modalPrimaryButtonRef}
|
|
1114
|
-
/>
|
|
1115
|
-
<Button
|
|
1116
|
-
color="secondary"
|
|
1117
|
-
label="Close"
|
|
1118
|
-
onClick={() => setModalOpen(false)}
|
|
1119
|
-
priority="outline"
|
|
1120
|
-
ref={modalCloseButtonRef}
|
|
1121
|
-
/>
|
|
1122
|
-
</ModalFooter>
|
|
1123
|
-
</Modal>
|
|
1124
|
-
)}
|
|
1125
|
-
</div>
|
|
1126
|
-
</>
|
|
1127
|
-
);
|
|
1128
|
-
}}
|
|
1129
|
-
</Playground>
|
|
1130
|
-
|
|
1131
|
-
### Long Content and Autofocus
|
|
1132
|
-
|
|
1133
|
-
👉 If you have a Modal with `scrolling` set to `none`, you may want to disable
|
|
1134
|
-
`autoFocus` to prevent the modal from scrolling to the end immediately after
|
|
1135
|
-
being opened.
|
|
1136
|
-
|
|
1137
|
-
## Prevent Scrolling Underneath the Modal
|
|
1138
|
-
|
|
1139
|
-
You can choose the mode in which Modal prevents the scroll of the page underneath.
|
|
1140
|
-
Default mode prevents scrolling on `<body>` element and accounts for the scrollbar
|
|
1141
|
-
width. If you choose `off`, there will be no scroll prevention. If you need more
|
|
1142
|
-
flexibility, define your methods `start` (called on Modal's mount) and `reset`
|
|
1143
|
-
(called on Modal unmount) wrapped by an object and handle scroll prevention
|
|
1144
|
-
yourself.
|
|
1145
|
-
|
|
1146
|
-
<Playground>
|
|
1147
|
-
{() => {
|
|
1148
|
-
const [modalOpen, setModalOpen] = React.useState(null);
|
|
1149
|
-
const modalPrimaryButtonRef = React.useRef();
|
|
1150
|
-
const modalCloseButtonRef = React.useRef();
|
|
1151
|
-
const customScrollPreventionObject = {
|
|
1152
|
-
start: () => {
|
|
1153
|
-
// YOUR CUSTOM SCROLL PREVENTING LOGIC GOES HERE
|
|
1154
|
-
window.document.body.style.overflowY = 'hidden'
|
|
1155
|
-
},
|
|
1156
|
-
reset: () => {
|
|
1157
|
-
// YOUR CUSTOM SCROLL RE-ENABLING LOGIC GOES HERE
|
|
1158
|
-
window.document.body.style.overflowY = 'auto'
|
|
1159
|
-
},
|
|
1160
|
-
};
|
|
1161
|
-
return (
|
|
1162
|
-
<>
|
|
1163
|
-
<Button
|
|
1164
|
-
label="Launch modal with default scroll prevention"
|
|
1165
|
-
onClick={() => setModalOpen(1)}
|
|
1166
|
-
/>
|
|
1167
|
-
<Button
|
|
1168
|
-
label="Launch modal with no scroll prevention"
|
|
1169
|
-
onClick={() => setModalOpen(2)}
|
|
1170
|
-
/>
|
|
1171
|
-
<Button
|
|
1172
|
-
label="Launch modal with custom scroll prevention"
|
|
1173
|
-
onClick={() => setModalOpen(3)}
|
|
1174
|
-
/>
|
|
1175
|
-
<div>
|
|
1176
|
-
{modalOpen === 1 && (
|
|
1177
|
-
<Modal
|
|
1178
|
-
closeButtonRef={modalCloseButtonRef}
|
|
1179
|
-
primaryButtonRef={modalPrimaryButtonRef}
|
|
1180
|
-
>
|
|
1181
|
-
<ModalHeader>
|
|
1182
|
-
<ModalTitle>Modal with default scroll prevention</ModalTitle>
|
|
1183
|
-
<ModalCloseButton onClick={() => setModalOpen(null)} />
|
|
1184
|
-
</ModalHeader>
|
|
1185
|
-
<ModalBody>
|
|
1186
|
-
<ModalContent>
|
|
1187
|
-
<p>
|
|
1188
|
-
This Modal uses default scroll prevention on the document's
|
|
1189
|
-
<code>body</code> element.
|
|
1190
|
-
</p>
|
|
1191
|
-
</ModalContent>
|
|
1192
|
-
</ModalBody>
|
|
1193
|
-
<ModalFooter>
|
|
1194
|
-
<Button
|
|
1195
|
-
label="Acknowledge"
|
|
1196
|
-
onClick={() => setModalOpen(null)}
|
|
1197
|
-
ref={modalPrimaryButtonRef}
|
|
1198
|
-
/>
|
|
1199
|
-
<Button
|
|
1200
|
-
color="secondary"
|
|
1201
|
-
label="Close"
|
|
1202
|
-
onClick={() => setModalOpen(null)}
|
|
1203
|
-
priority="outline"
|
|
1204
|
-
ref={modalCloseButtonRef}
|
|
1205
|
-
/>
|
|
1206
|
-
</ModalFooter>
|
|
1207
|
-
</Modal>
|
|
1208
|
-
)}
|
|
1209
|
-
{modalOpen === 2 && (
|
|
1210
|
-
<Modal
|
|
1211
|
-
closeButtonRef={modalCloseButtonRef}
|
|
1212
|
-
preventScrollUnderneath="off"
|
|
1213
|
-
primaryButtonRef={modalPrimaryButtonRef}
|
|
1214
|
-
>
|
|
1215
|
-
<ModalHeader>
|
|
1216
|
-
<ModalTitle>Modal with no scroll prevention</ModalTitle>
|
|
1217
|
-
<ModalCloseButton onClick={() => setModalOpen(null)} />
|
|
1218
|
-
</ModalHeader>
|
|
1219
|
-
<ModalBody>
|
|
1220
|
-
<ModalContent>
|
|
1221
|
-
<p>
|
|
1222
|
-
This Modal does not prevent scrolling.
|
|
1223
|
-
</p>
|
|
1224
|
-
</ModalContent>
|
|
1225
|
-
</ModalBody>
|
|
1226
|
-
<ModalFooter>
|
|
1227
|
-
<Button
|
|
1228
|
-
label="Acknowledge"
|
|
1229
|
-
onClick={() => setModalOpen(null)}
|
|
1230
|
-
ref={modalPrimaryButtonRef}
|
|
1231
|
-
/>
|
|
1232
|
-
<Button
|
|
1233
|
-
color="secondary"
|
|
1234
|
-
label="Close"
|
|
1235
|
-
onClick={() => setModalOpen(null)}
|
|
1236
|
-
priority="outline"
|
|
1237
|
-
ref={modalCloseButtonRef}
|
|
1238
|
-
/>
|
|
1239
|
-
</ModalFooter>
|
|
1240
|
-
</Modal>
|
|
1241
|
-
)}
|
|
1242
|
-
{modalOpen === 3 && (
|
|
1243
|
-
<Modal
|
|
1244
|
-
closeButtonRef={modalCloseButtonRef}
|
|
1245
|
-
preventScrollUnderneath={customScrollPreventionObject}
|
|
1246
|
-
primaryButtonRef={modalPrimaryButtonRef}
|
|
1247
|
-
>
|
|
1248
|
-
<ModalHeader>
|
|
1249
|
-
<ModalTitle>Modal with custom scroll prevention</ModalTitle>
|
|
1250
|
-
<ModalCloseButton onClick={() => setModalOpen(null)} />
|
|
1251
|
-
</ModalHeader>
|
|
1252
|
-
<ModalBody>
|
|
1253
|
-
<ModalContent>
|
|
1254
|
-
<p>
|
|
1255
|
-
This Modal uses provided custom functions to prevent scrolling
|
|
1256
|
-
and reset it on unmount.
|
|
1257
|
-
</p>
|
|
1258
|
-
</ModalContent>
|
|
1259
|
-
</ModalBody>
|
|
1260
|
-
<ModalFooter>
|
|
1261
|
-
<Button
|
|
1262
|
-
label="Acknowledge"
|
|
1263
|
-
onClick={() => setModalOpen(null)}
|
|
1264
|
-
ref={modalPrimaryButtonRef}
|
|
1265
|
-
/>
|
|
1266
|
-
<Button
|
|
1267
|
-
color="secondary"
|
|
1268
|
-
label="Close"
|
|
1269
|
-
onClick={() => setModalOpen(null)}
|
|
1270
|
-
priority="outline"
|
|
1271
|
-
ref={modalCloseButtonRef}
|
|
1272
|
-
/>
|
|
1273
|
-
</ModalFooter>
|
|
1274
|
-
</Modal>
|
|
1275
|
-
)}
|
|
1276
|
-
</div>
|
|
1277
|
-
</>
|
|
1278
|
-
);
|
|
1279
|
-
}}
|
|
1280
|
-
</Playground>
|
|
1281
|
-
|
|
1282
|
-
<!-- markdownlint-disable MD024 -->
|
|
1283
|
-
|
|
1284
|
-
## Forwarding HTML Attributes
|
|
1285
|
-
|
|
1286
|
-
In addition to the options below in the [component's API](#api) section, you
|
|
1287
|
-
can specify [React synthetic events] or **any HTML attribute you like.** All
|
|
1288
|
-
attributes that don't interfere with the API are forwarded to the:
|
|
1289
|
-
|
|
1290
|
-
- `<div>` HTML element in case of the `Modal` component. This `<div>` is not the
|
|
1291
|
-
root, but its first child which represents the modal window.
|
|
1292
|
-
- root `<div>` HTML element in case of `ModalHeader`, `ModalBody`, `ModalContent`
|
|
1293
|
-
and `ModalFooter` components.
|
|
1294
|
-
- heading HTML element, which level can be specified through `level` option, in
|
|
1295
|
-
case of the `ModalTitle` component.
|
|
1296
|
-
- native HTML `<button>` in case of the `ModalCloseButton` component.
|
|
1297
|
-
|
|
1298
|
-
This enables making the component interactive and helps to improve its
|
|
1299
|
-
accessibility.
|
|
1300
|
-
|
|
1301
|
-
👉 Refer to the MDN reference for the full list of supported attributes of the
|
|
1302
|
-
[div], [heading] and [button] element.
|
|
1303
|
-
|
|
1304
|
-
## API
|
|
1305
|
-
|
|
1306
|
-
<Props table of={Modal} />
|
|
1307
|
-
|
|
1308
|
-
### ModalHeader
|
|
1309
|
-
|
|
1310
|
-
<Props table of={ModalHeader} />
|
|
1311
|
-
|
|
1312
|
-
### ModalTitle
|
|
1313
|
-
|
|
1314
|
-
<Props table of={ModalTitle} />
|
|
1315
|
-
|
|
1316
|
-
### ModalCloseButton
|
|
1317
|
-
|
|
1318
|
-
<Props table of={ModalCloseButton} />
|
|
1319
|
-
|
|
1320
|
-
### ModalBody
|
|
1321
|
-
|
|
1322
|
-
<Props table of={ModalBody} />
|
|
1323
|
-
|
|
1324
|
-
### ModalContent
|
|
1325
|
-
|
|
1326
|
-
<Props table of={ModalContent} />
|
|
1327
|
-
|
|
1328
|
-
### ModalFooter
|
|
1329
|
-
|
|
1330
|
-
<Props table of={ModalFooter} />
|
|
1331
|
-
|
|
1332
|
-
## Theming
|
|
1333
|
-
|
|
1334
|
-
| Custom Property | Description |
|
|
1335
|
-
|------------------------------------------------------|---------------------------------------------------------------|
|
|
1336
|
-
| `--rui-Modal__padding-x` | Inline padding of individual modal components |
|
|
1337
|
-
| `--rui-Modal__padding-y` | Block padding of individual modal components |
|
|
1338
|
-
| `--rui-Modal__background` | Modal background (including `url()` or gradient) |
|
|
1339
|
-
| `--rui-Modal__box-shadow` | Modal box shadow |
|
|
1340
|
-
| `--rui-Modal__separator__width` | Width of separator between modal header, body, and footer |
|
|
1341
|
-
| `--rui-Modal__separator__color` | Color of separator between modal header, body, and footer |
|
|
1342
|
-
| `--rui-Modal__outer-spacing-xs` | Spacing around modal, `xs` screen size |
|
|
1343
|
-
| `--rui-Modal__outer-spacing-sm` | Spacing around modal, `sm` screen size and bigger |
|
|
1344
|
-
| `--rui-Modal__header__gap` | Modal header gap between children |
|
|
1345
|
-
| `--rui-Modal__footer__background` | Modal footer background (including `url()` or gradient) |
|
|
1346
|
-
| `--rui-Modal__footer__gap` | Modal footer gap between children |
|
|
1347
|
-
| `--rui-Modal__backdrop__background` | Modal backdrop background (including `url()` or gradient) |
|
|
1348
|
-
| `--rui-Modal--auto__min-width` | Min width of auto-sized modal (when enough screen estate) |
|
|
1349
|
-
| `--rui-Modal--auto__max-width` | Max width of auto-sized modal (when enough screen estate) |
|
|
1350
|
-
| `--rui-Modal--small__width` | Width of small modal |
|
|
1351
|
-
| `--rui-Modal--medium__width` | Width of medium modal |
|
|
1352
|
-
| `--rui-Modal--large__width` | Width of large modal |
|
|
1353
|
-
| `--rui-Modal--fullscreen__width` | Width of fullscreen modal |
|
|
1354
|
-
| `--rui-Modal--fullscreen__height` | Height of fullscreen modal |
|
|
1355
|
-
|
|
1356
|
-
[nng-modal]: https://www.nngroup.com/articles/modal-nonmodal-dialog/
|
|
1357
|
-
[React synthetic events]: https://reactjs.org/docs/events.html
|
|
1358
|
-
[div]: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/div#attributes
|
|
1359
|
-
[heading]: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/Heading_Elements#attributes
|
|
1360
|
-
[button]: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/button#attributes
|