@carbon/react 1.100.0 → 1.101.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 (134) hide show
  1. package/.playwright/INTERNAL_AVT_REPORT_DO_NOT_USE.json +953 -953
  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 +25 -12
  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/Dropdown/Dropdown.js +4 -4
  21. package/es/components/ExpandableSearch/ExpandableSearch.js +1 -1
  22. package/es/components/FileUploader/FileUploaderItem.d.ts +1 -1
  23. package/es/components/FileUploader/FileUploaderItem.js +3 -2
  24. package/es/components/ListBox/test-helpers.d.ts +71 -0
  25. package/es/components/Menu/Menu.js +8 -4
  26. package/es/components/Menu/MenuItem.d.ts +5 -1
  27. package/es/components/Menu/MenuItem.js +11 -1
  28. package/es/components/MenuButton/index.d.ts +1 -1
  29. package/es/components/MenuButton/index.js +3 -2
  30. package/es/components/MultiSelect/FilterableMultiSelect.d.ts +1 -1
  31. package/es/components/MultiSelect/FilterableMultiSelect.js +8 -6
  32. package/es/components/MultiSelect/MultiSelect.js +8 -4
  33. package/es/components/Notification/Notification.js +2 -1
  34. package/es/components/NumberInput/NumberInput.d.ts +1 -1
  35. package/es/components/NumberInput/NumberInput.js +6 -5
  36. package/es/components/OverflowMenu/OverflowMenu.d.ts +1 -0
  37. package/es/components/OverflowMenu/OverflowMenu.js +8 -4
  38. package/es/components/PageHeader/PageHeader.d.ts +1 -1
  39. package/es/components/PageHeader/PageHeader.js +5 -5
  40. package/es/components/Popover/index.js +1 -1
  41. package/es/components/ProgressIndicator/ProgressIndicator.d.ts +1 -1
  42. package/es/components/ProgressIndicator/ProgressIndicator.js +1 -1
  43. package/es/components/RadioButtonGroup/RadioButtonGroup.js +4 -3
  44. package/es/components/Search/Search.d.ts +1 -1
  45. package/es/components/Search/Search.js +1 -1
  46. package/es/components/Select/Select.js +3 -2
  47. package/es/components/StructuredList/StructuredList.d.ts +1 -1
  48. package/es/components/StructuredList/StructuredList.js +2 -4
  49. package/es/components/Tabs/Tabs.d.ts +2 -2
  50. package/es/components/Tabs/Tabs.js +20 -26
  51. package/es/components/Tag/DismissibleTag.js +3 -2
  52. package/es/components/Tag/OperationalTag.js +3 -2
  53. package/es/components/Tag/SelectableTag.js +3 -2
  54. package/es/components/Tag/Tag.js +3 -2
  55. package/es/components/TextArea/TextArea.d.ts +2 -2
  56. package/es/components/TextArea/TextArea.js +7 -6
  57. package/es/components/TextInput/ControlledPasswordInput.js +7 -6
  58. package/es/components/TextInput/PasswordInput.js +5 -6
  59. package/es/components/TextInput/TextInput.js +4 -4
  60. package/es/components/TimePicker/TimePicker.js +2 -2
  61. package/es/components/Tooltip/DefinitionTooltip.d.ts +1 -1
  62. package/es/components/Tooltip/DefinitionTooltip.js +3 -2
  63. package/es/internal/useId.js +3 -4
  64. package/es/internal/usePresence.js +3 -2
  65. package/es/internal/useResizeObserver.d.ts +1 -1
  66. package/es/internal/useResizeObserver.js +5 -7
  67. package/es/tools/events.d.ts +1 -1
  68. package/lib/components/AILabel/index.d.ts +1 -1
  69. package/lib/components/AILabel/index.js +1 -12
  70. package/lib/components/Checkbox/Checkbox.js +5 -3
  71. package/lib/components/CheckboxGroup/CheckboxGroup.js +4 -3
  72. package/lib/components/CodeSnippet/CodeSnippet.d.ts +1 -1
  73. package/lib/components/ComboBox/ComboBox.js +25 -12
  74. package/lib/components/ComboButton/index.d.ts +1 -1
  75. package/lib/components/ComboButton/index.js +2 -1
  76. package/lib/components/ComposedModal/ComposedModal.js +16 -21
  77. package/lib/components/ComposedModal/ModalHeader.d.ts +2 -2
  78. package/lib/components/ComposedModal/ModalHeader.js +1 -1
  79. package/lib/components/Copy/Copy.d.ts +1 -1
  80. package/lib/components/CopyButton/CopyButton.d.ts +1 -1
  81. package/lib/components/DataTable/DataTable.d.ts +2 -0
  82. package/lib/components/DataTable/DataTable.js +6 -5
  83. package/lib/components/DataTable/Table.d.ts +1 -1
  84. package/lib/components/DataTable/Table.js +10 -4
  85. package/lib/components/DataTable/state/sorting.d.ts +4 -2
  86. package/lib/components/Dropdown/Dropdown.js +4 -4
  87. package/lib/components/ExpandableSearch/ExpandableSearch.js +1 -1
  88. package/lib/components/FileUploader/FileUploaderItem.d.ts +1 -1
  89. package/lib/components/FileUploader/FileUploaderItem.js +2 -1
  90. package/lib/components/ListBox/test-helpers.d.ts +71 -0
  91. package/lib/components/Menu/Menu.js +7 -3
  92. package/lib/components/Menu/MenuItem.d.ts +5 -1
  93. package/lib/components/Menu/MenuItem.js +11 -1
  94. package/lib/components/MenuButton/index.d.ts +1 -1
  95. package/lib/components/MenuButton/index.js +2 -1
  96. package/lib/components/MultiSelect/FilterableMultiSelect.d.ts +1 -1
  97. package/lib/components/MultiSelect/FilterableMultiSelect.js +7 -5
  98. package/lib/components/MultiSelect/MultiSelect.js +7 -3
  99. package/lib/components/Notification/Notification.js +2 -1
  100. package/lib/components/NumberInput/NumberInput.d.ts +1 -1
  101. package/lib/components/NumberInput/NumberInput.js +6 -5
  102. package/lib/components/OverflowMenu/OverflowMenu.d.ts +1 -0
  103. package/lib/components/OverflowMenu/OverflowMenu.js +7 -3
  104. package/lib/components/PageHeader/PageHeader.d.ts +1 -1
  105. package/lib/components/PageHeader/PageHeader.js +4 -4
  106. package/lib/components/Popover/index.js +1 -1
  107. package/lib/components/ProgressIndicator/ProgressIndicator.d.ts +1 -1
  108. package/lib/components/ProgressIndicator/ProgressIndicator.js +1 -1
  109. package/lib/components/RadioButtonGroup/RadioButtonGroup.js +4 -3
  110. package/lib/components/Search/Search.d.ts +1 -1
  111. package/lib/components/Search/Search.js +1 -1
  112. package/lib/components/Select/Select.js +3 -2
  113. package/lib/components/StructuredList/StructuredList.d.ts +1 -1
  114. package/lib/components/StructuredList/StructuredList.js +2 -4
  115. package/lib/components/Tabs/Tabs.d.ts +2 -2
  116. package/lib/components/Tabs/Tabs.js +15 -21
  117. package/lib/components/Tag/DismissibleTag.js +2 -1
  118. package/lib/components/Tag/OperationalTag.js +2 -1
  119. package/lib/components/Tag/SelectableTag.js +2 -1
  120. package/lib/components/Tag/Tag.js +2 -1
  121. package/lib/components/TextArea/TextArea.d.ts +2 -2
  122. package/lib/components/TextArea/TextArea.js +7 -6
  123. package/lib/components/TextInput/ControlledPasswordInput.js +7 -6
  124. package/lib/components/TextInput/PasswordInput.js +5 -6
  125. package/lib/components/TextInput/TextInput.js +4 -4
  126. package/lib/components/TimePicker/TimePicker.js +2 -2
  127. package/lib/components/Tooltip/DefinitionTooltip.d.ts +1 -1
  128. package/lib/components/Tooltip/DefinitionTooltip.js +3 -2
  129. package/lib/internal/useId.js +2 -3
  130. package/lib/internal/usePresence.js +2 -1
  131. package/lib/internal/useResizeObserver.d.ts +1 -1
  132. package/lib/internal/useResizeObserver.js +4 -6
  133. package/lib/tools/events.d.ts +1 -1
  134. package/package.json +9 -9
@@ -96,7 +96,7 @@ ModalHeader.propTypes = {
96
96
  /**
97
97
  * Specify an optional label to be displayed
98
98
  */
99
- label: PropTypes.node,
99
+ label: PropTypes.string,
100
100
  /**
101
101
  * Specify an optional className to be applied to the modal header label
102
102
  */
@@ -50,7 +50,7 @@ declare namespace Copy {
50
50
  /**
51
51
  * Specify how the trigger should align with the tooltip
52
52
  */
53
- align: PropTypes.Requireable<string> | PropTypes.Validator<string>;
53
+ align: PropTypes.Requireable<import("@floating-ui/utils").Placement | "top-left" | "top-right" | "bottom-left" | "bottom-right" | "left-bottom" | "left-top" | "right-bottom" | "right-top"> | PropTypes.Validator<import("@floating-ui/utils").Placement | "top-left" | "top-right" | "bottom-left" | "bottom-right" | "left-bottom" | "left-top" | "right-bottom" | "right-top">;
54
54
  /**
55
55
  * **Experimental**: Will attempt to automatically align the tooltip. Requires
56
56
  * React v17+
@@ -51,7 +51,7 @@ declare namespace CopyButton {
51
51
  /**
52
52
  * Specify how the trigger should align with the tooltip
53
53
  */
54
- align: PropTypes.Requireable<string> | PropTypes.Validator<string>;
54
+ align: PropTypes.Requireable<import("@floating-ui/utils").Placement | "top-left" | "top-right" | "bottom-left" | "bottom-right" | "left-bottom" | "left-top" | "right-bottom" | "right-top"> | PropTypes.Validator<import("@floating-ui/utils").Placement | "top-left" | "top-right" | "bottom-left" | "bottom-right" | "left-bottom" | "left-top" | "right-bottom" | "right-top">;
55
55
  /**
56
56
  * **Experimental**: Will attempt to automatically align the tooltip. Requires
57
57
  * React v17+
@@ -51,6 +51,7 @@ export interface DataTableHeader {
51
51
  header: ReactNode;
52
52
  slug?: ReactElement;
53
53
  decorator?: ReactElement;
54
+ isSortable?: boolean;
54
55
  }
55
56
  export interface DataTableRenderProps<RowType, ColTypes extends any[]> {
56
57
  /**
@@ -435,6 +436,7 @@ export declare const DataTable: {
435
436
  headers: PropTypes.Validator<(PropTypes.InferProps<{
436
437
  key: PropTypes.Validator<string>;
437
438
  header: PropTypes.Validator<NonNullable<PropTypes.ReactNodeLike>>;
439
+ isSortable: PropTypes.Requireable<boolean>;
438
440
  }> | null | undefined)[]>;
439
441
  /**
440
442
  * Specify whether the table should be able to be sorted by its headers
@@ -98,7 +98,7 @@ const DataTable = props => {
98
98
  render,
99
99
  translateWithId: t = defaultTranslateWithId,
100
100
  size,
101
- isSortable: isSortableProp,
101
+ isSortable,
102
102
  useZebraStyles,
103
103
  useStaticWidth,
104
104
  stickyHeader,
@@ -137,7 +137,7 @@ const DataTable = props => {
137
137
  const getHeaderProps = ({
138
138
  header,
139
139
  onClick,
140
- isSortable = isSortableProp,
140
+ isSortable: headerIsSortable,
141
141
  ...rest
142
142
  }) => {
143
143
  const {
@@ -153,7 +153,7 @@ const DataTable = props => {
153
153
  ...rest,
154
154
  key,
155
155
  sortDirection,
156
- isSortable,
156
+ isSortable: headerIsSortable ?? header.isSortable ?? isSortable,
157
157
  isSortHeader: sortHeaderKey === key,
158
158
  slug,
159
159
  decorator,
@@ -312,7 +312,7 @@ const DataTable = props => {
312
312
  return {
313
313
  useZebraStyles,
314
314
  size: size ?? 'lg',
315
- isSortable: isSortableProp,
315
+ isSortable,
316
316
  useStaticWidth,
317
317
  stickyHeader,
318
318
  overflowMenuOnHover: overflowMenuOnHover ?? false,
@@ -602,7 +602,8 @@ DataTable.propTypes = {
602
602
  */
603
603
  headers: PropTypes.arrayOf(PropTypes.shape({
604
604
  key: PropTypes.string.isRequired,
605
- header: PropTypes.node.isRequired
605
+ header: PropTypes.node.isRequired,
606
+ isSortable: PropTypes.bool
606
607
  })).isRequired,
607
608
  /**
608
609
  * Specify whether the table should be able to be sorted by its headers
@@ -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.
@@ -74,12 +74,18 @@ const Table = ({
74
74
  [`${prefix}--data-table--visible-overflow-menu`]: !overflowMenuOnHover
75
75
  });
76
76
  const toggleTableBodyAlignmentClass = React.useCallback((alignTop = false) => {
77
- // eslint-disable-next-line @typescript-eslint/no-unused-expressions -- https://github.com/carbon-design-system/carbon/issues/20452
78
- alignTop ? tableRef.current?.classList.add(`${prefix}--data-table--top-aligned-body`) : tableRef.current?.classList.remove(`${prefix}--data-table--top-aligned-body`);
77
+ if (alignTop) {
78
+ tableRef.current?.classList.add(`${prefix}--data-table--top-aligned-body`);
79
+ } else {
80
+ tableRef.current?.classList.remove(`${prefix}--data-table--top-aligned-body`);
81
+ }
79
82
  }, [prefix]);
80
83
  const toggleTableHeaderAlignmentClass = React.useCallback((alignTop = false) => {
81
- // eslint-disable-next-line @typescript-eslint/no-unused-expressions -- https://github.com/carbon-design-system/carbon/issues/20452
82
- alignTop ? tableRef.current?.classList.add(`${prefix}--data-table--top-aligned-header`) : tableRef.current?.classList.remove(`${prefix}--data-table--top-aligned-header`);
84
+ if (alignTop) {
85
+ tableRef.current?.classList.add(`${prefix}--data-table--top-aligned-header`);
86
+ } else {
87
+ tableRef.current?.classList.remove(`${prefix}--data-table--top-aligned-header`);
88
+ }
83
89
  }, [prefix]);
84
90
  const setTableAlignment = React.useCallback(() => {
85
91
  if (experimentalAutoAlign) {
@@ -43,7 +43,8 @@ export declare const getNextSortDirection: (prevHeader: string, currentHeader: s
43
43
  * @param state - Current table state.
44
44
  * @param key - Header key to sort by.
45
45
  */
46
- export declare const getNextSortState: <ColTypes extends any[]>(props: Props, state: State<ColTypes>, { key }: {
46
+ export declare const getNextSortState: <ColTypes extends any[]>(// eslint-disable-line @typescript-eslint/no-explicit-any -- https://github.com/carbon-design-system/carbon/issues/20452
47
+ props: Props, state: State<ColTypes>, { key }: {
47
48
  key: string;
48
49
  }) => Pick<State<ColTypes>, "sortHeaderKey" | "sortDirection" | "rowIds">;
49
50
  /**
@@ -54,5 +55,6 @@ export declare const getNextSortState: <ColTypes extends any[]>(props: Props, st
54
55
  * @param key - Header key to sort by.
55
56
  * @param sortDirection - Sort direction to apply.
56
57
  */
57
- export declare const getSortedState: <ColTypes extends any[]>({ locale, sortRow }: Props, { rowIds, cellsById, initialRowOrder }: State<ColTypes>, key: string, sortDirection: DataTableSortState) => Pick<State<ColTypes>, "rowIds" | "sortDirection" | "sortHeaderKey">;
58
+ export declare const getSortedState: <ColTypes extends any[]>(// eslint-disable-line @typescript-eslint/no-explicit-any -- https://github.com/carbon-design-system/carbon/issues/20452
59
+ { locale, sortRow }: Props, { rowIds, cellsById, initialRowOrder }: State<ColTypes>, key: string, sortDirection: DataTableSortState) => Pick<State<ColTypes>, "rowIds" | "sortDirection" | "sortHeaderKey">;
58
60
  export {};
@@ -264,7 +264,7 @@ const Dropdown = /*#__PURE__*/React.forwardRef(({
264
264
  className: helperClasses
265
265
  }, helperText) : null;
266
266
  const handleFocus = evt => {
267
- setIsFocused(evt.type === 'focus' && !selectedItem ? true : false);
267
+ setIsFocused(evt.type === 'focus' && !selectedItem);
268
268
  };
269
269
  const buttonRef = React.useRef(null);
270
270
  const mergedRef = mergeRefs.mergeRefs(toggleButtonProps.ref, ref, buttonRef);
@@ -353,10 +353,10 @@ const Dropdown = /*#__PURE__*/React.forwardRef(({
353
353
  size: size,
354
354
  className: className,
355
355
  invalid: normalizedProps.invalid,
356
- invalidText: isFluid ? invalidText : undefined,
356
+ invalidText: invalidText,
357
357
  invalidTextId: normalizedProps.invalidId,
358
358
  warn: normalizedProps.warn,
359
- warnText: isFluid ? warnText : undefined,
359
+ warnText: warnText,
360
360
  warnTextId: normalizedProps.warnId,
361
361
  light: light,
362
362
  isOpen: isOpen,
@@ -402,7 +402,7 @@ const Dropdown = /*#__PURE__*/React.forwardRef(({
402
402
  }, itemProps), itemToElement ? itemToElement(item) : itemToString(item), selectedItem === item && /*#__PURE__*/React.createElement(iconsReact.Checkmark, {
403
403
  className: `${prefix}--list-box__menu-item__selected-icon`
404
404
  }));
405
- }))), !inline && !isFluid && !normalizedProps.validation && helper, !inline && !isFluid && normalizedProps.validation);
405
+ }))), !inline && !isFluid && !normalizedProps.validation && helper);
406
406
  });
407
407
 
408
408
  // Workaround problems with forwardRef() and generics. In the long term, should stop using forwardRef().
@@ -32,7 +32,7 @@ const ExpandableSearch = frFn((props, forwardedRef) => {
32
32
  ...rest
33
33
  } = props;
34
34
  const [expanded, setExpanded] = React.useState(isExpanded || false);
35
- const [hasContent, setHasContent] = React.useState(defaultValue ? true : false);
35
+ const [hasContent, setHasContent] = React.useState(Boolean(defaultValue));
36
36
  const searchRef = React.useRef(null);
37
37
  const prefix = usePrefix.usePrefix();
38
38
  function handleBlur(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.
@@ -19,6 +19,7 @@ var match = require('../../internal/keyboard/match.js');
19
19
  var useId = require('../../internal/useId.js');
20
20
  var usePrefix = require('../../internal/usePrefix.js');
21
21
  var noopFn = require('../../internal/noopFn.js');
22
+ var useIsomorphicEffect = require('../../internal/useIsomorphicEffect.js');
22
23
  var Text = require('../Text/Text.js');
23
24
  require('../Text/TextDirection.js');
24
25
  require('../Tooltip/DefinitionTooltip.js');
@@ -62,7 +63,7 @@ function FileUploaderItem({
62
63
  setIsEllipsisApplied(isActive);
63
64
  return isActive;
64
65
  };
65
- React.useLayoutEffect(() => {
66
+ useIsomorphicEffect.default(() => {
66
67
  isEllipsisActive(textRef.current);
67
68
  }, [prefix, name]);
68
69
  return /*#__PURE__*/React.createElement("span", _rollupPluginBabelHelpers.extends({
@@ -0,0 +1,71 @@
1
+ /**
2
+ * Copyright IBM Corp. 2016, 2026
3
+ *
4
+ * This source code is licensed under the Apache-2.0 license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ */
7
+ import '@testing-library/jest-dom/jest-globals';
8
+ export declare const findListBoxNode: () => Element | null;
9
+ export declare const findMenuNode: () => Element | null;
10
+ export declare const findMenuItemNode: (index: number) => Element;
11
+ export declare const findMenuIconNode: () => Element | null;
12
+ export declare const findFieldNode: () => Element | null;
13
+ export declare const findComboboxNode: () => Element | null;
14
+ export declare const findPopupNode: () => Element | null;
15
+ export declare const openMenu: () => Promise<void>;
16
+ export declare const assertMenuOpen: (mockProps: {
17
+ items: unknown[];
18
+ }) => void;
19
+ export declare const assertMenuClosed: () => void;
20
+ /**
21
+ * 'GenericItem' corresponds to an item in a collection that is passed to
22
+ * `MultiSelect` that is in a predictable shape and works with the default
23
+ * `itemToString` function.
24
+ */
25
+ export declare const generateGenericItem: (index: number) => {
26
+ id: string;
27
+ label: string;
28
+ value: number;
29
+ };
30
+ /**
31
+ * 'CustomItem' corresponds to a potentially different item structure that might
32
+ * be passed into `MultiSelect` that we would need to supply a custom
33
+ * `itemToString` method for.
34
+ */
35
+ export declare const generateCustomItem: (index: number) => {
36
+ field: string;
37
+ value: string;
38
+ };
39
+ /**
40
+ * Generates an array of values generated by the `generator` function.
41
+ */
42
+ export declare const generateItems: <T>(amount: number, generator: (index: number) => T) => T[];
43
+ export declare const customItemToString: ({ field, }: {
44
+ field: string;
45
+ value: string;
46
+ }) => string;
47
+ /**
48
+ * This object contains two sets of three items that share the same root
49
+ * word in different portions of the string (beginning, middle, end):
50
+ *
51
+ * - 'struct'
52
+ * - 'port'
53
+ *
54
+ * Separated by a disabled item, these derivative words are helpful when
55
+ * testing fuzzy search functions and components that do substring filtering.
56
+ */
57
+ export declare const cognateItems: ({
58
+ id: string;
59
+ text: string;
60
+ disabled?: undefined;
61
+ } | {
62
+ id: string;
63
+ text: string;
64
+ disabled: boolean;
65
+ })[];
66
+ /**
67
+ * Flushes microtasks to ensure element position state is settled
68
+ * From https://floating-ui.com/docs/react#testing
69
+ * More context here: https://github.com/floating-ui/react-popper/issues/368#issuecomment-1340413010
70
+ */
71
+ export declare const waitForPosition: () => Promise<void>;
@@ -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(() => {
@@ -622,7 +624,7 @@ const FilterableMultiSelect = /*#__PURE__*/React.forwardRef(function FilterableM
622
624
  if (evt?.target.classList.contains(`${prefix}--tag__close-icon`) || evt?.target.classList.contains(`${prefix}--list-box__selection`)) {
623
625
  setIsFocused(false);
624
626
  } else {
625
- setIsFocused(evt?.type === 'focus' ? true : false);
627
+ setIsFocused(evt?.type === 'focus');
626
628
  }
627
629
  };
628
630
  const mergedRef = mergeRefs.mergeRefs(textInput, inputProp.ref);
@@ -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');
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.
@@ -447,7 +447,7 @@ const NumberInput = /*#__PURE__*/React.forwardRef((props, forwardRef) => {
447
447
  if ('type' in evt.target && evt.target.type === 'button') {
448
448
  setIsFocused(false);
449
449
  } else {
450
- setIsFocused(evt.type === 'focus' ? true : false);
450
+ setIsFocused(evt.type === 'focus');
451
451
  }
452
452
  };
453
453
  const outerElementClasses = cx(`${prefix}--form-item`, {
@@ -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`);
@@ -42,7 +42,7 @@ const Popover = /*#__PURE__*/React.forwardRef(function PopoverRenderFunction({
42
42
  autoAlign = false,
43
43
  autoAlignBoundary,
44
44
  backgroundToken = 'layer',
45
- caret = isTabTip ? false : true,
45
+ caret = !isTabTip,
46
46
  className: customClassName,
47
47
  children,
48
48
  border = false,
@@ -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.