carbon-react 101.2.0 → 101.3.3

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 (34) hide show
  1. package/lib/__internal__/checkable-input/checkable-input.component.js +26 -8
  2. package/lib/__internal__/checkable-input/checkable-input.d.ts +2 -0
  3. package/lib/__internal__/checkable-input/hidden-checkable-input.component.js +1 -20
  4. package/lib/__internal__/checkable-input/hidden-checkable-input.d.ts +0 -8
  5. package/lib/__internal__/form-field/form-field.component.js +3 -3
  6. package/lib/__internal__/form-field/form-field.d.ts +2 -2
  7. package/lib/__internal__/input-icon-toggle/input-icon-toggle.component.js +7 -3
  8. package/lib/__internal__/input-icon-toggle/input-icon-toggle.d.ts +1 -0
  9. package/lib/__internal__/label/label.component.js +5 -5
  10. package/lib/__internal__/label/label.d.ts +2 -2
  11. package/lib/__internal__/validations/validation-icon.component.js +5 -0
  12. package/lib/__internal__/validations/validation-icon.d.ts +2 -0
  13. package/lib/components/flat-table/flat-table.component.js +11 -5
  14. package/lib/components/flat-table/flat-table.style.js +12 -0
  15. package/lib/components/help/help.component.js +6 -1
  16. package/lib/components/help/help.d.ts +2 -0
  17. package/lib/components/icon/icon.component.js +5 -0
  18. package/lib/components/icon/icon.d.ts +2 -0
  19. package/lib/components/search/search.component.js +7 -2
  20. package/lib/components/search/search.d.ts +2 -0
  21. package/lib/components/tabs/__internal__/tab-title/index.d.ts +1 -0
  22. package/lib/components/tabs/__internal__/tab-title/tab-title.component.js +24 -13
  23. package/lib/components/tabs/__internal__/tab-title/tab-title.d.ts +39 -0
  24. package/lib/components/tabs/__internal__/tab-title/tab-title.style.js +80 -94
  25. package/lib/components/tabs/__internal__/tabs-header/index.d.ts +1 -0
  26. package/lib/components/tabs/__internal__/tabs-header/tab-header.d.ts +16 -0
  27. package/lib/components/tabs/__internal__/tabs-header/tabs-header.style.js +1 -1
  28. package/lib/components/tabs/tabs.component.js +1 -0
  29. package/lib/components/textarea/textarea.component.js +23 -1
  30. package/lib/components/textbox/textbox.component.js +24 -2
  31. package/lib/hooks/__internal__/useInputAccessibility/index.d.ts +24 -0
  32. package/lib/hooks/__internal__/useInputAccessibility/index.js +15 -0
  33. package/lib/hooks/__internal__/useInputAccessibility/useInputAccessibility.js +29 -0
  34. package/package.json +1 -1
@@ -19,6 +19,8 @@ var _hiddenCheckableInput = _interopRequireDefault(require("./hidden-checkable-i
19
19
 
20
20
  var _guid = _interopRequireDefault(require("../utils/helpers/guid"));
21
21
 
22
+ var _useInputAccessibility = _interopRequireDefault(require("../../hooks/__internal__/useInputAccessibility"));
23
+
22
24
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
23
25
 
24
26
  function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; }
@@ -26,6 +28,7 @@ function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return
26
28
  function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
27
29
 
28
30
  const CheckableInput = ({
31
+ ariaLabelledBy: externalAriaLabelledBy,
29
32
  autoFocus,
30
33
  checked,
31
34
  children,
@@ -58,16 +61,28 @@ const CheckableInput = ({
58
61
  const {
59
62
  current: id
60
63
  } = (0, _react.useRef)(inputId || (0, _guid.default)());
61
- const labelId = label ? `${id}-label` : undefined;
62
- const helpId = [error, warning, info, labelHelp].filter(validation => typeof validation === "string").length ? `${id}-help` : undefined;
63
- const fieldHelpId = fieldHelp ? `${id}-field-help` : undefined;
64
+ const {
65
+ labelId,
66
+ tooltipId,
67
+ fieldHelpId,
68
+ ariaDescribedBy,
69
+ ariaLabelledBy
70
+ } = (0, _useInputAccessibility.default)({
71
+ id,
72
+ error,
73
+ warning,
74
+ info,
75
+ label,
76
+ labelHelp,
77
+ fieldHelp
78
+ });
64
79
  const isRadio = type === "radio";
65
80
  const formFieldProps = {
66
81
  disabled,
67
82
  error,
68
83
  fieldHelp,
69
84
  fieldHelpInline,
70
- helpId,
85
+ tooltipId,
71
86
  fieldHelpId,
72
87
  id,
73
88
  info,
@@ -87,16 +102,16 @@ const CheckableInput = ({
87
102
  useValidationIcon: validationOnLabel
88
103
  };
89
104
  const inputProps = {
105
+ "aria-describedby": ariaDescribedBy,
106
+ "aria-labelledby": externalAriaLabelledBy || ariaLabelledBy,
107
+ "aria-invalid": !!error,
90
108
  autoFocus,
91
109
  checked,
92
110
  disabled,
93
- helpId,
94
- fieldHelpId,
95
111
  id,
96
112
  inputRef,
97
113
  type,
98
114
  value,
99
- labelId,
100
115
  name,
101
116
  onBlur,
102
117
  onChange,
@@ -202,7 +217,10 @@ CheckableInput.propTypes = {
202
217
  })]),
203
218
 
204
219
  /** When true, displays validation icon on label */
205
- validationOnLabel: _propTypes.default.bool
220
+ validationOnLabel: _propTypes.default.bool,
221
+
222
+ /** The id of the element that labels the input */
223
+ ariaLabelledBy: _propTypes.default.string
206
224
  };
207
225
  CheckableInput.defaultProps = {
208
226
  reverse: false,
@@ -33,6 +33,8 @@ export interface CommonCheckableInputProps
33
33
  reverse?: boolean;
34
34
  /** Size of the component */
35
35
  size?: "small" | "large";
36
+ /** The id of the element that labels the input */
37
+ ariaLabelledBy?: string;
36
38
  }
37
39
 
38
40
  export interface CheckableInputProps extends CommonCheckableInputProps {
@@ -22,9 +22,6 @@ function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj;
22
22
  function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
23
23
 
24
24
  const HiddenCheckableInput = ({
25
- helpId,
26
- fieldHelpId,
27
- labelId,
28
25
  name,
29
26
  checked,
30
27
  type,
@@ -32,7 +29,6 @@ const HiddenCheckableInput = ({
32
29
  inputRef,
33
30
  onChange,
34
31
  autoFocus,
35
- ariaLabelledBy,
36
32
  ...props
37
33
  }) => {
38
34
  const {
@@ -72,13 +68,10 @@ const HiddenCheckableInput = ({
72
68
  if (onMouseLeaveGroup) onMouseLeaveGroup(ev);
73
69
  };
74
70
 
75
- const ariaDescribedBy = [fieldHelpId, helpId].filter(Boolean).join(" ");
76
71
  return /*#__PURE__*/_react.default.createElement(_hiddenCheckableInput.default, _extends({
77
72
  autoFocus: autoFocus,
78
73
  "aria-checked": checked,
79
74
  checked: checked,
80
- "aria-labelledby": ariaLabelledBy || labelId,
81
- "aria-describedby": ariaDescribedBy,
82
75
  name: name,
83
76
  role: type,
84
77
  type: type,
@@ -100,12 +93,6 @@ HiddenCheckableInput.propTypes = {
100
93
  /** Checked state of the input */
101
94
  checked: _propTypes.default.bool,
102
95
 
103
- /** Element id for aria-describedby */
104
- helpId: _propTypes.default.string,
105
-
106
- /** Element id for aria-describedby */
107
- fieldHelpId: _propTypes.default.string,
108
-
109
96
  /** Input name */
110
97
  name: _propTypes.default.string,
111
98
 
@@ -124,9 +111,6 @@ HiddenCheckableInput.propTypes = {
124
111
  /** OnMouseEnter event handler */
125
112
  onMouseEnter: _propTypes.default.func,
126
113
 
127
- /** Element id for aria-labelledby */
128
- labelId: _propTypes.default.string,
129
-
130
114
  /** HTML type attribute of the input */
131
115
  type: _propTypes.default.string.isRequired,
132
116
 
@@ -136,10 +120,7 @@ HiddenCheckableInput.propTypes = {
136
120
  /** A callback to retrieve the input reference */
137
121
  inputRef: _propTypes.default.oneOfType([_propTypes.default.func, _propTypes.default.shape({
138
122
  current: _propTypes.default.instanceOf(Element)
139
- })]),
140
-
141
- /** The id of the element that labels the input */
142
- ariaLabelledBy: _propTypes.default.string
123
+ })])
143
124
  };
144
125
 
145
126
  var _default = /*#__PURE__*/_react.default.memo(HiddenCheckableInput);
@@ -31,14 +31,6 @@ export interface HiddenCheckableInputProps
31
31
  extends CommonHiddenCheckableInputProps {
32
32
  /** HTML type attribute of the input */
33
33
  type: string;
34
- /** Element id for aria-describedby */
35
- helpId?: string;
36
- /** Element id for aria-describedby */
37
- fieldHelpId?: string;
38
- /** Element id for aria-labelledby */
39
- labelId?: string;
40
- /** The id of the element that labels the input */
41
- ariaLabelledBy?: string;
42
34
  }
43
35
 
44
36
  declare function HiddenCheckableInput(
@@ -43,7 +43,7 @@ const FormField = ({
43
43
  error,
44
44
  warning,
45
45
  info,
46
- helpId,
46
+ tooltipId,
47
47
  fieldHelpId,
48
48
  helpTabIndex,
49
49
  label,
@@ -93,7 +93,7 @@ const FormField = ({
93
93
  warning: warning,
94
94
  info: info,
95
95
  help: labelHelp,
96
- helpId: helpId,
96
+ tooltipId: tooltipId,
97
97
  helpTabIndex: helpTabIndex,
98
98
  htmlFor: id,
99
99
  helpIcon: labelHelpIcon,
@@ -128,7 +128,7 @@ FormField.propTypes = {
128
128
  error: errorPropType,
129
129
  warning: errorPropType,
130
130
  info: errorPropType,
131
- helpId: _propTypes.default.string,
131
+ tooltipId: _propTypes.default.string,
132
132
  fieldHelpId: _propTypes.default.string,
133
133
  helpTabIndex: _propTypes.default.oneOfType([_propTypes.default.number, _propTypes.default.string]),
134
134
  id: _propTypes.default.string.isRequired,
@@ -9,8 +9,8 @@ export interface CommonFormFieldPropTypes
9
9
  disabled?: boolean;
10
10
  /** Help content to be displayed under an input */
11
11
  fieldHelp?: React.ReactNode;
12
- /** The unique id of the Help component */
13
- helpId?: string;
12
+ /** The unique id of the Help component tooltip, used for accessibility */
13
+ tooltipId?: string;
14
14
  /** The unique id of the FieldHelp component */
15
15
  fieldHelpId?: string;
16
16
  /** Overrides the default tabindex of the Help component */
@@ -40,7 +40,8 @@ const InputIconToggle = ({
40
40
  info,
41
41
  useValidationIcon,
42
42
  align,
43
- iconTabIndex
43
+ iconTabIndex,
44
+ tooltipId
44
45
  }) => {
45
46
  if (useValidationIcon && !disabled && shouldDisplayValidationIcon({
46
47
  error,
@@ -59,6 +60,7 @@ const InputIconToggle = ({
59
60
  onBlur: onBlur,
60
61
  isPartOfInput: true,
61
62
  tabIndex: iconTabIndex,
63
+ tooltipId: tooltipId,
62
64
  tooltipPosition: align === "right" ? "left" : "right"
63
65
  }));
64
66
  }
@@ -72,7 +74,8 @@ const InputIconToggle = ({
72
74
  onMouseDown: onMouseDown,
73
75
  tabIndex: iconTabIndex
74
76
  }, /*#__PURE__*/_react.default.createElement(_icon.default, {
75
- type: type
77
+ type: type,
78
+ tooltipId: tooltipId
76
79
  }));
77
80
  }
78
81
 
@@ -93,7 +96,8 @@ InputIconToggle.propTypes = {
93
96
  size: _propTypes.default.oneOf(["small", "medium", "large"]),
94
97
  align: _propTypes.default.oneOf(["left", "right"]),
95
98
  useValidationIcon: _propTypes.default.bool,
96
- iconTabIndex: _propTypes.default.number
99
+ iconTabIndex: _propTypes.default.number,
100
+ tooltipId: _propTypes.default.string
97
101
  };
98
102
  var _default = InputIconToggle;
99
103
  exports.default = _default;
@@ -15,6 +15,7 @@ export interface InputIconToggleProps {
15
15
  align?: "left" | "right";
16
16
  useValidationIcon?: boolean;
17
17
  iconTabIndex?: number;
18
+ tooltipId?: string;
18
19
  }
19
20
  declare function InputIconToggle(props: InputIconToggleProps): JSX.Element;
20
21
 
@@ -51,7 +51,7 @@ const Label = ({
51
51
  width,
52
52
  optional,
53
53
  labelId,
54
- helpId,
54
+ tooltipId,
55
55
  children,
56
56
  error,
57
57
  warning,
@@ -104,7 +104,7 @@ const Label = ({
104
104
  inline
105
105
  });
106
106
  return /*#__PURE__*/_react.default.createElement(_iconWrapper.default, null, /*#__PURE__*/_react.default.createElement(_validationIcon.default, {
107
- iconId: helpId,
107
+ tooltipId: tooltipId,
108
108
  error: error,
109
109
  warning: warning,
110
110
  info: info,
@@ -114,7 +114,7 @@ const Label = ({
114
114
  }
115
115
 
116
116
  return help && /*#__PURE__*/_react.default.createElement(_iconWrapper.default, wrapperProps, /*#__PURE__*/_react.default.createElement(_help.default, {
117
- helpId: helpId,
117
+ tooltipId: tooltipId,
118
118
  tabIndex: helpTabIndex,
119
119
  type: helpIcon,
120
120
  isFocused: isFocused
@@ -158,8 +158,8 @@ Label.propTypes = {
158
158
  /** The unique id of the label element */
159
159
  labelId: _propTypes.default.string,
160
160
 
161
- /** The unique id of the Help component */
162
- helpId: _propTypes.default.string,
161
+ /** The unique id of the Help component tooltip, used for accessibility */
162
+ tooltipId: _propTypes.default.string,
163
163
 
164
164
  /** Children elements */
165
165
  children: _propTypes.default.node,
@@ -16,8 +16,8 @@ export interface LabelPropTypes extends ValidationPropTypes {
16
16
  optional?: boolean;
17
17
  /** The unique id of the label element */
18
18
  labelId?: string;
19
- /** The unique id of the Help component */
20
- helpId?: string;
19
+ /** The unique id of the Help component tooltip, used for accessibility */
20
+ tooltipId?: string;
21
21
  /** Children elements */
22
22
  children?: React.ReactNode;
23
23
  /** A message that the Help component will display */
@@ -48,6 +48,7 @@ const ValidationIcon = ({
48
48
  onFocus,
49
49
  onBlur,
50
50
  iconId,
51
+ tooltipId,
51
52
  isPartOfInput,
52
53
  tabIndex,
53
54
  onClick,
@@ -95,6 +96,7 @@ const ValidationIcon = ({
95
96
  key: `${validationType}-icon`,
96
97
  type: validationType,
97
98
  tabIndex: tabIndex,
99
+ tooltipId: tooltipId,
98
100
  tooltipMessage: validationMessage,
99
101
  tooltipPosition: tooltipPosition,
100
102
  tooltipVisible: hasFocus || hasMouseOver || groupHasFocus || groupHasMouseOver || triggeredByIcon,
@@ -130,6 +132,9 @@ ValidationIcon.propTypes = { ...marginPropTypes,
130
132
  `The \`${propName}\` prop supplied to \`${componentName}\` must be an array containing some or all of ["top", "bottom", "left", "right"].`);
131
133
  },
132
134
 
135
+ /** Id passed to the tooltip container, used for accessibility purposes. */
136
+ tooltipId: _propTypes.default.string,
137
+
133
138
  /** An onClick handler */
134
139
  onClick: _propTypes.default.func,
135
140
 
@@ -15,6 +15,8 @@ export interface ValidationIconProps extends ValidationPropTypes {
15
15
  * (see https://popper.js.org/docs/v2/modifiers/flip/#fallbackplacements)
16
16
  */
17
17
  tooltipFlipOverrides?: ["top" | "bottom" | "left" | "right"];
18
+ /** Id passed to the tooltip container, used for accessibility purposes */
19
+ tooltipId?: string;
18
20
  /** An onClick handler */
19
21
  onClick?: (ev: React.MouseEvent<HTMLElement>) => void;
20
22
  /** An onBlur handler */
@@ -39,6 +39,7 @@ const FlatTable = ({
39
39
  hasMaxHeight = false,
40
40
  ariaDescribedby,
41
41
  minHeight,
42
+ overflowX,
42
43
  ...rest
43
44
  }) => {
44
45
  const addDefaultHeight = !height && (hasStickyHead || hasStickyFooter);
@@ -57,16 +58,18 @@ const FlatTable = ({
57
58
  }) => /*#__PURE__*/_react.default.createElement(_flatTable.StyledFlatTableWrapper, _extends({
58
59
  isInSidebar: isInSidebar,
59
60
  hasStickyHead: hasStickyHead,
60
- colorTheme: colorTheme
61
- }, rest, {
61
+ colorTheme: colorTheme,
62
62
  minHeight: minHeight,
63
63
  overflowY: !isInSidebar && (hasStickyHead || hasStickyFooter) ? "auto" : undefined,
64
64
  height: addDefaultHeight && !hasMaxHeight ? "99%" : height,
65
65
  maxHeight: hasMaxHeight ? "100%" : undefined,
66
66
  display: "flex",
67
67
  flexDirection: "column",
68
- justifyContent: hasStickyFooter || height ? "space-between" : undefined
69
- }), /*#__PURE__*/_react.default.createElement(_flatTable.StyledFlatTable, _extends({
68
+ justifyContent: hasStickyFooter || height ? "space-between" : undefined,
69
+ tabIndex: "0",
70
+ role: "region",
71
+ overflowX: overflowX
72
+ }, rest), /*#__PURE__*/_react.default.createElement(_flatTable.StyledFlatTable, _extends({
70
73
  "data-component": "flat-table"
71
74
  }, tableStylingProps), caption ? /*#__PURE__*/_react.default.createElement("caption", null, caption) : null, /*#__PURE__*/_react.default.createElement(FlatTableThemeContext.Provider, {
72
75
  value: {
@@ -114,7 +117,10 @@ FlatTable.propTypes = { ...marginPropTypes,
114
117
  size: _propTypes.default.oneOf(["compact", "small", "medium", "large", "extraLarge"]),
115
118
 
116
119
  /** Applies max-height of 100% to FlatTable if true */
117
- hasMaxHeight: _propTypes.default.bool
120
+ hasMaxHeight: _propTypes.default.bool,
121
+
122
+ /** Set the overflow X of the table wrapper. Any valid CSS string */
123
+ overflowX: _propTypes.default.string
118
124
  };
119
125
  FlatTable.defaultProps = {
120
126
  colorTheme: "dark",
@@ -107,6 +107,18 @@ const StyledFlatTableWrapper = (0, _styledComponents.default)(_box.default)`
107
107
  }) => (0, _styledComponents.css)`
108
108
  box-sizing: border-box;
109
109
 
110
+ :focus {
111
+ outline: 2px solid ${theme.colors.focus};
112
+
113
+ :not(:focus-visible) {
114
+ outline: none;
115
+ }
116
+
117
+ :focus-visible {
118
+ outline: 2px solid ${theme.colors.focus};
119
+ }
120
+ }
121
+
110
122
  ${isInSidebar ? "min-width: fit-content" : `box-shadow: inset 0px 0px 0px 1px ${theme.table.secondary}`};
111
123
  `}
112
124
 
@@ -45,6 +45,7 @@ const Help = ({
45
45
  tooltipPosition,
46
46
  isFocused,
47
47
  type,
48
+ tooltipId,
48
49
  tooltipBgColor,
49
50
  tooltipFontColor,
50
51
  tooltipFlipOverrides,
@@ -107,6 +108,7 @@ const Help = ({
107
108
  tooltipFontColor: tooltipFontColor,
108
109
  tooltipFlipOverrides: tooltipFlipOverrides,
109
110
  focusable: false,
111
+ tooltipId: tooltipId,
110
112
  "aria-hidden": "true"
111
113
  }, href && {
112
114
  role: "tooltip",
@@ -122,7 +124,7 @@ Help.propTypes = { ...marginPropTypes,
122
124
  /** Message to display in tooltip */
123
125
  children: _propTypes.default.node,
124
126
 
125
- /** The unique id of the component (used with aria-describedby for accessibility) */
127
+ /** The unique id of the component */
126
128
  helpId: _propTypes.default.string,
127
129
 
128
130
  /** Overrides the default tabindex of the component */
@@ -166,6 +168,9 @@ Help.propTypes = { ...marginPropTypes,
166
168
  `The \`${propName}\` prop supplied to \`${componentName}\` must be an array containing some or all of ["top", "bottom", "left", "right"].`);
167
169
  },
168
170
 
171
+ /** Id passed to the tooltip container, used for accessibility purposes. */
172
+ tooltipId: _propTypes.default.string,
173
+
169
174
  /** Aria label */
170
175
  ariaLabel: _propTypes.default.string
171
176
  };
@@ -28,6 +28,8 @@ export interface HelpProps extends MarginProps {
28
28
  tooltipFlipOverrides?: ["top" | "bottom" | "left" | "right"];
29
29
  /** Position of tooltip relative to target */
30
30
  tooltipPosition?: "top" | "bottom" | "left" | "right";
31
+ /** Id passed to the tooltip container, used for accessibility purposes */
32
+ tooltipId?: string;
31
33
  /** Help Icon type */
32
34
  type?: IconType;
33
35
  /** Aria label */
@@ -48,6 +48,7 @@ const Icon = /*#__PURE__*/_react.default.forwardRef(({
48
48
  tooltipBgColor,
49
49
  tooltipFontColor,
50
50
  tooltipFlipOverrides,
51
+ tooltipId,
51
52
  tabIndex,
52
53
  isPartOfInput,
53
54
  inputSize,
@@ -122,6 +123,7 @@ const Icon = /*#__PURE__*/_react.default.forwardRef(({
122
123
  message: tooltipMessage,
123
124
  position: tooltipPositionFromContext || tooltipPosition,
124
125
  type: type,
126
+ id: tooltipId,
125
127
  isVisible: visible,
126
128
  isPartOfInput: isPartOfInput,
127
129
  inputSize: inputSize,
@@ -186,6 +188,9 @@ Icon.propTypes = { ...marginPropTypes,
186
188
  /** Override font color of the Tooltip, provide any color from palette or any valid css color value. */
187
189
  tooltipFontColor: _propTypes.default.string,
188
190
 
191
+ /** Id passed to the tooltip container, used for accessibility purposes. */
192
+ tooltipId: _propTypes.default.string,
193
+
189
194
  /** Overrides the default flip behaviour of the Tooltip, must be an array containing some or all of ["top", "bottom", "left", "right"].
190
195
  *
191
196
  * See the Popper [documentation](https://popper.js.org/docs/v2/modifiers/flip/#fallbackplacements) for more information
@@ -233,6 +233,8 @@ export interface IconProps extends MarginProps {
233
233
  tooltipFontColor?: string;
234
234
  /** Overrides the default flip behaviour of the Tooltip */
235
235
  tooltipFlipOverrides?: TooltipPositions[];
236
+ /** Id passed to the tooltip container, used for accessibility purposes */
237
+ tooltipId?: string;
236
238
  }
237
239
 
238
240
  declare function Icon(
@@ -54,6 +54,7 @@ const Search = ({
54
54
  variant = "default",
55
55
  "aria-label": ariaLabel = "search",
56
56
  inputRef,
57
+ tabIndex,
57
58
  ...rest
58
59
  }) => {
59
60
  const isControlled = value !== undefined;
@@ -173,7 +174,8 @@ const Search = ({
173
174
  onBlur: onBlur,
174
175
  onChange: onChange,
175
176
  onKeyDown: onKeyDown,
176
- inputRef: assignInput
177
+ inputRef: assignInput,
178
+ tabIndex: tabIndex
177
179
  }), searchButton && /*#__PURE__*/_react.default.createElement(_search.StyledSearchButton, null, Boolean(isFocused || (!isControlled ? searchValue.length : value.length)) && /*#__PURE__*/_react.default.createElement(_button.default, _extends({
178
180
  tabIndex: iconTabIndex,
179
181
  size: "medium",
@@ -249,7 +251,10 @@ Search.propTypes = {
249
251
  */
250
252
  inputRef: _propTypes.default.shape({
251
253
  current: _propTypes.default.instanceOf(Element)
252
- })
254
+ }),
255
+
256
+ /** Input tabindex */
257
+ tabIndex: _propTypes.default.number
253
258
  };
254
259
  var _default = Search;
255
260
  exports.default = _default;
@@ -40,6 +40,8 @@ export interface SearchProps extends MarginProps {
40
40
  variant?: string;
41
41
  /** A callback to retrieve the input reference */
42
42
  inputRef?: React.RefObject<HTMLInputElement>;
43
+ /** Input tabindex */
44
+ tabIndex?: number;
43
45
  }
44
46
 
45
47
  declare function Search(props: SearchProps): JSX.Element;
@@ -0,0 +1 @@
1
+ export { default } from "./tab-title";
@@ -52,6 +52,7 @@ const TabTitle = /*#__PURE__*/_react.default.forwardRef(({
52
52
  isInSidebar,
53
53
  href,
54
54
  onKeyDown,
55
+ align,
55
56
  ...tabTitleProps
56
57
  }, ref) => {
57
58
  const keys = (0, _react.useRef)([]);
@@ -74,6 +75,8 @@ const TabTitle = /*#__PURE__*/_react.default.forwardRef(({
74
75
  };
75
76
 
76
77
  const handleClick = ev => {
78
+ var _ref$current;
79
+
77
80
  ev.preventDefault();
78
81
  const customEvent = { ...ev,
79
82
  target: { ...ev.target,
@@ -86,8 +89,10 @@ const TabTitle = /*#__PURE__*/_react.default.forwardRef(({
86
89
  if (href) {
87
90
  onClick(customEvent);
88
91
  return window.open(href, "_blank");
89
- }
92
+ } // safari does not focus buttons by default
90
93
 
94
+
95
+ (_ref$current = ref.current) === null || _ref$current === void 0 ? void 0 : _ref$current.focus();
91
96
  return onClick(customEvent);
92
97
  };
93
98
 
@@ -131,18 +136,17 @@ const TabTitle = /*#__PURE__*/_react.default.forwardRef(({
131
136
  error: error,
132
137
  warning: warning,
133
138
  info: info,
134
- size: size,
135
139
  noRightBorder: noRightBorder,
136
140
  alternateStyling: alternateStyling || isInSidebar,
137
141
  borders: borders,
138
142
  isInSidebar: isInSidebar
139
- }, tabTitleProps, (0, _tags.default)("tab-header", tabTitleProps), {
140
- onKeyDown: handleKeyDown
141
- }), /*#__PURE__*/_react.default.createElement(_tabTitle.StyledTitleContent, _extends({}, isHref && {
143
+ }, tabTitleProps, isHref && {
142
144
  href,
143
145
  target: "_blank",
144
146
  as: "a"
145
- }, {
147
+ }, (0, _tags.default)("tab-header", tabTitleProps), {
148
+ onKeyDown: handleKeyDown
149
+ }), /*#__PURE__*/_react.default.createElement(_tabTitle.StyledTitleContent, {
146
150
  error: error,
147
151
  warning: warning,
148
152
  info: info,
@@ -155,23 +159,29 @@ const TabTitle = /*#__PURE__*/_react.default.forwardRef(({
155
159
  hasSiblings: !!siblings,
156
160
  isTabSelected: isTabSelected,
157
161
  hasCustomLayout: !!customLayout,
158
- alternateStyling: hasAlternateStyling
159
- }), renderContent(), isHref && /*#__PURE__*/_react.default.createElement(_icon.default, {
162
+ alternateStyling: hasAlternateStyling,
163
+ align: align,
164
+ hasHref: !!href
165
+ }, renderContent(), isHref && /*#__PURE__*/_react.default.createElement(_icon.default, {
160
166
  type: "link"
161
- }), /*#__PURE__*/_react.default.createElement(_tabTitle.StyledLayoutWrapper, {
167
+ }), hasFailedValidation && /*#__PURE__*/_react.default.createElement(_tabTitle.StyledLayoutWrapper, {
168
+ position: position,
162
169
  hasCustomSibling: !!customLayout
163
170
  }, error && /*#__PURE__*/_react.default.createElement(_validationIcon.default, {
164
171
  onClick: handleClick,
165
172
  tooltipPosition: "top",
166
- error: errorMessage
173
+ error: errorMessage,
174
+ tabIndex: null
167
175
  }), !error && warning && /*#__PURE__*/_react.default.createElement(_validationIcon.default, {
168
176
  onClick: handleClick,
169
177
  tooltipPosition: "top",
170
- warning: warningMessage
178
+ warning: warningMessage,
179
+ tabIndex: null
171
180
  }), !warning && !error && info && /*#__PURE__*/_react.default.createElement(_validationIcon.default, {
172
181
  onClick: handleClick,
173
182
  tooltipPosition: "top",
174
- info: infoMessage
183
+ info: infoMessage,
184
+ tabIndex: null
175
185
  }))), !(hasFailedValidation || hasAlternateStyling) && isTabSelected && /*#__PURE__*/_react.default.createElement(_tabTitle.StyledSelectedIndicator, {
176
186
  "data-element": "tab-selected-indicator",
177
187
  position: position,
@@ -204,7 +214,8 @@ TabTitle.propTypes = {
204
214
  noRightBorder: _propTypes.default.bool,
205
215
  customLayout: _propTypes.default.node,
206
216
  isInSidebar: _propTypes.default.bool,
207
- href: _propTypes.default.string
217
+ href: _propTypes.default.string,
218
+ align: _propTypes.default.oneOf(["left", "right"])
208
219
  };
209
220
  var _default = TabTitle;
210
221
  exports.default = _default;
@@ -0,0 +1,39 @@
1
+ import * as React from "react";
2
+
3
+ export interface TabTitleProps {
4
+ title: string;
5
+ id?: string;
6
+ dataTabId?: string;
7
+ className?: string;
8
+ children?: React.ReactNode;
9
+ isTabSelected?: boolean;
10
+ position?: "top" | "left";
11
+ errorMessage?: string;
12
+ warningMessage?: string;
13
+ infoMessage?: string;
14
+ errors?: boolean;
15
+ warning?: boolean;
16
+ info?: boolean;
17
+ borders?: boolean;
18
+ noLeftBorder?: boolean;
19
+ noRightBorder?: boolean;
20
+ alternateStyling?: boolean;
21
+ isInSidebar?: boolean;
22
+ siblings?: React.ReactNode[];
23
+ titlePosition?: "before" | "after";
24
+ href?: string;
25
+ tabIndex?: string;
26
+ size?: "default" | "large";
27
+ align?: "left" | "right";
28
+ customLayout?: React.ReactNode;
29
+ onClick?: (
30
+ ev: React.MouseEvent<HTMLButtonElement | HTMLAnchorElement>
31
+ ) => void;
32
+ onKeyDown?: (
33
+ ev: React.KeyboardEvent<HTMLButtonElement | HTMLAnchorElement>
34
+ ) => void;
35
+ }
36
+
37
+ declare function TabTitle(props: TabTitleProps): JSX.Element;
38
+
39
+ export default TabTitle;
@@ -21,8 +21,9 @@ function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return
21
21
 
22
22
  function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
23
23
 
24
- const StyledTitleContent = _styledComponents.default.div`
24
+ const StyledTitleContent = _styledComponents.default.span`
25
25
  outline: none;
26
+ display: inline-block;
26
27
 
27
28
  ${({
28
29
  theme,
@@ -32,17 +33,22 @@ const StyledTitleContent = _styledComponents.default.div`
32
33
  noLeftBorder,
33
34
  noRightBorder,
34
35
  isTabSelected,
35
- hasSiblings,
36
- href,
36
+ hasHref,
37
37
  error,
38
- warning,
39
- info,
40
- alternateStyling
38
+ alternateStyling,
39
+ align
41
40
  }) => (0, _styledComponents.css)`
42
41
  line-height: 20px;
43
42
  margin: 0;
43
+ text-align: ${align};
44
+
45
+ ${position === "left" && (0, _styledComponents.css)`
46
+ display: flex;
47
+ width: 100%;
48
+ justify-content: ${align === "right" ? "flex-end" : "flex-start"};
49
+ `}
44
50
 
45
- ${href && (0, _styledComponents.css)`
51
+ ${hasHref && (0, _styledComponents.css)`
46
52
  color: ${theme.text.color};
47
53
  display: block;
48
54
  text-decoration: none;
@@ -81,10 +87,8 @@ const StyledTitleContent = _styledComponents.default.div`
81
87
 
82
88
  ${size === "large" && position === "top" && (0, _styledComponents.css)`
83
89
  padding: 10px 24px;
90
+ ${borders && `padding-bottom: 9px;`}
84
91
  font-size: 16px;
85
- ${isTabSelected && !hasSiblings && !(error || warning || info) && (0, _styledComponents.css)`
86
- padding-bottom: 6px;
87
- `}
88
92
  `}
89
93
 
90
94
  ${size === "large" && position === "left" && (0, _styledComponents.css)`
@@ -95,11 +99,12 @@ const StyledTitleContent = _styledComponents.default.div`
95
99
 
96
100
  ${size === "default" && (0, _styledComponents.css)`
97
101
  padding: 10px 16px;
98
- ${isTabSelected && !(error || warning || info) && position === "top" && (0, _styledComponents.css)`
99
- padding-bottom: 8px;
100
- `}
101
102
 
102
- ${position === "left" && !isTabSelected && !alternateStyling && error && `margin-right: -2px;`}
103
+ ${borders && `padding-bottom: 9px;`}
104
+
105
+ ${position === "left" && !isTabSelected && !alternateStyling && error && `
106
+ margin-right: -2px;
107
+ `}
103
108
  `}
104
109
  `}
105
110
 
@@ -131,7 +136,7 @@ const StyledTitleContent = _styledComponents.default.div`
131
136
  padding-right: ${size === "large" ? "26px;" : "18px;"};
132
137
  `}
133
138
 
134
- &:hover {
139
+ &:hover {
135
140
  outline: 1px solid;
136
141
  outline-offset: -1px;
137
142
 
@@ -174,10 +179,10 @@ const StyledTitleContent = _styledComponents.default.div`
174
179
 
175
180
  ${position === "left" && (0, _styledComponents.css)`
176
181
  border-right-color: transparent;
177
- padding-right: ${size === "large" ? "26px;" : "18px;"};
182
+ padding-right: ${size === "large" ? "26px" : "18px"};
178
183
  `}
179
184
 
180
- &:hover {
185
+ &:hover {
181
186
  outline: 2px solid ${theme.colors.error};
182
187
  outline-offset: -2px;
183
188
  ${position === "top" && (0, _styledComponents.css)`
@@ -190,7 +195,7 @@ const StyledTitleContent = _styledComponents.default.div`
190
195
 
191
196
  ${position === "left" && (0, _styledComponents.css)`
192
197
  border-right-color: transparent;
193
- padding-right: ${size === "large" ? "26px;" : "18px;"};
198
+ padding-right: ${size === "large" ? "26px" : "18px"};
194
199
  `}
195
200
  }
196
201
  `}
@@ -206,23 +211,11 @@ const StyledTitleContent = _styledComponents.default.div`
206
211
  position
207
212
  }) => hasSiblings && !hasCustomLayout && position === "top" && (0, _styledComponents.css)`
208
213
  height: 20px;
214
+ padding-top: 10px;
215
+ padding-bottom: 10px;
209
216
 
210
- ${size === "default" && (0, _styledComponents.css)`
211
- padding-top: 10px;
212
- padding-bottom: 10px;
213
-
214
- ${!(error || warning || info) && isTabSelected && (0, _styledComponents.css)`
215
- padding-bottom: 8px;
216
- `}
217
- `}
218
-
219
- ${size === "large" && (0, _styledComponents.css)`
220
- padding-top: 10px;
221
- padding-bottom: 10px;
222
-
223
- ${!(error || warning || info) && isTabSelected && (0, _styledComponents.css)`
224
- padding-bottom: 6px;
225
- `}
217
+ ${size === "large" && !(error || warning || info) && isTabSelected && (0, _styledComponents.css)`
218
+ padding-bottom: 6px;
226
219
  `}
227
220
  `}
228
221
 
@@ -238,13 +231,13 @@ const StyledTitleContent = _styledComponents.default.div`
238
231
  display: flex;
239
232
 
240
233
  ${position === "left" && (0, _styledComponents.css)`
241
- padding: ${size === "large" ? "2px;" : "0px;"}
242
- ${isTabSelected && (0, _styledComponents.css)`
243
- padding-right: 0px;
244
- `}
245
- ${(error || warning || info) && (0, _styledComponents.css)`
246
- padding-right: ${size === "large" ? "26px" : "18px"};
247
- `};
234
+ padding: ${size === "large" ? "2px" : "0px"};
235
+ ${isTabSelected && (0, _styledComponents.css)`
236
+ padding-right: 0px;
237
+ `}
238
+ ${(error || warning || info) && (0, _styledComponents.css)`
239
+ padding-right: ${size === "large" ? "26px" : "18px"};
240
+ `}
248
241
  `}
249
242
 
250
243
  ${position === "top" && (0, _styledComponents.css)`
@@ -253,49 +246,63 @@ const StyledTitleContent = _styledComponents.default.div`
253
246
  padding-bottom: 0px;
254
247
  `}
255
248
  ${(error || warning || info) && (0, _styledComponents.css)`
256
- padding-bottom: ${size === "large" ? "4px;" : "2px;"}
257
- padding-right: ${size === "large" ? "18px;" : "14px;"}
258
-
259
- &:hover {
260
249
  padding-bottom: ${size === "large" ? "4px;" : "2px;"}
261
- }
262
- `};
250
+ padding-right: ${size === "large" ? "18px;" : "14px;"}
251
+
252
+ &:hover {
253
+ padding-bottom: ${size === "large" ? "4px;" : "2px;"}
254
+ }
255
+ `};
263
256
  `}
264
257
  `}
265
258
  `;
266
259
  exports.StyledTitleContent = StyledTitleContent;
267
- const StyledTabTitle = _styledComponents.default.li`
260
+ const StyledTabTitle = _styledComponents.default.button`
268
261
  background-color: transparent;
269
262
  display: inline-block;
270
263
  font-weight: bold;
271
- height: 100%;
272
264
  position: relative;
265
+ border: none;
266
+ cursor: pointer;
267
+ font-size: 14px;
268
+ padding: 0px;
269
+ text-decoration: none;
270
+ outline-offset: 0px;
271
+ margin: 0;
272
+
273
+ a:visited {
274
+ color: inherit;
275
+ }
273
276
 
274
277
  ${({
275
278
  position,
276
279
  borders,
277
280
  noRightBorder,
278
281
  noLeftBorder
279
- }) => `
280
- ${position === "top" && (0, _styledComponents.css)`
281
- ${borders && !(noRightBorder || noLeftBorder) && (0, _styledComponents.css)`
282
- &:not(:first-of-type) {
283
- margin-left: -1px;
284
- }
285
- `}
286
- `}
287
- ${position === "left" && (0, _styledComponents.css)`
288
- ${borders && (0, _styledComponents.css)`
289
- &:not(:first-of-type) {
290
- margin-top: -1px;
291
- }
292
- `}
293
- `}
294
- `}
282
+ }) => (0, _styledComponents.css)`
283
+ ${position === "top" && (0, _styledComponents.css)`
284
+ height: 40px;
295
285
 
296
- &:first-child {
297
- margin-left: 0;
298
- }
286
+ ${borders && !(noRightBorder || noLeftBorder) && (0, _styledComponents.css)`
287
+ &:nth-of-type(n + 1) {
288
+ margin-left: -1px;
289
+ }
290
+ &:first-child {
291
+ margin-left: 0;
292
+ }
293
+ `}
294
+ `}
295
+ ${position === "left" && (0, _styledComponents.css)`
296
+ ${borders && (0, _styledComponents.css)`
297
+ &:nth-of-type(n + 1) {
298
+ margin-top: -1px;
299
+ }
300
+ &:first-child {
301
+ margin-top: 0;
302
+ }
303
+ `}
304
+ `}
305
+ `}
299
306
 
300
307
  ${({
301
308
  isTabSelected,
@@ -319,27 +326,12 @@ const StyledTabTitle = _styledComponents.default.li`
319
326
  error,
320
327
  warning,
321
328
  info,
322
- size,
323
- isInSidebar,
324
- position
329
+ isInSidebar
325
330
  }) => isTabSelected && (0, _styledComponents.css)`
326
331
  ${!isInSidebar && "z-index: 1;"}
327
332
  color: ${theme.text.color};
328
333
  background-color: ${theme.colors.white};
329
334
 
330
- ${alternateStyling && (0, _styledComponents.css)`
331
- border-bottom: 2px solid ${theme.tab.background};
332
- `}
333
-
334
- ${!alternateStyling && (0, _styledComponents.css)`
335
- padding-bottom: 2px;
336
- `}
337
-
338
- ${size === "large" && (0, _styledComponents.css)`
339
- ${position === "top" && `
340
- padding-bottom: ${alternateStyling ? "3px" : "4px"};
341
- `}
342
- `}
343
335
  ${(error || warning || info) && (0, _styledComponents.css)`
344
336
  padding-bottom: 0px;
345
337
  `}
@@ -364,7 +356,6 @@ const StyledTabTitle = _styledComponents.default.li`
364
356
 
365
357
  ${({
366
358
  position,
367
- size,
368
359
  borders,
369
360
  theme,
370
361
  alternateStyling,
@@ -387,7 +378,7 @@ const StyledTabTitle = _styledComponents.default.li`
387
378
  }
388
379
  `}
389
380
 
390
- display: block;
381
+ display: flex;
391
382
  height: auto;
392
383
  margin-left: 0px;
393
384
 
@@ -422,12 +413,6 @@ const StyledTabTitle = _styledComponents.default.li`
422
413
 
423
414
  background-color: ${theme.colors.white};
424
415
 
425
- ${size === "large" && (0, _styledComponents.css)`
426
- & ${StyledTitleContent} {
427
- padding-right: 22px;
428
- }
429
- `}
430
-
431
416
  &:hover {
432
417
  ${alternateStyling && ` border-right-color: ${theme.tab.background};`}
433
418
  background-color: ${theme.colors.white};
@@ -473,7 +458,8 @@ const StyledLayoutWrapper = _styledComponents.default.div`
473
458
  ${({
474
459
  hasCustomLayout,
475
460
  titlePosition,
476
- hasCustomSibling
461
+ hasCustomSibling,
462
+ position
477
463
  }) => !hasCustomLayout && (0, _styledComponents.css)`
478
464
  display: inline-flex;
479
465
 
@@ -500,7 +486,7 @@ const StyledLayoutWrapper = _styledComponents.default.div`
500
486
  ${_icon.default} {
501
487
  height: 16px;
502
488
  left: -2px;
503
- top: 3px;
489
+ top: ${position === "left" ? "1px" : "3px"};
504
490
  }
505
491
  }
506
492
  `}
@@ -0,0 +1 @@
1
+ export { default } from "./tab-header";
@@ -0,0 +1,16 @@
1
+ import * as React from "react";
2
+
3
+ export interface TabHeaderProps {
4
+ role?: string;
5
+ position?: "top" | "left";
6
+ extendedLine?: boolean;
7
+ noRightBorder?: boolean;
8
+ alternateStyling?: boolean;
9
+ isInSidebar?: boolean;
10
+ children: React.ReactNode;
11
+ align?: "left" | "right";
12
+ }
13
+
14
+ declare function TabHeader(props: TabHeaderProps): JSX.Element;
15
+
16
+ export default TabHeader;
@@ -50,7 +50,7 @@ const StyledTabsHeaderWrapper = _styledComponents.default.div`
50
50
  `}
51
51
  `;
52
52
  exports.StyledTabsHeaderWrapper = StyledTabsHeaderWrapper;
53
- const StyledTabsHeaderList = _styledComponents.default.ul`
53
+ const StyledTabsHeaderList = _styledComponents.default.div`
54
54
  display: flex;
55
55
  box-shadow: inset 0px ${computeLineWidth} 0px 0px
56
56
  ${({
@@ -249,6 +249,7 @@ const Tabs = ({
249
249
  noRightBorder: ["no right side", "no sides"].includes(borders),
250
250
  customLayout: customLayout,
251
251
  isInSidebar: isInSidebar,
252
+ align: align,
252
253
  onFocus: () => {
253
254
  if (!hasTabStop(tabId)) {
254
255
  setTabStopId(tabId);
@@ -33,6 +33,8 @@ var _i18nContext = _interopRequireDefault(require("../../__internal__/i18n-conte
33
33
 
34
34
  var _tooltipProvider = require("../../__internal__/tooltip-provider");
35
35
 
36
+ var _useInputAccessibility = _interopRequireDefault(require("../../hooks/__internal__/useInputAccessibility"));
37
+
36
38
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
37
39
 
38
40
  function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; }
@@ -101,6 +103,21 @@ const Textarea = ({
101
103
  }
102
104
  };
103
105
 
106
+ const {
107
+ labelId,
108
+ tooltipId,
109
+ fieldHelpId,
110
+ ariaDescribedBy,
111
+ ariaLabelledBy
112
+ } = (0, _useInputAccessibility.default)({
113
+ id,
114
+ error,
115
+ warning,
116
+ info,
117
+ label,
118
+ labelHelp,
119
+ fieldHelp
120
+ });
104
121
  (0, _react.useEffect)(() => {
105
122
  if (expandable) {
106
123
  expandTextarea();
@@ -146,10 +163,12 @@ const Textarea = ({
146
163
  "data-element": dataElement
147
164
  }, (0, _utils.filterStyledSystemMarginProps)(props)), /*#__PURE__*/_react.default.createElement(_formField.default, {
148
165
  fieldHelp: fieldHelp,
166
+ fieldHelpId: fieldHelpId,
149
167
  error: error,
150
168
  warning: warning,
151
169
  info: info,
152
170
  label: label,
171
+ labelId: labelId,
153
172
  disabled: disabled,
154
173
  id: id,
155
174
  labelInline: labelInline,
@@ -157,6 +176,7 @@ const Textarea = ({
157
176
  labelWidth: labelWidth,
158
177
  labelHelp: labelHelp,
159
178
  labelSpacing: labelSpacing,
179
+ tooltipId: tooltipId,
160
180
  isRequired: props.required,
161
181
  useValidationIcon: validationOnLabel,
162
182
  adaptiveLabelBreakpoint: adaptiveLabelBreakpoint
@@ -169,9 +189,11 @@ const Textarea = ({
169
189
  warning: warning,
170
190
  info: info
171
191
  }, /*#__PURE__*/_react.default.createElement(_input2.default, _extends({
192
+ "aria-invalid": !!error,
193
+ "aria-labelledby": ariaLabelledBy,
194
+ "aria-describedby": ariaDescribedBy,
172
195
  autoFocus: autoFocus,
173
196
  name: name,
174
- "aria-invalid": !!error,
175
197
  ref: inputRef,
176
198
  maxLength: enforceCharacterLimit && characterLimit ? characterLimit : undefined,
177
199
  onChange: onChange,
@@ -29,6 +29,8 @@ var _tooltipProvider = require("../../__internal__/tooltip-provider");
29
29
 
30
30
  var _useCharacterCount = _interopRequireDefault(require("../../hooks/__internal__/useCharacterCount"));
31
31
 
32
+ var _useInputAccessibility = _interopRequireDefault(require("../../hooks/__internal__/useInputAccessibility/useInputAccessibility"));
33
+
32
34
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
33
35
 
34
36
  function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
@@ -42,7 +44,7 @@ const Textbox = ({
42
44
  disabled,
43
45
  inputIcon,
44
46
  leftChildren,
45
- labelId,
47
+ labelId: externalLabelId,
46
48
  label,
47
49
  labelAlign,
48
50
  labelHelp,
@@ -90,12 +92,29 @@ const Textbox = ({
90
92
  ...props
91
93
  }) => {
92
94
  const [maxLength, characterCount] = (0, _useCharacterCount.default)(value, characterLimit, warnOverLimit, enforceCharacterLimit);
95
+ const {
96
+ labelId: internalLabelId,
97
+ tooltipId,
98
+ fieldHelpId,
99
+ ariaDescribedBy
100
+ } = (0, _useInputAccessibility.default)({
101
+ id,
102
+ error,
103
+ warning,
104
+ info,
105
+ label,
106
+ labelHelp,
107
+ fieldHelp
108
+ });
109
+ const labelId = externalLabelId || internalLabelId;
93
110
  return /*#__PURE__*/_react.default.createElement(_tooltipProvider.TooltipProvider, {
94
111
  helpAriaLabel: helpAriaLabel,
95
112
  tooltipPosition: tooltipPosition
96
113
  }, /*#__PURE__*/_react.default.createElement(_inputBehaviour.InputBehaviour, null, /*#__PURE__*/_react.default.createElement(_formField.default, _extends({
114
+ tooltipId: tooltipId,
97
115
  disabled: disabled,
98
116
  fieldHelp: fieldHelp,
117
+ fieldHelpId: fieldHelpId,
99
118
  error: error,
100
119
  warning: warning,
101
120
  info: info,
@@ -132,6 +151,8 @@ const Textbox = ({
132
151
  }, {
133
152
  align: align,
134
153
  "aria-invalid": !!error,
154
+ "aria-labelledby": labelId,
155
+ "aria-describedby": ariaDescribedBy,
135
156
  autoFocus: autoFocus,
136
157
  deferTimeout: deferTimeout,
137
158
  disabled: disabled,
@@ -160,7 +181,8 @@ const Textbox = ({
160
181
  readOnly: readOnly,
161
182
  size: size,
162
183
  useValidationIcon: !validationOnLabel,
163
- warning: warning
184
+ warning: warning,
185
+ tooltipId: tooltipId
164
186
  }))), characterCount));
165
187
  };
166
188
 
@@ -0,0 +1,24 @@
1
+ interface InputAccessibilityProperties {
2
+ labelId?: string;
3
+ tooltipId?: string;
4
+ fieldHelpId?: string;
5
+ ariaDescribedBy?: string;
6
+ ariaLabelledBy?: string;
7
+ }
8
+
9
+ export default function useInputAccessibility(
10
+ /** Input id - */
11
+ id: string,
12
+ /** Error validation message */
13
+ error?: string,
14
+ /** Warning validation message */
15
+ warning?: string,
16
+ /** Info validation message */
17
+ info?: string,
18
+ /** Label */
19
+ label?: string,
20
+ /** labelHelp message */
21
+ labelHelp?: string,
22
+ /** fieldHelp message */
23
+ fieldHelp?: string
24
+ ): void;
@@ -0,0 +1,15 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ Object.defineProperty(exports, "default", {
7
+ enumerable: true,
8
+ get: function () {
9
+ return _useInputAccessibility.default;
10
+ }
11
+ });
12
+
13
+ var _useInputAccessibility = _interopRequireDefault(require("./useInputAccessibility"));
14
+
15
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
@@ -0,0 +1,29 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = useInputAccessibility;
7
+
8
+ function useInputAccessibility({
9
+ id,
10
+ error,
11
+ warning,
12
+ info,
13
+ label,
14
+ labelHelp,
15
+ fieldHelp
16
+ }) {
17
+ const labelId = label ? `${id}-label` : undefined;
18
+ const tooltipId = [error, warning, info, labelHelp].filter(validation => typeof validation === "string").length ? `${id}-tooltip` : undefined;
19
+ const fieldHelpId = fieldHelp ? `${id}-field-help` : undefined;
20
+ const ariaDescribedBy = [fieldHelpId, tooltipId].filter(Boolean).join(" ");
21
+ const ariaLabelledBy = labelId;
22
+ return {
23
+ labelId,
24
+ tooltipId,
25
+ fieldHelpId,
26
+ ariaDescribedBy,
27
+ ariaLabelledBy
28
+ };
29
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "carbon-react",
3
- "version": "101.2.0",
3
+ "version": "101.3.3",
4
4
  "description": "A library of reusable React components for easily building user interfaces.",
5
5
  "engineStrict": true,
6
6
  "engines": {