@react-ui-org/react-ui 0.51.0 → 0.52.0

Sign up to get free protection for your applications and to get access to all the features.
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);