@carbon/react 1.100.0-rc.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 (148) hide show
  1. package/.playwright/INTERNAL_AVT_REPORT_DO_NOT_USE.json +933 -933
  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.d.ts +3 -4
  8. package/es/components/ComboBox/ComboBox.js +20 -18
  9. package/es/components/ComboButton/index.d.ts +1 -1
  10. package/es/components/ComboButton/index.js +3 -2
  11. package/es/components/ComposedModal/ComposedModal.js +17 -22
  12. package/es/components/ComposedModal/ModalHeader.d.ts +2 -2
  13. package/es/components/ComposedModal/ModalHeader.js +1 -1
  14. package/es/components/Copy/Copy.d.ts +1 -1
  15. package/es/components/CopyButton/CopyButton.d.ts +1 -1
  16. package/es/components/DataTable/DataTable.d.ts +2 -0
  17. package/es/components/DataTable/DataTable.js +6 -5
  18. package/es/components/DataTable/Table.d.ts +1 -1
  19. package/es/components/DataTable/Table.js +10 -4
  20. package/es/components/DataTable/state/sorting.d.ts +4 -2
  21. package/es/components/Dropdown/Dropdown.d.ts +3 -4
  22. package/es/components/Dropdown/Dropdown.js +16 -13
  23. package/es/components/FileUploader/FileUploaderItem.d.ts +1 -1
  24. package/es/components/FileUploader/FileUploaderItem.js +3 -2
  25. package/es/components/FluidComboBox/FluidComboBox.d.ts +2 -7
  26. package/es/components/FluidComboBox/FluidComboBox.js +1 -2
  27. package/es/components/FluidDropdown/FluidDropdown.d.ts +1 -6
  28. package/es/components/FluidDropdown/FluidDropdown.js +1 -2
  29. package/es/components/FluidMultiSelect/FluidMultiSelect.d.ts +1 -6
  30. package/es/components/FluidMultiSelect/FluidMultiSelect.js +1 -2
  31. package/es/components/InlineLoading/InlineLoading.js +5 -11
  32. package/es/components/Menu/Menu.js +8 -4
  33. package/es/components/Menu/MenuItem.d.ts +5 -1
  34. package/es/components/Menu/MenuItem.js +11 -1
  35. package/es/components/MenuButton/index.d.ts +1 -1
  36. package/es/components/MenuButton/index.js +3 -2
  37. package/es/components/MultiSelect/FilterableMultiSelect.d.ts +1 -1
  38. package/es/components/MultiSelect/FilterableMultiSelect.js +7 -5
  39. package/es/components/MultiSelect/MultiSelect.d.ts +3 -4
  40. package/es/components/MultiSelect/MultiSelect.js +10 -13
  41. package/es/components/Notification/Notification.js +5 -3
  42. package/es/components/NumberInput/NumberInput.d.ts +1 -1
  43. package/es/components/NumberInput/NumberInput.js +5 -4
  44. package/es/components/OverflowMenu/OverflowMenu.d.ts +1 -0
  45. package/es/components/OverflowMenu/OverflowMenu.js +8 -4
  46. package/es/components/PageHeader/PageHeader.d.ts +1 -1
  47. package/es/components/PageHeader/PageHeader.js +5 -5
  48. package/es/components/RadioButtonGroup/RadioButtonGroup.js +4 -3
  49. package/es/components/Select/Select.js +2 -1
  50. package/es/components/StructuredList/StructuredList.d.ts +1 -1
  51. package/es/components/StructuredList/StructuredList.js +2 -4
  52. package/es/components/Tabs/Tabs.d.ts +2 -2
  53. package/es/components/Tabs/Tabs.js +20 -26
  54. package/es/components/Tag/DismissibleTag.js +3 -2
  55. package/es/components/Tag/OperationalTag.js +3 -2
  56. package/es/components/Tag/SelectableTag.js +3 -2
  57. package/es/components/Tag/Tag.js +3 -2
  58. package/es/components/TextArea/TextArea.d.ts +1 -1
  59. package/es/components/TextArea/TextArea.js +7 -8
  60. package/es/components/TextInput/ControlledPasswordInput.js +7 -6
  61. package/es/components/TextInput/PasswordInput.js +5 -6
  62. package/es/components/TextInput/TextInput.js +4 -4
  63. package/es/components/Tile/Tile.d.ts +1 -1
  64. package/es/components/Tile/Tile.js +37 -69
  65. package/es/components/TimePicker/TimePicker.js +2 -2
  66. package/es/components/Tooltip/DefinitionTooltip.d.ts +1 -1
  67. package/es/components/Tooltip/DefinitionTooltip.js +3 -2
  68. package/es/components/UIShell/SideNav.d.ts +0 -1
  69. package/es/components/UIShell/SideNav.js +12 -3
  70. package/es/internal/useId.js +3 -4
  71. package/es/internal/usePresence.js +3 -2
  72. package/es/internal/useResizeObserver.d.ts +1 -1
  73. package/es/internal/useResizeObserver.js +5 -7
  74. package/es/tools/events.d.ts +1 -1
  75. package/lib/components/AILabel/index.d.ts +1 -1
  76. package/lib/components/AILabel/index.js +1 -12
  77. package/lib/components/Checkbox/Checkbox.js +5 -3
  78. package/lib/components/CheckboxGroup/CheckboxGroup.js +4 -3
  79. package/lib/components/CodeSnippet/CodeSnippet.d.ts +1 -1
  80. package/lib/components/ComboBox/ComboBox.d.ts +3 -4
  81. package/lib/components/ComboBox/ComboBox.js +20 -18
  82. package/lib/components/ComboButton/index.d.ts +1 -1
  83. package/lib/components/ComboButton/index.js +2 -1
  84. package/lib/components/ComposedModal/ComposedModal.js +16 -21
  85. package/lib/components/ComposedModal/ModalHeader.d.ts +2 -2
  86. package/lib/components/ComposedModal/ModalHeader.js +1 -1
  87. package/lib/components/Copy/Copy.d.ts +1 -1
  88. package/lib/components/CopyButton/CopyButton.d.ts +1 -1
  89. package/lib/components/DataTable/DataTable.d.ts +2 -0
  90. package/lib/components/DataTable/DataTable.js +6 -5
  91. package/lib/components/DataTable/Table.d.ts +1 -1
  92. package/lib/components/DataTable/Table.js +10 -4
  93. package/lib/components/DataTable/state/sorting.d.ts +4 -2
  94. package/lib/components/Dropdown/Dropdown.d.ts +3 -4
  95. package/lib/components/Dropdown/Dropdown.js +16 -13
  96. package/lib/components/FileUploader/FileUploaderItem.d.ts +1 -1
  97. package/lib/components/FileUploader/FileUploaderItem.js +2 -1
  98. package/lib/components/FluidComboBox/FluidComboBox.d.ts +2 -7
  99. package/lib/components/FluidComboBox/FluidComboBox.js +1 -2
  100. package/lib/components/FluidDropdown/FluidDropdown.d.ts +1 -6
  101. package/lib/components/FluidDropdown/FluidDropdown.js +1 -2
  102. package/lib/components/FluidMultiSelect/FluidMultiSelect.d.ts +1 -6
  103. package/lib/components/FluidMultiSelect/FluidMultiSelect.js +1 -2
  104. package/lib/components/InlineLoading/InlineLoading.js +5 -11
  105. package/lib/components/Menu/Menu.js +7 -3
  106. package/lib/components/Menu/MenuItem.d.ts +5 -1
  107. package/lib/components/Menu/MenuItem.js +11 -1
  108. package/lib/components/MenuButton/index.d.ts +1 -1
  109. package/lib/components/MenuButton/index.js +2 -1
  110. package/lib/components/MultiSelect/FilterableMultiSelect.d.ts +1 -1
  111. package/lib/components/MultiSelect/FilterableMultiSelect.js +6 -4
  112. package/lib/components/MultiSelect/MultiSelect.d.ts +3 -4
  113. package/lib/components/MultiSelect/MultiSelect.js +9 -12
  114. package/lib/components/Notification/Notification.js +5 -3
  115. package/lib/components/NumberInput/NumberInput.d.ts +1 -1
  116. package/lib/components/NumberInput/NumberInput.js +5 -4
  117. package/lib/components/OverflowMenu/OverflowMenu.d.ts +1 -0
  118. package/lib/components/OverflowMenu/OverflowMenu.js +7 -3
  119. package/lib/components/PageHeader/PageHeader.d.ts +1 -1
  120. package/lib/components/PageHeader/PageHeader.js +4 -4
  121. package/lib/components/RadioButtonGroup/RadioButtonGroup.js +4 -3
  122. package/lib/components/Select/Select.js +2 -1
  123. package/lib/components/StructuredList/StructuredList.d.ts +1 -1
  124. package/lib/components/StructuredList/StructuredList.js +2 -4
  125. package/lib/components/Tabs/Tabs.d.ts +2 -2
  126. package/lib/components/Tabs/Tabs.js +15 -21
  127. package/lib/components/Tag/DismissibleTag.js +2 -1
  128. package/lib/components/Tag/OperationalTag.js +2 -1
  129. package/lib/components/Tag/SelectableTag.js +2 -1
  130. package/lib/components/Tag/Tag.js +2 -1
  131. package/lib/components/TextArea/TextArea.d.ts +1 -1
  132. package/lib/components/TextArea/TextArea.js +7 -8
  133. package/lib/components/TextInput/ControlledPasswordInput.js +7 -6
  134. package/lib/components/TextInput/PasswordInput.js +5 -6
  135. package/lib/components/TextInput/TextInput.js +4 -4
  136. package/lib/components/Tile/Tile.d.ts +1 -1
  137. package/lib/components/Tile/Tile.js +35 -67
  138. package/lib/components/TimePicker/TimePicker.js +2 -2
  139. package/lib/components/Tooltip/DefinitionTooltip.d.ts +1 -1
  140. package/lib/components/Tooltip/DefinitionTooltip.js +3 -2
  141. package/lib/components/UIShell/SideNav.d.ts +0 -1
  142. package/lib/components/UIShell/SideNav.js +11 -2
  143. package/lib/internal/useId.js +2 -3
  144. package/lib/internal/usePresence.js +2 -1
  145. package/lib/internal/useResizeObserver.d.ts +1 -1
  146. package/lib/internal/useResizeObserver.js +4 -6
  147. package/lib/tools/events.d.ts +1 -1
  148. package/package.json +8 -8
@@ -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
@@ -148,9 +148,7 @@ const TextArea = frFn((props, forwardRef) => {
148
148
  setTimeout(() => {
149
149
  setTextCount(0);
150
150
  }, 0);
151
- return;
152
- }
153
- if (enableCounter && typeof maxCount !== 'undefined' && textareaRef.current !== null) {
151
+ } else if (enableCounter && typeof maxCount !== 'undefined' && textareaRef.current !== null) {
154
152
  const matchedWords = evt.target?.value?.match(/\p{L}+/gu);
155
153
  if (matchedWords && matchedWords.length <= maxCount) {
156
154
  textareaRef.current.removeAttribute('maxLength');
@@ -199,24 +197,25 @@ const TextArea = frFn((props, forwardRef) => {
199
197
  const helperTextClasses = cx(`${prefix}--form__helper-text`, {
200
198
  [`${prefix}--form__helper-text--disabled`]: disabled
201
199
  });
202
- const label = labelText ? /*#__PURE__*/React.createElement(Text.Text, {
200
+ const label = typeof labelText !== 'undefined' && labelText !== null && /*#__PURE__*/React.createElement(Text.Text, {
203
201
  as: "label",
204
202
  htmlFor: id,
205
203
  className: labelClasses
206
- }, labelText) : null;
204
+ }, labelText);
207
205
  const counter = enableCounter && maxCount && (counterMode === 'character' || counterMode === 'word') ? /*#__PURE__*/React.createElement(Text.Text, {
208
206
  as: "div",
209
207
  className: counterClasses,
210
208
  "aria-hidden": "true"
211
209
  }, `${textCount}/${maxCount}`) : null;
212
210
  const counterDescriptionId = enableCounter && maxCount ? `${id}-counter-desc` : undefined;
213
- const helperId = !helperText ? undefined : `text-area-helper-text-${textAreaInstanceId}`;
214
- 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, {
215
214
  as: "div",
216
215
  id: helperId,
217
216
  className: helperTextClasses,
218
217
  ref: helperTextRef
219
- }, helperText) : null;
218
+ }, helperText);
220
219
  const errorId = id + '-error-msg';
221
220
  const error = invalid ? /*#__PURE__*/React.createElement(Text.Text, {
222
221
  as: "div",
@@ -75,10 +75,10 @@ const ControlledPasswordInput = /*#__PURE__*/React.forwardRef(({
75
75
  const helperTextClasses = cx(`${prefix}--form__helper-text`, {
76
76
  [`${prefix}--form__helper-text--disabled`]: disabled
77
77
  });
78
- const label = labelText ? /*#__PURE__*/React.createElement("label", {
78
+ const label = typeof labelText !== 'undefined' && labelText !== null && /*#__PURE__*/React.createElement("label", {
79
79
  htmlFor: id,
80
80
  className: labelClasses
81
- }, labelText) : null;
81
+ }, labelText);
82
82
  const error = invalid ? /*#__PURE__*/React.createElement("div", {
83
83
  className: `${prefix}--form-requirement`,
84
84
  id: errorId
@@ -93,12 +93,13 @@ const ControlledPasswordInput = /*#__PURE__*/React.forwardRef(({
93
93
  [`${prefix}--tooltip--${tooltipPosition}`]: tooltipPosition,
94
94
  [`${prefix}--tooltip--align-${tooltipAlignment}`]: tooltipAlignment
95
95
  });
96
- const helperId = !helperText ? undefined : `controlled-password-helper-text-${controlledPasswordInstanceId}`;
96
+ const hasHelper = typeof helperText !== 'undefined' && helperText !== null;
97
+ const helperId = !hasHelper ? undefined : `controlled-password-helper-text-${controlledPasswordInstanceId}`;
97
98
  const input = /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("input", _rollupPluginBabelHelpers.extends({}, util.getTextInputProps({
98
99
  invalid,
99
100
  sharedTextInputProps,
100
101
  invalidId: errorId,
101
- hasHelper: !error && helperText ? true : false,
102
+ hasHelper: !error && hasHelper,
102
103
  helperId
103
104
  }), {
104
105
  "data-toggle-password-visibility": type === 'password'
@@ -109,10 +110,10 @@ const ControlledPasswordInput = /*#__PURE__*/React.forwardRef(({
109
110
  }, /*#__PURE__*/React.createElement("span", {
110
111
  className: `${prefix}--assistive-text`
111
112
  }, passwordIsVisible ? hidePasswordLabel : showPasswordLabel), passwordVisibilityIcon));
112
- const helper = helperText ? /*#__PURE__*/React.createElement("div", {
113
+ const helper = hasHelper && /*#__PURE__*/React.createElement("div", {
113
114
  id: helperId,
114
115
  className: helperTextClasses
115
- }, helperText) : null;
116
+ }, helperText);
116
117
  return /*#__PURE__*/React.createElement("div", {
117
118
  className: `${prefix}--form-item ${prefix}--text-input-wrapper ${prefix}--password-input-wrapper`
118
119
  }, label, /*#__PURE__*/React.createElement("div", {
@@ -65,8 +65,7 @@ const PasswordInput = /*#__PURE__*/React.forwardRef(({
65
65
  } = React.useContext(FormContext.FormContext);
66
66
  const handleTogglePasswordVisibility = event => {
67
67
  setInputType(inputType === 'password' ? 'text' : 'password');
68
- // eslint-disable-next-line @typescript-eslint/no-unused-expressions -- https://github.com/carbon-design-system/carbon/issues/20452
69
- onTogglePasswordVisibility && onTogglePasswordVisibility(event);
68
+ onTogglePasswordVisibility?.(event);
70
69
  };
71
70
  const textInputClasses = cx(`${prefix}--text-input`, `${prefix}--password-input`, className, {
72
71
  [`${prefix}--text-input--light`]: light,
@@ -121,14 +120,14 @@ const PasswordInput = /*#__PURE__*/React.forwardRef(({
121
120
  [`${prefix}--text-input__invalid-icon`]: normalizedProps.invalid || normalizedProps.warn,
122
121
  [`${prefix}--text-input__invalid-icon--warning`]: normalizedProps.warn
123
122
  });
124
- const label = labelText ? /*#__PURE__*/React.createElement("label", {
123
+ const label = typeof labelText !== 'undefined' && labelText !== null && /*#__PURE__*/React.createElement("label", {
125
124
  htmlFor: id,
126
125
  className: labelClasses
127
- }, labelText) : null;
128
- const helper = helperText ? /*#__PURE__*/React.createElement("div", {
126
+ }, labelText);
127
+ const helper = typeof helperText !== 'undefined' && helperText !== null && /*#__PURE__*/React.createElement("div", {
129
128
  id: normalizedProps.helperId,
130
129
  className: helperTextClasses
131
- }, helperText) : null;
130
+ }, helperText);
132
131
  const passwordIsVisible = inputType === 'text';
133
132
  const passwordVisibilityIcon = passwordIsVisible ? /*#__PURE__*/React.createElement(iconsReact.ViewOff, {
134
133
  className: `${prefix}--icon-visibility-off`
@@ -145,19 +145,19 @@ const TextInput = /*#__PURE__*/React.forwardRef(({
145
145
  as: "div",
146
146
  className: counterClasses
147
147
  }, `${textCount}/${maxCount}`) : null;
148
- const label = labelText ? /*#__PURE__*/React.createElement(Text.Text, {
148
+ const label = typeof labelText !== 'undefined' && labelText !== null && /*#__PURE__*/React.createElement(Text.Text, {
149
149
  as: "label",
150
150
  htmlFor: id,
151
151
  className: labelClasses
152
- }, labelText) : null;
152
+ }, labelText);
153
153
  const labelWrapper = /*#__PURE__*/React.createElement("div", {
154
154
  className: `${prefix}--text-input__label-wrapper`
155
155
  }, label, counter);
156
- const helper = helperText ? /*#__PURE__*/React.createElement(Text.Text, {
156
+ const helper = typeof helperText !== 'undefined' && helperText !== null && /*#__PURE__*/React.createElement(Text.Text, {
157
157
  as: "div",
158
158
  id: normalizedProps.helperId,
159
159
  className: helperTextClasses
160
- }, helperText) : null;
160
+ }, helperText);
161
161
  const input = /*#__PURE__*/React.createElement("input", util.getTextInputProps({
162
162
  sharedTextInputProps,
163
163
  invalid: normalizedProps.invalid,
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Copyright IBM Corp. 2019, 2025
2
+ * Copyright IBM Corp. 2019, 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.
@@ -384,11 +384,8 @@ const ExpandableTile = /*#__PURE__*/React.forwardRef(({
384
384
  hasRoundedCorners,
385
385
  ...rest
386
386
  }, forwardRef) => {
387
- const [isTileMaxHeight, setIsTileMaxHeight] = React.useState(tileMaxHeight);
388
- const [isTilePadding, setIsTilePadding] = React.useState(tilePadding);
389
- const [prevExpanded, setPrevExpanded] = React.useState(expanded);
390
- const [prevTileMaxHeight, setPrevTileMaxHeight] = React.useState(tileMaxHeight);
391
- const [prevTilePadding, setPrevTilePadding] = React.useState(tilePadding);
387
+ const [measuredAboveHeight, setMeasuredAboveHeight] = React.useState(0);
388
+ const [measuredPadding, setMeasuredPadding] = React.useState(0);
392
389
  const [isExpanded, setIsExpanded] = React.useState(expanded);
393
390
  const [interactive, setInteractive] = React.useState(true);
394
391
  const aboveTheFold = React.useRef(null);
@@ -398,105 +395,74 @@ const ExpandableTile = /*#__PURE__*/React.forwardRef(({
398
395
  const tile = React.useRef(null);
399
396
  const ref = useMergedRefs.useMergedRefs([forwardRef, tile]);
400
397
  const prefix = usePrefix.usePrefix();
401
- if (expanded !== prevExpanded) {
398
+ React.useEffect(() => {
402
399
  setIsExpanded(expanded);
403
- setPrevExpanded(expanded);
404
- setMaxHeight();
405
- }
406
- if (tileMaxHeight !== prevTileMaxHeight) {
407
- setIsTileMaxHeight(tileMaxHeight);
408
- setPrevTileMaxHeight(tileMaxHeight);
409
- }
410
- if (tilePadding !== prevTilePadding) {
411
- setIsTilePadding(tilePadding);
412
- setPrevTilePadding(tilePadding);
413
- }
414
- function setMaxHeight() {
415
- if (isExpanded && tileContent.current) {
416
- setIsTileMaxHeight(tileContent.current.getBoundingClientRect()?.height);
417
- }
418
- if (aboveTheFold.current) {
419
- setIsTileMaxHeight(aboveTheFold.current.getBoundingClientRect().height);
420
- }
421
- }
422
- function handleClick(evt) {
423
- evt?.persist?.();
424
- setIsExpanded(!isExpanded);
425
- setMaxHeight();
426
- }
427
- function handleKeyUp(evt) {
400
+ }, [expanded]);
401
+ const handleClick = () => {
402
+ setIsExpanded(prev => !prev);
403
+ };
404
+ const handleKeyUp = evt => {
428
405
  if (evt.target !== tile.current && evt.target !== chevronInteractiveRef.current) {
429
406
  if (match.matches(evt, [keys.Enter, keys.Space])) {
430
407
  evt.preventDefault();
431
408
  }
432
409
  }
433
- }
434
- function getChildren() {
435
- return React.Children.toArray(children);
436
- }
410
+ };
437
411
  const classNames = cx(`${prefix}--tile`, `${prefix}--tile--expandable`, {
438
412
  [`${prefix}--tile--is-expanded`]: isExpanded,
439
413
  [`${prefix}--tile--light`]: light
440
414
  }, className);
441
- const interactiveClassNames = cx(`${prefix}--tile`, `${prefix}--tile--expandable`, `${prefix}--tile--expandable--interactive`, {
442
- [`${prefix}--tile--is-expanded`]: isExpanded,
443
- [`${prefix}--tile--light`]: light,
415
+ const interactiveClassNames = cx(classNames, `${prefix}--tile--expandable--interactive`, {
444
416
  [`${prefix}--tile--slug`]: slug,
445
417
  [`${prefix}--tile--slug-rounded`]: slug && hasRoundedCorners,
446
418
  [`${prefix}--tile--decorator`]: decorator,
447
419
  [`${prefix}--tile--decorator-rounded`]: decorator && hasRoundedCorners
448
- }, className);
420
+ });
449
421
  const chevronInteractiveClassNames = cx(`${prefix}--tile__chevron`, `${prefix}--tile__chevron--interactive`);
450
- const childrenAsArray = getChildren();
422
+ const childrenAsArray = React.Children.toArray(children);
451
423
  useIsomorphicEffect.default(() => {
452
424
  if (!tile.current || !aboveTheFold.current) {
453
425
  return;
454
426
  }
455
- const getStyle = window.getComputedStyle(tile.current, null);
456
- const {
457
- current: node
458
- } = aboveTheFold;
459
- const {
460
- height
461
- } = node.getBoundingClientRect();
462
- const paddingTop = parseInt(getStyle.getPropertyValue('padding-top'), 10);
463
- const paddingBottom = parseInt(getStyle.getPropertyValue('padding-bottom'), 10);
464
- setIsTileMaxHeight(height);
465
- setIsTilePadding(paddingTop + paddingBottom);
466
- }, [isTileMaxHeight]);
427
+ const style = window.getComputedStyle(tile.current);
428
+ const paddingTop = parseInt(style.getPropertyValue('padding-top'), 10) || 0;
429
+ const paddingBottom = parseInt(style.getPropertyValue('padding-bottom'), 10) || 0;
430
+ setMeasuredPadding(paddingTop + paddingBottom);
431
+ setMeasuredAboveHeight(aboveTheFold.current.scrollHeight);
432
+ }, []);
467
433
  useIsomorphicEffect.default(() => {
468
434
  if (!aboveTheFold.current || !belowTheFold.current) {
469
435
  return;
470
436
  }
471
-
472
- // Interactive elements or elements that are given a role should be treated
473
- // the same because elements with a role can not be rendered inside a `button`
474
- if (!useNoInteractiveChildren.getInteractiveContent(belowTheFold.current) && !useNoInteractiveChildren.getRoleContent(belowTheFold.current) && !useNoInteractiveChildren.getInteractiveContent(aboveTheFold.current) && !useNoInteractiveChildren.getRoleContent(aboveTheFold.current) && !(slug || decorator)) {
475
- setInteractive(false);
476
- }
477
- }, [slug, decorator]);
437
+ const hasInteractive = Boolean(useNoInteractiveChildren.getInteractiveContent(aboveTheFold.current)) || Boolean(useNoInteractiveChildren.getRoleContent(aboveTheFold.current)) || Boolean(useNoInteractiveChildren.getInteractiveContent(belowTheFold.current)) || Boolean(useNoInteractiveChildren.getRoleContent(belowTheFold.current)) || Boolean(slug || decorator);
438
+ setInteractive(hasInteractive);
439
+ }, [slug, decorator, children]);
478
440
  useIsomorphicEffect.default(() => {
479
441
  if (!tile.current) {
480
442
  return;
481
443
  }
482
444
  if (isExpanded) {
483
445
  tile.current.style.maxHeight = '';
484
- } else {
485
- tile.current.style.maxHeight = isTileMaxHeight + isTilePadding + 'px';
446
+ return;
486
447
  }
487
- }, [isExpanded, isTileMaxHeight, isTilePadding]);
448
+ const measured = measuredAboveHeight || aboveTheFold.current?.scrollHeight || 0;
449
+ const baseHeight = tileMaxHeight > 0 ? tileMaxHeight : measured;
450
+ const pad = tilePadding > 0 ? tilePadding : measuredPadding;
451
+ tile.current.style.maxHeight = `${baseHeight + pad}px`;
452
+ }, [isExpanded, tileMaxHeight, tilePadding, measuredAboveHeight, measuredPadding]);
488
453
  React.useEffect(() => {
489
454
  if (!aboveTheFold.current) {
490
455
  return;
491
456
  }
492
- const resizeObserver = new ResizeObserver(entries => {
493
- const [aboveTheFold] = entries;
494
- setIsTileMaxHeight(aboveTheFold.contentRect.height);
457
+ const resizeObserver = new ResizeObserver(() => {
458
+ if (aboveTheFold.current) {
459
+ setMeasuredAboveHeight(aboveTheFold.current.scrollHeight);
460
+ }
495
461
  });
496
462
  resizeObserver.observe(aboveTheFold.current);
497
463
  return () => resizeObserver.disconnect();
498
- }, [isTileMaxHeight, isTilePadding]);
499
- const belowTheFoldId = useId.useId('expandable-tile-interactive');
464
+ }, []);
465
+ const belowTheFoldId = useId.useId(interactive ? 'expandable-tile-interactive' : 'expandable-tile');
500
466
 
501
467
  // AILabel is always size `xs`
502
468
  const candidate = slug ?? decorator;
@@ -531,6 +497,7 @@ const ExpandableTile = /*#__PURE__*/React.forwardRef(({
531
497
  type: "button",
532
498
  ref: ref,
533
499
  className: classNames,
500
+ "aria-controls": belowTheFoldId,
534
501
  "aria-expanded": isExpanded,
535
502
  title: isExpanded ? tileExpandedIconText : tileCollapsedIconText
536
503
  }, rest, {
@@ -546,6 +513,7 @@ const ExpandableTile = /*#__PURE__*/React.forwardRef(({
546
513
  className: `${prefix}--tile__chevron`
547
514
  }, /*#__PURE__*/React.createElement("span", null, isExpanded ? tileExpandedLabel : tileCollapsedLabel), _ChevronDown2 || (_ChevronDown2 = /*#__PURE__*/React.createElement(iconsReact.ChevronDown, null))), /*#__PURE__*/React.createElement("div", {
548
515
  ref: belowTheFold,
516
+ id: belowTheFoldId,
549
517
  className: `${prefix}--tile-content`
550
518
  }, childrenAsArray[1])));
551
519
  });
@@ -102,10 +102,10 @@ const TimePicker = frFn((props, ref) => {
102
102
  [`${prefix}--visually-hidden`]: hideLabel,
103
103
  [`${prefix}--label--disabled`]: disabled
104
104
  });
105
- const label = labelText ? /*#__PURE__*/React.createElement("label", {
105
+ const label = typeof labelText !== 'undefined' && labelText !== null && /*#__PURE__*/React.createElement("label", {
106
106
  htmlFor: id,
107
107
  className: labelClasses
108
- }, labelText) : null;
108
+ }, labelText);
109
109
  function getInternalPickerSelects() {
110
110
  const readOnlyEventHandlers = {
111
111
  onMouseDown: evt => {
@@ -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.
@@ -50,8 +50,9 @@ const DefinitionTooltip = ({
50
50
  setOpen(false);
51
51
  },
52
52
  onMouseEnter: () => {
53
- // eslint-disable-next-line @typescript-eslint/no-unused-expressions -- https://github.com/carbon-design-system/carbon/issues/20452
54
- openOnHover ? setOpen(true) : null;
53
+ if (openOnHover) {
54
+ setOpen(true);
55
+ }
55
56
  },
56
57
  onFocus: () => {
57
58
  setOpen(true);
@@ -19,7 +19,6 @@ export interface SideNavProps {
19
19
  onOverlayClick?: MouseEventHandler<HTMLDivElement> | undefined;
20
20
  onSideNavBlur?: () => void;
21
21
  enterDelayMs?: number;
22
- inert?: boolean;
23
22
  }
24
23
  interface SideNavContextData {
25
24
  isRail?: boolean | undefined;
@@ -161,6 +161,16 @@ const SideNav = frFn((props, ref) => {
161
161
  });
162
162
  const lgMediaQuery = `(min-width: ${layout.breakpoints.lg.width})`;
163
163
  const isLg = useMatchMedia.useMatchMedia(lgMediaQuery);
164
+ const inertEnabled = !isRail ? !(expanded || isLg) : false;
165
+ React.useEffect(() => {
166
+ const node = sideNavRef.current;
167
+ if (!node) return;
168
+ if (inertEnabled) {
169
+ node.setAttribute('inert', '');
170
+ } else {
171
+ node.removeAttribute('inert');
172
+ }
173
+ }, [inertEnabled]);
164
174
  return /*#__PURE__*/React.createElement(SideNavContext.Provider, {
165
175
  value: {
166
176
  isRail
@@ -174,8 +184,7 @@ const SideNav = frFn((props, ref) => {
174
184
  }), /*#__PURE__*/React.createElement("nav", _rollupPluginBabelHelpers.extends({
175
185
  tabIndex: -1,
176
186
  ref: navRef,
177
- className: `${prefix}--side-nav__navigation ${className}`,
178
- inert: !isRail ? !(expanded || isLg) : undefined
187
+ className: `${prefix}--side-nav__navigation ${className}`
179
188
  }, accessibilityLabel, eventHandlers, other), childrenToRender));
180
189
  });
181
190
  SideNav.displayName = 'SideNav';