@pingux/astro 1.36.2-alpha.0 → 1.36.2-alpha.2

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 (55) hide show
  1. package/lib/cjs/components/CheckboxField/CheckboxField.js +7 -2
  2. package/lib/cjs/components/CheckboxField/CheckboxField.test.js +16 -0
  3. package/lib/cjs/components/ComboBoxField/ComboBoxField.js +5 -2
  4. package/lib/cjs/components/ComboBoxField/ComboBoxField.test.js +20 -0
  5. package/lib/cjs/components/FieldHelperText/FieldHelperText.js +8 -3
  6. package/lib/cjs/components/FileInputField/FileInputField.js +6 -2
  7. package/lib/cjs/components/FileInputField/FileInputField.test.js +15 -0
  8. package/lib/cjs/components/FileInputField/FileItem.js +5 -2
  9. package/lib/cjs/components/ImageUploadField/ImageUploadField.js +19 -6
  10. package/lib/cjs/components/ImageUploadField/ImageUploadFieldBase.js +4 -3
  11. package/lib/cjs/components/LinkSelectField/LinkSelectField.js +13 -3
  12. package/lib/cjs/components/LinkSelectField/LinkSelectField.test.js +16 -3
  13. package/lib/cjs/components/MultivaluesField/MultivaluesField.js +4 -4
  14. package/lib/cjs/components/MultivaluesField/MultivaluesField.test.js +10 -4
  15. package/lib/cjs/components/NumberField/NumberField.js +8 -2
  16. package/lib/cjs/components/NumberField/NumberField.test.js +14 -0
  17. package/lib/cjs/components/RadioGroupField/RadioGroupField.js +8 -2
  18. package/lib/cjs/components/RadioGroupField/RadioGroupField.test.js +14 -0
  19. package/lib/cjs/components/SelectField/SelectField.js +4 -1
  20. package/lib/cjs/components/SelectField/SelectField.test.js +20 -0
  21. package/lib/cjs/components/SelectFieldBase/SelectFieldBase.js +7 -2
  22. package/lib/cjs/components/SelectFieldBase/SelectFieldBase.test.js +17 -0
  23. package/lib/cjs/components/TextAreaField/TextAreaField.js +8 -2
  24. package/lib/cjs/components/TextAreaField/TextAreaField.test.js +20 -0
  25. package/lib/cjs/components/TextField/TextField.js +9 -2
  26. package/lib/cjs/components/TextField/TextField.test.js +20 -0
  27. package/lib/cjs/recipes/AttributeMappingReadOnlyField.stories.js +7 -1
  28. package/lib/components/CheckboxField/CheckboxField.js +6 -2
  29. package/lib/components/CheckboxField/CheckboxField.test.js +13 -0
  30. package/lib/components/ComboBoxField/ComboBoxField.js +5 -2
  31. package/lib/components/ComboBoxField/ComboBoxField.test.js +15 -0
  32. package/lib/components/FieldHelperText/FieldHelperText.js +8 -3
  33. package/lib/components/FileInputField/FileInputField.js +6 -2
  34. package/lib/components/FileInputField/FileInputField.test.js +13 -0
  35. package/lib/components/FileInputField/FileItem.js +5 -2
  36. package/lib/components/ImageUploadField/ImageUploadField.js +17 -6
  37. package/lib/components/ImageUploadField/ImageUploadFieldBase.js +3 -2
  38. package/lib/components/LinkSelectField/LinkSelectField.js +11 -3
  39. package/lib/components/LinkSelectField/LinkSelectField.test.js +14 -3
  40. package/lib/components/MultivaluesField/MultivaluesField.js +5 -5
  41. package/lib/components/MultivaluesField/MultivaluesField.test.js +8 -4
  42. package/lib/components/NumberField/NumberField.js +7 -2
  43. package/lib/components/NumberField/NumberField.test.js +12 -0
  44. package/lib/components/RadioGroupField/RadioGroupField.js +7 -2
  45. package/lib/components/RadioGroupField/RadioGroupField.test.js +12 -0
  46. package/lib/components/SelectField/SelectField.js +4 -1
  47. package/lib/components/SelectField/SelectField.test.js +15 -0
  48. package/lib/components/SelectFieldBase/SelectFieldBase.js +7 -2
  49. package/lib/components/SelectFieldBase/SelectFieldBase.test.js +13 -0
  50. package/lib/components/TextAreaField/TextAreaField.js +7 -2
  51. package/lib/components/TextAreaField/TextAreaField.test.js +15 -0
  52. package/lib/components/TextField/TextField.js +8 -2
  53. package/lib/components/TextField/TextField.test.js +15 -0
  54. package/lib/recipes/AttributeMappingReadOnlyField.stories.js +6 -1
  55. package/package.json +1 -1
@@ -42,6 +42,8 @@ var _toggle = require("@react-stately/toggle");
42
42
 
43
43
  var _propTypes = _interopRequireDefault(require("prop-types"));
44
44
 
45
+ var _uuid = require("uuid");
46
+
45
47
  var _ = require("../../");
46
48
 
47
49
  var _ariaAttributes = require("../../utils/devUtils/props/ariaAttributes");
@@ -111,15 +113,18 @@ var CheckboxField = /*#__PURE__*/(0, _react.forwardRef)(function (props, ref) {
111
113
  fieldControlProps = _useField.fieldControlProps,
112
114
  fieldLabelProps = _useField.fieldLabelProps;
113
115
 
116
+ var helperTextId = (0, _uuid.v4)();
114
117
  return (0, _react2.jsx)(_.Box, fieldContainerProps, (0, _react2.jsx)(_.Label, (0, _extends2["default"])({
115
118
  variant: "forms.label.checkbox"
116
119
  }, fieldLabelProps), (0, _react2.jsx)(_.Checkbox, (0, _extends2["default"])({
117
- ref: checkboxRef
120
+ ref: checkboxRef,
121
+ "aria-describedby": helperText && helperTextId
118
122
  }, fieldControlProps)), label), helperText && (0, _react2.jsx)(_.FieldHelperText, {
119
123
  status: status,
120
124
  sx: {
121
125
  pt: 7
122
- }
126
+ },
127
+ id: helperTextId
123
128
  }, helperText));
124
129
  });
125
130
  CheckboxField.propTypes = _objectSpread({
@@ -12,6 +12,8 @@ var _testAxe = _interopRequireDefault(require("../../utils/testUtils/testAxe"));
12
12
 
13
13
  var _testWrapper = require("../../utils/testUtils/testWrapper");
14
14
 
15
+ var _statuses = _interopRequireDefault(require("../../utils/devUtils/constants/statuses"));
16
+
15
17
  var _CheckboxField = _interopRequireDefault(require("../CheckboxField"));
16
18
 
17
19
  var _react2 = require("@emotion/react");
@@ -119,6 +121,20 @@ test('read only checkbox', function () {
119
121
 
120
122
  expect(input).toHaveAttribute('readonly');
121
123
  });
124
+ test('passing helper text should display it and correct aria attributes on input', function () {
125
+ var testHelperText = 'testHelperText';
126
+ getComponent({
127
+ helperText: testHelperText,
128
+ status: _statuses["default"].ERROR
129
+ });
130
+
131
+ var helper = _testWrapper.screen.getByText(testHelperText);
132
+
133
+ expect(helper).toBeInTheDocument();
134
+ expect(helper).toHaveClass("is-".concat(_statuses["default"].ERROR));
135
+ var helperTextID = helper.getAttribute('id');
136
+ expect(_testWrapper.screen.getByRole('checkbox')).toHaveAttribute('aria-describedby', helperTextID);
137
+ });
122
138
  test('indeterminate checkbox', function () {
123
139
  var _getComponent = getComponent({
124
140
  isIndeterminate: true
@@ -76,7 +76,7 @@ var _ScrollBox = _interopRequireDefault(require("../ScrollBox"));
76
76
 
77
77
  var _react2 = require("@emotion/react");
78
78
 
79
- var _excluded = ["hasAutoFocus", "hasAddOption", "hasCustomValue", "hasNoEmptySelection", "selectedKey", "onSelectionChange", "defaultItems", "items", "loadingState", "onLoadMore", "inputValue", "menuTrigger", "isNotFlippable", "direction", "scrollBoxProps", "controlProps", "defaultFilter"],
79
+ var _excluded = ["hasAutoFocus", "hasAddOption", "hasCustomValue", "hasNoEmptySelection", "selectedKey", "onSelectionChange", "defaultItems", "items", "loadingState", "onLoadMore", "inputValue", "menuTrigger", "isNotFlippable", "direction", "scrollBoxProps", "controlProps", "defaultFilter", "status", "helperText"],
80
80
  _excluded2 = ["shouldFocusOnHover", "shouldSelectOnPressUp"];
81
81
 
82
82
  function _getRequireWildcardCache(nodeInterop) { if (typeof _WeakMap !== "function") return null; var cacheBabelInterop = new _WeakMap(); var cacheNodeInterop = new _WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
@@ -114,6 +114,8 @@ var ComboBoxField = /*#__PURE__*/(0, _react.forwardRef)(function (props, ref) {
114
114
  scrollBoxProps = props.scrollBoxProps,
115
115
  controlProps = props.controlProps,
116
116
  defaultFilter = props.defaultFilter,
117
+ status = props.status,
118
+ helperText = props.helperText,
117
119
  others = (0, _objectWithoutProperties2["default"])(props, _excluded);
118
120
 
119
121
  var _getAriaAttributeProp = (0, _ariaAttributes.getAriaAttributeProps)(others),
@@ -277,7 +279,8 @@ var ComboBoxField = /*#__PURE__*/(0, _react.forwardRef)(function (props, ref) {
277
279
  inputRef: inputRef,
278
280
  triggerProps: buttonProps,
279
281
  triggerRef: buttonRef,
280
- controlProps: controlProps
282
+ controlProps: controlProps,
283
+ "aria-invalid": status === 'error' && true
281
284
  })), (0, _react2.jsx)(_PopoverContainer["default"], {
282
285
  hasNoArrow: true,
283
286
  isDismissable: true,
@@ -60,6 +60,8 @@ var _index = require("../../index");
60
60
 
61
61
  var _loadingStates = _interopRequireDefault(require("../../utils/devUtils/constants/loadingStates"));
62
62
 
63
+ var _statuses = _interopRequireDefault(require("../../utils/devUtils/constants/statuses"));
64
+
63
65
  var _react3 = require("@emotion/react");
64
66
 
65
67
  function _getRequireWildcardCache(nodeInterop) { if (typeof _WeakMap !== "function") return null; var cacheBabelInterop = new _WeakMap(); var cacheNodeInterop = new _WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
@@ -1110,6 +1112,24 @@ test('if "hasAddOption" is provided, then custom value is added to listbox on bl
1110
1112
 
1111
1113
  expect(options[options.length - 1]).toHaveTextContent(inputValue);
1112
1114
  });
1115
+ test('passing helper text should display it and correct aria attributes on input', function () {
1116
+ var testHelperText = 'testHelperText';
1117
+ getComponent({
1118
+ helperText: testHelperText,
1119
+ status: _statuses["default"].ERROR
1120
+ });
1121
+
1122
+ var helper = _testWrapper.screen.getByText(testHelperText);
1123
+
1124
+ expect(helper).toBeInTheDocument();
1125
+ expect(helper).toHaveClass("is-".concat(_statuses["default"].ERROR));
1126
+
1127
+ var input = _testWrapper.screen.getByRole('combobox');
1128
+
1129
+ expect(input).toHaveAttribute('aria-invalid', 'true');
1130
+ var helperTextID = helper.getAttribute('id');
1131
+ expect(input).toHaveAttribute('aria-describedby', helperTextID);
1132
+ });
1113
1133
  test('should have no accessibility violations', /*#__PURE__*/(0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee5() {
1114
1134
  var _getComponent6, container, results;
1115
1135
 
@@ -36,7 +36,7 @@ var _Text = _interopRequireDefault(require("../Text"));
36
36
 
37
37
  var _react2 = require("@emotion/react");
38
38
 
39
- var _excluded = ["className", "status"];
39
+ var _excluded = ["className", "status", "id"];
40
40
 
41
41
  function _getRequireWildcardCache(nodeInterop) { if (typeof _WeakMap !== "function") return null; var cacheBabelInterop = new _WeakMap(); var cacheNodeInterop = new _WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
42
42
 
@@ -51,6 +51,7 @@ function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj &&
51
51
  var FieldHelperText = /*#__PURE__*/(0, _react.forwardRef)(function (props, ref) {
52
52
  var className = props.className,
53
53
  status = props.status,
54
+ id = props.id,
54
55
  others = (0, _objectWithoutProperties2["default"])(props, _excluded);
55
56
 
56
57
  var _useStatusClasses = (0, _hooks.useStatusClasses)(className, (0, _defineProperty2["default"])({}, "is-".concat(status), true)),
@@ -60,14 +61,18 @@ var FieldHelperText = /*#__PURE__*/(0, _react.forwardRef)(function (props, ref)
60
61
  ref: ref,
61
62
  pt: "sm",
62
63
  variant: "fieldHelperText",
63
- role: "status"
64
+ role: status === 'error' ? 'alert' : 'status',
65
+ id: id
64
66
  }, others, {
65
67
  className: classNames
66
68
  }));
67
69
  });
68
70
  FieldHelperText.propTypes = {
69
71
  /** Determines the color of the field message. */
70
- status: _propTypes["default"].oneOf((0, _values["default"])(_statuses["default"]))
72
+ status: _propTypes["default"].oneOf((0, _values["default"])(_statuses["default"])),
73
+
74
+ /** The element's unique identifier. See [MDN](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/id). */
75
+ id: _propTypes["default"].string
71
76
  };
72
77
  FieldHelperText.defaultProps = {
73
78
  status: _statuses["default"].DEFAULT
@@ -132,6 +132,8 @@ var FileInputField = /*#__PURE__*/(0, _react.forwardRef)(function (_ref, ref) {
132
132
  fieldControlProps = _useField.fieldControlProps,
133
133
  fieldLabelProps = _useField.fieldLabelProps;
134
134
 
135
+ var helperTextId = (0, _uuid.v4)();
136
+
135
137
  var _useVisuallyHidden = (0, _visuallyHidden.useVisuallyHidden)(),
136
138
  visuallyHiddenProps = _useVisuallyHidden.visuallyHiddenProps;
137
139
 
@@ -210,7 +212,8 @@ var FileInputField = /*#__PURE__*/(0, _react.forwardRef)(function (_ref, ref) {
210
212
  handleFileDelete: handleFileDelete,
211
213
  isDisabled: isDisabled || isLoading,
212
214
  key: fileProps.id,
213
- textProps: textProps
215
+ textProps: textProps,
216
+ helperTextId: helperTextId
214
217
  }, fileProps));
215
218
  });
216
219
  }, [uploadedFilesImperative, uploadedFiles, handleFileDelete, isDisabled, isLoading, textProps]);
@@ -257,7 +260,8 @@ var FileInputField = /*#__PURE__*/(0, _react.forwardRef)(function (_ref, ref) {
257
260
  },
258
261
  "data-testid": "file-input-field__loader"
259
262
  })), helperText && (0, _react2.jsx)(_.FieldHelperText, {
260
- status: status
263
+ status: status,
264
+ id: helperTextId
261
265
  }, helperText));
262
266
  });
263
267
  FileInputField.displayName = 'FileInputField';
@@ -218,6 +218,21 @@ test('should display loader if appropriate prop is passed', function () {
218
218
  });
219
219
  expect(_react2.screen.getByTestId(loaderTestId)).toBeInTheDocument();
220
220
  });
221
+ test('passing helper text should display it and correct aria attributes on input', function () {
222
+ var testHelperText = 'testHelperText';
223
+ getComponent({
224
+ helperText: testHelperText,
225
+ status: _statuses["default"].ERROR,
226
+ defaultFileList: [testFileObject]
227
+ });
228
+
229
+ var helper = _react2.screen.getByText(testHelperText);
230
+
231
+ expect(helper).toBeInTheDocument();
232
+ expect(helper).toHaveClass("is-".concat(_statuses["default"].ERROR));
233
+ var helperTextID = helper.getAttribute('id');
234
+ expect(_react2.screen.getAllByRole('button')[0]).toHaveAttribute('aria-describedby', helperTextID);
235
+ });
221
236
  test('should display helper text if passed', function () {
222
237
  var testHelperText = 'testHelperText';
223
238
  getComponent({
@@ -49,7 +49,8 @@ var FileItem = function FileItem(props) {
49
49
  isDisabled = props.isDisabled,
50
50
  name = props.name,
51
51
  status = props.status,
52
- textProps = props.textProps;
52
+ textProps = props.textProps,
53
+ helperTextId = props.helperTextId;
53
54
  var handleDeleteButtonPress = (0, _react.useCallback)(function (e) {
54
55
  return handleFileDelete(e, id);
55
56
  }, [id, handleFileDelete]);
@@ -95,7 +96,8 @@ var FileItem = function FileItem(props) {
95
96
  isDisabled: isDisabled,
96
97
  "aria-label": name,
97
98
  "data-testid": "file-uploaded__download-file-button",
98
- onPress: handleDownloadPress
99
+ onPress: handleDownloadPress,
100
+ "aria-describedby": helperTextId
99
101
  }, (0, _react2.jsx)(_index.Text, (0, _extends2["default"])({
100
102
  color: "active"
101
103
  }, textProps), name)), (0, _react2.jsx)(_index.IconButton, {
@@ -129,6 +131,7 @@ FileItem.propTypes = {
129
131
  id: _propTypes["default"].string,
130
132
  isDisabled: _propTypes["default"].bool,
131
133
  name: _propTypes["default"].string,
134
+ helperTextId: _propTypes["default"].string,
132
135
  status: _propTypes["default"].oneOf((0, _values["default"])(_statuses["default"])),
133
136
  textProps: _propTypes["default"].shape({})
134
137
  };
@@ -38,6 +38,10 @@ var _react = _interopRequireWildcard(require("react"));
38
38
 
39
39
  var _propTypes = _interopRequireDefault(require("prop-types"));
40
40
 
41
+ var _visuallyHidden = require("@react-aria/visually-hidden");
42
+
43
+ var _uuid = require("uuid");
44
+
41
45
  var _ = require("../../");
42
46
 
43
47
  var _ariaAttributes = require("../../utils/devUtils/props/ariaAttributes");
@@ -76,6 +80,7 @@ var ImageUploadField = /*#__PURE__*/(0, _react.forwardRef)(function (props, ref)
76
80
  (0, _react.useImperativeHandle)(ref, function () {
77
81
  return inputRef.current;
78
82
  });
83
+ var statusId = (0, _uuid.v4)();
79
84
  var onAction = (0, _react.useCallback)(function (action) {
80
85
  // eslint-disable-next-line default-case
81
86
  switch (action) {
@@ -97,7 +102,7 @@ var ImageUploadField = /*#__PURE__*/(0, _react.forwardRef)(function (props, ref)
97
102
  }
98
103
  }
99
104
  }, [state.showFileDialog, props === null || props === void 0 ? void 0 : props.onRemove, state.removePreview]);
100
- return (0, _react2.jsx)(_ImageUploadFieldBase["default"], (0, _extends2["default"])({
105
+ return (0, _react2.jsx)(_react["default"].Fragment, null, (0, _react2.jsx)(_ImageUploadFieldBase["default"], (0, _extends2["default"])({
101
106
  fileName: state.fileName,
102
107
  handleInputChange: state.handleInputChange,
103
108
  handleLabelClick: state.handleLabelClick,
@@ -116,14 +121,22 @@ var ImageUploadField = /*#__PURE__*/(0, _react.forwardRef)(function (props, ref)
116
121
  previewHeight: props === null || props === void 0 ? void 0 : props.previewHeight,
117
122
  previewImage: state.previewImage,
118
123
  previewWidth: props === null || props === void 0 ? void 0 : props.previewWidth,
119
- widthHeightSx: state.widthHeightSx
124
+ widthHeightSx: state.widthHeightSx,
125
+ "aria-haspopup": state.isMenuOpen
120
126
  }), (0, _react2.jsx)(_.Menu, {
121
- onAction: onAction
127
+ onAction: onAction,
128
+ "aria-labelledby": statusId
122
129
  }, (0, _react2.jsx)(_.Item, {
123
- key: "upload"
130
+ key: "upload",
131
+ role: "button"
124
132
  }, uploadItemText), (0, _react2.jsx)(_.Item, {
125
- key: "remove"
126
- }, removeItemText)));
133
+ key: "remove",
134
+ role: "button"
135
+ }, removeItemText))), (0, _react2.jsx)(_visuallyHidden.VisuallyHidden, {
136
+ "aria-live": "polite",
137
+ role: state.isMenuOpen ? 'button' : 'status',
138
+ id: statusId
139
+ }, state.isMenuOpen && 'Menu pop up expanded'));
127
140
  });
128
141
  ImageUploadField.propTypes = _objectSpread({
129
142
  /** Image preview (controlled), used to represent the current image state. */
@@ -38,10 +38,10 @@ var _react = _interopRequireWildcard(require("react"));
38
38
 
39
39
  var _propTypes = _interopRequireDefault(require("prop-types"));
40
40
 
41
- var _visuallyHidden = require("@react-aria/visually-hidden");
42
-
43
41
  var _omit = _interopRequireDefault(require("lodash/omit"));
44
42
 
43
+ var _visuallyHidden = require("@react-aria/visually-hidden");
44
+
45
45
  var _index = require("../../index");
46
46
 
47
47
  var _useField2 = _interopRequireDefault(require("../../hooks/useField"));
@@ -95,7 +95,8 @@ var ImageUploadFieldBase = /*#__PURE__*/(0, _react.forwardRef)(function (props,
95
95
  variant: "forms.input.wrapper"
96
96
  }, fieldContainerProps), (0, _react2.jsx)(_Label["default"], (0, _extends2["default"])({}, fieldLabelProps, {
97
97
  onClick: handleLabelClick,
98
- ref: labelRef
98
+ ref: labelRef,
99
+ tabIndex: "-1"
99
100
  })), (0, _react2.jsx)(_index.PopoverMenu, {
100
101
  isOpen: isMenuOpen,
101
102
  onOpenChange: handleOpenMenuChange
@@ -40,6 +40,10 @@ var _propTypes = _interopRequireDefault(require("prop-types"));
40
40
 
41
41
  var _MenuDownIcon = _interopRequireDefault(require("mdi-react/MenuDownIcon"));
42
42
 
43
+ var _uuid = require("uuid");
44
+
45
+ var _visuallyHidden = require("@react-aria/visually-hidden");
46
+
43
47
  var _ = require("../../");
44
48
 
45
49
  var _ariaAttributes = require("../../utils/devUtils/props/ariaAttributes");
@@ -70,11 +74,13 @@ function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { va
70
74
  var LinkSelectField = /*#__PURE__*/(0, _react.forwardRef)(function (props, ref) {
71
75
  var placeholder = props.placeholder,
72
76
  isDisabled = props.isDisabled,
73
- status = props.status;
77
+ status = props.status,
78
+ helperText = props.helperText;
74
79
 
75
80
  var _getAriaAttributeProp = (0, _ariaAttributes.getAriaAttributeProps)(props),
76
81
  ariaProps = _getAriaAttributeProp.ariaProps;
77
82
 
83
+ var helperTextId = (0, _uuid.v4)();
78
84
  (0, _hooks.usePropWarning)(props, 'disabled', 'isDisabled');
79
85
 
80
86
  var _useSelectField = (0, _hooks.useSelectField)(_objectSpread(_objectSpread({
@@ -96,7 +102,8 @@ var LinkSelectField = /*#__PURE__*/(0, _react.forwardRef)(function (props, ref)
96
102
  className: fieldControlProps.className,
97
103
  ref: triggerRef,
98
104
  variant: "link",
99
- tabIndex: isDisabled ? -1 : 0
105
+ tabIndex: isDisabled ? -1 : 0,
106
+ "aria-describedby": helperText && helperTextId
100
107
  }, triggerProps, ariaProps), (0, _react2.jsx)(_.Text, {
101
108
  variant: "label",
102
109
  color: "active"
@@ -113,7 +120,10 @@ var LinkSelectField = /*#__PURE__*/(0, _react.forwardRef)(function (props, ref)
113
120
  sx: state.isOpen ? {
114
121
  transform: 'rotate(180deg)'
115
122
  } : null
116
- }))));
123
+ }))), (0, _react2.jsx)(_visuallyHidden.VisuallyHidden, {
124
+ "aria-live": "polite",
125
+ id: helperTextId
126
+ }, helperText));
117
127
  return (0, _react2.jsx)(_SelectFieldBase["default"], (0, _extends2["default"])({}, props, selectFieldProps, {
118
128
  trigger: trigger
119
129
  }));
@@ -181,10 +181,10 @@ test('select field with helper text', function () {
181
181
  status: _statuses["default"].ERROR
182
182
  });
183
183
 
184
- var fieldHelperText = _testWrapper.screen.getByText(helperText);
184
+ var fieldHelperText = _testWrapper.screen.getAllByText(helperText);
185
185
 
186
- expect(fieldHelperText).toBeInTheDocument();
187
- expect(fieldHelperText).toHaveClass("is-".concat(_statuses["default"].ERROR));
186
+ expect(fieldHelperText[1]).toBeInTheDocument();
187
+ expect(fieldHelperText[1]).toHaveClass("is-".concat(_statuses["default"].ERROR));
188
188
  });
189
189
  test('displays a loader while loading', function () {
190
190
  var _getComponent = getComponent({
@@ -205,6 +205,19 @@ test('displays a loader while loading', function () {
205
205
  });
206
206
  expect(loader).not.toBeInTheDocument();
207
207
  });
208
+ test('passing helper text should display it and correct aria attributes on input', function () {
209
+ var testHelperText = 'testHelperText';
210
+ getComponent({
211
+ helperText: testHelperText,
212
+ status: _statuses["default"].ERROR
213
+ });
214
+
215
+ var helper = _testWrapper.screen.getAllByText(testHelperText)[0];
216
+
217
+ expect(helper).toBeInTheDocument();
218
+ var helperTextID = helper.getAttribute('id');
219
+ expect(_testWrapper.screen.getByRole('button')).toHaveAttribute('aria-describedby', helperTextID);
220
+ });
208
221
  test('should have no accessibility violations', /*#__PURE__*/(0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee() {
209
222
  var _getComponent2, container, results;
210
223
 
@@ -478,10 +478,10 @@ var MultivaluesField = /*#__PURE__*/(0, _react.forwardRef)(function (props, ref)
478
478
  slots: {
479
479
  beforeInput: (0, _react2.jsx)(_react["default"].Fragment, null, readOnlyItems, " ", selectedItems, readOnlyInputEntry)
480
480
  },
481
- value: filterString
482
- }, ariaProps, inputProps)), helperText && (0, _react2.jsx)(_.FieldHelperText, {
483
- status: status
484
- }, helperText), (0, _react2.jsx)(_.PopoverContainer, {
481
+ value: filterString,
482
+ helperText: helperText,
483
+ "aria-invalid": status === 'error' && true
484
+ }, ariaProps, inputProps)), (0, _react2.jsx)(_.PopoverContainer, {
485
485
  hasNoArrow: true,
486
486
  isDismissable: true,
487
487
  isNonModal: true,
@@ -523,17 +523,23 @@ test('read only keys', function () {
523
523
  var deleteButton2 = firstChip.nextSibling;
524
524
  expect(deleteButton2).toBeNull();
525
525
  });
526
- test(' multivalue field with helper text', function () {
527
- var helperText = 'helper text';
526
+ test('passing helper text should display it and correct aria attributes on input', function () {
527
+ var testHelperText = 'testHelperText';
528
528
  getComponent({
529
- helperText: helperText,
529
+ helperText: testHelperText,
530
530
  status: _statuses["default"].ERROR
531
531
  });
532
532
 
533
- var helper = _testWrapper.screen.getByText(helperText);
533
+ var helper = _testWrapper.screen.getByText(testHelperText);
534
534
 
535
535
  expect(helper).toBeInTheDocument();
536
536
  expect(helper).toHaveClass("is-".concat(_statuses["default"].ERROR));
537
+
538
+ var input = _testWrapper.screen.getByRole('combobox');
539
+
540
+ expect(input).toHaveAttribute('aria-invalid', 'true');
541
+ var helperTextID = helper.getAttribute('id');
542
+ expect(input).toHaveAttribute('aria-describedby', helperTextID);
537
543
  });
538
544
  test('read only field', function () {
539
545
  var isReadOnly = true;
@@ -54,6 +54,8 @@ var _utils = require("@react-aria/utils");
54
54
 
55
55
  var _omit = _interopRequireDefault(require("lodash/omit"));
56
56
 
57
+ var _uuid = require("uuid");
58
+
57
59
  var _ = require("../../");
58
60
 
59
61
  var _ariaAttributes = require("../../utils/devUtils/props/ariaAttributes");
@@ -177,6 +179,7 @@ var NumberField = /*#__PURE__*/(0, _react.forwardRef)(function (props, ref) {
177
179
  };
178
180
 
179
181
  inputProps['aria-roledescription'] = null;
182
+ var helperTextId = (0, _uuid.v4)();
180
183
  return (0, _react2.jsx)(_.Box, fieldContainerProps, (0, _react2.jsx)(_.Label, (0, _utils.mergeProps)(fieldLabelProps, labelProps)), (0, _react2.jsx)(_.Box, (0, _extends2["default"])({
181
184
  variant: "numberField.noDefaultArrows"
182
185
  }, groupProps), (0, _react2.jsx)(_.Box, {
@@ -188,9 +191,12 @@ var NumberField = /*#__PURE__*/(0, _react.forwardRef)(function (props, ref) {
188
191
  // overwrite them like defaultValue, value, ect.
189
192
 
190
193
  }, updatedFieldControlProps, (0, _omit["default"])(inputProps, ['name', 'onFocus', 'onBlur']), {
191
- onChange: onInputChange
194
+ onChange: onInputChange,
195
+ "aria-describedby": helperText && helperTextId,
196
+ role: "textbox"
192
197
  })), ControlArrows), helperText && (0, _react2.jsx)(_.FieldHelperText, {
193
- status: status
198
+ status: status,
199
+ id: helperTextId
194
200
  }, helperText)));
195
201
  });
196
202
  var _default = NumberField;
@@ -183,4 +183,18 @@ test('number field can be focused', function () {
183
183
  _userEvent["default"].tab();
184
184
 
185
185
  expect(_testWrapper.screen.getByLabelText(testLabel)).toHaveClass('is-focused');
186
+ });
187
+ test('passing helper text should display it and correct aria attributes on input', function () {
188
+ var testHelperText = 'testHelperText';
189
+ getComponent({
190
+ helperText: testHelperText,
191
+ status: _statuses["default"].ERROR
192
+ });
193
+
194
+ var helper = _testWrapper.screen.getByText(testHelperText);
195
+
196
+ expect(helper).toBeInTheDocument();
197
+ expect(helper).toHaveClass("is-".concat(_statuses["default"].ERROR));
198
+ var helperTextID = helper.getAttribute('id');
199
+ expect(_testWrapper.screen.getByRole('textbox')).toHaveAttribute('aria-describedby', helperTextID);
186
200
  });
@@ -42,6 +42,8 @@ var _radio2 = require("@react-stately/radio");
42
42
 
43
43
  var _propTypes = _interopRequireDefault(require("prop-types"));
44
44
 
45
+ var _uuid = require("uuid");
46
+
45
47
  var _ = require("../../");
46
48
 
47
49
  var _ariaAttributes = require("../../utils/devUtils/props/ariaAttributes");
@@ -97,6 +99,7 @@ var RadioGroupField = /*#__PURE__*/(0, _react.forwardRef)(function (props, ref)
97
99
  var unhandledAriaProps = {
98
100
  'aria-controls': props['aria-controls']
99
101
  };
102
+ var helperTextId = (0, _uuid.v4)();
100
103
  return (0, _react2.jsx)(_.Box, (0, _extends2["default"])({
101
104
  ref: ref,
102
105
  className: classNames
@@ -107,7 +110,9 @@ var RadioGroupField = /*#__PURE__*/(0, _react.forwardRef)(function (props, ref)
107
110
  variant: "forms.label.radioGroup"
108
111
  }, labelProps), label), (0, _react2.jsx)(_.Box, {
109
112
  variant: "forms.radioGroupWrapper",
110
- isRow: orientation === _orientation["default"].HORIZONTAL
113
+ isRow: orientation === _orientation["default"].HORIZONTAL,
114
+ "aria-labelledby": helperText && helperTextId,
115
+ "data-testid": "radioGroupWrapper"
111
116
  }, (0, _react2.jsx)(_RadioField.RadioContext.Provider, {
112
117
  value: _objectSpread({
113
118
  isDisabled: isDisabled
@@ -116,7 +121,8 @@ var RadioGroupField = /*#__PURE__*/(0, _react.forwardRef)(function (props, ref)
116
121
  status: status,
117
122
  sx: {
118
123
  pt: 'xs'
119
- }
124
+ },
125
+ id: helperTextId
120
126
  }, helperText));
121
127
  });
122
128
  RadioGroupField.propTypes = _objectSpread({
@@ -199,4 +199,18 @@ test('radio group with horizontal orientation', function () {
199
199
  var group = _testWrapper.screen.getByRole('radiogroup');
200
200
 
201
201
  expect(group).toHaveAttribute('aria-orientation', _orientation["default"].HORIZONTAL);
202
+ });
203
+ test('passing helper text should display it and correct aria attributes on input', function () {
204
+ var testHelperText = 'testHelperText';
205
+ getComponent({
206
+ helperText: testHelperText,
207
+ status: _statuses["default"].ERROR
208
+ });
209
+
210
+ var helper = _testWrapper.screen.getByText(testHelperText);
211
+
212
+ expect(helper).toBeInTheDocument();
213
+ expect(helper).toHaveClass("is-".concat(_statuses["default"].ERROR));
214
+ var helperTextID = helper.getAttribute('id');
215
+ expect(_testWrapper.screen.getByTestId('radioGroupWrapper')).toHaveAttribute('aria-labelledby', helperTextID);
202
216
  });
@@ -64,12 +64,15 @@ function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { va
64
64
  * React Stately.
65
65
  */
66
66
  var SelectField = /*#__PURE__*/(0, _react.forwardRef)(function (props, ref) {
67
+ var status = props.status;
67
68
  (0, _hooks.usePropWarning)(props, 'disabled', 'isDisabled');
68
69
 
69
70
  var _useSelectField = (0, _hooks.useSelectField)(props, ref),
70
71
  selectFieldProps = (0, _extends2["default"])({}, _useSelectField);
71
72
 
72
- return (0, _react2.jsx)(_SelectFieldBase["default"], (0, _extends2["default"])({}, props, selectFieldProps));
73
+ return (0, _react2.jsx)(_SelectFieldBase["default"], (0, _extends2["default"])({}, props, selectFieldProps, {
74
+ "aria-invalid": status === 'error' && true
75
+ }));
73
76
  });
74
77
  SelectField.propTypes = _objectSpread({
75
78
  /** Alignment of the popover menu relative to the trigger. */
@@ -12,6 +12,8 @@ var _testWrapper = require("../../utils/testUtils/testWrapper");
12
12
 
13
13
  var _index = require("../../index");
14
14
 
15
+ var _statuses = _interopRequireDefault(require("../../utils/devUtils/constants/statuses"));
16
+
15
17
  var _react2 = require("@emotion/react");
16
18
 
17
19
  var items = [{
@@ -82,4 +84,22 @@ test('default select field', function () {
82
84
  expect(hiddenLabel.closest('[aria-hidden="true"]')).not.toBeNull();
83
85
  expect(visibleLabel.closest('[aria-hidden="true"]')).toBeNull();
84
86
  /* eslint-enable testing-library/no-node-access */
87
+ });
88
+ test('passing helper text should display it and correct aria attributes on input', function () {
89
+ var testHelperText = 'testHelperText';
90
+ getComponent({
91
+ helperText: testHelperText,
92
+ status: _statuses["default"].ERROR
93
+ });
94
+
95
+ var helper = _testWrapper.screen.getByText(testHelperText);
96
+
97
+ expect(helper).toBeInTheDocument();
98
+ expect(helper).toHaveClass("is-".concat(_statuses["default"].ERROR));
99
+
100
+ var visibleInput = _testWrapper.screen.getAllByLabelText(defaultProps.label)[1];
101
+
102
+ expect(visibleInput).toHaveAttribute('aria-invalid', 'true');
103
+ var helperTextID = helper.getAttribute('id');
104
+ expect(_testWrapper.screen.getByRole('button')).toHaveAttribute('aria-describedby', helperTextID);
85
105
  });
@@ -44,6 +44,8 @@ var _select = require("@react-aria/select");
44
44
 
45
45
  var _MenuDownIcon = _interopRequireDefault(require("mdi-react/MenuDownIcon"));
46
46
 
47
+ var _uuid = require("uuid");
48
+
47
49
  var _ariaAttributes = require("../../utils/devUtils/props/ariaAttributes");
48
50
 
49
51
  var _statuses = _interopRequireDefault(require("../../utils/devUtils/constants/statuses"));
@@ -108,13 +110,15 @@ var SelectFieldBase = /*#__PURE__*/(0, _react.forwardRef)(function (_ref, ref) {
108
110
  var _getAriaAttributeProp = (0, _ariaAttributes.getAriaAttributeProps)(others),
109
111
  ariaProps = _getAriaAttributeProp.ariaProps;
110
112
 
113
+ var helperTextId = (0, _uuid.v4)();
111
114
  var defaultTrigger = (0, _react2.jsx)(_Box["default"], {
112
115
  className: fieldControlProps.className,
113
116
  variant: "forms.input.container"
114
117
  }, (0, _react2.jsx)(_Button["default"], (0, _extends2["default"])({
115
118
  className: fieldControlProps.className,
116
119
  ref: triggerRef,
117
- variant: "forms.select"
120
+ variant: "forms.select",
121
+ "aria-describedby": helperText && helperTextId
118
122
  }, triggerProps, ariaProps), (0, _react2.jsx)(_Box["default"], (0, _extends2["default"])({
119
123
  as: "span",
120
124
  variant: "forms.select.currentValue"
@@ -144,7 +148,8 @@ var SelectFieldBase = /*#__PURE__*/(0, _react.forwardRef)(function (_ref, ref) {
144
148
  name: name,
145
149
  isDisabled: true
146
150
  }), trigger || defaultTrigger, overlay, helperText && (0, _react2.jsx)(_FieldHelperText["default"], {
147
- status: status
151
+ status: status,
152
+ id: helperTextId
148
153
  }, helperText));
149
154
  });
150
155
  SelectFieldBase.propTypes = _objectSpread({