@react-ui-org/react-ui 0.58.0 → 0.59.1
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 +2 -11
- package/dist/react-ui.css +17 -17
- package/dist/react-ui.development.css +1230 -1053
- package/dist/react-ui.development.js +126 -66
- package/dist/react-ui.js +1 -1
- package/package.json +5 -5
- package/src/components/Alert/Alert.jsx +4 -4
- package/src/components/Alert/README.md +1 -27
- package/src/components/Alert/_settings.scss +1 -2
- package/src/components/Badge/Badge.jsx +2 -2
- package/src/components/Button/Button.jsx +2 -2
- package/src/components/ButtonGroup/ButtonGroup.jsx +2 -2
- package/src/components/Card/Card.jsx +6 -6
- package/src/components/Card/Card.module.scss +2 -2
- package/src/components/Card/CardBody.jsx +1 -1
- package/src/components/Card/CardFooter.jsx +1 -1
- package/src/components/Card/README.md +12 -30
- package/src/components/Card/_settings.scss +1 -2
- package/src/components/Card/_theme.scss +2 -0
- package/src/components/CheckboxField/CheckboxField.jsx +2 -2
- package/src/components/FileInputField/FileInputField.jsx +147 -21
- package/src/components/FileInputField/FileInputField.module.scss +87 -1
- package/src/components/FileInputField/README.md +83 -2
- package/src/components/FileInputField/_settings.scss +15 -0
- package/src/components/FormLayout/FormLayout.jsx +2 -2
- package/src/components/FormLayout/FormLayoutCustomField.jsx +2 -2
- package/src/components/FormLayout/README.md +8 -6
- package/src/components/Grid/Grid.jsx +1 -1
- package/src/components/Grid/Grid.module.scss +2 -2
- package/src/components/Grid/GridSpan.jsx +1 -1
- package/src/components/InputGroup/InputGroup.jsx +2 -2
- package/src/components/InputGroup/InputGroup.module.scss +3 -3
- package/src/components/InputGroup/README.md +1 -1
- package/src/components/Modal/Modal.jsx +117 -45
- package/src/components/Modal/Modal.module.scss +34 -18
- package/src/components/Modal/ModalBody.jsx +2 -2
- package/src/components/Modal/ModalBody.module.scss +18 -0
- package/src/components/Modal/ModalCloseButton.jsx +1 -1
- package/src/components/Modal/ModalContent.jsx +1 -1
- package/src/components/Modal/ModalFooter.jsx +2 -2
- package/src/components/Modal/ModalFooter.module.scss +6 -2
- package/src/components/Modal/ModalHeader.jsx +2 -2
- package/src/components/Modal/ModalHeader.module.scss +8 -1
- package/src/components/Modal/ModalTitle.jsx +1 -1
- package/src/components/Modal/README.md +391 -171
- package/src/components/Modal/_animations.scss +9 -0
- package/src/components/Modal/_helpers/dialogOnCancelHandler.js +28 -0
- package/src/components/Modal/_helpers/dialogOnClickHandler.js +46 -0
- package/src/components/Modal/_helpers/dialogOnCloseHandler.js +28 -0
- package/src/components/Modal/_helpers/dialogOnKeyDownHandler.js +62 -0
- package/src/components/Modal/_helpers/getPositionClassName.js +1 -1
- package/src/components/Modal/_hooks/useModalFocus.js +24 -91
- package/src/components/Modal/_settings.scss +4 -3
- package/src/components/Modal/_theme.scss +1 -0
- package/src/components/Paper/Paper.jsx +2 -2
- package/src/components/Popover/Popover.jsx +2 -2
- package/src/components/Popover/PopoverWrapper.jsx +1 -1
- package/src/components/Radio/Radio.jsx +2 -2
- package/src/components/ScrollView/ScrollView.jsx +2 -2
- package/src/components/SelectField/SelectField.jsx +2 -2
- package/src/components/Table/Table.jsx +1 -1
- package/src/components/Tabs/Tabs.jsx +1 -1
- package/src/components/Tabs/TabsItem.jsx +2 -2
- package/src/components/Text/Text.jsx +2 -2
- package/src/components/TextArea/TextArea.jsx +2 -2
- package/src/components/TextField/TextField.jsx +2 -2
- package/src/components/TextLink/TextLink.jsx +1 -1
- package/src/components/Toggle/Toggle.jsx +2 -2
- package/src/components/Toolbar/Toolbar.jsx +2 -2
- package/src/components/Toolbar/ToolbarGroup.jsx +2 -2
- package/src/components/Toolbar/ToolbarItem.jsx +2 -2
- package/src/helpers/classNames/README.md +65 -0
- package/src/helpers/classNames/classNames.js +11 -0
- package/src/helpers/classNames/index.js +1 -0
- package/src/helpers/transferProps/README.md +46 -0
- package/src/helpers/transferProps/index.js +1 -0
- package/src/index.js +3 -3
- package/src/styles/elements/_links.scss +2 -14
- package/src/styles/generic/_focus.scss +1 -1
- package/src/styles/theme/_form-fields.scss +5 -5
- package/src/styles/tools/_accessibility.scss +3 -5
- package/src/styles/tools/_collections.scss +3 -20
- package/src/styles/tools/_links.scss +17 -0
- package/src/styles/tools/form-fields/_box-field-elements.scss +21 -9
- package/src/styles/tools/form-fields/_box-field-layout.scss +2 -2
- package/src/styles/tools/form-fields/_box-field-sizes.scss +6 -10
- package/src/styles/tools/form-fields/_variants.scss +10 -10
- package/src/theme.scss +53 -3
- package/src/translations/en.js +5 -0
- package/src/styles/settings/_z-indexes.scss +0 -2
- package/src/utils/classNames.js +0 -8
- /package/src/{utils → helpers/transferProps}/transferProps.js +0 -0
@@ -92,11 +92,24 @@ See [API](#api) for all available options.
|
|
92
92
|
- **Modal actions** should correspond to the modal purpose, too. E.g. “Delete”
|
93
93
|
tells better what happens rather than “OK”.
|
94
94
|
|
95
|
-
-
|
96
|
-
|
97
|
-
|
95
|
+
- While native `<dialog>` (that is used under the hood) can be present in DOM,
|
96
|
+
modal is a more feature-rich component that provides more control over the
|
97
|
+
modal behavior and shall be **removed from DOM when closed**.
|
98
|
+
|
99
|
+
- Modal **automatically focuses the first non-disabled form field** by default.
|
100
|
+
When no field is found then the primary button (in the footer) is focused. To turn
|
98
101
|
this feature off, set the `autofocus` prop to `false`.
|
99
102
|
|
103
|
+
- Modal **submits the form when the user presses the `Enter` key** . A click is
|
104
|
+
programmatically triggered on the primary button in this case. To turn this
|
105
|
+
feature off, set the `allowPrimaryActionOnEnterKey` prop to `false`.
|
106
|
+
|
107
|
+
- Modal **closes when the user presses the `Escape` key**. A click is
|
108
|
+
programmatically triggered on the close button in this case. To turn this
|
109
|
+
feature off, set the `allowCloseOnEscapeKey` prop to `false`. Modal can be
|
110
|
+
also **closed by clicking on the backdrop**. To turn this feature off,
|
111
|
+
set the `allowCloseOnBackdropClick` prop to `false`.
|
112
|
+
|
100
113
|
- **Avoid stacking** of modals. While it may technically work, the modal is just
|
101
114
|
not designed for that.
|
102
115
|
|
@@ -114,143 +127,8 @@ Modal is decomposed into the following components:
|
|
114
127
|
- [ModalFooter](#modalfooter)
|
115
128
|
|
116
129
|
Using different combinations, you can compose different kinds of modals,
|
117
|
-
e.g. dialog modal,
|
118
|
-
|
119
|
-
```docoff-react-preview
|
120
|
-
React.createElement(() => {
|
121
|
-
const [modalOpen, setModalOpen] = React.useState(null);
|
122
|
-
const modalPrimaryButtonRef = React.useRef();
|
123
|
-
const modalCloseButtonRef = React.useRef();
|
124
|
-
{/*
|
125
|
-
The `preventScrollUnderneath` feature is necessary for Modals to work in
|
126
|
-
React UI docs. You may not need it in your application.
|
127
|
-
*/}
|
128
|
-
return (
|
129
|
-
<GlobalPropsProvider globalProps={{
|
130
|
-
Modal: { preventScrollUnderneath: window.document.documentElement }
|
131
|
-
}}>
|
132
|
-
<Button
|
133
|
-
label="Launch blocking modal without title"
|
134
|
-
onClick={() => {
|
135
|
-
setModalOpen(1);
|
136
|
-
setTimeout(() => setModalOpen(null), 2500);
|
137
|
-
}}
|
138
|
-
/>
|
139
|
-
<Button
|
140
|
-
label="Launch blocking modal with title"
|
141
|
-
onClick={() => {
|
142
|
-
setModalOpen(2);
|
143
|
-
setTimeout(() => setModalOpen(null), 3500);
|
144
|
-
}}
|
145
|
-
/>
|
146
|
-
<Button
|
147
|
-
label="Launch modal as dialog"
|
148
|
-
onClick={() => setModalOpen(3)}
|
149
|
-
/>
|
150
|
-
<Button
|
151
|
-
label="Launch modal as form"
|
152
|
-
onClick={() => setModalOpen(4)}
|
153
|
-
/>
|
154
|
-
<div>
|
155
|
-
{modalOpen === 1 && (
|
156
|
-
<Modal>
|
157
|
-
<ModalBody>
|
158
|
-
<ModalContent>
|
159
|
-
<p className="text-center">
|
160
|
-
Application is being loaded.
|
161
|
-
<span className="d-inline-flex align-items-center animation-spin-counterclockwise">
|
162
|
-
<rui-icon icon="loading" />
|
163
|
-
</span>
|
164
|
-
</p>
|
165
|
-
</ModalContent>
|
166
|
-
</ModalBody>
|
167
|
-
</Modal>
|
168
|
-
)}
|
169
|
-
{modalOpen === 2 && (
|
170
|
-
<Modal>
|
171
|
-
<ModalHeader>
|
172
|
-
<ModalTitle>Action finished</ModalTitle>
|
173
|
-
</ModalHeader>
|
174
|
-
<ModalBody>
|
175
|
-
<ModalContent>
|
176
|
-
<p>
|
177
|
-
Action has been successfully finished.
|
178
|
-
You will be redirected within a few seconds.
|
179
|
-
</p>
|
180
|
-
</ModalContent>
|
181
|
-
</ModalBody>
|
182
|
-
</Modal>
|
183
|
-
)}
|
184
|
-
{modalOpen === 3 && (
|
185
|
-
<Modal
|
186
|
-
closeButtonRef={modalCloseButtonRef}
|
187
|
-
primaryButtonRef={modalPrimaryButtonRef}
|
188
|
-
>
|
189
|
-
<ModalHeader>
|
190
|
-
<ModalTitle>Delete the user?</ModalTitle>
|
191
|
-
<ModalCloseButton onClick={() => setModalOpen(false)} />
|
192
|
-
</ModalHeader>
|
193
|
-
<ModalBody>
|
194
|
-
<ModalContent>
|
195
|
-
<p>
|
196
|
-
Do you really want to delete the user <code>admin</code>?
|
197
|
-
This cannot be undone.
|
198
|
-
</p>
|
199
|
-
</ModalContent>
|
200
|
-
</ModalBody>
|
201
|
-
<ModalFooter>
|
202
|
-
<Button
|
203
|
-
color="danger"
|
204
|
-
label="Delete"
|
205
|
-
onClick={() => setModalOpen(false)}
|
206
|
-
ref={modalPrimaryButtonRef}
|
207
|
-
/>
|
208
|
-
<Button
|
209
|
-
label="Close"
|
210
|
-
onClick={() => setModalOpen(false)}
|
211
|
-
priority="outline"
|
212
|
-
ref={modalCloseButtonRef}
|
213
|
-
/>
|
214
|
-
</ModalFooter>
|
215
|
-
</Modal>
|
216
|
-
)}
|
217
|
-
{modalOpen === 4 && (
|
218
|
-
<Modal
|
219
|
-
closeButtonRef={modalCloseButtonRef}
|
220
|
-
primaryButtonRef={modalPrimaryButtonRef}
|
221
|
-
>
|
222
|
-
<ModalHeader>
|
223
|
-
<ModalTitle>Add new user</ModalTitle>
|
224
|
-
<ModalCloseButton onClick={() => setModalOpen(false)} />
|
225
|
-
</ModalHeader>
|
226
|
-
<ModalBody>
|
227
|
-
<ModalContent>
|
228
|
-
<FormLayout fieldLayout="horizontal">
|
229
|
-
<TextField label="Username" />
|
230
|
-
<TextField label="Password" type="password" />
|
231
|
-
</FormLayout>
|
232
|
-
</ModalContent>
|
233
|
-
</ModalBody>
|
234
|
-
<ModalFooter>
|
235
|
-
<Button
|
236
|
-
label="Save"
|
237
|
-
onClick={() => setModalOpen(false)}
|
238
|
-
ref={modalPrimaryButtonRef}
|
239
|
-
/>
|
240
|
-
<Button
|
241
|
-
label="Close"
|
242
|
-
onClick={() => setModalOpen(false)}
|
243
|
-
priority="outline"
|
244
|
-
ref={modalCloseButtonRef}
|
245
|
-
/>
|
246
|
-
</ModalFooter>
|
247
|
-
</Modal>
|
248
|
-
)}
|
249
|
-
</div>
|
250
|
-
</GlobalPropsProvider>
|
251
|
-
);
|
252
|
-
});
|
253
|
-
```
|
130
|
+
e.g. dialog modal, [modal with form](#forms), [blocking modal](#interaction-blocking),
|
131
|
+
[scrollable modal](#scrolling-long-content), etc.
|
254
132
|
|
255
133
|
### ModalHeader
|
256
134
|
|
@@ -812,16 +690,106 @@ React.createElement(() => {
|
|
812
690
|
});
|
813
691
|
```
|
814
692
|
|
815
|
-
##
|
693
|
+
## Color Variants
|
694
|
+
|
695
|
+
Modal can be colored using the `color` prop. The `color` prop implements the
|
696
|
+
[Feedback color collection](/docs/foundation/collections#colors)
|
697
|
+
and is applied to the border of the modal and the modal footer.
|
698
|
+
|
699
|
+
```docoff-react-preview
|
700
|
+
React.createElement(() => {
|
701
|
+
const [modalOpen, setModalOpen] = React.useState(false);
|
702
|
+
const [modalColor, setModalColor] = React.useState('success');
|
703
|
+
const modalCloseButtonRef = React.useRef();
|
704
|
+
{/*
|
705
|
+
The `preventScrollUnderneath` feature is necessary for Modals to work in
|
706
|
+
React UI docs. You may not need it in your application.
|
707
|
+
*/}
|
708
|
+
return (
|
709
|
+
<GlobalPropsProvider globalProps={{
|
710
|
+
Modal: { preventScrollUnderneath: window.document.documentElement }
|
711
|
+
}}>
|
712
|
+
<Button
|
713
|
+
label="Launch modal with color options"
|
714
|
+
onClick={() => setModalOpen(true)}
|
715
|
+
/>
|
716
|
+
<div>
|
717
|
+
{modalOpen && (
|
718
|
+
<Modal
|
719
|
+
closeButtonRef={modalCloseButtonRef}
|
720
|
+
color={modalColor}
|
721
|
+
>
|
722
|
+
<ModalHeader>
|
723
|
+
<ModalTitle>Modal color</ModalTitle>
|
724
|
+
<ModalCloseButton onClick={() => setModalOpen(false)} />
|
725
|
+
</ModalHeader>
|
726
|
+
<ModalBody>
|
727
|
+
<ModalContent>
|
728
|
+
<Radio
|
729
|
+
label="Modal color"
|
730
|
+
onChange={(e) => setModalColor(e.target.value)}
|
731
|
+
options={[
|
732
|
+
{
|
733
|
+
label: 'success',
|
734
|
+
value: 'success',
|
735
|
+
},
|
736
|
+
{
|
737
|
+
label: 'warning',
|
738
|
+
value: 'warning',
|
739
|
+
},
|
740
|
+
{
|
741
|
+
label: 'danger',
|
742
|
+
value: 'danger',
|
743
|
+
},
|
744
|
+
{
|
745
|
+
label: 'info',
|
746
|
+
value: 'info',
|
747
|
+
},
|
748
|
+
{
|
749
|
+
label: 'help',
|
750
|
+
value: 'help',
|
751
|
+
},
|
752
|
+
{
|
753
|
+
label: 'note',
|
754
|
+
value: 'note',
|
755
|
+
},
|
756
|
+
]}
|
757
|
+
value={modalColor}
|
758
|
+
/>
|
759
|
+
</ModalContent>
|
760
|
+
</ModalBody>
|
761
|
+
<ModalFooter>
|
762
|
+
<Button
|
763
|
+
color={modalColor}
|
764
|
+
label="Close"
|
765
|
+
onClick={() => setModalOpen(false)}
|
766
|
+
ref={modalCloseButtonRef}
|
767
|
+
/>
|
768
|
+
</ModalFooter>
|
769
|
+
</Modal>
|
770
|
+
)}
|
771
|
+
</div>
|
772
|
+
</GlobalPropsProvider>
|
773
|
+
);
|
774
|
+
});
|
775
|
+
```
|
776
|
+
|
777
|
+
## Mouse and Keyboard Control
|
816
778
|
|
817
779
|
Modal can be controlled either by mouse or keyboard. To enhance user
|
818
|
-
experience, primary action can be fired by pressing `Enter` key and
|
819
|
-
can be closed by pressing the `Escape` key.
|
780
|
+
experience, primary action can be fired by pressing `Enter` key and
|
781
|
+
the modal can be closed by pressing the `Escape` key. Modal can be
|
782
|
+
also closed by clicking on the backdrop.
|
820
783
|
|
821
784
|
To enable it, you just need to pass a reference to the buttons using
|
822
|
-
`primaryButtonRef` and `closeButtonRef` props on Modal. The advantage
|
823
|
-
a reference to the button is that if the button is disabled,
|
824
|
-
not fire the event.
|
785
|
+
`primaryButtonRef` and `closeButtonRef` props on Modal. The advantage
|
786
|
+
of passing a reference to the button is that if the button is disabled,
|
787
|
+
the key press or the mouse click will not fire the event.
|
788
|
+
|
789
|
+
As `primaryButtonRef` and `closeButtonRef` are used for more than just
|
790
|
+
actions mentioned above, you can explicitly disable the default behavior
|
791
|
+
by changing `allowCloseOnBackdropClick`, `allowCloseOnEscapeKey` or
|
792
|
+
`allowPrimaryActionOnEnterKey` to `false`.
|
825
793
|
|
826
794
|
👉 We strongly recommend using this feature together with Autofocus for a better
|
827
795
|
user experience.
|
@@ -839,7 +807,241 @@ is focused.
|
|
839
807
|
Autofocus is enabled by default, so if you want to control the focus of
|
840
808
|
elements manually, set the `autoFocus` prop on Modal to `false`.
|
841
809
|
|
842
|
-
##
|
810
|
+
## Use Cases
|
811
|
+
|
812
|
+
### Interaction blocking
|
813
|
+
|
814
|
+
Modal can be used to block user interaction while an action is being
|
815
|
+
performed.
|
816
|
+
|
817
|
+
```docoff-react-preview
|
818
|
+
React.createElement(() => {
|
819
|
+
const [modalOpen, setModalOpen] = React.useState(null);
|
820
|
+
const modalPrimaryButtonRef = React.useRef();
|
821
|
+
const modalCloseButtonRef = React.useRef();
|
822
|
+
{/*
|
823
|
+
The `preventScrollUnderneath` feature is necessary for Modals to work in
|
824
|
+
React UI docs. You may not need it in your application.
|
825
|
+
*/}
|
826
|
+
return (
|
827
|
+
<GlobalPropsProvider globalProps={{
|
828
|
+
Modal: { preventScrollUnderneath: window.document.documentElement }
|
829
|
+
}}>
|
830
|
+
<Button
|
831
|
+
label="Launch blocking modal without title"
|
832
|
+
onClick={() => {
|
833
|
+
setModalOpen(1);
|
834
|
+
setTimeout(() => setModalOpen(null), 2500);
|
835
|
+
}}
|
836
|
+
/>
|
837
|
+
<Button
|
838
|
+
label="Launch blocking modal with title"
|
839
|
+
onClick={() => {
|
840
|
+
setModalOpen(2);
|
841
|
+
setTimeout(() => setModalOpen(null), 3500);
|
842
|
+
}}
|
843
|
+
/>
|
844
|
+
<div>
|
845
|
+
{modalOpen === 1 && (
|
846
|
+
<Modal>
|
847
|
+
<ModalBody>
|
848
|
+
<ModalContent>
|
849
|
+
<p className="text-center">
|
850
|
+
Application is being loaded.
|
851
|
+
<span className="d-inline-flex align-items-center animation-spin-counterclockwise">
|
852
|
+
<rui-icon icon="loading" />
|
853
|
+
</span>
|
854
|
+
</p>
|
855
|
+
</ModalContent>
|
856
|
+
</ModalBody>
|
857
|
+
</Modal>
|
858
|
+
)}
|
859
|
+
{modalOpen === 2 && (
|
860
|
+
<Modal>
|
861
|
+
<ModalHeader>
|
862
|
+
<ModalTitle>Action finished</ModalTitle>
|
863
|
+
</ModalHeader>
|
864
|
+
<ModalBody>
|
865
|
+
<ModalContent>
|
866
|
+
<p>
|
867
|
+
Action has been successfully finished.
|
868
|
+
You will be redirected within a few seconds.
|
869
|
+
</p>
|
870
|
+
</ModalContent>
|
871
|
+
</ModalBody>
|
872
|
+
</Modal>
|
873
|
+
)}
|
874
|
+
</div>
|
875
|
+
</GlobalPropsProvider>
|
876
|
+
);
|
877
|
+
});
|
878
|
+
```
|
879
|
+
|
880
|
+
### Forms
|
881
|
+
|
882
|
+
Modal can be used to display forms. It is recommended to use
|
883
|
+
[FormLayout](/components/FormLayout) component to layout form fields.
|
884
|
+
|
885
|
+
While we support only [controlled components][controlled-components],
|
886
|
+
and we encourage you to use them, it is possible to use native form and its
|
887
|
+
functionality inside the modal. This might be useful when you need to use
|
888
|
+
native form features like validation, submission, etc.
|
889
|
+
|
890
|
+
To do so, you need to set `allowPrimaryActionOnEnterKey` to `false` and remove
|
891
|
+
`onClick` from the primary button. Then, you need to set `form` attribute on the
|
892
|
+
primary button to the `id` of the form to connect it with the form.
|
893
|
+
|
894
|
+
```docoff-react-preview
|
895
|
+
React.createElement(() => {
|
896
|
+
const [modalOpen, setModalOpen] = React.useState(null);
|
897
|
+
const modalPrimaryButtonRef = React.useRef();
|
898
|
+
const modalCloseButtonRef = React.useRef();
|
899
|
+
{/*
|
900
|
+
The `preventScrollUnderneath` feature is necessary for Modals to work in
|
901
|
+
React UI docs. You may not need it in your application.
|
902
|
+
*/}
|
903
|
+
return (
|
904
|
+
<GlobalPropsProvider globalProps={{
|
905
|
+
Modal: { preventScrollUnderneath: window.document.documentElement }
|
906
|
+
}}>
|
907
|
+
<Button
|
908
|
+
label="Launch modal as form"
|
909
|
+
onClick={() => setModalOpen(1)}
|
910
|
+
/>
|
911
|
+
<Button
|
912
|
+
label="Launch modal as native form"
|
913
|
+
onClick={() => setModalOpen(2)}
|
914
|
+
/>
|
915
|
+
<div>
|
916
|
+
{modalOpen === 1 && (
|
917
|
+
<Modal
|
918
|
+
closeButtonRef={modalCloseButtonRef}
|
919
|
+
primaryButtonRef={modalPrimaryButtonRef}
|
920
|
+
>
|
921
|
+
<ModalHeader>
|
922
|
+
<ModalTitle>Add new user</ModalTitle>
|
923
|
+
<ModalCloseButton onClick={() => setModalOpen(false)} />
|
924
|
+
</ModalHeader>
|
925
|
+
<ModalBody>
|
926
|
+
<ModalContent>
|
927
|
+
<FormLayout fieldLayout="horizontal" labelWidth="limited">
|
928
|
+
<Toggle
|
929
|
+
label="Enabled"
|
930
|
+
/>
|
931
|
+
<TextField label="Username" required />
|
932
|
+
<TextField label="Password" type="password" />
|
933
|
+
<CheckboxField label="Force password on login" />
|
934
|
+
<Radio
|
935
|
+
label="Type of collaboration"
|
936
|
+
options={[
|
937
|
+
{ label: 'Internal', value: 'internal'},
|
938
|
+
{ label: 'External', value: 'external'},
|
939
|
+
]}
|
940
|
+
/>
|
941
|
+
<SelectField
|
942
|
+
label="Role"
|
943
|
+
options={[
|
944
|
+
{ label: 'Programmer', value: 'programmer' },
|
945
|
+
{ label: 'Team leader', value: 'team-leader' },
|
946
|
+
{ label: 'Project manager', value: 'project-manager' },
|
947
|
+
]}
|
948
|
+
/>
|
949
|
+
<FileInputField label="Photo" onFilesChanged={() => {}} />
|
950
|
+
<TextArea
|
951
|
+
label="Additional info"
|
952
|
+
helpText={<p>Enter key is used for new line,<br />so <strong>Enter won't submit the form</strong>.</p>}
|
953
|
+
/>
|
954
|
+
</FormLayout>
|
955
|
+
</ModalContent>
|
956
|
+
</ModalBody>
|
957
|
+
<ModalFooter>
|
958
|
+
<Button
|
959
|
+
label="Save"
|
960
|
+
onClick={() => setModalOpen(false)}
|
961
|
+
ref={modalPrimaryButtonRef}
|
962
|
+
/>
|
963
|
+
<Button
|
964
|
+
label="Close"
|
965
|
+
onClick={() => setModalOpen(false)}
|
966
|
+
priority="outline"
|
967
|
+
ref={modalCloseButtonRef}
|
968
|
+
/>
|
969
|
+
</ModalFooter>
|
970
|
+
</Modal>
|
971
|
+
)}
|
972
|
+
{modalOpen === 2 && (
|
973
|
+
<Modal
|
974
|
+
allowPrimaryActionOnEnterKey={false}
|
975
|
+
closeButtonRef={modalCloseButtonRef}
|
976
|
+
onCancel={(e) => {
|
977
|
+
console.log('cancel', e);
|
978
|
+
}}
|
979
|
+
onClose={(e) => {
|
980
|
+
console.log('close', e);
|
981
|
+
}}
|
982
|
+
primaryButtonRef={modalPrimaryButtonRef}
|
983
|
+
>
|
984
|
+
<ModalHeader>
|
985
|
+
<ModalTitle>Add new user using native form</ModalTitle>
|
986
|
+
<ModalCloseButton onClick={() => setModalOpen(false)} />
|
987
|
+
</ModalHeader>
|
988
|
+
<ModalBody>
|
989
|
+
<ModalContent>
|
990
|
+
<form method="dialog" id="native-form">
|
991
|
+
<FormLayout fieldLayout="horizontal" labelWidth="limited">
|
992
|
+
<Toggle
|
993
|
+
label="Enabled"
|
994
|
+
/>
|
995
|
+
<TextField label="Username" required />
|
996
|
+
<TextField label="Password" type="password" />
|
997
|
+
<CheckboxField label="Force password on login" />
|
998
|
+
<Radio
|
999
|
+
label="Type of collaboration"
|
1000
|
+
options={[
|
1001
|
+
{ label: 'Internal', value: 'internal'},
|
1002
|
+
{ label: 'External', value: 'external'},
|
1003
|
+
]}
|
1004
|
+
/>
|
1005
|
+
<SelectField
|
1006
|
+
label="Role"
|
1007
|
+
options={[
|
1008
|
+
{ label: 'Programmer', value: 'programmer' },
|
1009
|
+
{ label: 'Team leader', value: 'team-leader' },
|
1010
|
+
{ label: 'Project manager', value: 'project-manager' },
|
1011
|
+
]}
|
1012
|
+
/>
|
1013
|
+
<FileInputField label="Photo" />
|
1014
|
+
<TextArea
|
1015
|
+
label="Additional info"
|
1016
|
+
helpText={<p>Enter key is used for new line,<br />so <strong>Enter won't submit the form</strong>.</p>}
|
1017
|
+
/>
|
1018
|
+
</FormLayout>
|
1019
|
+
</form>
|
1020
|
+
</ModalContent>
|
1021
|
+
</ModalBody>
|
1022
|
+
<ModalFooter>
|
1023
|
+
<Button
|
1024
|
+
form="native-form"
|
1025
|
+
label="Save"
|
1026
|
+
ref={modalPrimaryButtonRef}
|
1027
|
+
type="submit"
|
1028
|
+
/>
|
1029
|
+
<Button
|
1030
|
+
label="Close"
|
1031
|
+
onClick={() => setModalOpen(false)}
|
1032
|
+
priority="outline"
|
1033
|
+
ref={modalCloseButtonRef}
|
1034
|
+
/>
|
1035
|
+
</ModalFooter>
|
1036
|
+
</Modal>
|
1037
|
+
)}
|
1038
|
+
</div>
|
1039
|
+
</GlobalPropsProvider>
|
1040
|
+
);
|
1041
|
+
});
|
1042
|
+
```
|
1043
|
+
|
1044
|
+
### Scrolling Long Content
|
843
1045
|
|
844
1046
|
When modals become too long for the user's viewport or device, they scroll
|
845
1047
|
independent of the page itself. This can be done in three ways using the
|
@@ -1004,7 +1206,7 @@ React.createElement(() => {
|
|
1004
1206
|
});
|
1005
1207
|
```
|
1006
1208
|
|
1007
|
-
|
1209
|
+
#### Long Content and Autofocus
|
1008
1210
|
|
1009
1211
|
👉 If you wrap ModalContent with ScrollView, you may want to turn `autoFocus`
|
1010
1212
|
off to prevent the modal from scrolling to the end immediately after being
|
@@ -1019,8 +1221,7 @@ can specify **any HTML attribute you like.** All attributes that don't
|
|
1019
1221
|
interfere with the API of the React component and that aren't filtered out by
|
1020
1222
|
[`transferProps`](/docs/js-helpers/transferProps) helper are forwarded to:
|
1021
1223
|
|
1022
|
-
- the `<
|
1023
|
-
the root, but its first child which represents the modal window.
|
1224
|
+
- the `<dialog>` HTML element in case of the `Modal` component.
|
1024
1225
|
- the root `<div>` HTML element in case of `ModalHeader`, `ModalBody`, `ModalContent`
|
1025
1226
|
and `ModalFooter` components.
|
1026
1227
|
- the heading (e.g. `<h1>`) HTML element in case of the `ModalTitle` component.
|
@@ -1031,6 +1232,7 @@ accessibility.
|
|
1031
1232
|
|
1032
1233
|
👉 For the full list of supported attributes refer to:
|
1033
1234
|
|
1235
|
+
- [`<dialog>` HTML element attributes][dialog-attributes]{:target="_blank"}
|
1034
1236
|
- [`<div>` HTML element attributes][div-attributes]{:target="_blank"}
|
1035
1237
|
- [`<h1>`-`<h6>` HTML element attributes][heading-attributes]{:target="_blank"}
|
1036
1238
|
- [`<button>` HTML element attributes][button-attributes]{:target="_blank"}
|
@@ -1066,29 +1268,47 @@ accessibility.
|
|
1066
1268
|
|
1067
1269
|
## Theming
|
1068
1270
|
|
1069
|
-
| Custom Property | Description
|
1070
|
-
|
1071
|
-
| `--rui-Modal__padding-x` | Inline padding of individual modal components
|
1072
|
-
| `--rui-Modal__padding-y` | Block padding of individual modal components
|
1073
|
-
| `--rui-Modal__background` | Modal background (including `url()` or gradient)
|
1074
|
-
| `--rui-Modal__box-shadow` | Modal box shadow
|
1075
|
-
| `--rui-Modal__separator__width` | Width of separator between modal header, body, and footer
|
1076
|
-
| `--rui-Modal__separator__color` | Color of separator between modal header, body, and footer
|
1077
|
-
| `--rui-Modal__outer-spacing-xs` | Spacing around modal, `xs` screen size
|
1078
|
-
| `--rui-Modal__outer-spacing-sm` | Spacing around modal, `sm` screen size and bigger
|
1079
|
-
| `--rui-Modal__header__gap` | Modal header gap between children
|
1080
|
-
| `--rui-Modal__footer__background` | Modal footer background (including `url()` or gradient)
|
1081
|
-
| `--rui-Modal__footer__gap` | Modal footer gap between children
|
1082
|
-
| `--rui-Modal__backdrop__background` | Modal backdrop background (including `url()` or gradient)
|
1083
|
-
| `--rui-Modal--auto__min-width` | Min width of auto-sized modal (when enough screen estate)
|
1084
|
-
| `--rui-Modal--auto__max-width` | Max width of auto-sized modal (when enough screen estate)
|
1085
|
-
| `--rui-Modal--small__width` | Width of small modal
|
1086
|
-
| `--rui-Modal--medium__width` | Width of medium modal
|
1087
|
-
| `--rui-Modal--large__width` | Width of large modal
|
1088
|
-
| `--rui-Modal--fullscreen__width` | Width of fullscreen modal
|
1089
|
-
| `--rui-Modal--fullscreen__height` | Height of fullscreen modal
|
1271
|
+
| Custom Property | Description |
|
1272
|
+
|------------------------------------------------------|-------------------------------------------------------------|
|
1273
|
+
| `--rui-Modal__padding-x` | Inline padding of individual modal components |
|
1274
|
+
| `--rui-Modal__padding-y` | Block padding of individual modal components |
|
1275
|
+
| `--rui-Modal__background` | Modal background (including `url()` or gradient) |
|
1276
|
+
| `--rui-Modal__box-shadow` | Modal box shadow |
|
1277
|
+
| `--rui-Modal__separator__width` | Width of separator between modal header, body, and footer |
|
1278
|
+
| `--rui-Modal__separator__color` | Color of separator between modal header, body, and footer |
|
1279
|
+
| `--rui-Modal__outer-spacing-xs` | Spacing around modal, `xs` screen size |
|
1280
|
+
| `--rui-Modal__outer-spacing-sm` | Spacing around modal, `sm` screen size and bigger |
|
1281
|
+
| `--rui-Modal__header__gap` | Modal header gap between children |
|
1282
|
+
| `--rui-Modal__footer__background` | Modal footer background (including `url()` or gradient) |
|
1283
|
+
| `--rui-Modal__footer__gap` | Modal footer gap between children |
|
1284
|
+
| `--rui-Modal__backdrop__background` | Modal backdrop background (including `url()` or gradient) |
|
1285
|
+
| `--rui-Modal--auto__min-width` | Min width of auto-sized modal (when enough screen estate) |
|
1286
|
+
| `--rui-Modal--auto__max-width` | Max width of auto-sized modal (when enough screen estate) |
|
1287
|
+
| `--rui-Modal--small__width` | Width of small modal |
|
1288
|
+
| `--rui-Modal--medium__width` | Width of medium modal |
|
1289
|
+
| `--rui-Modal--large__width` | Width of large modal |
|
1290
|
+
| `--rui-Modal--fullscreen__width` | Width of fullscreen modal |
|
1291
|
+
| `--rui-Modal--fullscreen__height` | Height of fullscreen modal |
|
1292
|
+
| `--rui-Modal__animation__duration` | Duration of animation used (when opening modal) |
|
1293
|
+
|
1294
|
+
### Theming Variants
|
1295
|
+
|
1296
|
+
It's possible to adjust the theme of specific color variant. Naming convention
|
1297
|
+
looks as follows:
|
1298
|
+
|
1299
|
+
`--rui-Modal--<COLOR>__<PROPERTY>`
|
1300
|
+
|
1301
|
+
Where:
|
1302
|
+
|
1303
|
+
- `<COLOR>` is a value from supported
|
1304
|
+
[color collections](/docs/foundation/collections#colors)
|
1305
|
+
(check [color variants](#color-variants) and [API](#api) to see which
|
1306
|
+
collections are supported),
|
1307
|
+
- `<PROPERTY>` is one of `border-color` or `background-color`.
|
1090
1308
|
|
1091
1309
|
[button-attributes]: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/button#attributes
|
1310
|
+
[controlled-components]: /docs/getting-started/usage#foundation-css
|
1311
|
+
[dialog-attributes]: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/dialog#attributes
|
1092
1312
|
[div-attributes]: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/div#attributes
|
1093
1313
|
[heading-attributes]: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/Heading_Elements#attributes
|
1094
1314
|
[React common props]: https://react.dev/reference/react-dom/components/common#common-props
|
@@ -0,0 +1,28 @@
|
|
1
|
+
// Disable coverage for the following function
|
2
|
+
/* istanbul ignore next */
|
3
|
+
|
4
|
+
/**
|
5
|
+
* Handles the cancel event of the dialog which is fired when the user presses the Escape key or triggers cancel event
|
6
|
+
* by native dialog mechanism.
|
7
|
+
*
|
8
|
+
* It prevents the default behaviour of the native dialog and closes the dialog manually by clicking the close button,
|
9
|
+
* if the close button is not disabled.
|
10
|
+
*
|
11
|
+
* @param e
|
12
|
+
* @param closeButtonRef
|
13
|
+
* @param onCancelHandler
|
14
|
+
*/
|
15
|
+
export const dialogOnCancelHandler = (e, closeButtonRef, onCancelHandler = undefined) => {
|
16
|
+
// Prevent the default behaviour of the event as we want to close dialog manually.
|
17
|
+
e.preventDefault();
|
18
|
+
|
19
|
+
// If the close button is not disabled, close the modal.
|
20
|
+
if (closeButtonRef?.current != null && closeButtonRef?.current?.disabled === false) {
|
21
|
+
closeButtonRef.current.click();
|
22
|
+
}
|
23
|
+
|
24
|
+
// This is a custom handler that is passed as a prop to the Modal component
|
25
|
+
if (onCancelHandler) {
|
26
|
+
onCancelHandler(e);
|
27
|
+
}
|
28
|
+
};
|