@react-ui-org/react-ui 0.63.1 → 0.64.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 (49) hide show
  1. package/.claude/agents/code-reviewer.md +122 -0
  2. package/.claude/rules/code.md +22 -0
  3. package/.claude/rules/docs.md +35 -0
  4. package/.claude/rules/frontend.md +72 -0
  5. package/.claude/rules/git.md +13 -0
  6. package/.claude/rules/safety-guards.md +9 -0
  7. package/.claude/rules/styling.md +32 -0
  8. package/.claude/rules/testing.md +59 -0
  9. package/.claude/settings.json +32 -0
  10. package/.claude/skills/commit/SKILL.md +54 -0
  11. package/.devcontainer/devcontainer.json +23 -0
  12. package/.mcp.json +8 -0
  13. package/CLAUDE.md +82 -0
  14. package/dist/react-ui.css +4 -4
  15. package/dist/react-ui.development.css +600 -590
  16. package/dist/react-ui.development.js +20 -10
  17. package/dist/react-ui.js +1 -1
  18. package/docker-compose.base.yml +93 -0
  19. package/docker-compose.yml.dist +41 -0
  20. package/opencode.json +10 -0
  21. package/package.json +3 -2
  22. package/scripts/auto-start-mkdocs.sh +5 -0
  23. package/scripts/auto-start-node.sh +33 -0
  24. package/scripts/mcps/chrome-host/README.md +118 -0
  25. package/scripts/mcps/chrome-host/cdp_proxy.py +90 -0
  26. package/scripts/mcps/chrome-host/mcp-entry.sh +33 -0
  27. package/scripts/mcps/chrome-host/mcp-launch.sh +36 -0
  28. package/scripts/mcps/chrome-host/mcp-setup.sh +70 -0
  29. package/scripts/mcps/chrome-host/start-host-chrome.sh +267 -0
  30. package/scripts/write-lockfile-hash.sh +15 -0
  31. package/setup.sh +107 -0
  32. package/src/components/Button/Button.jsx +4 -0
  33. package/src/components/Button/Button.module.scss +11 -0
  34. package/src/components/FileInputField/FileInputField.jsx +9 -2
  35. package/src/components/FormLayout/FormLayoutCustomField.jsx +4 -1
  36. package/src/components/FormLayout/FormLayoutCustomFieldContext.js +3 -0
  37. package/src/components/FormLayout/README.md +168 -161
  38. package/src/components/FormLayout/index.js +1 -0
  39. package/src/components/Popover/Popover.jsx +1 -0
  40. package/src/components/Popover/Popover.module.scss +1 -0
  41. package/src/components/Popover/README.md +29 -0
  42. package/src/components/Popover/_helpers/cleanPlacementStyle.js +1 -0
  43. package/src/components/Popover/_theme.scss +1 -0
  44. package/src/components/SelectField/SelectField.jsx +8 -3
  45. package/src/components/TextArea/TextArea.jsx +9 -2
  46. package/src/components/TextField/TextField.jsx +8 -3
  47. package/src/theme.scss +1 -0
  48. package/.env.playwright +0 -9
  49. package/.env.playwright.dist +0 -9
@@ -14,7 +14,8 @@ And use it:
14
14
 
15
15
  ```docoff-react-preview
16
16
  <FormLayout>
17
- <TextField label="A form element" />
17
+ <TextField label="A text field" />
18
+ <Button label="Submit" />
18
19
  </FormLayout>
19
20
  ```
20
21
 
@@ -27,18 +28,14 @@ one after another in a row by default.** The FormLayout component is there to
27
28
  make building **vertical and horizontal forms** easy. It uses the right tool for
28
29
  the job: the [CSS grid layout][grid].
29
30
 
30
- - Put **only form field components** from React UI inside the FormLayout and
31
- make sure they are **direct descendants** of it (React [fragments] are
32
- supported!). All React UI form components are ready for this use case and
33
- don't need to be wrapped in any `div`s. Namely, the FormLayout supports the
34
- following React UI components:
35
- [CheckboxField](/components/CheckboxField),
36
- [Radio](/components/Radio), [SelectField](/components/SelectField),
37
- [TextArea](/components/TextArea), [TextField](/components/TextField),
38
- and [Toggle](/components/Toggle).
39
-
40
- - Use the [FormLayoutCustomField](#custom-fields) component when you need to
41
- place any **custom content** inside the FormLayout. This layout helper ensures
31
+ - Put **only form field components or buttons** from React UI inside the
32
+ FormLayout and make sure they are **direct descendants** of it (React
33
+ [fragments][fragments] are supported!). All React UI form components are
34
+ [ready for this use case](#supported-form-fields), no wrapping `<div>`s are
35
+ needed.
36
+
37
+ - To **place any custom content** inside the FormLayout, use the
38
+ [FormLayoutCustomField](#custom-fields) component. This layout helper ensures
42
39
  your content is properly spaced and aligned with other FormLayout elements.
43
40
  Do **not** try to put any custom HTML or React components directly into
44
41
  FormLayout without wrapping it with the FormLayoutCustomField first.
@@ -48,6 +45,132 @@ for your FormLayout. This prevents FormLayout from unexpectedly growing in
48
45
  browsers that [don't support][rui-232] [CSS subgrid][subgrid] in cases when
49
46
  there are longer validation messages or help texts.
50
47
 
48
+ ## Supported Form Fields
49
+
50
+ The FormLayout supports buttons and all React UI form fields:
51
+ [Button](/components/Button), [CheckboxField](/components/CheckboxField),
52
+ [FileInputField](/components/FileInputField), [Radio](/components/Radio),
53
+ [SelectField](/components/SelectField), [TextArea](/components/TextArea),
54
+ [TextField](/components/TextField), and [Toggle](/components/Toggle).
55
+
56
+ ```docoff-react-preview
57
+ React.createElement(() => {
58
+ const [fieldLayout, setFieldLayout] = React.useState('horizontal');
59
+ const [fruit, setFruit] = React.useState('apple');
60
+ const [isDeliveryAddress, setIsDeliveryAddress] = React.useState(true);
61
+ const [receiveNewsletter, setReceiveNewsletter] = React.useState(true);
62
+ const options = [
63
+ {
64
+ label: 'Apple',
65
+ value: 'apple',
66
+ },
67
+ {
68
+ label: 'Banana',
69
+ value: 'banana',
70
+ },
71
+ {
72
+ label: 'Grapefruit',
73
+ value: 'grapefruit',
74
+ },
75
+ ];
76
+ return (
77
+ <div>
78
+ <Toolbar>
79
+ <ToolbarItem>
80
+ <ButtonGroup>
81
+ <Button
82
+ color={fieldLayout === 'horizontal' ? 'selected' : 'secondary'}
83
+ label="Horizontal layout"
84
+ onClick={() => setFieldLayout('horizontal')}
85
+ />
86
+ <Button
87
+ color={fieldLayout === 'vertical' ? 'selected' : 'secondary'}
88
+ label="Vertical layout"
89
+ onClick={() => setFieldLayout('vertical')}
90
+ />
91
+ </ButtonGroup>
92
+ </ToolbarItem>
93
+ </Toolbar>
94
+ <FormLayout fieldLayout={fieldLayout} labelWidth="auto">
95
+ <>
96
+ <TextField
97
+ label="First Name"
98
+ />
99
+ <TextField
100
+ label="Last Name"
101
+ />
102
+ </>
103
+ <TextField
104
+ helpText="Optional"
105
+ label="Email address"
106
+ type="email"
107
+ />
108
+ <>
109
+ <TextField
110
+ label="Address"
111
+ placeholder="Address line 1"
112
+ />
113
+ <TextField
114
+ isLabelVisible={false}
115
+ label="Address 2"
116
+ placeholder="Address line 2"
117
+ />
118
+ <TextField
119
+ inputSize={6}
120
+ label="ZIP"
121
+ validationState="invalid"
122
+ validationText="ZIP should be 5 to 6 digits long code."
123
+ />
124
+ <FormLayoutCustomField label="Country">
125
+ <span>Czech Republic</span>
126
+ </FormLayoutCustomField>
127
+ <CheckboxField
128
+ checked={isDeliveryAddress}
129
+ helpText="Uncheck if you wish to deliver to a different address."
130
+ label="This is my delivery address"
131
+ onChange={() => setIsDeliveryAddress(!isDeliveryAddress)}
132
+ />
133
+ </>
134
+ <SelectField
135
+ label="Your favourite fruit"
136
+ onChange={(e) => setFruit(e.target.value)}
137
+ options={options}
138
+ value={fruit}
139
+ />
140
+ <TextArea
141
+ fullWidth
142
+ label="Message"
143
+ rows={3}
144
+ />
145
+ <FileInputField
146
+ id="my-file"
147
+ label="Attachment"
148
+ onFilesChanged={() => {}}
149
+ />
150
+ <Toggle
151
+ checked={receiveNewsletter}
152
+ helpText="Only once per week!"
153
+ label="Receive weekly newsletter"
154
+ onChange={() => setReceiveNewsletter(!receiveNewsletter)}
155
+ required
156
+ />
157
+ <Radio
158
+ label="And fruit again!"
159
+ onChange={(e) => setFruit(e.target.value)}
160
+ options={options}
161
+ value={fruit}
162
+ />
163
+ <InputGroup label="Promo code">
164
+ <TextField label="Code" />
165
+ <Button label="Apply" color="secondary" priority="outline" />
166
+ </InputGroup>
167
+ <Button label="Submit" />
168
+ </FormLayout>
169
+ </div>
170
+ )
171
+ });
172
+ ```
173
+
51
174
  ## Vertical Layout
52
175
 
53
176
  Vertical FormLayout works similar to single-column [Grid](/components/Grid)
@@ -59,6 +182,7 @@ layout, simply wrap your form fields with the FormLayout component:
59
182
  <TextField label="A form element" />
60
183
  <TextField label="Another form element" />
61
184
  <TextField label="Yet another one" />
185
+ <Button label="Submit" />
62
186
  </FormLayout>
63
187
  ```
64
188
 
@@ -73,6 +197,7 @@ viewport size onward and it forces the horizontal layout on the fields.
73
197
  <TextField label="A form element" />
74
198
  <TextField label="Another form element" />
75
199
  <TextField label="Yet another one" />
200
+ <Button label="Submit" />
76
201
  </FormLayout>
77
202
  ```
78
203
 
@@ -194,11 +319,9 @@ the FormLayout component.
194
319
 
195
320
  ```docoff-react-preview
196
321
  <FormLayout fieldLayout="horizontal" labelWidth="auto">
197
- <TextField label="A form element" />
198
322
  <FormLayoutCustomField label="Optional custom field label">
199
323
  <docoff-placeholder bordered>Custom field content</docoff-placeholder>
200
324
  </FormLayoutCustomField>
201
- <TextField label="Another form element" />
202
325
  </FormLayout>
203
326
  ```
204
327
 
@@ -207,6 +330,29 @@ and its styles may affect contained form fields through CSS cascade, don't
207
330
  forget to mirror the aforementioned properties to the contained form fields too
208
331
  as API options as such are **not** inherited.
209
332
 
333
+ ### Nested Fields Labels
334
+
335
+ When placing box form fields — TextField, TextArea, SelectField, or
336
+ FileInputField — inside a FormLayoutCustomField, their labels are hidden
337
+ automatically.
338
+
339
+ ```docoff-react-preview
340
+ <FormLayout fieldLayout="horizontal" labelWidth="auto">
341
+ <FormLayoutCustomField
342
+ innerFieldSize="medium"
343
+ label="Custom field with invisible label"
344
+ >
345
+ <TextField
346
+ label="This field's label is hidden"
347
+ />
348
+ </FormLayoutCustomField>
349
+ </FormLayout>
350
+ ```
351
+
352
+ ℹ️ Labels are hidden regardless of `fieldLayout`. In a horizontal FormLayout,
353
+ the nested field's own label would conflict with the FormLayout grid and
354
+ produce incorrect alignment, so it is always hidden for consistency.
355
+
210
356
  ### Label Alignment
211
357
 
212
358
  If you are in a situation with one or more box form fields inside your
@@ -218,18 +364,15 @@ this task.
218
364
 
219
365
  ```docoff-react-preview
220
366
  <FormLayout fieldLayout="horizontal" labelWidth="auto">
221
- <TextField label="A form element" />
222
367
  <FormLayoutCustomField
223
368
  innerFieldSize="medium"
224
369
  label="Custom field label aligned to inner text input"
225
370
  >
226
371
  <TextField
227
- isLabelVisible={false}
228
372
  label="A form element"
229
373
  placeholder="Text field with invisible label"
230
374
  />
231
375
  </FormLayoutCustomField>
232
- <TextField label="Another form element" />
233
376
  </FormLayout>
234
377
  ```
235
378
 
@@ -240,14 +383,12 @@ provide labels with optional feedback style.
240
383
 
241
384
  ```docoff-react-preview
242
385
  <FormLayout fieldLayout="horizontal" labelWidth="auto">
243
- <TextField label="A form element" />
244
386
  <FormLayoutCustomField
245
387
  label="Custom field label in valid state"
246
388
  validationState="valid"
247
389
  >
248
390
  <docoff-placeholder bordered>Custom field content</docoff-placeholder>
249
391
  </FormLayoutCustomField>
250
- <TextField label="Another form element" />
251
392
  </FormLayout>
252
393
  ```
253
394
 
@@ -264,153 +405,19 @@ React.createElement(() => {
264
405
  const [isChecked, setIsChecked] = React.useState(false);
265
406
  return (
266
407
  <FormLayout fieldLayout="horizontal" labelWidth="auto">
267
- <TextField label="A form element" />
268
408
  <FormLayoutCustomField
269
409
  fullWidth
270
- label="Custom field label aligned with medium form field"
271
- labelForId="my-text-field-custom-accessibility-2"
410
+ label="Custom field label associated with a text field"
411
+ labelForId="my-text-field-custom-accessibility"
272
412
  innerFieldSize="medium"
273
413
  >
274
- <Toolbar align="middle" dense>
275
- <ToolbarItem>
276
- <TextField
277
- isLabelVisible={false}
278
- label="A form element"
279
- placeholder="Text field with invisible label"
280
- />
281
- </ToolbarItem>
282
- <ToolbarItem>
283
- <CheckboxField
284
- checked={isChecked}
285
- label="Another form field"
286
- onChange={() => setIsChecked(!isChecked)}
287
- />
288
- </ToolbarItem>
289
- </Toolbar>
290
- </FormLayoutCustomField>
291
- <TextField label="Another form element" />
292
- </FormLayout>
293
- )
294
- });
295
- ```
296
-
297
- ## Full Example
298
-
299
- This is a demo of all components supported by FormLayout.
300
-
301
- ```docoff-react-preview
302
- React.createElement(() => {
303
- const [fieldLayout, setFieldLayout] = React.useState('horizontal');
304
- const [fruit, setFruit] = React.useState('apple');
305
- const [isDeliveryAddress, setIsDeliveryAddress] = React.useState(true);
306
- const [receiveNewsletter, setReceiveNewsletter] = React.useState(true);
307
- const options = [
308
- {
309
- label: 'Apple',
310
- value: 'apple',
311
- },
312
- {
313
- label: 'Banana',
314
- value: 'banana',
315
- },
316
- {
317
- label: 'Grapefruit',
318
- value: 'grapefruit',
319
- },
320
- ];
321
- return (
322
- <div>
323
- <Toolbar>
324
- <ToolbarItem>
325
- <ButtonGroup>
326
- <Button
327
- color={fieldLayout === 'horizontal' ? 'selected' : 'secondary'}
328
- label="Horizontal layout"
329
- onClick={() => setFieldLayout('horizontal')}
330
- />
331
- <Button
332
- color={fieldLayout === 'vertical' ? 'selected' : 'secondary'}
333
- label="Vertical layout"
334
- onClick={() => setFieldLayout('vertical')}
335
- />
336
- </ButtonGroup>
337
- </ToolbarItem>
338
- </Toolbar>
339
- <FormLayout fieldLayout={fieldLayout} labelWidth="auto">
340
- <>
341
- <TextField
342
- label="First Name"
343
- />
344
- <TextField
345
- label="Last Name"
346
- />
347
- </>
348
414
  <TextField
349
- helpText="Optional"
350
- label="Email address"
351
- type="email"
415
+ id="my-text-field-custom-accessibility"
416
+ label="A form element"
417
+ placeholder="Text field with invisible label"
352
418
  />
353
- <>
354
- <TextField
355
- label="Address"
356
- placeholder="Address line 1"
357
- />
358
- <TextField
359
- isLabelVisible={false}
360
- label="Address 2"
361
- placeholder="Address line 2"
362
- />
363
- <TextField
364
- inputSize={6}
365
- label="ZIP"
366
- validationState="invalid"
367
- validationText="ZIP should be 5 to 6 digits long code."
368
- />
369
- <FormLayoutCustomField label="Country">
370
- <span>Czech Republic</span>
371
- </FormLayoutCustomField>
372
- <CheckboxField
373
- checked={isDeliveryAddress}
374
- helpText="Uncheck if you wish to deliver to a different address."
375
- label="This is my delivery address"
376
- onChange={() => setIsDeliveryAddress(!isDeliveryAddress)}
377
- />
378
- </>
379
- <SelectField
380
- label="Your favourite fruit"
381
- onChange={(e) => setFruit(e.target.value)}
382
- options={options}
383
- value={fruit}
384
- />
385
- <TextArea
386
- fullWidth
387
- label="Message"
388
- rows={3}
389
- />
390
- <FileInputField
391
- id="my-file"
392
- label="Attachment"
393
- onFilesChanged={() => {}}
394
- />
395
- <Toggle
396
- checked={receiveNewsletter}
397
- helpText="Only once per week!"
398
- label="Receive weekly newsletter"
399
- onChange={() => setReceiveNewsletter(!receiveNewsletter)}
400
- required
401
- />
402
- <Radio
403
- label="And fruit again!"
404
- onChange={(e) => setFruit(e.target.value)}
405
- options={options}
406
- value={fruit}
407
- />
408
- <InputGroup label="Promo code">
409
- <TextField label="Code" />
410
- <Button label="Apply" color="secondary" priority="outline" />
411
- </InputGroup>
412
- </FormLayout>
413
- </div>
419
+ </FormLayoutCustomField>
420
+ </FormLayout>
414
421
  )
415
422
  });
416
423
  ```
@@ -1,3 +1,4 @@
1
1
  export { default as FormLayout } from './FormLayout';
2
2
  export { FormLayoutContext } from './FormLayoutContext';
3
+ export { FormLayoutCustomFieldContext } from './FormLayoutCustomFieldContext';
3
4
  export { default as FormLayoutCustomField } from './FormLayoutCustomField';
@@ -105,6 +105,7 @@ Popover.propTypes = {
105
105
  top: PropTypes.string,
106
106
  'transform-origin': PropTypes.string,
107
107
  translate: PropTypes.string,
108
+ visibility: PropTypes.string,
108
109
  }),
109
110
  /**
110
111
  * If set, the popover will become controlled, meaning it will be hidden by default and will need a trigger to open.
@@ -13,6 +13,7 @@
13
13
  @layer components.popover {
14
14
  .root {
15
15
  position: absolute;
16
+ z-index: theme.$z-index;
16
17
  width: max-content;
17
18
  max-width: theme.$max-width;
18
19
  padding: theme.$padding;
@@ -178,10 +178,15 @@ position the popover. The allowed props are:
178
178
  - `left`
179
179
  - `translate`
180
180
  - `transform-origin`
181
+ - `visibility`
181
182
 
182
183
  ⚠️ [`inset`][mdn-inset] is a shorthand for `top right bottom left`, not for
183
184
  `inset-*` properties.
184
185
 
186
+ ℹ️ `visibility` can be used to hide the Popover before its initial position is
187
+ computed, preventing a flash of the Popover in a wrong position. Set it to
188
+ `hidden` initially, then remove or update it once the position is ready.
189
+
185
190
  As opposed to `top right bottom left` and the `inset` shorthand, `inset-*`
186
191
  properties are writing-direction aware.
187
192
 
@@ -307,6 +312,29 @@ React.createElement(() => {
307
312
  });
308
313
  ```
309
314
 
315
+ ## z-index
316
+
317
+ By default, the Popover's `z-index` is `auto`, which means it participates in
318
+ the stacking context of its nearest positioned ancestor. This works well in most
319
+ cases, but can cause the Popover to appear behind other positioned elements such
320
+ as sticky headers, fixed toolbars, or modals.
321
+
322
+ When that happens, set `--rui-Popover__z-index` to a numeric value high enough
323
+ to place the Popover above the conflicting layer. The override can be applied
324
+ globally or scoped to a specific context:
325
+
326
+ ```css
327
+ /* Global override */
328
+ :root {
329
+ --rui-Popover__z-index: 1000;
330
+ }
331
+
332
+ /* Scoped override */
333
+ .my-context {
334
+ --rui-Popover__z-index: 1000;
335
+ }
336
+ ```
337
+
310
338
  ## Controlled Popover
311
339
 
312
340
  Popover API can be used to control visibility of Popover component. You need to
@@ -379,6 +407,7 @@ which enables [Advanced Positioning](#advanced-positioning).
379
407
  | `--rui-Popover__color` | Text color |
380
408
  | `--rui-Popover__background-color` | Background color |
381
409
  | `--rui-Popover__box-shadow` | Popover box shadow |
410
+ | `--rui-Popover__z-index` | Popover z-index (default: `auto`) |
382
411
 
383
412
  [div-attributes]: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/div#attributes
384
413
  [Floating UI]: https://floating-ui.com/docs/react-dom
@@ -12,6 +12,7 @@ export default (placementStyle) => {
12
12
  'left',
13
13
  'translate',
14
14
  'transform-origin',
15
+ 'visibility',
15
16
  ];
16
17
 
17
18
  return Object.fromEntries(
@@ -2,6 +2,7 @@
2
2
 
3
3
  @use "sass:math";
4
4
 
5
+ $z-index: var(--rui-Popover__z-index);
5
6
  $max-width: var(--rui-Popover__max-width);
6
7
  $padding: var(--rui-Popover__padding);
7
8
  $border-width: var(--rui-Popover__border-width);
@@ -6,7 +6,10 @@ import { transferProps } from '../../helpers/transferProps';
6
6
  import { getRootSizeClassName } from '../_helpers/getRootSizeClassName';
7
7
  import { getRootValidationStateClassName } from '../_helpers/getRootValidationStateClassName';
8
8
  import { resolveContextOrProp } from '../_helpers/resolveContextOrProp';
9
- import { FormLayoutContext } from '../FormLayout';
9
+ import {
10
+ FormLayoutContext,
11
+ FormLayoutCustomFieldContext,
12
+ } from '../FormLayout';
10
13
  import { InputGroupContext } from '../InputGroup/InputGroupContext';
11
14
  import { Option } from './_components/Option';
12
15
  import styles from './SelectField.module.scss';
@@ -31,6 +34,7 @@ export const SelectField = React.forwardRef((props, ref) => {
31
34
  } = props;
32
35
 
33
36
  const formLayoutContext = useContext(FormLayoutContext);
37
+ const formLayoutCustomFieldContext = useContext(FormLayoutCustomFieldContext);
34
38
  const inputGroupContext = useContext(InputGroupContext);
35
39
 
36
40
  return (
@@ -58,7 +62,7 @@ export const SelectField = React.forwardRef((props, ref) => {
58
62
  <div
59
63
  className={classNames(
60
64
  styles.label,
61
- (!isLabelVisible || inputGroupContext) && styles.isLabelHidden,
65
+ (!isLabelVisible || inputGroupContext || formLayoutCustomFieldContext) && styles.isLabelHidden,
62
66
  )}
63
67
  id={id && `${id}__labelText`}
64
68
  >
@@ -181,7 +185,8 @@ SelectField.propTypes = {
181
185
  * If `false`, the label will be visually hidden (but remains accessible by assistive
182
186
  * technologies).
183
187
  *
184
- * Automatically set to `false` when the component is rendered within `InputGroup` component.
188
+ * Automatically set to `false` when the component is rendered within `InputGroup` or
189
+ * `FormLayoutCustomField` component.
185
190
  */
186
191
  isLabelVisible: PropTypes.bool,
187
192
  /**
@@ -6,7 +6,10 @@ import { transferProps } from '../../helpers/transferProps';
6
6
  import { getRootSizeClassName } from '../_helpers/getRootSizeClassName';
7
7
  import { getRootValidationStateClassName } from '../_helpers/getRootValidationStateClassName';
8
8
  import { resolveContextOrProp } from '../_helpers/resolveContextOrProp';
9
- import { FormLayoutContext } from '../FormLayout';
9
+ import {
10
+ FormLayoutContext,
11
+ FormLayoutCustomFieldContext,
12
+ } from '../FormLayout';
10
13
  import styles from './TextArea.module.scss';
11
14
 
12
15
  export const TextArea = React.forwardRef((props, ref) => {
@@ -27,6 +30,7 @@ export const TextArea = React.forwardRef((props, ref) => {
27
30
  } = props;
28
31
 
29
32
  const context = useContext(FormLayoutContext);
33
+ const formLayoutCustomFieldContext = useContext(FormLayoutCustomFieldContext);
30
34
 
31
35
  return (
32
36
  <label
@@ -49,7 +53,7 @@ export const TextArea = React.forwardRef((props, ref) => {
49
53
  <div
50
54
  className={classNames(
51
55
  styles.label,
52
- !isLabelVisible && styles.isLabelHidden,
56
+ (!isLabelVisible || formLayoutCustomFieldContext) && styles.isLabelHidden,
53
57
  )}
54
58
  id={id && `${id}__labelText`}
55
59
  >
@@ -127,6 +131,9 @@ TextArea.propTypes = {
127
131
  /**
128
132
  * If `false`, the label will be visually hidden (but remains accessible by assistive
129
133
  * technologies).
134
+ *
135
+ * Automatically set to `false` when the component is rendered within `FormLayoutCustomField`
136
+ * component.
130
137
  */
131
138
  isLabelVisible: PropTypes.bool,
132
139
  /**
@@ -6,7 +6,10 @@ import { transferProps } from '../../helpers/transferProps';
6
6
  import { getRootSizeClassName } from '../_helpers/getRootSizeClassName';
7
7
  import { getRootValidationStateClassName } from '../_helpers/getRootValidationStateClassName';
8
8
  import { resolveContextOrProp } from '../_helpers/resolveContextOrProp';
9
- import { FormLayoutContext } from '../FormLayout';
9
+ import {
10
+ FormLayoutContext,
11
+ FormLayoutCustomFieldContext,
12
+ } from '../FormLayout';
10
13
  import { InputGroupContext } from '../InputGroup/InputGroupContext';
11
14
  import styles from './TextField.module.scss';
12
15
 
@@ -31,6 +34,7 @@ export const TextField = React.forwardRef((props, ref) => {
31
34
  ...restProps
32
35
  } = props;
33
36
  const formLayoutContext = useContext(FormLayoutContext);
37
+ const formLayoutCustomFieldContext = useContext(FormLayoutCustomFieldContext);
34
38
  const inputGroupContext = useContext(InputGroupContext);
35
39
  const hasSmallInput = (inputSize !== undefined) && (inputSize <= SMALL_INPUT_SIZE);
36
40
 
@@ -62,7 +66,7 @@ export const TextField = React.forwardRef((props, ref) => {
62
66
  <div
63
67
  className={classNames(
64
68
  styles.label,
65
- (!isLabelVisible || inputGroupContext) && styles.isLabelHidden,
69
+ (!isLabelVisible || inputGroupContext || formLayoutCustomFieldContext) && styles.isLabelHidden,
66
70
  )}
67
71
  id={id && `${id}__labelText`}
68
72
  >
@@ -153,7 +157,8 @@ TextField.propTypes = {
153
157
  * If `false`, the label will be visually hidden (but remains accessible by assistive
154
158
  * technologies).
155
159
  *
156
- * Automatically set to `false` when the component is rendered within `InputGroup` component.
160
+ * Automatically set to `false` when the component is rendered within `InputGroup` or
161
+ * `FormLayoutCustomField` component.
157
162
  */
158
163
  isLabelVisible: PropTypes.bool,
159
164
  /**
package/src/theme.scss CHANGED
@@ -1090,6 +1090,7 @@
1090
1090
  --rui-Popover__color: var(--rui-color-text-primary);
1091
1091
  --rui-Popover__background-color: var(--rui-color-background-layer-2);
1092
1092
  --rui-Popover__box-shadow: var(--rui-shadow-layer-2);
1093
+ --rui-Popover__z-index: auto;
1093
1094
 
1094
1095
  //
1095
1096
  // Tabs
package/.env.playwright DELETED
@@ -1,9 +0,0 @@
1
- ###########################
2
- # Playwright configuration #
3
- ###########################
4
-
5
- # Number of workers to use to run Playwright tests
6
- PW_WORKERS=1
7
-
8
- # Port used by Playwright Component Testing to serve the test files
9
- PW_CT_PORT=3100
@@ -1,9 +0,0 @@
1
- ###########################
2
- # Playwright configuration #
3
- ###########################
4
-
5
- # Number of workers to use to run Playwright tests
6
- PW_WORKERS=1
7
-
8
- # Port used by Playwright Component Testing to serve the test files
9
- PW_CT_PORT=3100