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

Sign up to get free protection for your applications and to get access to all the features.
Files changed (82) hide show
  1. package/dist/lib.development.js +157 -49
  2. package/dist/lib.js +1 -1
  3. package/package.json +1 -1
  4. package/src/lib/components/Alert/Alert.jsx +1 -3
  5. package/src/lib/components/Alert/Alert.scss +1 -9
  6. package/src/lib/components/Alert/README.mdx +0 -20
  7. package/src/lib/components/Alert/_settings.scss +1 -1
  8. package/src/lib/components/Alert/_theme.scss +0 -10
  9. package/src/lib/components/Badge/Badge.jsx +1 -3
  10. package/src/lib/components/Badge/Badge.scss +25 -44
  11. package/src/lib/components/Badge/README.mdx +6 -14
  12. package/src/lib/components/Button/Button.jsx +20 -10
  13. package/src/lib/components/Button/README.mdx +8 -3
  14. package/src/lib/components/Button/_base.scss +21 -12
  15. package/src/lib/components/Button/_priorities.scss +13 -18
  16. package/src/lib/components/Button/_settings.scss +1 -1
  17. package/src/lib/components/Button/_theme.scss +0 -10
  18. package/src/lib/components/ButtonGroup/ButtonGroup.jsx +5 -3
  19. package/src/lib/components/ButtonGroup/ButtonGroup.scss +26 -1
  20. package/src/lib/components/ButtonGroup/README.mdx +85 -59
  21. package/src/lib/components/ButtonGroup/_theme.scss +13 -0
  22. package/src/lib/components/Card/Card.jsx +1 -3
  23. package/src/lib/components/Card/Card.scss +0 -9
  24. package/src/lib/components/Card/README.mdx +0 -16
  25. package/src/lib/components/Card/_theme.scss +0 -10
  26. package/src/lib/components/FormLayout/README.mdx +22 -8
  27. package/src/lib/components/Grid/_helpers/generateResponsiveCustomProperties.js +1 -1
  28. package/src/lib/components/InputGroup/InputGroup.jsx +170 -0
  29. package/src/lib/components/InputGroup/InputGroup.scss +92 -0
  30. package/src/lib/components/InputGroup/InputGroupContext.js +3 -0
  31. package/src/lib/components/InputGroup/README.mdx +278 -0
  32. package/src/lib/components/InputGroup/_theme.scss +2 -0
  33. package/src/lib/components/InputGroup/index.js +2 -0
  34. package/src/lib/components/Modal/Modal.jsx +58 -97
  35. package/src/lib/components/Modal/ModalCloseButton.scss +2 -2
  36. package/src/lib/components/Modal/README.mdx +392 -128
  37. package/src/lib/components/Modal/_helpers/getPositionClassName.js +7 -0
  38. package/src/lib/components/Modal/_helpers/getSizeClassName.js +19 -0
  39. package/src/lib/components/Modal/_hooks/useModalFocus.js +126 -0
  40. package/src/lib/components/Modal/_hooks/useModalScrollPrevention.js +35 -0
  41. package/src/lib/components/Modal/_settings.scss +2 -2
  42. package/src/lib/components/Popover/README.mdx +7 -4
  43. package/src/lib/components/Radio/README.mdx +9 -1
  44. package/src/lib/components/Radio/Radio.jsx +39 -31
  45. package/src/lib/components/Radio/Radio.scss +11 -1
  46. package/src/lib/components/ScrollView/README.mdx +2 -2
  47. package/src/lib/components/SelectField/SelectField.jsx +21 -8
  48. package/src/lib/components/SelectField/SelectField.scss +5 -0
  49. package/src/lib/components/Table/_components/TableCell.scss +6 -5
  50. package/src/lib/components/Table/_components/TableHeaderCell/TableHeaderCell.jsx +8 -5
  51. package/src/lib/components/Table/_settings.scss +5 -6
  52. package/src/lib/components/Text/README.mdx +14 -8
  53. package/src/lib/components/TextField/TextField.jsx +21 -8
  54. package/src/lib/components/TextField/TextField.scss +5 -0
  55. package/src/lib/components/TextLink/README.mdx +8 -6
  56. package/src/lib/components/TextLink/TextLink.scss +5 -0
  57. package/src/lib/components/TextLink/_theme.scss +2 -0
  58. package/src/lib/components/Toolbar/README.mdx +19 -11
  59. package/src/lib/components/_helpers/getRootColorClassName.js +4 -0
  60. package/src/lib/index.js +1 -0
  61. package/src/lib/styles/elements/_code.scss +1 -3
  62. package/src/lib/styles/elements/_page.scss +1 -0
  63. package/src/lib/styles/elements/_rulers.scss +1 -3
  64. package/src/lib/styles/elements/_small.scss +1 -1
  65. package/src/lib/styles/settings/_form-fields.scss +1 -1
  66. package/src/lib/styles/settings/_utilities.scss +46 -14
  67. package/src/lib/styles/theme/_accessibility.scss +4 -4
  68. package/src/lib/styles/theme/_borders.scss +3 -2
  69. package/src/lib/styles/theme/_code.scss +2 -2
  70. package/src/lib/styles/theme/_links.scss +6 -4
  71. package/src/lib/styles/theme/_lists.scss +1 -1
  72. package/src/lib/styles/theme/_page.scss +2 -2
  73. package/src/lib/styles/theme/_spacing.scss +11 -11
  74. package/src/lib/styles/theme/_typography.scss +19 -18
  75. package/src/lib/styles/theme-constants/_colors.scss +23 -23
  76. package/src/lib/styles/tools/_spacing.scss +1 -1
  77. package/src/lib/styles/tools/form-fields/_box-field-elements.scss +19 -2
  78. package/src/lib/styles/tools/form-fields/_box-field-sizes.scss +11 -8
  79. package/src/lib/styles/tools/form-fields/_foundation.scss +7 -0
  80. package/src/lib/theme.scss +650 -567
  81. package/src/lib/styles/theme/_colors.scss +0 -65
  82. /package/src/lib/components/{Button/helpers → _helpers}/getRootPriorityClassName.js +0 -0
@@ -43,6 +43,13 @@ See [API](#api) for all available options.
43
43
  - Use button group to group **related actions** that a user can take. Buttons
44
44
  should not be grouped just to save space on the screen.
45
45
 
46
+ - **Mixing multiple button priorities** and some other properties within a
47
+ button group is [not allowed](#shared-properties). The priority can only be
48
+ set for all buttons in the group at once.
49
+
50
+ - In most use cases, **secondary action color** is probably the best option for
51
+ buttons in a group as it works good with the colors of the selected state.
52
+
46
53
  - Use **short labels or icons** so the buttons can fit small screens.
47
54
 
48
55
  - For toggling between on/off states, use rather the
@@ -52,17 +59,28 @@ See [API](#api) for all available options.
52
59
  the [SelectField](/components/select-field) or
53
60
  [Radio](/components/radio) components.
54
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
+
55
67
  - Be careful with using `startCorner` and `endCorner` options for grouped
56
68
  buttons. Overflowing elements may cause undesired interaction problems.
57
69
 
58
70
  ### Shared Properties
59
71
 
60
72
  You can set the following properties directly on ButtonGroup to be shared for
61
- all buttons inside the group: size, priority, disabled state, and block width.
73
+ all buttons inside the group:
74
+
75
+ - `size`,
76
+ - `priority`,
77
+ - `disabled` state,
78
+ - and `block` width.
79
+
62
80
  These properties are then passed over to individual buttons. At the same time,
63
- they **cannot be overridden** on the buttons' level. While technically possible,
64
- from the design point of view it's undesirable to group buttons of totally
65
- different types or sizes.
81
+ they **cannot be overridden** on the buttons' level. While (in theory)
82
+ technically possible, from the design point of view it's undesirable to group
83
+ buttons of totally different types or sizes.
66
84
 
67
85
  ## Priorities
68
86
 
@@ -73,6 +91,9 @@ priorities of the [Button](/components/button) component:
73
91
  2. outline
74
92
  3. flat
75
93
 
94
+ 👉 To avoid undesired combinations, the visual priority of the button group
95
+ **cannot be overridden** on the Button level.
96
+
76
97
  ### Filled
77
98
 
78
99
  The default, high-emphasis priority should be used for primary actions of your
@@ -80,9 +101,9 @@ app.
80
101
 
81
102
  <Playground>
82
103
  <ButtonGroup>
83
- <Button label="Week" />
84
- <Button label="Month" />
85
- <Button label="Year" />
104
+ <Button color="secondary" label="Week" />
105
+ <Button color="secondary" label="Month" />
106
+ <Button color="secondary" label="Year" />
86
107
  </ButtonGroup>
87
108
  </Playground>
88
109
 
@@ -93,9 +114,9 @@ in your app.
93
114
 
94
115
  <Playground>
95
116
  <ButtonGroup priority="outline">
96
- <Button label="Week" />
97
- <Button label="Month" />
98
- <Button label="Year" />
117
+ <Button color="secondary" label="Week" />
118
+ <Button color="secondary" label="Month" />
119
+ <Button color="secondary" label="Year" />
99
120
  </ButtonGroup>
100
121
  </Playground>
101
122
 
@@ -106,9 +127,9 @@ the content.
106
127
 
107
128
  <Playground>
108
129
  <ButtonGroup priority="flat">
109
- <Button label="Week" />
110
- <Button label="Month" />
111
- <Button label="Year" />
130
+ <Button color="secondary" label="Week" />
131
+ <Button color="secondary" label="Month" />
132
+ <Button color="secondary" label="Year" />
112
133
  </ButtonGroup>
113
134
  </Playground>
114
135
 
@@ -119,19 +140,19 @@ medium, and large.
119
140
 
120
141
  <Playground>
121
142
  <ButtonGroup size="small">
122
- <Button label="Week" />
123
- <Button label="Month" />
124
- <Button label="Year" />
143
+ <Button color="secondary" label="Week" />
144
+ <Button color="secondary" label="Month" />
145
+ <Button color="secondary" label="Year" />
125
146
  </ButtonGroup>
126
147
  <ButtonGroup>
127
- <Button label="Week" />
128
- <Button label="Month" />
129
- <Button label="Year" />
148
+ <Button color="secondary" label="Week" />
149
+ <Button color="secondary" label="Month" />
150
+ <Button color="secondary" label="Year" />
130
151
  </ButtonGroup>
131
152
  <ButtonGroup size="large">
132
- <Button label="Week" />
133
- <Button label="Month" />
134
- <Button label="Year" />
153
+ <Button color="secondary" label="Week" />
154
+ <Button color="secondary" label="Month" />
155
+ <Button color="secondary" label="Year" />
135
156
  </ButtonGroup>
136
157
  </Playground>
137
158
 
@@ -139,9 +160,9 @@ Block button groups span the full width of a parent:
139
160
 
140
161
  <Playground>
141
162
  <ButtonGroup block>
142
- <Button label="Week" />
143
- <Button label="Month" />
144
- <Button label="Year" />
163
+ <Button color="secondary" label="Week" />
164
+ <Button color="secondary" label="Month" />
165
+ <Button color="secondary" label="Year" />
145
166
  </ButtonGroup>
146
167
  </Playground>
147
168
 
@@ -153,19 +174,19 @@ Disables all buttons inside the group.
153
174
 
154
175
  <Playground>
155
176
  <ButtonGroup disabled>
156
- <Button label="Week" />
157
- <Button label="Month" />
158
- <Button label="Year" />
177
+ <Button color="secondary" label="Week" />
178
+ <Button color="secondary" label="Month" />
179
+ <Button color="secondary" label="Year" />
159
180
  </ButtonGroup>
160
181
  <ButtonGroup priority="outline" disabled>
161
- <Button label="Week" />
162
- <Button label="Month" />
163
- <Button label="Year" />
182
+ <Button color="secondary" label="Week" />
183
+ <Button color="secondary" label="Month" />
184
+ <Button color="secondary" label="Year" />
164
185
  </ButtonGroup>
165
186
  <ButtonGroup priority="flat" disabled>
166
- <Button label="Week" />
167
- <Button label="Month" />
168
- <Button label="Year" />
187
+ <Button color="secondary" label="Week" />
188
+ <Button color="secondary" label="Month" />
189
+ <Button color="secondary" label="Year" />
169
190
  </ButtonGroup>
170
191
  </Playground>
171
192
 
@@ -176,42 +197,42 @@ state of individual buttons can be indicated by showing an icon.
176
197
 
177
198
  <Playground>
178
199
  <ButtonGroup>
179
- <Button label="Week" color="success" feedbackIcon={<Icon icon="success" />} />
180
- <Button label="Month" />
181
- <Button label="Year" />
200
+ <Button color="success" label="Week" feedbackIcon={<Icon icon="success" />} />
201
+ <Button color="secondary" label="Month" />
202
+ <Button color="secondary" label="Year" />
182
203
  </ButtonGroup>
183
204
  <ButtonGroup priority="outline">
184
- <Button label="Week" color="success" feedbackIcon={<Icon icon="success" />} />
185
- <Button label="Month" />
186
- <Button label="Year" />
205
+ <Button color="success" label="Week" feedbackIcon={<Icon icon="success" />} />
206
+ <Button color="secondary" label="Month" />
207
+ <Button color="secondary" label="Year" />
187
208
  </ButtonGroup>
188
209
  <ButtonGroup priority="flat">
189
- <Button label="Week" color="success" feedbackIcon={<Icon icon="success" />} />
190
- <Button label="Month" />
191
- <Button label="Year" />
210
+ <Button color="success" label="Week" feedbackIcon={<Icon icon="success" />} />
211
+ <Button color="secondary" label="Month" />
212
+ <Button color="secondary" label="Year" />
192
213
  </ButtonGroup>
193
214
  </Playground>
194
215
 
195
- ### Active State
216
+ ### Selected State
196
217
 
197
- To highlight the selected option, the active state can be achieved by setting
198
- a different button variant for the active item.
218
+ To highlight the selected option, just apply the selected color variant for
219
+ the desired item.
199
220
 
200
221
  <Playground>
201
222
  <ButtonGroup>
202
- <Button color="dark" label="Week" />
203
- <Button label="Month" />
204
- <Button label="Year" />
223
+ <Button color="selected" label="Week" />
224
+ <Button color="secondary" label="Month" />
225
+ <Button color="secondary" label="Year" />
205
226
  </ButtonGroup>
206
227
  <ButtonGroup priority="outline">
207
- <Button color="dark" label="Week" />
208
- <Button label="Month" />
209
- <Button label="Year" />
228
+ <Button color="selected" label="Week" />
229
+ <Button color="secondary" label="Month" />
230
+ <Button color="secondary" label="Year" />
210
231
  </ButtonGroup>
211
232
  <ButtonGroup priority="flat">
212
- <Button color="dark" label="Week" />
213
- <Button label="Month" />
214
- <Button label="Year" />
233
+ <Button color="selected" label="Week" />
234
+ <Button color="secondary" label="Month" />
235
+ <Button color="secondary" label="Year" />
215
236
  </ButtonGroup>
216
237
  </Playground>
217
238
 
@@ -224,9 +245,9 @@ and communicating the state of individual options.
224
245
  <>
225
246
  <span id="period-label">Period:</span>
226
247
  <ButtonGroup aria-labelledby="period-label">
227
- <Button label="Week" aria-pressed color="dark" />
228
- <Button label="Month" aria-pressed={false} />
229
- <Button label="Year" aria-pressed={false} />
248
+ <Button color="selected" label="Week" aria-pressed />
249
+ <Button color="secondary" label="Month" aria-pressed={false} />
250
+ <Button color="secondary" label="Year" aria-pressed={false} />
230
251
  </ButtonGroup>
231
252
  </>
232
253
  </Playground>
@@ -250,13 +271,18 @@ its accessibility.
250
271
 
251
272
  | Custom Property | Description |
252
273
  |--------------------------------------------------------------------|------------------------------------------------|
274
+ | `--rui-ButtonGroup__inner-border-radius` | Inner border radius of buttons |
253
275
  | `--rui-ButtonGroup--filled__gap` | Gap between `filled` buttons |
254
276
  | `--rui-ButtonGroup--filled__separator__width` | Separator width for `filled` buttons |
255
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 |
256
281
  | `--rui-ButtonGroup--flat__gap` | Gap between `flat` buttons |
257
282
  | `--rui-ButtonGroup--flat__separator__width` | Separator width for `flat` buttons |
258
283
  | `--rui-ButtonGroup--flat__separator__color` | Separator color for `flat` buttons |
259
- | `--rui-ButtonGroup--outline__gap` | Gap between `outline` buttons |
260
284
 
285
+ [fieldset]: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/fieldset
286
+ [accessibility]: https://www.w3.org/WAI/tutorials/forms/grouping/
261
287
  [React synthetic events]: https://reactjs.org/docs/events.html
262
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);
@@ -46,9 +46,7 @@ Card.propTypes = {
46
46
  /**
47
47
  * [Color variant](/foundation/colors#component-colors) to clarify importance and meaning of the card.
48
48
  */
49
- color: PropTypes.oneOf(
50
- ['primary', 'secondary', 'success', 'warning', 'danger', 'help', 'info', 'note', 'light', 'dark'],
51
- ),
49
+ color: PropTypes.oneOf(['success', 'warning', 'danger', 'help', 'info', 'note', 'light', 'dark']),
52
50
  /**
53
51
  * Make the card more compact.
54
52
  */
@@ -1,6 +1,5 @@
1
1
  // 1. Retain equal card widths in flex and grid layouts independently on their content.
2
2
 
3
- @use "../../styles/theme/colors";
4
3
  @use "theme";
5
4
  @use "tools";
6
5
 
@@ -33,14 +32,6 @@
33
32
  box-shadow: theme.$raised-box-shadow;
34
33
  }
35
34
 
36
- .isRootColorPrimary {
37
- @include tools.color(primary);
38
- }
39
-
40
- .isRootColorSecondary {
41
- @include tools.color(secondary);
42
- }
43
-
44
35
  .isRootColorSuccess {
45
36
  @include tools.color(success);
46
37
  }
@@ -164,22 +164,6 @@ Card supports all
164
164
  of your app.
165
165
 
166
166
  <Playground>
167
- <Card color="primary">
168
- <CardBody>
169
- Hello! I&apos;m primary variant of card.
170
- </CardBody>
171
- <CardFooter>
172
- <Button label="Read more" priority="outline" />
173
- </CardFooter>
174
- </Card>
175
- <Card color="secondary">
176
- <CardBody>
177
- Hello! I&apos;m secondary variant of card.
178
- </CardBody>
179
- <CardFooter>
180
- <Button label="Read more" priority="outline" color="secondary" />
181
- </CardFooter>
182
- </Card>
183
167
  <Card color="success">
184
168
  <CardBody>
185
169
  Hello! I&apos;m success variant of card.
@@ -9,16 +9,6 @@ $disabled-background-color: var(--rui-Card--disabled__background-color);
9
9
  $disabled-opacity: var(--rui-Card--disabled__opacity);
10
10
 
11
11
  $colors: (
12
- primary: (
13
- color: var(--rui-Card--primary__color),
14
- border-color: var(--rui-Card--primary__border-color),
15
- background-color: var(--rui-Card--primary__background-color),
16
- ),
17
- secondary: (
18
- color: var(--rui-Card--secondary__color),
19
- border-color: var(--rui-Card--secondary__border-color),
20
- background-color: var(--rui-Card--secondary__background-color),
21
- ),
22
12
  success: (
23
13
  color: var(--rui-Card--success__color),
24
14
  border-color: var(--rui-Card--success__border-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
@@ -144,24 +145,31 @@ with CSS custom properties.
144
145
  <span id="label-width-options-label">Label width:</span>
145
146
  </ToolbarItem>
146
147
  <ToolbarItem>
147
- <ButtonGroup aria-labelledby="label-width-options-label">
148
+ <ButtonGroup
149
+ aria-labelledby="label-width-options-label"
150
+ priority="outline"
151
+ >
148
152
  <Button
149
- color={labelWidth === 'default' ? 'dark' : 'primary'}
153
+ aria-pressed={labelWidth === 'default'}
154
+ color={labelWidth === 'default' ? 'selected' : 'secondary'}
150
155
  label="default"
151
156
  onClick={() => setLabelWidth('default')}
152
157
  />
153
158
  <Button
154
- color={labelWidth === 'auto' ? 'dark' : 'primary'}
159
+ aria-pressed={labelWidth === 'auto'}
160
+ color={labelWidth === 'auto' ? 'selected' : 'secondary'}
155
161
  label="auto"
156
162
  onClick={() => setLabelWidth('auto')}
157
163
  />
158
164
  <Button
159
- color={labelWidth === 'limited' ? 'dark' : 'primary'}
165
+ aria-pressed={labelWidth === 'limited'}
166
+ color={labelWidth === 'limited' ? 'selected' : 'secondary'}
160
167
  label="limited"
161
168
  onClick={() => setLabelWidth('limited')}
162
169
  />
163
170
  <Button
164
- color={labelWidth === 'custom' ? 'dark' : 'primary'}
171
+ aria-pressed={labelWidth === 'custom'}
172
+ color={labelWidth === 'custom' ? 'selected' : 'secondary'}
165
173
  label="custom"
166
174
  onClick={() => setLabelWidth('custom')}
167
175
  />
@@ -351,14 +359,16 @@ This is a demo of all components supported by FormLayout.
351
359
  <div>
352
360
  <Toolbar>
353
361
  <ToolbarItem>
354
- <ButtonGroup>
362
+ <ButtonGroup priority="outline">
355
363
  <Button
356
- color={fieldLayout === 'vertical' ? 'dark' : 'primary'}
364
+ aria-pressed={fieldLayout === 'vertical'}
365
+ color={fieldLayout === 'vertical' ? 'selected' : 'secondary'}
357
366
  label="Vertical layout"
358
367
  onClick={() => setFieldLayout('vertical')}
359
368
  />
360
369
  <Button
361
- color={fieldLayout === 'horizontal' ? 'dark' : 'primary'}
370
+ aria-pressed={fieldLayout === 'horizontal'}
371
+ color={fieldLayout === 'horizontal' ? 'selected' : 'secondary'}
362
372
  label="Horizontal layout"
363
373
  onClick={() => setFieldLayout('horizontal')}
364
374
  />
@@ -432,6 +442,10 @@ This is a demo of all components supported by FormLayout.
432
442
  options={options}
433
443
  value={fruit}
434
444
  />
445
+ <InputGroup label="Promo code">
446
+ <TextField label="Code" />
447
+ <Button label="Apply" color="secondary" priority="outline" />
448
+ </InputGroup>
435
449
  </FormLayout>
436
450
  </div>
437
451
  )
@@ -1,6 +1,6 @@
1
1
  const prepareValueByType = (value, type) => {
2
2
  if (type === 'spacing') {
3
- return `var(--rui-spacing-${value})`;
3
+ return `var(--rui-dimension-space-${value})`;
4
4
  }
5
5
 
6
6
  return value;
@@ -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;