@carbon/react 1.100.0 → 1.101.0-rc.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 (118) hide show
  1. package/.playwright/INTERNAL_AVT_REPORT_DO_NOT_USE.json +966 -966
  2. package/es/components/AILabel/index.d.ts +1 -1
  3. package/es/components/AILabel/index.js +1 -12
  4. package/es/components/Checkbox/Checkbox.js +5 -3
  5. package/es/components/CheckboxGroup/CheckboxGroup.js +4 -3
  6. package/es/components/CodeSnippet/CodeSnippet.d.ts +1 -1
  7. package/es/components/ComboBox/ComboBox.js +18 -10
  8. package/es/components/ComboButton/index.d.ts +1 -1
  9. package/es/components/ComboButton/index.js +3 -2
  10. package/es/components/ComposedModal/ComposedModal.js +17 -22
  11. package/es/components/ComposedModal/ModalHeader.d.ts +2 -2
  12. package/es/components/ComposedModal/ModalHeader.js +1 -1
  13. package/es/components/Copy/Copy.d.ts +1 -1
  14. package/es/components/CopyButton/CopyButton.d.ts +1 -1
  15. package/es/components/DataTable/DataTable.d.ts +2 -0
  16. package/es/components/DataTable/DataTable.js +6 -5
  17. package/es/components/DataTable/Table.d.ts +1 -1
  18. package/es/components/DataTable/Table.js +10 -4
  19. package/es/components/DataTable/state/sorting.d.ts +4 -2
  20. package/es/components/FileUploader/FileUploaderItem.d.ts +1 -1
  21. package/es/components/FileUploader/FileUploaderItem.js +3 -2
  22. package/es/components/Menu/Menu.js +8 -4
  23. package/es/components/Menu/MenuItem.d.ts +5 -1
  24. package/es/components/Menu/MenuItem.js +11 -1
  25. package/es/components/MenuButton/index.d.ts +1 -1
  26. package/es/components/MenuButton/index.js +3 -2
  27. package/es/components/MultiSelect/FilterableMultiSelect.d.ts +1 -1
  28. package/es/components/MultiSelect/FilterableMultiSelect.js +7 -5
  29. package/es/components/MultiSelect/MultiSelect.js +8 -4
  30. package/es/components/Notification/Notification.js +2 -1
  31. package/es/components/NumberInput/NumberInput.d.ts +1 -1
  32. package/es/components/NumberInput/NumberInput.js +5 -4
  33. package/es/components/OverflowMenu/OverflowMenu.d.ts +1 -0
  34. package/es/components/OverflowMenu/OverflowMenu.js +8 -4
  35. package/es/components/PageHeader/PageHeader.d.ts +1 -1
  36. package/es/components/PageHeader/PageHeader.js +5 -5
  37. package/es/components/RadioButtonGroup/RadioButtonGroup.js +4 -3
  38. package/es/components/Select/Select.js +2 -1
  39. package/es/components/StructuredList/StructuredList.d.ts +1 -1
  40. package/es/components/StructuredList/StructuredList.js +2 -4
  41. package/es/components/Tabs/Tabs.d.ts +2 -2
  42. package/es/components/Tabs/Tabs.js +20 -26
  43. package/es/components/Tag/DismissibleTag.js +3 -2
  44. package/es/components/Tag/OperationalTag.js +3 -2
  45. package/es/components/Tag/SelectableTag.js +3 -2
  46. package/es/components/Tag/Tag.js +3 -2
  47. package/es/components/TextArea/TextArea.d.ts +1 -1
  48. package/es/components/TextArea/TextArea.js +6 -5
  49. package/es/components/TextInput/ControlledPasswordInput.js +7 -6
  50. package/es/components/TextInput/PasswordInput.js +5 -6
  51. package/es/components/TextInput/TextInput.js +4 -4
  52. package/es/components/TimePicker/TimePicker.js +2 -2
  53. package/es/components/Tooltip/DefinitionTooltip.d.ts +1 -1
  54. package/es/components/Tooltip/DefinitionTooltip.js +3 -2
  55. package/es/internal/useId.js +3 -4
  56. package/es/internal/usePresence.js +3 -2
  57. package/es/internal/useResizeObserver.d.ts +1 -1
  58. package/es/internal/useResizeObserver.js +5 -7
  59. package/es/tools/events.d.ts +1 -1
  60. package/lib/components/AILabel/index.d.ts +1 -1
  61. package/lib/components/AILabel/index.js +1 -12
  62. package/lib/components/Checkbox/Checkbox.js +5 -3
  63. package/lib/components/CheckboxGroup/CheckboxGroup.js +4 -3
  64. package/lib/components/CodeSnippet/CodeSnippet.d.ts +1 -1
  65. package/lib/components/ComboBox/ComboBox.js +18 -10
  66. package/lib/components/ComboButton/index.d.ts +1 -1
  67. package/lib/components/ComboButton/index.js +2 -1
  68. package/lib/components/ComposedModal/ComposedModal.js +16 -21
  69. package/lib/components/ComposedModal/ModalHeader.d.ts +2 -2
  70. package/lib/components/ComposedModal/ModalHeader.js +1 -1
  71. package/lib/components/Copy/Copy.d.ts +1 -1
  72. package/lib/components/CopyButton/CopyButton.d.ts +1 -1
  73. package/lib/components/DataTable/DataTable.d.ts +2 -0
  74. package/lib/components/DataTable/DataTable.js +6 -5
  75. package/lib/components/DataTable/Table.d.ts +1 -1
  76. package/lib/components/DataTable/Table.js +10 -4
  77. package/lib/components/DataTable/state/sorting.d.ts +4 -2
  78. package/lib/components/FileUploader/FileUploaderItem.d.ts +1 -1
  79. package/lib/components/FileUploader/FileUploaderItem.js +2 -1
  80. package/lib/components/Menu/Menu.js +7 -3
  81. package/lib/components/Menu/MenuItem.d.ts +5 -1
  82. package/lib/components/Menu/MenuItem.js +11 -1
  83. package/lib/components/MenuButton/index.d.ts +1 -1
  84. package/lib/components/MenuButton/index.js +2 -1
  85. package/lib/components/MultiSelect/FilterableMultiSelect.d.ts +1 -1
  86. package/lib/components/MultiSelect/FilterableMultiSelect.js +6 -4
  87. package/lib/components/MultiSelect/MultiSelect.js +7 -3
  88. package/lib/components/Notification/Notification.js +2 -1
  89. package/lib/components/NumberInput/NumberInput.d.ts +1 -1
  90. package/lib/components/NumberInput/NumberInput.js +5 -4
  91. package/lib/components/OverflowMenu/OverflowMenu.d.ts +1 -0
  92. package/lib/components/OverflowMenu/OverflowMenu.js +7 -3
  93. package/lib/components/PageHeader/PageHeader.d.ts +1 -1
  94. package/lib/components/PageHeader/PageHeader.js +4 -4
  95. package/lib/components/RadioButtonGroup/RadioButtonGroup.js +4 -3
  96. package/lib/components/Select/Select.js +2 -1
  97. package/lib/components/StructuredList/StructuredList.d.ts +1 -1
  98. package/lib/components/StructuredList/StructuredList.js +2 -4
  99. package/lib/components/Tabs/Tabs.d.ts +2 -2
  100. package/lib/components/Tabs/Tabs.js +15 -21
  101. package/lib/components/Tag/DismissibleTag.js +2 -1
  102. package/lib/components/Tag/OperationalTag.js +2 -1
  103. package/lib/components/Tag/SelectableTag.js +2 -1
  104. package/lib/components/Tag/Tag.js +2 -1
  105. package/lib/components/TextArea/TextArea.d.ts +1 -1
  106. package/lib/components/TextArea/TextArea.js +6 -5
  107. package/lib/components/TextInput/ControlledPasswordInput.js +7 -6
  108. package/lib/components/TextInput/PasswordInput.js +5 -6
  109. package/lib/components/TextInput/TextInput.js +4 -4
  110. package/lib/components/TimePicker/TimePicker.js +2 -2
  111. package/lib/components/Tooltip/DefinitionTooltip.d.ts +1 -1
  112. package/lib/components/Tooltip/DefinitionTooltip.js +3 -2
  113. package/lib/internal/useId.js +2 -3
  114. package/lib/internal/usePresence.js +2 -1
  115. package/lib/internal/useResizeObserver.d.ts +1 -1
  116. package/lib/internal/useResizeObserver.js +4 -6
  117. package/lib/tools/events.d.ts +1 -1
  118. package/package.json +8 -8
@@ -50,6 +50,8 @@ const Menu = /*#__PURE__*/React.forwardRef(function Menu({
50
50
  const [childState, childDispatch] = React.useReducer(MenuContext.menuReducer, {
51
51
  ...context.state,
52
52
  isRoot: false,
53
+ hasIcons: false,
54
+ hasSelectableItems: false,
53
55
  size,
54
56
  requestCloseRoot: isRoot ? handleClose : context.state.requestCloseRoot
55
57
  });
@@ -112,9 +114,9 @@ const Menu = /*#__PURE__*/React.forwardRef(function Menu({
112
114
  function handleKeyDown(e) {
113
115
  e.stopPropagation();
114
116
 
115
- // if the user presses escape or this is a submenu
116
- // and the user presses ArrowLeft, close it
117
- if ((match.match(e, keys.Escape) || !isRoot && match.match(e, keys.ArrowLeft)) && onClose) {
117
+ // If the user presses escape or tab, or this is a submenu and the user presses ArrowLeft, close it.
118
+ if ((match.match(e, keys.Escape) || match.match(e, keys.Tab) || !isRoot && match.match(e, keys.ArrowLeft)) && onClose) {
119
+ e.preventDefault();
118
120
  handleClose();
119
121
  } else {
120
122
  focusItem(e);
@@ -248,6 +250,8 @@ const Menu = /*#__PURE__*/React.forwardRef(function Menu({
248
250
  }
249
251
  return [fitValue(ranges.x, 'x') ?? -1, fitValue(ranges.y, 'y') ?? -1];
250
252
  }
253
+
254
+ // When a menu is opened, focus the first item.
251
255
  React.useEffect(() => {
252
256
  if (open) {
253
257
  const raf = requestAnimationFrame(() => {
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Copyright IBM Corp. 2023, 2025
2
+ * Copyright IBM Corp. 2023, 2026
3
3
  *
4
4
  * This source code is licensed under the Apache-2.0 license found in the
5
5
  * LICENSE file in the root directory of this source tree.
@@ -14,6 +14,10 @@ export interface MenuItemProps extends LiHTMLAttributes<HTMLLIElement> {
14
14
  * Additional CSS class names.
15
15
  */
16
16
  className?: string;
17
+ /**
18
+ * Specify the message read by screen readers for the danger menu item variant
19
+ */
20
+ dangerDescription?: string;
17
21
  /**
18
22
  * Specify whether the MenuItem is disabled or not.
19
23
  */
@@ -18,6 +18,7 @@ var match = require('../../internal/keyboard/match.js');
18
18
  var useControllableState = require('../../internal/useControllableState.js');
19
19
  var useMergedRefs = require('../../internal/useMergedRefs.js');
20
20
  var usePrefix = require('../../internal/usePrefix.js');
21
+ var useId = require('../../internal/useId.js');
21
22
  var Menu = require('./Menu.js');
22
23
  var MenuContext = require('./MenuContext.js');
23
24
  require('../LayoutDirection/LayoutDirection.js');
@@ -30,6 +31,7 @@ var _Checkmark, _CaretLeft, _CaretRight;
30
31
  const MenuItem = /*#__PURE__*/React.forwardRef(function MenuItem({
31
32
  children,
32
33
  className,
34
+ dangerDescription = 'danger',
33
35
  disabled,
34
36
  kind = 'default',
35
37
  label,
@@ -166,6 +168,7 @@ const MenuItem = /*#__PURE__*/React.forwardRef(function MenuItem({
166
168
  }
167
169
  });
168
170
  }, [floatingStyles, refs.floating]);
171
+ const assistiveId = useId.useId('danger-description');
169
172
  return /*#__PURE__*/React.createElement(react.FloatingFocusManager, {
170
173
  context: floatingContext,
171
174
  order: ['reference', 'floating'],
@@ -190,7 +193,10 @@ const MenuItem = /*#__PURE__*/React.forwardRef(function MenuItem({
190
193
  }, IconElement && /*#__PURE__*/React.createElement(IconElement, null)), /*#__PURE__*/React.createElement(Text.Text, {
191
194
  as: "div",
192
195
  className: `${prefix}--menu-item__label`
193
- }, label), shortcut && !hasChildren && /*#__PURE__*/React.createElement("div", {
196
+ }, label), isDanger && /*#__PURE__*/React.createElement("span", {
197
+ id: assistiveId,
198
+ className: `${prefix}--visually-hidden`
199
+ }, dangerDescription), shortcut && !hasChildren && /*#__PURE__*/React.createElement("div", {
194
200
  className: `${prefix}--menu-item__shortcut`
195
201
  }, shortcut), hasChildren && /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("div", {
196
202
  className: `${prefix}--menu-item__shortcut`
@@ -213,6 +219,10 @@ MenuItem.propTypes = {
213
219
  * Additional CSS class names.
214
220
  */
215
221
  className: PropTypes.string,
222
+ /**
223
+ * Specify the message read by screen readers for the danger menu item variant
224
+ */
225
+ dangerDescription: PropTypes.string,
216
226
  /**
217
227
  * Specify whether the MenuItem is disabled or not.
218
228
  */
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Copyright IBM Corp. 2023, 2025
2
+ * Copyright IBM Corp. 2023, 2026
3
3
  *
4
4
  * This source code is licensed under the Apache-2.0 license found in the
5
5
  * LICENSE file in the root directory of this source tree.
@@ -19,6 +19,7 @@ require('../Menu/MenuItem.js');
19
19
  var useAttachedMenu = require('../../internal/useAttachedMenu.js');
20
20
  var useId = require('../../internal/useId.js');
21
21
  var usePrefix = require('../../internal/usePrefix.js');
22
+ var useIsomorphicEffect = require('../../internal/useIsomorphicEffect.js');
22
23
  var react = require('@floating-ui/react');
23
24
  var index = require('../FeatureFlags/index.js');
24
25
  var mergeRefs = require('../../tools/mergeRefs.js');
@@ -97,7 +98,7 @@ const MenuButton = /*#__PURE__*/React.forwardRef(({
97
98
  handleMousedown,
98
99
  handleClose
99
100
  } = useAttachedMenu.useAttachedMenu(triggerRef);
100
- React.useLayoutEffect(() => {
101
+ useIsomorphicEffect.default(() => {
101
102
  Object.keys(floatingStyles).forEach(style => {
102
103
  if (refs.floating.current) {
103
104
  let value = floatingStyles[style];
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Copyright IBM Corp. 2016, 2025
2
+ * Copyright IBM Corp. 2016, 2026
3
3
  *
4
4
  * This source code is licensed under the Apache-2.0 license found in the
5
5
  * LICENSE file in the root directory of this source tree.
@@ -36,6 +36,7 @@ var index = require('../AILabel/index.js');
36
36
  var defaultItemToString = require('../../internal/defaultItemToString.js');
37
37
  var utils = require('../../internal/utils.js');
38
38
  var useNormalizedInputProps = require('../../internal/useNormalizedInputProps.js');
39
+ var useIsomorphicEffect = require('../../internal/useIsomorphicEffect.js');
39
40
  var ListBoxPropTypes = require('../ListBox/ListBoxPropTypes.js');
40
41
 
41
42
  const {
@@ -191,7 +192,7 @@ const FilterableMultiSelect = /*#__PURE__*/React.forwardRef(function FilterableM
191
192
  }), react.hide()],
192
193
  whileElementsMounted: react.autoUpdate
193
194
  } : {});
194
- React.useLayoutEffect(() => {
195
+ useIsomorphicEffect.default(() => {
195
196
  if (autoAlign) {
196
197
  const updatedFloatingStyles = {
197
198
  ...floatingStyles,
@@ -261,7 +262,8 @@ const FilterableMultiSelect = /*#__PURE__*/React.forwardRef(function FilterableM
261
262
  [`${prefix}--list-box__wrapper--decorator`]: decorator,
262
263
  [`${prefix}--autoalign`]: autoAlign
263
264
  });
264
- const helperId = !helperText ? undefined : `filterablemultiselect-helper-text-${filterableMultiSelectInstanceId}`;
265
+ const hasHelper = typeof helperText !== 'undefined' && helperText !== null;
266
+ const helperId = !hasHelper ? undefined : `filterablemultiselect-helper-text-${filterableMultiSelectInstanceId}`;
265
267
  const labelId = `${id}-label`;
266
268
  const titleClasses = cx({
267
269
  [`${prefix}--label`]: true,
@@ -277,10 +279,10 @@ const FilterableMultiSelect = /*#__PURE__*/React.forwardRef(function FilterableM
277
279
  [`${prefix}--text-input--empty`]: !inputValue,
278
280
  [`${prefix}--text-input--light`]: light
279
281
  });
280
- const helper = helperText ? /*#__PURE__*/React.createElement("div", {
282
+ const helper = hasHelper && /*#__PURE__*/React.createElement("div", {
281
283
  id: helperId,
282
284
  className: helperClasses
283
- }, helperText) : null;
285
+ }, helperText);
284
286
  const menuId = `${id}__menu`;
285
287
  const inputId = `${id}-input`;
286
288
  React.useEffect(() => {
@@ -35,6 +35,7 @@ var index$1 = require('../AILabel/index.js');
35
35
  var defaultItemToString = require('../../internal/defaultItemToString.js');
36
36
  var utils = require('../../internal/utils.js');
37
37
  var useNormalizedInputProps = require('../../internal/useNormalizedInputProps.js');
38
+ var useIsomorphicEffect = require('../../internal/useIsomorphicEffect.js');
38
39
  var ListBoxPropTypes = require('../ListBox/ListBoxPropTypes.js');
39
40
 
40
41
  const {
@@ -145,7 +146,7 @@ const MultiSelect = /*#__PURE__*/React.forwardRef(({
145
146
  }), autoAlign && react.hide()],
146
147
  whileElementsMounted: react.autoUpdate
147
148
  } : {});
148
- React.useLayoutEffect(() => {
149
+ useIsomorphicEffect.default(() => {
149
150
  if (enableFloatingStyles) {
150
151
  const updatedFloatingStyles = {
151
152
  ...floatingStyles,
@@ -388,8 +389,11 @@ const MultiSelect = /*#__PURE__*/React.forwardRef(({
388
389
  [`${prefix}--list-box__field--wrapper--input-focused`]: inputFocused
389
390
  });
390
391
  const handleFocus = evt => {
391
- // eslint-disable-next-line @typescript-eslint/no-unused-expressions -- https://github.com/carbon-design-system/carbon/issues/20452
392
- evt.target.classList.contains(`${prefix}--tag__close-icon`) ? setIsFocused(false) : setIsFocused(evt.type === 'focus' ? true : false);
392
+ if (evt.target.classList.contains(`${prefix}--tag__close-icon`)) {
393
+ setIsFocused(false);
394
+ } else {
395
+ setIsFocused(evt.type === 'focus' ? true : false);
396
+ }
393
397
  };
394
398
  const readOnlyEventHandlers = readOnly ? {
395
399
  onClick: evt => {
@@ -574,7 +574,8 @@ function ActionableNotification({
574
574
  role: "link",
575
575
  className: `${prefix}--visually-hidden`
576
576
  }, "Focus sentinel"), /*#__PURE__*/React.createElement("div", {
577
- ref: innerModal
577
+ ref: innerModal,
578
+ className: `${prefix}--actionable-notification__focus-wrapper`
578
579
  }, /*#__PURE__*/React.createElement("div", {
579
580
  className: `${prefix}--actionable-notification__details`
580
581
  }, /*#__PURE__*/React.createElement(NotificationIcon, {
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Copyright IBM Corp. 2016, 2025
2
+ * Copyright IBM Corp. 2016, 2026
3
3
  *
4
4
  * This source code is licensed under the Apache-2.0 license found in the
5
5
  * LICENSE file in the root directory of this source tree.
@@ -566,10 +566,11 @@ const NumberInput = /*#__PURE__*/React.forwardRef((props, forwardRef) => {
566
566
  onKeyUp: onKeyUp,
567
567
  onKeyDown: e => {
568
568
  if (type === 'text') {
569
- // eslint-disable-next-line @typescript-eslint/no-unused-expressions -- https://github.com/carbon-design-system/carbon/issues/20452
570
- match.match(e, keys.ArrowUp) && handleStep(e, 'up');
571
- // eslint-disable-next-line @typescript-eslint/no-unused-expressions -- https://github.com/carbon-design-system/carbon/issues/20452
572
- match.match(e, keys.ArrowDown) && handleStep(e, 'down');
569
+ if (match.match(e, keys.ArrowUp)) {
570
+ handleStep(e, 'up');
571
+ } else if (match.match(e, keys.ArrowDown)) {
572
+ handleStep(e, 'down');
573
+ }
573
574
  }
574
575
  if (rest?.onKeyDown) {
575
576
  rest?.onKeyDown(e);
@@ -44,6 +44,7 @@ export interface OverflowMenuProps extends Omit<IconButtonProps, 'type' | 'aria-
44
44
  */
45
45
  flipped?: boolean;
46
46
  /**
47
+ * @deprecated Tab key is handled with event handler so no need for focus trap.
47
48
  * Enable or disable focus trap behavior
48
49
  */
49
50
  focusTrap?: boolean;
@@ -101,7 +101,7 @@ const OverflowMenu = /*#__PURE__*/React.forwardRef(({
101
101
  className,
102
102
  direction = FloatingMenu.DIRECTION_BOTTOM,
103
103
  flipped = false,
104
- focusTrap = true,
104
+ focusTrap = false,
105
105
  iconClass,
106
106
  iconDescription = 'Options',
107
107
  id,
@@ -204,12 +204,15 @@ const OverflowMenu = /*#__PURE__*/React.forwardRef(({
204
204
  evt.preventDefault();
205
205
  }
206
206
 
207
- // Close the overflow menu on escape
208
- if (match.matches(evt, [keys.Escape])) {
207
+ // Close the overflow menu on escape or tab.
208
+ if (match.matches(evt, [keys.Escape, keys.Tab])) {
209
209
  closeMenuOnEscape();
210
210
 
211
211
  // Stop the esc keypress from bubbling out and closing something it shouldn't
212
212
  evt.stopPropagation();
213
+
214
+ // Stop the tab key from making the browser focus somewhere else.
215
+ evt.preventDefault();
213
216
  }
214
217
  };
215
218
 
@@ -394,6 +397,7 @@ OverflowMenu.propTypes = {
394
397
  */
395
398
  flipped: PropTypes.bool,
396
399
  /**
400
+ * @deprecated Tab key is handled with event handler so no need for focus trap.
397
401
  * Enable or disable focus trap behavior
398
402
  */
399
403
  focusTrap: PropTypes.bool,
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Copyright IBM Corp. 2025
2
+ * Copyright IBM Corp. 2025, 2026
3
3
  *
4
4
  * This source code is licensed under the Apache-2.0 license found in the
5
5
  * LICENSE file in the root directory of this source tree.
@@ -37,6 +37,7 @@ require('../Grid/Row.js');
37
37
  var Column = require('../Grid/Column.js');
38
38
  require('../Grid/ColumnHang.js');
39
39
  require('../Grid/GridContext.js');
40
+ var useIsomorphicEffect = require('../../internal/useIsomorphicEffect.js');
40
41
 
41
42
  /**
42
43
  * ----------
@@ -132,9 +133,8 @@ const PageHeaderContent = /*#__PURE__*/React.forwardRef(({
132
133
  setIsEllipsisApplied(element.offsetHeight < element.scrollHeight);
133
134
  return element.offsetHeight < element.scrollHeight;
134
135
  };
135
- React.useLayoutEffect(() => {
136
- // eslint-disable-next-line @typescript-eslint/no-unused-expressions -- https://github.com/carbon-design-system/carbon/issues/20452
137
- titleRef.current && isEllipsisActive(titleRef.current);
136
+ useIsomorphicEffect.default(() => {
137
+ if (titleRef.current) isEllipsisActive(titleRef.current);
138
138
  }, [title]);
139
139
  return /*#__PURE__*/React.createElement("div", _rollupPluginBabelHelpers.extends({
140
140
  className: classNames,
@@ -222,7 +222,7 @@ const PageHeaderContentPageActions = ({
222
222
 
223
223
  // need to set the grid columns width based on the menu button's width
224
224
  // to avoid overlapping when resizing
225
- React.useLayoutEffect(() => {
225
+ useIsomorphicEffect.default(() => {
226
226
  if (menuButtonVisibility && offsetRef.current) {
227
227
  const width = offsetRef.current.offsetWidth;
228
228
  document.documentElement.style.setProperty('--pageheader-title-grid-width', `${width}px`);
@@ -101,11 +101,12 @@ const RadioButtonGroup = /*#__PURE__*/React.forwardRef((props, ref) => {
101
101
  const helperClasses = cx(`${prefix}--form__helper-text`, {
102
102
  [`${prefix}--form__helper-text--disabled`]: disabled
103
103
  });
104
- const helperId = !helperText ? undefined : `radio-button-group-helper-text-${radioButtonGroupInstanceId}`;
105
- const helper = helperText ? /*#__PURE__*/React.createElement("div", {
104
+ const hasHelper = typeof helperText !== 'undefined' && helperText !== null;
105
+ const helperId = !hasHelper ? undefined : `radio-button-group-helper-text-${radioButtonGroupInstanceId}`;
106
+ const helper = hasHelper && /*#__PURE__*/React.createElement("div", {
106
107
  id: helperId,
107
108
  className: helperClasses
108
- }, helperText) : null;
109
+ }, helperText);
109
110
  const divRef = React.useRef(null);
110
111
 
111
112
  // AILabel is always size `mini`
@@ -98,7 +98,8 @@ const Select = /*#__PURE__*/React.forwardRef(({
98
98
  const helperTextClasses = cx(`${prefix}--form__helper-text`, {
99
99
  [`${prefix}--form__helper-text--disabled`]: normalizedProps.disabled
100
100
  });
101
- const helper = helperText ? /*#__PURE__*/React.createElement(Text.Text, {
101
+ const hasHelper = typeof helperText !== 'undefined' && helperText !== null;
102
+ const helper = hasHelper ? /*#__PURE__*/React.createElement(Text.Text, {
102
103
  as: "div",
103
104
  id: normalizedProps.helperId,
104
105
  className: helperTextClasses
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Copyright IBM Corp. 2016, 2025
2
+ * Copyright IBM Corp. 2016, 2026
3
3
  *
4
4
  * This source code is licensed under the Apache-2.0 license found in the
5
5
  * LICENSE file in the root directory of this source tree.
@@ -186,8 +186,7 @@ function StructuredListRow(props) {
186
186
  ref: itemRef,
187
187
  onClick: event => {
188
188
  setSelectedRow?.(rowId);
189
- // eslint-disable-next-line @typescript-eslint/no-unused-expressions -- https://github.com/carbon-design-system/carbon/issues/20452
190
- onClick && onClick(event);
189
+ onClick?.(event);
191
190
  if (selection) {
192
191
  // focus items only when selection is enabled
193
192
  setHasFocusWithin(true);
@@ -266,8 +265,7 @@ function StructuredListInput(props) {
266
265
  value: row?.id ?? '',
267
266
  onChange: event => {
268
267
  setSelectedRow?.(event.target.value);
269
- // eslint-disable-next-line @typescript-eslint/no-unused-expressions -- https://github.com/carbon-design-system/carbon/issues/20452
270
- onChange && onChange(event);
268
+ onChange?.(event);
271
269
  },
272
270
  id: id ?? defaultId,
273
271
  className: classes,
@@ -1,11 +1,11 @@
1
1
  /**
2
- * Copyright IBM Corp. 2016, 2025
2
+ * Copyright IBM Corp. 2016, 2026
3
3
  *
4
4
  * This source code is licensed under the Apache-2.0 license found in the
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  */
7
7
  import PropTypes from 'prop-types';
8
- import React, { type ReactNode, type MouseEvent, type KeyboardEvent, type HTMLAttributes, type ComponentType, type HTMLElementType } from 'react';
8
+ import React, { type ComponentType, type HTMLAttributes, type HTMLElementType, type KeyboardEvent, type MouseEvent, type ReactNode } from 'react';
9
9
  type DivAttributes = HTMLAttributes<HTMLDivElement>;
10
10
  /**
11
11
  * Tabs
@@ -19,7 +19,6 @@ require('../Grid/Row.js');
19
19
  require('../Grid/Column.js');
20
20
  require('../Grid/ColumnHang.js');
21
21
  require('../Grid/GridContext.js');
22
- var reactIs = require('react-is');
23
22
  require('../Tooltip/DefinitionTooltip.js');
24
23
  var Tooltip = require('../Tooltip/Tooltip.js');
25
24
  var useControllableState = require('../../internal/useControllableState.js');
@@ -36,6 +35,7 @@ var useMatchMedia = require('../../internal/useMatchMedia.js');
36
35
  var Text = require('../Text/Text.js');
37
36
  require('../Text/TextDirection.js');
38
37
  var index = require('../BadgeIndicator/index.js');
38
+ var utils = require('../../internal/utils.js');
39
39
  var debounce = require('../../node_modules/es-toolkit/dist/compat/function/debounce.js');
40
40
 
41
41
  var _ChevronLeft, _ChevronRight, _BadgeIndicator;
@@ -271,14 +271,7 @@ function TabList({
271
271
  const nextButton = React.useRef(null);
272
272
  const [isScrollable, setIsScrollable] = React.useState(false);
273
273
  const [scrollLeft, setScrollLeft] = React.useState(0);
274
- let hasSecondaryLabelTabs = false;
275
- if (contained) {
276
- hasSecondaryLabelTabs = React.Children.toArray(children).some(child => {
277
- // eslint-disable-next-line @typescript-eslint/no-explicit-any -- https://github.com/carbon-design-system/carbon/issues/20452
278
- const _child = child;
279
- return /*#__PURE__*/React.isValidElement(child) && !!_child.props.secondaryLabel;
280
- });
281
- }
274
+ const hasSecondaryLabelTabs = contained && React.Children.toArray(children).some(child => utils.isComponentElement(child, Tab) && typeof child.props.secondaryLabel !== 'undefined');
282
275
  const isLg = useMatchMedia.useMatchMedia(lgMediaQuery);
283
276
  const distributeWidth = fullWidth && contained && isLg && React.Children.toArray(children).length < 9;
284
277
  const className = cx(`${prefix}--tabs`, {
@@ -490,16 +483,15 @@ function TabList({
490
483
  onKeyDown: onKeyDown,
491
484
  onBlur: handleBlur
492
485
  }), React.Children.map(children, (child, index) => {
493
- return !reactIs.isElement(child) ? null : /*#__PURE__*/React.createElement(TabContext.Provider, {
486
+ return ! /*#__PURE__*/React.isValidElement(child) ? null : /*#__PURE__*/React.createElement(TabContext.Provider, {
494
487
  value: {
495
488
  index,
496
489
  hasSecondaryLabel: hasSecondaryLabelTabs,
497
490
  contained
498
491
  }
499
- }, /*#__PURE__*/React.cloneElement(
500
- // eslint-disable-next-line @typescript-eslint/no-explicit-any -- https://github.com/carbon-design-system/carbon/issues/20452
501
- child, {
492
+ }, /*#__PURE__*/React.cloneElement(child, {
502
493
  ref: node => {
494
+ if (!node) return;
503
495
  tabs.current[index] = node;
504
496
  }
505
497
  }));
@@ -643,8 +635,7 @@ function TabListVertical({
643
635
  if (containerTop && containerHeight) {
644
636
  // scrolls so selected tab is in view
645
637
  if (selectedPositionTop - halfTabHeight < containerTop || selectedPositionTop - containerTop + verticalTabHeight + halfTabHeight > containerHeight) {
646
- // eslint-disable-next-line @typescript-eslint/no-unused-expressions -- https://github.com/carbon-design-system/carbon/issues/20452
647
- ref.current && ref.current.scrollTo({
638
+ ref.current?.scrollTo({
648
639
  top: (selectedIndex - 1) * verticalTabHeight,
649
640
  behavior: 'smooth'
650
641
  });
@@ -693,15 +684,14 @@ function TabListVertical({
693
684
  onKeyDown: onKeyDown,
694
685
  onBlur: handleBlur
695
686
  }), React.Children.map(children, (child, index) => {
696
- return !reactIs.isElement(child) ? null : /*#__PURE__*/React.createElement(TabContext.Provider, {
687
+ return ! /*#__PURE__*/React.isValidElement(child) ? null : /*#__PURE__*/React.createElement(TabContext.Provider, {
697
688
  value: {
698
689
  index,
699
690
  hasSecondaryLabel: false
700
691
  }
701
- }, /*#__PURE__*/React.cloneElement(
702
- // eslint-disable-next-line @typescript-eslint/no-explicit-any -- https://github.com/carbon-design-system/carbon/issues/20452
703
- child, {
692
+ }, /*#__PURE__*/React.cloneElement(child, {
704
693
  ref: node => {
694
+ if (!node) return;
705
695
  tabs.current[index] = node;
706
696
  }
707
697
  }));
@@ -1047,7 +1037,11 @@ const IconTab = /*#__PURE__*/React.forwardRef(({
1047
1037
  const value = React.useMemo(() => ({
1048
1038
  badgeIndicator
1049
1039
  }), [badgeIndicator]);
1050
- const hasSize20 = /*#__PURE__*/React.isValidElement(children) && children.props.size === 20;
1040
+ const hasSize20 = /*#__PURE__*/React.isValidElement(children) &&
1041
+ // TODO: The interface allows `size` to be a string. Should this case be
1042
+ // handled here, or should the prop type be restricted to `number`
1043
+ // instead?
1044
+ children.props.size === 20;
1051
1045
  const classNames = cx(`${prefix}--tabs__nav-item--icon-only`, customClassName, {
1052
1046
  [`${prefix}--tabs__nav-item--icon-only__20`]: hasSize20
1053
1047
  });
@@ -1179,7 +1173,7 @@ function TabPanels({
1179
1173
  }
1180
1174
  });
1181
1175
  return /*#__PURE__*/React.createElement(React.Fragment, null, React.Children.map(children, (child, index) => {
1182
- return !reactIs.isElement(child) ? null : /*#__PURE__*/React.createElement(TabPanelContext.Provider, {
1176
+ return ! /*#__PURE__*/React.isValidElement(child) ? null : /*#__PURE__*/React.createElement(TabPanelContext.Provider, {
1183
1177
  value: index
1184
1178
  }, /*#__PURE__*/React.cloneElement(child, {
1185
1179
  ref: element => {
@@ -26,6 +26,7 @@ var isEllipsisActive = require('./isEllipsisActive.js');
26
26
  var mergeRefs = require('../../tools/mergeRefs.js');
27
27
  var index = require('../AILabel/index.js');
28
28
  var utils = require('../../internal/utils.js');
29
+ var useIsomorphicEffect = require('../../internal/useIsomorphicEffect.js');
29
30
 
30
31
  var _Close;
31
32
  // eslint-disable-next-line react/display-name -- https://github.com/carbon-design-system/carbon/issues/20452
@@ -52,7 +53,7 @@ const DismissibleTag = /*#__PURE__*/React.forwardRef(({
52
53
  const tagId = id || `tag-${useId.useId()}`;
53
54
  const tagClasses = cx(`${prefix}--tag--filter`, className);
54
55
  const [isEllipsisApplied, setIsEllipsisApplied] = React.useState(false);
55
- React.useLayoutEffect(() => {
56
+ useIsomorphicEffect.default(() => {
56
57
  const newElement = tagLabelRef.current?.getElementsByClassName(`${prefix}--tag__label`)[0];
57
58
  setIsEllipsisApplied(isEllipsisActive.isEllipsisActive(newElement));
58
59
  }, [prefix, tagLabelRef]);
@@ -22,6 +22,7 @@ var Text = require('../Text/Text.js');
22
22
  require('../Text/TextDirection.js');
23
23
  var isEllipsisActive = require('./isEllipsisActive.js');
24
24
  var mergeRefs = require('../../tools/mergeRefs.js');
25
+ var useIsomorphicEffect = require('../../internal/useIsomorphicEffect.js');
25
26
 
26
27
  const TYPES = {
27
28
  red: 'Red',
@@ -52,7 +53,7 @@ const OperationalTag = /*#__PURE__*/React.forwardRef(({
52
53
  const tagId = id || `tag-${useId.useId()}`;
53
54
  const tagClasses = cx(`${prefix}--tag--operational`, className);
54
55
  const [isEllipsisApplied, setIsEllipsisApplied] = React.useState(false);
55
- React.useLayoutEffect(() => {
56
+ useIsomorphicEffect.default(() => {
56
57
  const newElement = tagRef.current?.getElementsByClassName(`${prefix}--tag__label`)[0];
57
58
  setIsEllipsisApplied(isEllipsisActive.isEllipsisActive(newElement));
58
59
  }, [prefix, tagRef]);
@@ -23,6 +23,7 @@ require('../Text/TextDirection.js');
23
23
  var isEllipsisActive = require('./isEllipsisActive.js');
24
24
  var mergeRefs = require('../../tools/mergeRefs.js');
25
25
  var useControllableState = require('../../internal/useControllableState.js');
26
+ var useIsomorphicEffect = require('../../internal/useIsomorphicEffect.js');
26
27
 
27
28
  // eslint-disable-next-line react/display-name -- https://github.com/carbon-design-system/carbon/issues/20452
28
29
  const SelectableTag = /*#__PURE__*/React.forwardRef(({
@@ -51,7 +52,7 @@ const SelectableTag = /*#__PURE__*/React.forwardRef(({
51
52
  [`${prefix}--tag--selectable-selected`]: selectedTag
52
53
  });
53
54
  const [isEllipsisApplied, setIsEllipsisApplied] = React.useState(false);
54
- React.useLayoutEffect(() => {
55
+ useIsomorphicEffect.default(() => {
55
56
  const newElement = tagRef.current?.getElementsByClassName(`${prefix}--tag__label`)[0];
56
57
  setIsEllipsisApplied(isEllipsisActive.isEllipsisActive(newElement));
57
58
  }, [prefix, tagRef]);
@@ -25,6 +25,7 @@ var isEllipsisActive = require('./isEllipsisActive.js');
25
25
  var useMergedRefs = require('../../internal/useMergedRefs.js');
26
26
  var index = require('../AILabel/index.js');
27
27
  var utils = require('../../internal/utils.js');
28
+ var useIsomorphicEffect = require('../../internal/useIsomorphicEffect.js');
28
29
 
29
30
  var _Close;
30
31
  const TYPES = {
@@ -80,7 +81,7 @@ const TagBase = /*#__PURE__*/React.forwardRef(({
80
81
  // eslint-disable-next-line react-hooks/rules-of-hooks -- https://github.com/carbon-design-system/carbon/issues/20452
81
82
  const tagId = id || `tag-${useId.useId()}`;
82
83
  const [isEllipsisApplied, setIsEllipsisApplied] = React.useState(false);
83
- React.useLayoutEffect(() => {
84
+ useIsomorphicEffect.default(() => {
84
85
  const newElement = tagRef.current?.getElementsByClassName(`${prefix}--tag__label`)[0];
85
86
  setIsEllipsisApplied(isEllipsisActive.isEllipsisActive(newElement));
86
87
  }, [prefix, tagRef]);
@@ -5,7 +5,7 @@
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  */
7
7
  import React, { type ReactNode } from 'react';
8
- export interface TextAreaProps extends React.InputHTMLAttributes<HTMLTextAreaElement> {
8
+ export interface TextAreaProps extends React.TextareaHTMLAttributes<HTMLTextAreaElement> {
9
9
  /**
10
10
  * Provide a custom className that is applied directly to the underlying
11
11
  * `<textarea>` node
@@ -197,24 +197,25 @@ const TextArea = frFn((props, forwardRef) => {
197
197
  const helperTextClasses = cx(`${prefix}--form__helper-text`, {
198
198
  [`${prefix}--form__helper-text--disabled`]: disabled
199
199
  });
200
- const label = labelText ? /*#__PURE__*/React.createElement(Text.Text, {
200
+ const label = typeof labelText !== 'undefined' && labelText !== null && /*#__PURE__*/React.createElement(Text.Text, {
201
201
  as: "label",
202
202
  htmlFor: id,
203
203
  className: labelClasses
204
- }, labelText) : null;
204
+ }, labelText);
205
205
  const counter = enableCounter && maxCount && (counterMode === 'character' || counterMode === 'word') ? /*#__PURE__*/React.createElement(Text.Text, {
206
206
  as: "div",
207
207
  className: counterClasses,
208
208
  "aria-hidden": "true"
209
209
  }, `${textCount}/${maxCount}`) : null;
210
210
  const counterDescriptionId = enableCounter && maxCount ? `${id}-counter-desc` : undefined;
211
- const helperId = !helperText ? undefined : `text-area-helper-text-${textAreaInstanceId}`;
212
- const helper = helperText ? /*#__PURE__*/React.createElement(Text.Text, {
211
+ const hasHelper = typeof helperText !== 'undefined' && helperText !== null;
212
+ const helperId = !hasHelper ? undefined : `text-area-helper-text-${textAreaInstanceId}`;
213
+ const helper = hasHelper && /*#__PURE__*/React.createElement(Text.Text, {
213
214
  as: "div",
214
215
  id: helperId,
215
216
  className: helperTextClasses,
216
217
  ref: helperTextRef
217
- }, helperText) : null;
218
+ }, helperText);
218
219
  const errorId = id + '-error-msg';
219
220
  const error = invalid ? /*#__PURE__*/React.createElement(Text.Text, {
220
221
  as: "div",