@react-ui-org/react-ui 0.57.0 → 0.59.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.
Files changed (118) hide show
  1. package/.nvmrc +1 -1
  2. package/README.md +2 -11
  3. package/dist/react-ui.css +19 -19
  4. package/dist/react-ui.development.css +1351 -963
  5. package/dist/react-ui.development.js +187 -87
  6. package/dist/react-ui.js +1 -1
  7. package/package.json +16 -5
  8. package/src/components/Alert/Alert.jsx +7 -9
  9. package/src/components/Alert/Alert.module.scss +3 -3
  10. package/src/components/Alert/README.md +18 -32
  11. package/src/components/Alert/_settings.scss +1 -2
  12. package/src/components/Badge/Badge.jsx +3 -3
  13. package/src/components/Button/Button.jsx +3 -3
  14. package/src/components/ButtonGroup/ButtonGroup.jsx +3 -3
  15. package/src/components/Card/Card.jsx +7 -7
  16. package/src/components/Card/Card.module.scss +8 -7
  17. package/src/components/Card/CardBody.jsx +2 -2
  18. package/src/components/Card/CardFooter.jsx +2 -2
  19. package/src/components/Card/README.md +20 -17
  20. package/src/components/Card/_settings.scss +1 -2
  21. package/src/components/Card/_theme.scss +1 -0
  22. package/src/components/CheckboxField/CheckboxField.jsx +11 -5
  23. package/src/components/CheckboxField/README.md +110 -5
  24. package/src/components/FileInputField/FileInputField.jsx +148 -22
  25. package/src/components/FileInputField/FileInputField.module.scss +87 -1
  26. package/src/components/FileInputField/README.md +83 -2
  27. package/src/components/FileInputField/_settings.scss +15 -0
  28. package/src/components/FormLayout/FormLayout.jsx +3 -3
  29. package/src/components/FormLayout/FormLayoutCustomField.jsx +3 -3
  30. package/src/components/FormLayout/README.md +1 -0
  31. package/src/components/Grid/Grid.jsx +2 -2
  32. package/src/components/Grid/Grid.module.scss +2 -2
  33. package/src/components/Grid/GridSpan.jsx +2 -2
  34. package/src/components/InputGroup/InputGroup.jsx +4 -4
  35. package/src/components/InputGroup/InputGroup.module.scss +12 -8
  36. package/src/components/InputGroup/README.md +1 -1
  37. package/src/components/Modal/Modal.jsx +118 -46
  38. package/src/components/Modal/Modal.module.scss +34 -18
  39. package/src/components/Modal/ModalBody.jsx +3 -3
  40. package/src/components/Modal/ModalBody.module.scss +18 -0
  41. package/src/components/Modal/ModalCloseButton.jsx +4 -6
  42. package/src/components/Modal/ModalContent.jsx +2 -2
  43. package/src/components/Modal/ModalFooter.jsx +3 -3
  44. package/src/components/Modal/ModalFooter.module.scss +6 -2
  45. package/src/components/Modal/ModalHeader.jsx +3 -3
  46. package/src/components/Modal/ModalHeader.module.scss +8 -1
  47. package/src/components/Modal/ModalTitle.jsx +2 -2
  48. package/src/components/Modal/README.md +407 -187
  49. package/src/components/Modal/_animations.scss +9 -0
  50. package/src/components/Modal/_helpers/dialogOnCancelHandler.js +28 -0
  51. package/src/components/Modal/_helpers/dialogOnClickHandler.js +46 -0
  52. package/src/components/Modal/_helpers/dialogOnCloseHandler.js +28 -0
  53. package/src/components/Modal/_helpers/dialogOnKeyDownHandler.js +62 -0
  54. package/src/components/Modal/_helpers/getPositionClassName.js +1 -1
  55. package/src/components/Modal/_hooks/useModalFocus.js +24 -91
  56. package/src/components/Modal/_settings.scss +4 -3
  57. package/src/components/Modal/_theme.scss +1 -0
  58. package/src/components/Paper/Paper.jsx +3 -3
  59. package/src/components/Popover/Popover.jsx +60 -15
  60. package/src/components/Popover/Popover.module.scss +37 -9
  61. package/src/components/Popover/PopoverWrapper.jsx +2 -2
  62. package/src/components/Popover/README.md +60 -3
  63. package/src/components/Popover/_helpers/cleanPlacementStyle.js +20 -0
  64. package/src/components/Radio/README.md +103 -0
  65. package/src/components/Radio/Radio.jsx +11 -5
  66. package/src/components/Radio/Radio.module.scss +4 -0
  67. package/src/components/ScrollView/ScrollView.jsx +5 -7
  68. package/src/components/SelectField/README.md +103 -0
  69. package/src/components/SelectField/SelectField.jsx +11 -5
  70. package/src/components/Table/Table.jsx +2 -2
  71. package/src/components/Tabs/Tabs.jsx +2 -2
  72. package/src/components/Tabs/TabsItem.jsx +3 -3
  73. package/src/components/Text/Text.jsx +3 -3
  74. package/src/components/TextArea/TextArea.jsx +3 -3
  75. package/src/components/TextField/README.md +14 -2
  76. package/src/components/TextField/TextField.jsx +3 -3
  77. package/src/components/TextLink/README.md +10 -3
  78. package/src/components/TextLink/TextLink.jsx +2 -2
  79. package/src/components/TextLink/_theme.scss +3 -3
  80. package/src/components/Toggle/README.md +83 -1
  81. package/src/components/Toggle/Toggle.jsx +11 -5
  82. package/src/components/Toolbar/Toolbar.jsx +3 -3
  83. package/src/components/Toolbar/ToolbarGroup.jsx +3 -3
  84. package/src/components/Toolbar/ToolbarItem.jsx +3 -3
  85. package/src/components/_helpers/resolveContextOrProp.js +6 -3
  86. package/src/helpers/classNames/README.md +65 -0
  87. package/src/helpers/classNames/classNames.js +11 -0
  88. package/src/helpers/classNames/index.js +1 -0
  89. package/src/helpers/transferProps/README.md +46 -0
  90. package/src/helpers/transferProps/index.js +1 -0
  91. package/src/index.js +6 -5
  92. package/src/providers/globalProps/GlobalPropsContext.jsx +5 -0
  93. package/src/providers/globalProps/GlobalPropsProvider.jsx +33 -0
  94. package/src/providers/globalProps/index.js +3 -0
  95. package/src/{provider → providers/globalProps}/withGlobalProps.jsx +16 -16
  96. package/src/providers/translations/TranslationsContext.jsx +6 -0
  97. package/src/providers/translations/TranslationsProvider.jsx +33 -0
  98. package/src/providers/translations/index.js +2 -0
  99. package/src/styles/elements/_links.scss +2 -9
  100. package/src/styles/generic/_focus.scss +1 -1
  101. package/src/styles/theme/_form-fields.scss +19 -0
  102. package/src/styles/theme/_links.scss +4 -3
  103. package/src/styles/tools/_accessibility.scss +3 -5
  104. package/src/styles/tools/_collections.scss +62 -5
  105. package/src/styles/tools/_links.scss +17 -0
  106. package/src/styles/tools/form-fields/_box-field-elements.scss +21 -9
  107. package/src/styles/tools/form-fields/_box-field-layout.scss +2 -2
  108. package/src/styles/tools/form-fields/_box-field-sizes.scss +6 -10
  109. package/src/styles/tools/form-fields/_foundation.scss +6 -4
  110. package/src/styles/tools/form-fields/_variants.scss +12 -8
  111. package/src/theme.scss +53 -2
  112. package/src/translations/en.js +5 -0
  113. package/src/provider/RUIContext.jsx +0 -9
  114. package/src/provider/RUIProvider.jsx +0 -42
  115. package/src/provider/index.js +0 -3
  116. package/src/styles/settings/_z-indexes.scss +0 -2
  117. package/src/utils/classNames.js +0 -8
  118. /package/src/{utils → helpers/transferProps}/transferProps.js +0 -0
@@ -0,0 +1,15 @@
1
+ @use "../../styles/theme/typography";
2
+
3
+ $drop-zone-color: var(--rui-color-text-primary);
4
+ $drop-zone-disabled-color: var(--rui-color-text-primary-disabled);
5
+ $drop-zone-border-color: var(--rui-color-border-primary);
6
+ $drop-zone-hover-border-color: var(--rui-color-border-primary-hover);
7
+ $drop-zone-active-border-color: var(--rui-color-border-primary-active);
8
+ $drop-zone-dragging-border-color: var(--rui-color-border-primary-active);
9
+ $drop-zone-disabled-border-color: var(--rui-color-border-primary);
10
+ $drop-zone-background-color: var(--rui-color-background-basic);
11
+ $drop-zone-disabled-background-color: var(--rui-color-background-disabled);
12
+ $drop-zone-disabled-cursor: var(--rui-cursor-not-allowed);
13
+ $drop-zone-font-weight: typography.$font-weight-base;
14
+ $drop-zone-line-height: typography.$line-height-base;
15
+ $drop-zone-font-family: typography.$font-family-base;
@@ -1,8 +1,8 @@
1
1
  import PropTypes from 'prop-types';
2
2
  import React, { useMemo } from 'react';
3
- import { withGlobalProps } from '../../provider';
4
- import { classNames } from '../../utils/classNames';
5
- import { transferProps } from '../../utils/transferProps';
3
+ import { withGlobalProps } from '../../providers/globalProps';
4
+ import { classNames } from '../../helpers/classNames/classNames';
5
+ import { transferProps } from '../../helpers/transferProps';
6
6
  import { isChildrenEmpty } from '../_helpers/isChildrenEmpty';
7
7
  import { FormLayoutContext } from './FormLayoutContext';
8
8
  import styles from './FormLayout.module.scss';
@@ -1,8 +1,8 @@
1
1
  import PropTypes from 'prop-types';
2
2
  import React, { useContext } from 'react';
3
- import { withGlobalProps } from '../../provider';
4
- import { classNames } from '../../utils/classNames';
5
- import { transferProps } from '../../utils/transferProps';
3
+ import { withGlobalProps } from '../../providers/globalProps';
4
+ import { classNames } from '../../helpers/classNames/classNames';
5
+ import { transferProps } from '../../helpers/transferProps';
6
6
  import { getRootSizeClassName } from '../_helpers/getRootSizeClassName';
7
7
  import { getRootValidationStateClassName } from '../_helpers/getRootValidationStateClassName';
8
8
  import { isChildrenEmpty } from '../_helpers/isChildrenEmpty';
@@ -389,6 +389,7 @@ React.createElement(() => {
389
389
  />
390
390
  <FileInputField
391
391
  label="Attachment"
392
+ onFilesChanged={() => {}}
392
393
  />
393
394
  <Toggle
394
395
  checked={receiveNewsletter}
@@ -1,7 +1,7 @@
1
1
  import PropTypes from 'prop-types';
2
2
  import React from 'react';
3
- import { withGlobalProps } from '../../provider';
4
- import { transferProps } from '../../utils/transferProps';
3
+ import { withGlobalProps } from '../../providers/globalProps';
4
+ import { transferProps } from '../../helpers/transferProps';
5
5
  import { isChildrenEmpty } from '../_helpers/isChildrenEmpty';
6
6
  import { generateResponsiveCustomProperties } from './_helpers/generateResponsiveCustomProperties';
7
7
  import styles from './Grid.module.scss';
@@ -20,8 +20,8 @@
20
20
  //
21
21
  // 2. Apply custom property value that is defined within current breakpoint, see 1.
22
22
  //
23
- // 3. Intentionally use longhand properties because the custom property fallback mechanism evaluates `initial` values as
24
- // empty. That makes the other value of the shorthand property unexpectedly used for both axes.
23
+ // 3. Intentionally use longhand properties because the custom property fallback mechanism evaluates `initial` values
24
+ // as empty. That makes the other value of the shorthand property unexpectedly used for both axes.
25
25
 
26
26
  @use "sass:map";
27
27
  @use "../../styles/tools/spacing";
@@ -1,7 +1,7 @@
1
1
  import PropTypes from 'prop-types';
2
2
  import React from 'react';
3
- import { withGlobalProps } from '../../provider';
4
- import { transferProps } from '../../utils/transferProps';
3
+ import { withGlobalProps } from '../../providers/globalProps';
4
+ import { transferProps } from '../../helpers/transferProps';
5
5
  import { isChildrenEmpty } from '../_helpers/isChildrenEmpty';
6
6
  import { generateResponsiveCustomProperties } from './_helpers/generateResponsiveCustomProperties';
7
7
  import styles from './Grid.module.scss';
@@ -3,15 +3,15 @@ import React, {
3
3
  useContext,
4
4
  useMemo,
5
5
  } from 'react';
6
- import { Text } from '../Text';
7
- import { withGlobalProps } from '../../provider';
8
- import { classNames } from '../../utils/classNames';
9
- import { transferProps } from '../../utils/transferProps';
6
+ import { withGlobalProps } from '../../providers/globalProps';
7
+ import { classNames } from '../../helpers/classNames/classNames';
8
+ import { transferProps } from '../../helpers/transferProps';
10
9
  import { getRootSizeClassName } from '../_helpers/getRootSizeClassName';
11
10
  import { getRootValidationStateClassName } from '../_helpers/getRootValidationStateClassName';
12
11
  import { isChildrenEmpty } from '../_helpers/isChildrenEmpty';
13
12
  import { resolveContextOrProp } from '../_helpers/resolveContextOrProp';
14
13
  import { FormLayoutContext } from '../FormLayout';
14
+ import { Text } from '../Text';
15
15
  import { InputGroupContext } from './InputGroupContext';
16
16
  import styles from './InputGroup.module.scss';
17
17
 
@@ -1,7 +1,9 @@
1
1
  // 1. The class name is intentionally singular because it's targeted by other mixins too.
2
2
  // 2. Use a block-level display mode to prevent extra white space below grouped inputs in Safari.
3
- // 3. Prevent individual inputs from overlapping inside narrow containers.
4
- // 4. Legends are tricky to style, let's use a `div` instead.
3
+ // 3. Let wide input groups honor the minimum input width and overflow horizontally without wrapping and distorting
4
+ // the inputs.
5
+ // 4. Prevent individual inputs from overlapping inside narrow containers.
6
+ // 5. Legends are tricky to style, let's use a `div` instead.
5
7
  // https://developer.mozilla.org/en-US/docs/Web/HTML/Element/fieldset#styling_with_css
6
8
 
7
9
  @use "../../styles/tools/form-fields/box-field-elements";
@@ -19,12 +21,12 @@
19
21
  @include foundation.fieldset();
20
22
  }
21
23
 
22
- // 4.
24
+ // 5.
23
25
  .legend {
24
26
  @include accessibility.hide-text();
25
27
  }
26
28
 
27
- // 4.
29
+ // 5.
28
30
  .label {
29
31
  @include foundation.label();
30
32
  }
@@ -63,11 +65,13 @@
63
65
  .isRootLayoutVertical,
64
66
  .isRootLayoutHorizontal {
65
67
  @include box-field-layout.vertical();
68
+
69
+ max-width: none; // 3.
66
70
  }
67
71
 
68
72
  .isRootLayoutVertical .field,
69
73
  .isRootLayoutHorizontal .field {
70
- max-width: none; // 3.
74
+ max-width: none; // 4.
71
75
  }
72
76
 
73
77
  .isRootLayoutHorizontal {
@@ -80,14 +84,14 @@
80
84
 
81
85
  // Sizes
82
86
  .isRootSizeSmall {
83
- @include box-field-sizes.size(small, $has-input: false);
87
+ @include box-field-sizes.size(small);
84
88
  }
85
89
 
86
90
  .isRootSizeMedium {
87
- @include box-field-sizes.size(medium, $has-input: false);
91
+ @include box-field-sizes.size(medium);
88
92
  }
89
93
 
90
94
  .isRootSizeLarge {
91
- @include box-field-sizes.size(large, $has-input: false);
95
+ @include box-field-sizes.size(large);
92
96
  }
93
97
  }
@@ -145,7 +145,7 @@ supports this kind of layout as well.
145
145
  label="Horizontal layout"
146
146
  layout="horizontal"
147
147
  >
148
- <TextField label="Label" />
148
+ <FileInputField label="Attachment" onFilesChanged={() => {}} />
149
149
  <Button label="Submit" />
150
150
  </InputGroup>
151
151
  ```
@@ -1,9 +1,19 @@
1
1
  import PropTypes from 'prop-types';
2
- import React, { useRef } from 'react';
2
+ import React, {
3
+ useCallback,
4
+ useEffect,
5
+ useImperativeHandle,
6
+ useRef,
7
+ } from 'react';
3
8
  import { createPortal } from 'react-dom';
4
- import { withGlobalProps } from '../../provider';
5
- import { classNames } from '../../utils/classNames';
6
- import { transferProps } from '../../utils/transferProps';
9
+ import { classNames } from '../../helpers/classNames';
10
+ import { transferProps } from '../../helpers/transferProps';
11
+ import { withGlobalProps } from '../../providers/globalProps';
12
+ import { getRootColorClassName } from '../_helpers/getRootColorClassName';
13
+ import { dialogOnCancelHandler } from './_helpers/dialogOnCancelHandler';
14
+ import { dialogOnClickHandler } from './_helpers/dialogOnClickHandler';
15
+ import { dialogOnCloseHandler } from './_helpers/dialogOnCloseHandler';
16
+ import { dialogOnKeyDownHandler } from './_helpers/dialogOnKeyDownHandler';
7
17
  import { getPositionClassName } from './_helpers/getPositionClassName';
8
18
  import { getSizeClassName } from './_helpers/getSizeClassName';
9
19
  import { useModalFocus } from './_hooks/useModalFocus';
@@ -12,44 +22,37 @@ import styles from './Modal.module.scss';
12
22
 
13
23
  const preRender = (
14
24
  children,
15
- childrenWrapperRef,
16
- closeButtonRef,
25
+ color,
26
+ dialogRef,
17
27
  position,
18
- restProps,
19
28
  size,
29
+ events,
30
+ restProps,
20
31
  ) => (
21
- <div
22
- className={styles.backdrop}
23
- onClick={(e) => {
24
- e.preventDefault();
25
- if (closeButtonRef?.current != null) {
26
- closeButtonRef.current.click();
27
- }
28
- }}
29
- role="presentation"
32
+ <dialog
33
+ {...transferProps(restProps)}
34
+ {...transferProps(events)}
35
+ className={classNames(
36
+ styles.root,
37
+ color && getRootColorClassName(color, styles),
38
+ getSizeClassName(size, styles),
39
+ getPositionClassName(position, styles),
40
+ )}
41
+ ref={dialogRef}
30
42
  >
31
- <div
32
- {...transferProps(restProps)}
33
- className={classNames(
34
- styles.root,
35
- getSizeClassName(size, styles),
36
- getPositionClassName(position, styles),
37
- )}
38
- onClick={(e) => {
39
- e.stopPropagation();
40
- }}
41
- ref={childrenWrapperRef}
42
- role="presentation"
43
- >
44
- {children}
45
- </div>
46
- </div>
43
+ {children}
44
+ </dialog>
47
45
  );
48
46
 
49
47
  export const Modal = ({
48
+ allowCloseOnBackdropClick,
49
+ allowCloseOnEscapeKey,
50
+ allowPrimaryActionOnEnterKey,
50
51
  autoFocus,
51
52
  children,
52
53
  closeButtonRef,
54
+ color,
55
+ dialogRef,
53
56
  portalId,
54
57
  position,
55
58
  preventScrollUnderneath,
@@ -57,45 +60,89 @@ export const Modal = ({
57
60
  size,
58
61
  ...restProps
59
62
  }) => {
60
- const childrenWrapperRef = useRef();
63
+ const internalDialogRef = useRef();
61
64
 
62
- useModalFocus(
63
- autoFocus,
64
- childrenWrapperRef,
65
- primaryButtonRef,
66
- closeButtonRef,
67
- );
65
+ useEffect(() => {
66
+ internalDialogRef.current.showModal();
67
+ }, []);
68
68
 
69
+ // We need to have a reference to the dialog element to be able to call its methods,
70
+ // but at the same time we want to expose this reference to the parent component for
71
+ // case someone wants to call dialog methods from outside the component.
72
+ useImperativeHandle(dialogRef, () => internalDialogRef.current);
73
+
74
+ useModalFocus(autoFocus, internalDialogRef, primaryButtonRef);
69
75
  useModalScrollPrevention(preventScrollUnderneath);
70
76
 
77
+ const onCancel = useCallback(
78
+ (e) => dialogOnCancelHandler(e, closeButtonRef, restProps.onCancel),
79
+ [closeButtonRef, restProps.onCancel],
80
+ );
81
+ const onClick = useCallback(
82
+ (e) => dialogOnClickHandler(e, closeButtonRef, internalDialogRef, allowCloseOnBackdropClick),
83
+ [allowCloseOnBackdropClick, closeButtonRef, internalDialogRef],
84
+ );
85
+ const onClose = useCallback(
86
+ (e) => dialogOnCloseHandler(e, closeButtonRef, restProps.onClose),
87
+ [closeButtonRef, restProps.onClose],
88
+ );
89
+ const onKeyDown = useCallback(
90
+ (e) => dialogOnKeyDownHandler(
91
+ e,
92
+ closeButtonRef,
93
+ primaryButtonRef,
94
+ allowCloseOnEscapeKey,
95
+ allowPrimaryActionOnEnterKey,
96
+ ),
97
+ [
98
+ allowCloseOnEscapeKey,
99
+ allowPrimaryActionOnEnterKey,
100
+ closeButtonRef,
101
+ primaryButtonRef,
102
+ ],
103
+ );
104
+ const events = {
105
+ onCancel,
106
+ onClick,
107
+ onClose,
108
+ onKeyDown,
109
+ };
110
+
71
111
  if (portalId === null) {
72
112
  return preRender(
73
113
  children,
74
- childrenWrapperRef,
75
- closeButtonRef,
114
+ color,
115
+ internalDialogRef,
76
116
  position,
77
- restProps,
78
117
  size,
118
+ events,
119
+ restProps,
79
120
  );
80
121
  }
81
122
 
82
123
  return createPortal(
83
124
  preRender(
84
125
  children,
85
- childrenWrapperRef,
86
- closeButtonRef,
126
+ color,
127
+ internalDialogRef,
87
128
  position,
88
- restProps,
89
129
  size,
130
+ events,
131
+ restProps,
90
132
  ),
91
133
  document.getElementById(portalId),
92
134
  );
93
135
  };
94
136
 
95
137
  Modal.defaultProps = {
138
+ allowCloseOnBackdropClick: true,
139
+ allowCloseOnEscapeKey: true,
140
+ allowPrimaryActionOnEnterKey: true,
96
141
  autoFocus: true,
97
142
  children: null,
98
143
  closeButtonRef: null,
144
+ color: undefined,
145
+ dialogRef: null,
99
146
  portalId: null,
100
147
  position: 'center',
101
148
  preventScrollUnderneath: window.document.body,
@@ -104,6 +151,18 @@ Modal.defaultProps = {
104
151
  };
105
152
 
106
153
  Modal.propTypes = {
154
+ /**
155
+ * If `true`, the `Modal` can be closed by clicking on the backdrop.
156
+ */
157
+ allowCloseOnBackdropClick: PropTypes.bool,
158
+ /**
159
+ * If `true`, the `Modal` can be closed by pressing the Escape key.
160
+ */
161
+ allowCloseOnEscapeKey: PropTypes.bool,
162
+ /**
163
+ * If `true`, the `Modal` can be submitted by pressing the Enter key.
164
+ */
165
+ allowPrimaryActionOnEnterKey: PropTypes.bool,
107
166
  /**
108
167
  * If `true`, focus the first input element in the `Modal`, or primary button (referenced by the `primaryButtonRef`
109
168
  * prop), or other focusable element when the `Modal` is opened. If there are none or `autoFocus` is set to `false`,
@@ -121,12 +180,25 @@ Modal.propTypes = {
121
180
  */
122
181
  children: PropTypes.node,
123
182
  /**
124
- * Reference to close button element. It is used to close modal when Escape key is pressed or the backdrop is clicked.
183
+ * Reference to close button element. It is used to close modal when Escape key is pressed
184
+ * or the backdrop is clicked.
125
185
  */
126
186
  closeButtonRef: PropTypes.shape({
127
187
  // eslint-disable-next-line react/forbid-prop-types
128
188
  current: PropTypes.any,
129
189
  }),
190
+ /**
191
+ * Color to clarify importance and meaning of the modal. Implements
192
+ * [Feedback color collection](/docs/foundation/collections#colors).
193
+ */
194
+ color: PropTypes.oneOf(['success', 'warning', 'danger', 'help', 'info', 'note']),
195
+ /**
196
+ * Reference to dialog element
197
+ */
198
+ dialogRef: PropTypes.shape({
199
+ // eslint-disable-next-line react/forbid-prop-types
200
+ current: PropTypes.any,
201
+ }),
130
202
  /**
131
203
  * If set, modal is rendered in the React Portal with that ID.
132
204
  */
@@ -1,9 +1,16 @@
1
+ // 1. Modal uses <dialog> element that uses the browser's built-in dialog functionality, so that:
2
+ // * visibility of the .root element and its backdrop is managed by the browser
3
+ // * positioning of the .root element and its backdrop is managed by the browser
4
+ // * z-index of the .root element and its backdrop is not needed as dialog is rendered in browser's Top layer
5
+
1
6
  @use "sass:map";
2
7
  @use "../../styles/theme/typography";
3
8
  @use "../../styles/tools/accessibility";
4
9
  @use "../../styles/tools/breakpoint";
10
+ @use "../../styles/tools/collections";
5
11
  @use "../../styles/tools/reset";
6
12
  @use "../../styles/tools/spacing";
13
+ @use "animations";
7
14
  @use "settings";
8
15
  @use "theme";
9
16
 
@@ -13,18 +20,16 @@
13
20
  --rui-local-max-width: calc(100% - (2 * var(--rui-local-outer-spacing)));
14
21
  --rui-local-max-height: calc(100% - (2 * var(--rui-local-outer-spacing)));
15
22
 
16
- position: fixed;
17
- left: 50%;
18
- z-index: settings.$z-index;
19
- display: flex;
20
23
  flex-direction: column;
21
24
  max-width: var(--rui-local-max-width);
22
25
  max-height: var(--rui-local-max-height);
26
+ padding: 0;
23
27
  overflow-y: auto;
28
+ color: inherit;
29
+ border-width: 0;
24
30
  border-radius: settings.$border-radius;
25
31
  background: theme.$background;
26
32
  box-shadow: theme.$box-shadow;
27
- transform: translateX(-50%);
28
33
  overscroll-behavior: contain;
29
34
 
30
35
  @include breakpoint.up(sm) {
@@ -32,14 +37,20 @@
32
37
  }
33
38
  }
34
39
 
35
- .backdrop {
36
- position: fixed;
37
- top: 0;
38
- left: 0;
39
- z-index: settings.$backdrop-z-index;
40
- width: 100vw;
41
- height: 100vh;
40
+ .root[open] {
41
+ display: flex;
42
+
43
+ @media (prefers-reduced-motion: no-preference) {
44
+ animation: fade-in theme.$animation-duration ease-out;
45
+ }
46
+ }
47
+
48
+ .root[open]::backdrop {
42
49
  background: theme.$backdrop-background;
50
+
51
+ @media (prefers-reduced-motion: no-preference) {
52
+ animation: inherit;
53
+ }
43
54
  }
44
55
 
45
56
  .isRootSizeSmall {
@@ -64,17 +75,22 @@
64
75
  }
65
76
 
66
77
  .isRootSizeAuto {
67
- width: auto;
68
78
  min-width: min(var(--rui-local-max-width), #{map.get(theme.$sizes, auto, min-width)});
69
79
  max-width: min(var(--rui-local-max-width), #{map.get(theme.$sizes, auto, max-width)});
70
80
  }
71
81
 
72
- .isRootPositionCenter {
73
- top: 50%;
74
- transform: translate(-50%, -50%);
75
- }
76
-
77
82
  .isRootPositionTop {
78
83
  top: var(--rui-local-outer-spacing);
84
+ bottom: auto;
85
+ }
86
+
87
+ @each $color in settings.$colors {
88
+ @include collections.generate-class(
89
+ $prefix: "rui-",
90
+ $component-name: "Modal",
91
+ $variant-name: "color",
92
+ $variant-value: $color,
93
+ $properties: settings.$themeable-properties,
94
+ );
79
95
  }
80
96
  }
@@ -1,8 +1,8 @@
1
1
  import PropTypes from 'prop-types';
2
2
  import React from 'react';
3
- import { withGlobalProps } from '../../provider';
4
- import { classNames } from '../../utils/classNames';
5
- import { transferProps } from '../../utils/transferProps';
3
+ import { withGlobalProps } from '../../providers/globalProps';
4
+ import { classNames } from '../../helpers/classNames/classNames';
5
+ import { transferProps } from '../../helpers/transferProps';
6
6
  import { isChildrenEmpty } from '../_helpers/isChildrenEmpty';
7
7
  import { getScrollingClassName } from './_helpers/getScrollingClassName';
8
8
  import styles from './ModalBody.module.scss';
@@ -1,6 +1,24 @@
1
+ // 1. Intentionally do not provide a fallback value for the border color. Setting a fallback value (e.g. `transparent`)
2
+ // will result in the border being skewed at both ends.
3
+
4
+ @use "settings";
5
+
1
6
  @layer components.modal {
2
7
  .root {
3
8
  flex: 1 1 auto;
9
+ border-inline: settings.$border-width solid var(--rui-local-border-color); // 1.
10
+
11
+ &:first-child {
12
+ border-top: settings.$border-width solid var(--rui-local-border-color); // 1.
13
+ border-top-left-radius: settings.$border-radius;
14
+ border-top-right-radius: settings.$border-radius;
15
+ }
16
+
17
+ &:last-child {
18
+ border-bottom: settings.$border-width solid var(--rui-local-border-color); // 1.
19
+ border-bottom-right-radius: settings.$border-radius;
20
+ border-bottom-left-radius: settings.$border-radius;
21
+ }
4
22
  }
5
23
 
6
24
  .isRootScrollingAuto,
@@ -1,10 +1,8 @@
1
1
  import PropTypes from 'prop-types';
2
2
  import React, { useContext } from 'react';
3
- import {
4
- RUIContext,
5
- withGlobalProps,
6
- } from '../../provider';
7
- import { transferProps } from '../../utils/transferProps';
3
+ import { TranslationsContext } from '../../providers/translations';
4
+ import { withGlobalProps } from '../../providers/globalProps';
5
+ import { transferProps } from '../../helpers/transferProps';
8
6
  import styles from './ModalCloseButton.module.scss';
9
7
 
10
8
  export const ModalCloseButton = React.forwardRef((props, ref) => {
@@ -13,7 +11,7 @@ export const ModalCloseButton = React.forwardRef((props, ref) => {
13
11
  ...restProps
14
12
  } = props;
15
13
 
16
- const { translations } = useContext(RUIContext);
14
+ const translations = useContext(TranslationsContext);
17
15
 
18
16
  return (
19
17
  <button
@@ -1,7 +1,7 @@
1
1
  import PropTypes from 'prop-types';
2
2
  import React from 'react';
3
- import { withGlobalProps } from '../../provider';
4
- import { transferProps } from '../../utils/transferProps';
3
+ import { withGlobalProps } from '../../providers/globalProps';
4
+ import { transferProps } from '../../helpers/transferProps';
5
5
  import { isChildrenEmpty } from '../_helpers/isChildrenEmpty';
6
6
  import styles from './ModalContent.module.scss';
7
7
 
@@ -1,8 +1,8 @@
1
1
  import PropTypes from 'prop-types';
2
2
  import React from 'react';
3
- import { withGlobalProps } from '../../provider';
4
- import { classNames } from '../../utils/classNames';
5
- import { transferProps } from '../../utils/transferProps';
3
+ import { withGlobalProps } from '../../providers/globalProps';
4
+ import { classNames } from '../../helpers/classNames/classNames';
5
+ import { transferProps } from '../../helpers/transferProps';
6
6
  import { getJustifyClassName } from './_helpers/getJustifyClassName';
7
7
  import styles from './ModalFooter.module.scss';
8
8
 
@@ -1,3 +1,6 @@
1
+ // 1. Intentionally do not provide a fallback value for the border color. Setting a fallback value (e.g. `transparent`)
2
+ // will result in the border being skewed at both ends.
3
+
1
4
  @use "settings";
2
5
  @use "theme";
3
6
 
@@ -9,10 +12,11 @@
9
12
  gap: theme.$footer-gap;
10
13
  align-items: center;
11
14
  padding: theme.$padding-y theme.$padding-x;
12
- border-top: theme.$separator-width solid theme.$separator-color;
15
+ border: settings.$border-width solid var(--rui-local-border-color); // 1.
16
+ border-top: theme.$separator-width solid var(--rui-local-border-color, #{theme.$separator-color});
13
17
  border-bottom-right-radius: settings.$border-radius;
14
18
  border-bottom-left-radius: settings.$border-radius;
15
- background: theme.$footer-background;
19
+ background: var(--rui-local-background-color, #{theme.$footer-background});
16
20
  }
17
21
 
18
22
  .isRootJustifiedToStart {
@@ -1,8 +1,8 @@
1
1
  import PropTypes from 'prop-types';
2
2
  import React from 'react';
3
- import { withGlobalProps } from '../../provider';
4
- import { classNames } from '../../utils/classNames';
5
- import { transferProps } from '../../utils/transferProps';
3
+ import { withGlobalProps } from '../../providers/globalProps';
4
+ import { classNames } from '../../helpers/classNames/classNames';
5
+ import { transferProps } from '../../helpers/transferProps';
6
6
  import { getJustifyClassName } from './_helpers/getJustifyClassName';
7
7
  import styles from './ModalHeader.module.scss';
8
8
 
@@ -1,3 +1,7 @@
1
+ // 1. Intentionally do not provide a fallback value for the border color. Setting a fallback value (e.g. `transparent`)
2
+ // will result in the border being skewed at both ends.
3
+
4
+ @use "settings";
1
5
  @use "theme";
2
6
 
3
7
  @layer components.modal {
@@ -7,7 +11,10 @@
7
11
  gap: theme.$header-gap;
8
12
  align-items: baseline;
9
13
  padding: theme.$padding-y theme.$padding-x;
10
- border-bottom: theme.$separator-width solid theme.$separator-color;
14
+ border: settings.$border-width solid var(--rui-local-border-color); // 1.
15
+ border-bottom: theme.$separator-width solid var(--rui-local-border-color, #{theme.$separator-color});
16
+ border-top-left-radius: settings.$border-radius;
17
+ border-top-right-radius: settings.$border-radius;
11
18
  }
12
19
 
13
20
  .isRootJustifiedToStart {
@@ -1,7 +1,7 @@
1
1
  import PropTypes from 'prop-types';
2
2
  import React from 'react';
3
- import { withGlobalProps } from '../../provider';
4
- import { transferProps } from '../../utils/transferProps';
3
+ import { withGlobalProps } from '../../providers/globalProps';
4
+ import { transferProps } from '../../helpers/transferProps';
5
5
  import styles from './ModalTitle.module.scss';
6
6
 
7
7
  export const ModalTitle = ({