@react-ui-org/react-ui 0.51.0 → 0.52.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 (39) hide show
  1. package/dist/lib.development.js +140 -32
  2. package/dist/lib.js +1 -1
  3. package/package.json +1 -1
  4. package/src/lib/components/Button/Button.jsx +17 -9
  5. package/src/lib/components/Button/_base.scss +21 -12
  6. package/src/lib/components/Button/_priorities.scss +1 -18
  7. package/src/lib/components/Button/_theme.scss +0 -10
  8. package/src/lib/components/ButtonGroup/ButtonGroup.jsx +5 -3
  9. package/src/lib/components/ButtonGroup/ButtonGroup.scss +26 -1
  10. package/src/lib/components/ButtonGroup/README.mdx +11 -1
  11. package/src/lib/components/ButtonGroup/_theme.scss +13 -0
  12. package/src/lib/components/FormLayout/README.mdx +5 -0
  13. package/src/lib/components/InputGroup/InputGroup.jsx +170 -0
  14. package/src/lib/components/InputGroup/InputGroup.scss +92 -0
  15. package/src/lib/components/InputGroup/InputGroupContext.js +3 -0
  16. package/src/lib/components/InputGroup/README.mdx +278 -0
  17. package/src/lib/components/InputGroup/_theme.scss +2 -0
  18. package/src/lib/components/InputGroup/index.js +2 -0
  19. package/src/lib/components/Modal/Modal.jsx +58 -97
  20. package/src/lib/components/Modal/README.mdx +288 -15
  21. package/src/lib/components/Modal/_helpers/getPositionClassName.js +7 -0
  22. package/src/lib/components/Modal/_helpers/getSizeClassName.js +19 -0
  23. package/src/lib/components/Modal/_hooks/useModalFocus.js +126 -0
  24. package/src/lib/components/Modal/_hooks/useModalScrollPrevention.js +35 -0
  25. package/src/lib/components/Modal/_settings.scss +1 -1
  26. package/src/lib/components/Radio/README.mdx +9 -1
  27. package/src/lib/components/Radio/Radio.jsx +39 -31
  28. package/src/lib/components/Radio/Radio.scss +11 -1
  29. package/src/lib/components/SelectField/SelectField.jsx +21 -8
  30. package/src/lib/components/SelectField/SelectField.scss +5 -0
  31. package/src/lib/components/TextField/TextField.jsx +21 -8
  32. package/src/lib/components/TextField/TextField.scss +5 -0
  33. package/src/lib/index.js +1 -0
  34. package/src/lib/styles/theme/_borders.scss +2 -1
  35. package/src/lib/styles/tools/form-fields/_box-field-elements.scss +19 -2
  36. package/src/lib/styles/tools/form-fields/_box-field-sizes.scss +11 -8
  37. package/src/lib/styles/tools/form-fields/_foundation.scss +7 -0
  38. package/src/lib/theme.scss +23 -11
  39. /package/src/lib/components/{Button/helpers → _helpers}/getRootPriorityClassName.js +0 -0
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@react-ui-org/react-ui",
3
3
  "description": "React UI is a themeable UI library for React apps.",
4
- "version": "0.51.0",
4
+ "version": "0.52.0",
5
5
  "keywords": [
6
6
  "react",
7
7
  "ui",
@@ -7,8 +7,9 @@ import { getRootSizeClassName } from '../_helpers/getRootSizeClassName';
7
7
  import { resolveContextOrProp } from '../_helpers/resolveContextOrProp';
8
8
  import { transferProps } from '../_helpers/transferProps';
9
9
  import { ButtonGroupContext } from '../ButtonGroup';
10
+ import { InputGroupContext } from '../InputGroup/InputGroupContext';
11
+ import getRootPriorityClassName from '../_helpers/getRootPriorityClassName';
10
12
  import getRootLabelVisibilityClassName from './helpers/getRootLabelVisibilityClassName';
11
- import getRootPriorityClassName from './helpers/getRootPriorityClassName';
12
13
  import styles from './Button.scss';
13
14
 
14
15
  export const Button = React.forwardRef((props, ref) => {
@@ -28,8 +29,14 @@ export const Button = React.forwardRef((props, ref) => {
28
29
  color,
29
30
  ...restProps
30
31
  } = props;
32
+ const buttonGroupContext = useContext(ButtonGroupContext);
33
+ const inputGroupContext = useContext(InputGroupContext);
31
34
 
32
- const context = useContext(ButtonGroupContext);
35
+ if (buttonGroupContext && inputGroupContext) {
36
+ throw new Error('Button cannot be placed both in `ButtonGroup` and `InputGroup`.');
37
+ }
38
+
39
+ const primaryContext = buttonGroupContext ?? inputGroupContext;
33
40
 
34
41
  return (
35
42
  /* No worries, `type` is always assigned correctly through props. */
@@ -39,20 +46,21 @@ export const Button = React.forwardRef((props, ref) => {
39
46
  className={classNames(
40
47
  styles.root,
41
48
  getRootPriorityClassName(
42
- resolveContextOrProp(context && context.priority, priority),
49
+ resolveContextOrProp(buttonGroupContext && buttonGroupContext.priority, priority),
43
50
  styles,
44
51
  ),
45
52
  getRootColorClassName(color, styles),
46
53
  getRootSizeClassName(
47
- resolveContextOrProp(context && context.size, size),
54
+ resolveContextOrProp(primaryContext && primaryContext.size, size),
48
55
  styles,
49
56
  ),
50
57
  getRootLabelVisibilityClassName(labelVisibility, styles),
51
- resolveContextOrProp(context && context.block, block) && styles.isRootBlock,
52
- context && styles.isRootGrouped,
58
+ resolveContextOrProp(buttonGroupContext && buttonGroupContext.block, block) && styles.isRootBlock,
59
+ buttonGroupContext && styles.isRootInButtonGroup,
60
+ inputGroupContext && styles.isRootInInputGroup,
53
61
  feedbackIcon && styles.hasRootFeedback,
54
62
  )}
55
- disabled={resolveContextOrProp(context && context.disabled, disabled) || !!feedbackIcon}
63
+ disabled={resolveContextOrProp(primaryContext && primaryContext.disabled, disabled) || !!feedbackIcon}
56
64
  id={id}
57
65
  ref={ref}
58
66
  >
@@ -171,8 +179,8 @@ Button.propTypes = {
171
179
  /**
172
180
  * Size of the button.
173
181
  *
174
- * Ignored if the component is rendered within `ButtonGroup` component
175
- * as the value is inherited in such case.
182
+ * Ignored if the component is rendered within `ButtonGroup` or `InputGroup` component as the value is inherited in
183
+ * such case.
176
184
  */
177
185
  size: PropTypes.oneOf(['small', 'medium', 'large']),
178
186
  /**
@@ -1,3 +1,6 @@
1
+ // 1. ButtonGroup gap is implemented using the `margin` property so the buttons can overlap and reduce duplicate
2
+ // borders.
3
+
1
4
  @use "sass:map";
2
5
  @use "../../styles/tools/breakpoint";
3
6
  @use "settings";
@@ -76,28 +79,34 @@
76
79
  color: transparent;
77
80
  }
78
81
 
79
- .isRootGrouped {
82
+ .isRootInButtonGroup,
83
+ .isRootInInputGroup {
80
84
  z-index: map.get(settings.$group-z-indexes, button);
81
85
 
82
86
  &:not(:first-child) {
83
- margin-left: var(--rui-local-gap);
84
- border-top-left-radius: 0;
85
- border-bottom-left-radius: 0;
87
+ border-start-start-radius: var(--rui-local-inner-border-radius);
88
+ border-end-start-radius: var(--rui-local-inner-border-radius);
86
89
  }
87
90
 
88
91
  &:not(:last-child) {
89
- border-top-right-radius: 0;
90
- border-bottom-right-radius: 0;
92
+ border-start-end-radius: var(--rui-local-inner-border-radius);
93
+ border-end-end-radius: var(--rui-local-inner-border-radius);
91
94
  }
95
+ }
92
96
 
93
- &:focus,
94
- &:not(:disabled):hover {
95
- z-index: map.get(settings.$group-z-indexes, button-hover);
96
- }
97
+ .isRootInButtonGroup:not(:first-child) {
98
+ margin-inline-start: var(--rui-local-gap); // 1.
99
+ }
100
+
101
+ .isRootInButtonGroup:focus,
102
+ .isRootInButtonGroup:not(:disabled):hover {
103
+ z-index: map.get(settings.$group-z-indexes, button-hover);
97
104
  }
98
105
 
99
- .isRootGrouped .startCorner,
100
- .isRootGrouped .endCorner {
106
+ .isRootInButtonGroup .startCorner,
107
+ .isRootInInputGroup .startCorner,
108
+ .isRootInButtonGroup .endCorner,
109
+ .isRootInInputGroup .endCorner {
101
110
  z-index: map.get(settings.$group-z-indexes, button-overflowing-elements);
102
111
  }
103
112
 
@@ -135,8 +135,7 @@
135
135
  @include tools.button-color(flat, dark);
136
136
  }
137
137
 
138
- .isRootPriorityFilled.isRootGrouped:not(:first-child)::before,
139
- .isRootPriorityFlat.isRootGrouped:not(:first-child)::before {
138
+ .isRootInButtonGroup:not(:first-child)::before {
140
139
  content: "";
141
140
  position: absolute;
142
141
  top: calc(-1 * #{theme.$border-width});
@@ -146,19 +145,3 @@
146
145
  border-left: var(--rui-local-separator-width) solid var(--rui-local-separator-color);
147
146
  transform: translateX(calc(-0.5 * var(--rui-local-gap) - 50%));
148
147
  }
149
-
150
- .isRootPriorityFilled.isRootGrouped:not(:first-child) {
151
- --rui-local-gap: #{theme.$group-filled-gap};
152
- --rui-local-separator-width: #{theme.$group-filled-separator-width};
153
- --rui-local-separator-color: #{theme.$group-filled-separator-color};
154
- }
155
-
156
- .isRootPriorityFlat.isRootGrouped:not(:first-child) {
157
- --rui-local-gap: #{theme.$group-flat-gap};
158
- --rui-local-separator-width: #{theme.$group-flat-separator-width};
159
- --rui-local-separator-color: #{theme.$group-flat-separator-color};
160
- }
161
-
162
- .isRootPriorityOutline.isRootGrouped:not(:first-child) {
163
- --rui-local-gap: #{theme.$group-outline-gap};
164
- }
@@ -12,16 +12,6 @@ $disabled-cursor: var(--rui-Button--disabled__cursor);
12
12
  $feedback-opacity: var(--rui-Button--feedback__opacity);
13
13
  $feedback-cursor: var(--rui-Button--feedback__cursor);
14
14
 
15
- $group-filled-gap: var(--rui-ButtonGroup--filled__gap);
16
- $group-filled-separator-width: var(--rui-ButtonGroup--filled__separator__width);
17
- $group-filled-separator-color: var(--rui-ButtonGroup--filled__separator__color);
18
-
19
- $group-flat-gap: var(--rui-ButtonGroup--flat__gap);
20
- $group-flat-separator-width: var(--rui-ButtonGroup--flat__separator__width);
21
- $group-flat-separator-color: var(--rui-ButtonGroup--flat__separator__color);
22
-
23
- $group-outline-gap: var(--rui-ButtonGroup--outline__gap);
24
-
25
15
  $sizes: (
26
16
  small: (
27
17
  height: var(--rui-Button--small__height),
@@ -2,6 +2,7 @@ import PropTypes from 'prop-types';
2
2
  import React from 'react';
3
3
  import { withGlobalProps } from '../../provider';
4
4
  import { classNames } from '../../utils/classNames';
5
+ import getRootPriorityClassName from '../_helpers/getRootPriorityClassName';
5
6
  import { isChildrenEmpty } from '../_helpers/isChildrenEmpty';
6
7
  import { transferProps } from '../_helpers/transferProps';
7
8
  import styles from './ButtonGroup.scss';
@@ -20,13 +21,14 @@ export const ButtonGroup = ({
20
21
  }
21
22
 
22
23
  return (
23
- <div
24
+ <fieldset
24
25
  {...transferProps(restProps)}
25
26
  className={classNames(
26
27
  styles.root,
27
28
  block && styles.isRootBlock,
29
+ getRootPriorityClassName(priority, styles),
28
30
  )}
29
- role="group"
31
+ disabled={disabled}
30
32
  >
31
33
  <ButtonGroupContext.Provider
32
34
  value={{
@@ -38,7 +40,7 @@ export const ButtonGroup = ({
38
40
  >
39
41
  {children}
40
42
  </ButtonGroupContext.Provider>
41
- </div>
43
+ </fieldset>
42
44
  );
43
45
  };
44
46
 
@@ -1,5 +1,30 @@
1
+ // 1. ButtonGroup gap is implemented using the `margin` property on buttons so the buttons can overlap and reduce
2
+ // duplicate borders.
3
+
4
+ @use "theme";
5
+
1
6
  .root {
2
- display: inline-flex;
7
+ --rui-local-inner-border-radius: #{theme.$inner-border-radius};
8
+
9
+ display: inline-flex; // 1.
10
+ }
11
+
12
+ .isRootPriorityFilled {
13
+ --rui-local-gap: #{theme.$filled-gap};
14
+ --rui-local-separator-width: #{theme.$filled-separator-width};
15
+ --rui-local-separator-color: #{theme.$filled-separator-color};
16
+ }
17
+
18
+ .isRootPriorityOutline {
19
+ --rui-local-gap: #{theme.$outline-gap};
20
+ --rui-local-separator-width: #{theme.$outline-separator-width};
21
+ --rui-local-separator-color: #{theme.$outline-separator-color};
22
+ }
23
+
24
+ .isRootPriorityFlat {
25
+ --rui-local-gap: #{theme.$flat-gap};
26
+ --rui-local-separator-width: #{theme.$flat-separator-width};
27
+ --rui-local-separator-color: #{theme.$flat-separator-color};
3
28
  }
4
29
 
5
30
  .isRootBlock {
@@ -59,6 +59,11 @@ See [API](#api) for all available options.
59
59
  the [SelectField](/components/select-field) or
60
60
  [Radio](/components/radio) components.
61
61
 
62
+ - In the background, ButtonGroup uses the [`fieldset`][fieldset] element. Not
63
+ only it improves the [accessibility] of the group, it also allows you to make
64
+ use of its built-in features like disabling all nested inputs or pairing the
65
+ group with a form outside. Consult [the MDN docs][fieldset] to learn more.
66
+
62
67
  - Be careful with using `startCorner` and `endCorner` options for grouped
63
68
  buttons. Overflowing elements may cause undesired interaction problems.
64
69
 
@@ -266,13 +271,18 @@ its accessibility.
266
271
 
267
272
  | Custom Property | Description |
268
273
  |--------------------------------------------------------------------|------------------------------------------------|
274
+ | `--rui-ButtonGroup__inner-border-radius` | Inner border radius of buttons |
269
275
  | `--rui-ButtonGroup--filled__gap` | Gap between `filled` buttons |
270
276
  | `--rui-ButtonGroup--filled__separator__width` | Separator width for `filled` buttons |
271
277
  | `--rui-ButtonGroup--filled__separator__color` | Separator color for `filled` buttons |
278
+ | `--rui-ButtonGroup--outline__gap` | Gap between `outline` buttons |
279
+ | `--rui-ButtonGroup--outline__separator__width` | Separator width for `outline` buttons |
280
+ | `--rui-ButtonGroup--outline__separator__color` | Separator color for `outline` buttons |
272
281
  | `--rui-ButtonGroup--flat__gap` | Gap between `flat` buttons |
273
282
  | `--rui-ButtonGroup--flat__separator__width` | Separator width for `flat` buttons |
274
283
  | `--rui-ButtonGroup--flat__separator__color` | Separator color for `flat` buttons |
275
- | `--rui-ButtonGroup--outline__gap` | Gap between `outline` buttons |
276
284
 
285
+ [fieldset]: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/fieldset
286
+ [accessibility]: https://www.w3.org/WAI/tutorials/forms/grouping/
277
287
  [React synthetic events]: https://reactjs.org/docs/events.html
278
288
  [div]: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/div#attributes
@@ -0,0 +1,13 @@
1
+ $inner-border-radius: var(--rui-ButtonGroup__inner-border-radius);
2
+
3
+ $filled-gap: var(--rui-ButtonGroup--filled__gap);
4
+ $filled-separator-width: var(--rui-ButtonGroup--filled__separator__width);
5
+ $filled-separator-color: var(--rui-ButtonGroup--filled__separator__color);
6
+
7
+ $outline-gap: var(--rui-ButtonGroup--outline__gap);
8
+ $outline-separator-width: var(--rui-ButtonGroup--outline__separator__width);
9
+ $outline-separator-color: var(--rui-ButtonGroup--outline__separator__color);
10
+
11
+ $flat-gap: var(--rui-ButtonGroup--flat__gap);
12
+ $flat-separator-width: var(--rui-ButtonGroup--flat__separator__width);
13
+ $flat-separator-color: var(--rui-ButtonGroup--flat__separator__color);
@@ -27,6 +27,7 @@ import {
27
27
  ToolbarItem,
28
28
  FormLayout,
29
29
  FormLayoutCustomField,
30
+ InputGroup,
30
31
  } from '../..'
31
32
 
32
33
  ## Basic Usage
@@ -441,6 +442,10 @@ This is a demo of all components supported by FormLayout.
441
442
  options={options}
442
443
  value={fruit}
443
444
  />
445
+ <InputGroup label="Promo code">
446
+ <TextField label="Code" />
447
+ <Button label="Apply" color="secondary" priority="outline" />
448
+ </InputGroup>
444
449
  </FormLayout>
445
450
  </div>
446
451
  )
@@ -0,0 +1,170 @@
1
+ import PropTypes from 'prop-types';
2
+ import React, { useContext } from 'react';
3
+ import { Text } from '../Text';
4
+ import { withGlobalProps } from '../../provider';
5
+ import { classNames } from '../../utils/classNames';
6
+ import { getRootSizeClassName } from '../_helpers/getRootSizeClassName';
7
+ import { getRootValidationStateClassName } from '../_helpers/getRootValidationStateClassName';
8
+ import { isChildrenEmpty } from '../_helpers/isChildrenEmpty';
9
+ import { resolveContextOrProp } from '../_helpers/resolveContextOrProp';
10
+ import { transferProps } from '../_helpers/transferProps';
11
+ import { FormLayoutContext } from '../FormLayout';
12
+ import { InputGroupContext } from './InputGroupContext';
13
+ import styles from './InputGroup.scss';
14
+
15
+ export const InputGroup = ({
16
+ children,
17
+ disabled,
18
+ id,
19
+ isLabelVisible,
20
+ label,
21
+ layout,
22
+ size,
23
+ validationTexts,
24
+ ...restProps
25
+ }) => {
26
+ const formLayoutContext = useContext(FormLayoutContext);
27
+
28
+ if (isChildrenEmpty(children)) {
29
+ return null;
30
+ }
31
+
32
+ const validationState = children.reduce(
33
+ (state, child) => {
34
+ if (state === 'invalid' || (state === 'warning' && child.props.validationState === 'valid')) {
35
+ return state;
36
+ }
37
+ return child.props.validationState ?? state;
38
+ },
39
+ null,
40
+ );
41
+
42
+ return (
43
+ <fieldset
44
+ {...transferProps(restProps)}
45
+ id={id}
46
+ className={classNames(
47
+ styles.root,
48
+ formLayoutContext && styles.isRootInFormLayout,
49
+ resolveContextOrProp(formLayoutContext && formLayoutContext.layout, layout) === 'horizontal'
50
+ ? styles.isRootLayoutHorizontal
51
+ : styles.isRootLayoutVertical,
52
+ disabled && styles.isRootDisabled,
53
+ getRootSizeClassName(size, styles),
54
+ getRootValidationStateClassName(validationState, styles),
55
+ )}
56
+ disabled={disabled}
57
+ >
58
+ <legend
59
+ className={styles.legend}
60
+ id={id && `${id}__label`}
61
+ >
62
+ {label}
63
+ </legend>
64
+ <div
65
+ aria-hidden
66
+ className={classNames(
67
+ styles.label,
68
+ !isLabelVisible && styles.isLabelHidden,
69
+ )}
70
+ id={id && `${id}__displayLabel`}
71
+ >
72
+ {label}
73
+ </div>
74
+ <div className={styles.field}>
75
+ <div
76
+ className={styles.inputGroup}
77
+ id={id && `${id}__group`}
78
+ >
79
+ <InputGroupContext.Provider
80
+ value={{
81
+ disabled,
82
+ layout,
83
+ size,
84
+ }}
85
+ >
86
+ {children}
87
+ </InputGroupContext.Provider>
88
+ </div>
89
+ {validationTexts && (
90
+ <ul
91
+ className={styles.validationText}
92
+ id={id && `${id}__validationTexts`}
93
+ >
94
+ {validationTexts.map((validationText) => (
95
+ <li key={validationText}>
96
+ <Text blockLevel>
97
+ {validationText}
98
+ </Text>
99
+ </li>
100
+ ))}
101
+ </ul>
102
+ )}
103
+ </div>
104
+ </fieldset>
105
+ );
106
+ };
107
+
108
+ InputGroup.defaultProps = {
109
+ children: null,
110
+ disabled: false,
111
+ id: undefined,
112
+ isLabelVisible: true,
113
+ layout: 'vertical',
114
+ size: 'medium',
115
+ validationTexts: null,
116
+ };
117
+
118
+ InputGroup.propTypes = {
119
+ /**
120
+ * Supported elements to be grouped:
121
+ * * `Button`
122
+ * * `SelectField`
123
+ * * `TextField`
124
+ *
125
+ * If none are provided nothing is rendered.
126
+ */
127
+ children: PropTypes.node,
128
+ /**
129
+ * If `true`, the whole input group with all nested inputs and buttons will be disabled.
130
+ */
131
+ disabled: PropTypes.bool,
132
+ /**
133
+ * ID of the root HTML element.
134
+ *
135
+ * Also serves as base for ids of nested elements:
136
+ * * `<ID>__label`
137
+ * * `<ID>__displayLabel`
138
+ * * `<ID>__group`
139
+ * * `<ID>__validationTexts`
140
+ */
141
+ id: PropTypes.string,
142
+ /**
143
+ * If `false`, the label will be visually hidden (but remains accessible by assistive
144
+ * technologies).
145
+ */
146
+ isLabelVisible: PropTypes.bool,
147
+ /**
148
+ * Input group label.
149
+ */
150
+ label: PropTypes.string.isRequired,
151
+ /**
152
+ * Layout of the group.
153
+ *
154
+ * Ignored if the component is rendered within `FormLayout` component
155
+ * as the value is inherited in such case.
156
+ */
157
+ layout: PropTypes.oneOf(['horizontal', 'vertical']),
158
+ /**
159
+ * Size of the `children` elements.
160
+ */
161
+ size: PropTypes.oneOf(['small', 'medium', 'large']),
162
+ /**
163
+ * An array of validation messages to be displayed.
164
+ */
165
+ validationTexts: PropTypes.node,
166
+ };
167
+
168
+ export const InputGroupWithGlobalProps = withGlobalProps(InputGroup, 'InputGroup');
169
+
170
+ export default InputGroupWithGlobalProps;
@@ -0,0 +1,92 @@
1
+ // 1. The class name is intentionally singular because it's targeted by other mixins too.
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.
5
+ // https://developer.mozilla.org/en-US/docs/Web/HTML/Element/fieldset#styling_with_css
6
+
7
+ @use "../../styles/tools/form-fields/box-field-elements";
8
+ @use "../../styles/tools/form-fields/box-field-layout";
9
+ @use "../../styles/tools/form-fields/box-field-sizes";
10
+ @use "../../styles/tools/form-fields/foundation";
11
+ @use "../../styles/tools/form-fields/variants";
12
+ @use "../../styles/tools/accessibility";
13
+ @use "../../styles/tools/reset";
14
+ @use "theme";
15
+
16
+ .root {
17
+ @include foundation.root();
18
+ @include foundation.fieldset();
19
+ }
20
+
21
+ // 4.
22
+ .legend {
23
+ @include accessibility.hide-text();
24
+ }
25
+
26
+ // 4.
27
+ .label {
28
+ @include foundation.label();
29
+ }
30
+
31
+ .inputGroup {
32
+ --rui-local-inner-border-radius: #{theme.$inner-border-radius};
33
+
34
+ display: flex; // 2.
35
+ gap: theme.$gap;
36
+ }
37
+
38
+ // 1.
39
+ .validationText {
40
+ @include reset.list();
41
+ @include foundation.help-text();
42
+ }
43
+
44
+ // States
45
+ .isRootStateInvalid {
46
+ @include variants.validation(invalid);
47
+ }
48
+
49
+ .isRootStateValid {
50
+ @include variants.validation(valid);
51
+ }
52
+
53
+ .isRootStateWarning {
54
+ @include variants.validation(warning);
55
+ }
56
+
57
+ // Invisible label
58
+ .isLabelHidden {
59
+ @include accessibility.hide-text();
60
+ }
61
+
62
+ // Layouts
63
+ .isRootLayoutVertical,
64
+ .isRootLayoutHorizontal {
65
+ @include box-field-layout.vertical();
66
+ }
67
+
68
+ .isRootLayoutVertical .field,
69
+ .isRootLayoutHorizontal .field {
70
+ max-width: none; // 3.
71
+ }
72
+
73
+ .isRootLayoutHorizontal {
74
+ @include box-field-layout.horizontal();
75
+ }
76
+
77
+ .isRootInFormLayout {
78
+ @include box-field-layout.in-form-layout();
79
+ }
80
+
81
+ // Sizes
82
+ .isRootSizeSmall {
83
+ @include box-field-sizes.size(small, $has-input: false);
84
+ }
85
+
86
+ .isRootSizeMedium {
87
+ @include box-field-sizes.size(medium, $has-input: false);
88
+ }
89
+
90
+ .isRootSizeLarge {
91
+ @include box-field-sizes.size(large, $has-input: false);
92
+ }
@@ -0,0 +1,3 @@
1
+ import React from 'react';
2
+
3
+ export const InputGroupContext = React.createContext(null);