@patternfly/react-core 6.0.0-alpha.97 → 6.0.0-alpha.99

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 (161) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/components/package.json +1 -1
  3. package/deprecated/package.json +1 -1
  4. package/dist/dynamic/components/AboutModal/package.json +1 -1
  5. package/dist/dynamic/components/Accordion/package.json +1 -1
  6. package/dist/dynamic/components/ActionList/package.json +1 -1
  7. package/dist/dynamic/components/Alert/package.json +1 -1
  8. package/dist/dynamic/components/Avatar/package.json +1 -1
  9. package/dist/dynamic/components/BackToTop/package.json +1 -1
  10. package/dist/dynamic/components/Backdrop/package.json +1 -1
  11. package/dist/dynamic/components/BackgroundImage/package.json +1 -1
  12. package/dist/dynamic/components/Badge/package.json +1 -1
  13. package/dist/dynamic/components/Banner/package.json +1 -1
  14. package/dist/dynamic/components/Brand/package.json +1 -1
  15. package/dist/dynamic/components/Breadcrumb/package.json +1 -1
  16. package/dist/dynamic/components/Button/package.json +1 -1
  17. package/dist/dynamic/components/CalendarMonth/package.json +1 -1
  18. package/dist/dynamic/components/Card/package.json +1 -1
  19. package/dist/dynamic/components/Checkbox/package.json +1 -1
  20. package/dist/dynamic/components/ClipboardCopy/package.json +1 -1
  21. package/dist/dynamic/components/CodeBlock/package.json +1 -1
  22. package/dist/dynamic/components/Content/package.json +1 -1
  23. package/dist/dynamic/components/DataList/package.json +1 -1
  24. package/dist/dynamic/components/DatePicker/package.json +1 -1
  25. package/dist/dynamic/components/DescriptionList/package.json +1 -1
  26. package/dist/dynamic/components/Divider/package.json +1 -1
  27. package/dist/dynamic/components/Drawer/package.json +1 -1
  28. package/dist/dynamic/components/Dropdown/package.json +1 -1
  29. package/dist/dynamic/components/DualListSelector/package.json +1 -1
  30. package/dist/dynamic/components/EmptyState/package.json +1 -1
  31. package/dist/dynamic/components/ExpandableSection/package.json +1 -1
  32. package/dist/dynamic/components/FileUpload/package.json +1 -1
  33. package/dist/dynamic/components/Form/package.json +1 -1
  34. package/dist/dynamic/components/FormSelect/package.json +1 -1
  35. package/dist/dynamic/components/HelperText/package.json +1 -1
  36. package/dist/dynamic/components/Hint/package.json +1 -1
  37. package/dist/dynamic/components/Icon/package.json +1 -1
  38. package/dist/dynamic/components/InputGroup/package.json +1 -1
  39. package/dist/dynamic/components/JumpLinks/package.json +1 -1
  40. package/dist/dynamic/components/Label/package.json +1 -1
  41. package/dist/dynamic/components/List/package.json +1 -1
  42. package/dist/dynamic/components/LoginPage/package.json +1 -1
  43. package/dist/dynamic/components/Masthead/package.json +1 -1
  44. package/dist/dynamic/components/Menu/package.json +1 -1
  45. package/dist/dynamic/components/MenuToggle/package.json +1 -1
  46. package/dist/dynamic/components/Modal/package.json +1 -1
  47. package/dist/dynamic/components/MultipleFileUpload/package.json +1 -1
  48. package/dist/dynamic/components/Nav/package.json +1 -1
  49. package/dist/dynamic/components/NotificationBadge/package.json +1 -1
  50. package/dist/dynamic/components/NotificationDrawer/package.json +1 -1
  51. package/dist/dynamic/components/NumberInput/package.json +1 -1
  52. package/dist/dynamic/components/OverflowMenu/package.json +1 -1
  53. package/dist/dynamic/components/Page/package.json +1 -1
  54. package/dist/dynamic/components/Pagination/package.json +1 -1
  55. package/dist/dynamic/components/Panel/package.json +1 -1
  56. package/dist/dynamic/components/Popover/package.json +1 -1
  57. package/dist/dynamic/components/Progress/package.json +1 -1
  58. package/dist/dynamic/components/ProgressStepper/package.json +1 -1
  59. package/dist/dynamic/components/Radio/package.json +1 -1
  60. package/dist/dynamic/components/SearchInput/package.json +1 -1
  61. package/dist/dynamic/components/Select/package.json +1 -1
  62. package/dist/dynamic/components/Sidebar/package.json +1 -1
  63. package/dist/dynamic/components/SimpleList/package.json +1 -1
  64. package/dist/dynamic/components/Skeleton/package.json +1 -1
  65. package/dist/dynamic/components/SkipToContent/package.json +1 -1
  66. package/dist/dynamic/components/Slider/package.json +1 -1
  67. package/dist/dynamic/components/Spinner/package.json +1 -1
  68. package/dist/dynamic/components/Switch/package.json +1 -1
  69. package/dist/dynamic/components/Tabs/package.json +1 -1
  70. package/dist/dynamic/components/TextArea/package.json +1 -1
  71. package/dist/dynamic/components/TextInput/package.json +1 -1
  72. package/dist/dynamic/components/TextInputGroup/package.json +1 -1
  73. package/dist/dynamic/components/Tile/package.json +1 -1
  74. package/dist/dynamic/components/TimePicker/package.json +1 -1
  75. package/dist/dynamic/components/Timestamp/package.json +1 -1
  76. package/dist/dynamic/components/Title/package.json +1 -1
  77. package/dist/dynamic/components/ToggleGroup/package.json +1 -1
  78. package/dist/dynamic/components/Toolbar/package.json +1 -1
  79. package/dist/dynamic/components/Tooltip/package.json +1 -1
  80. package/dist/dynamic/components/TreeView/package.json +1 -1
  81. package/dist/dynamic/components/Truncate/package.json +1 -1
  82. package/dist/dynamic/components/Wizard/hooks/package.json +1 -1
  83. package/dist/dynamic/components/Wizard/package.json +1 -1
  84. package/dist/dynamic/deprecated/components/Chip/package.json +1 -1
  85. package/dist/dynamic/deprecated/components/DragDrop/package.json +1 -1
  86. package/dist/dynamic/deprecated/components/DualListSelector/package.json +1 -1
  87. package/dist/dynamic/deprecated/components/Modal/package.json +1 -1
  88. package/dist/dynamic/deprecated/components/Wizard/package.json +1 -1
  89. package/dist/dynamic/deprecated/components/package.json +1 -1
  90. package/dist/dynamic/helpers/FocusTrap/FocusTrap/package.json +1 -1
  91. package/dist/dynamic/helpers/GenerateId/GenerateId/package.json +1 -1
  92. package/dist/dynamic/helpers/KeyboardHandler/package.json +1 -1
  93. package/dist/dynamic/helpers/OUIA/ouia/package.json +1 -1
  94. package/dist/dynamic/helpers/Popper/Popper/package.json +1 -1
  95. package/dist/dynamic/helpers/constants/package.json +1 -1
  96. package/dist/dynamic/helpers/datetimeUtils/package.json +1 -1
  97. package/dist/dynamic/helpers/fileUtils/package.json +1 -1
  98. package/dist/dynamic/helpers/htmlConstants/package.json +1 -1
  99. package/dist/dynamic/helpers/package.json +1 -1
  100. package/dist/dynamic/helpers/resizeObserver/package.json +1 -1
  101. package/dist/dynamic/helpers/typeUtils/package.json +1 -1
  102. package/dist/dynamic/helpers/useInterval/package.json +1 -1
  103. package/dist/dynamic/helpers/useIsomorphicLayout/package.json +1 -1
  104. package/dist/dynamic/helpers/useUnmountEffect/package.json +1 -1
  105. package/dist/dynamic/helpers/util/package.json +1 -1
  106. package/dist/dynamic/layouts/Bullseye/package.json +1 -1
  107. package/dist/dynamic/layouts/Flex/package.json +1 -1
  108. package/dist/dynamic/layouts/Gallery/package.json +1 -1
  109. package/dist/dynamic/layouts/Grid/package.json +1 -1
  110. package/dist/dynamic/layouts/Level/package.json +1 -1
  111. package/dist/dynamic/layouts/Split/package.json +1 -1
  112. package/dist/dynamic/layouts/Stack/package.json +1 -1
  113. package/dist/dynamic/styles/package.json +1 -1
  114. package/dist/dynamic-modules.json +1 -0
  115. package/dist/esm/components/Dropdown/Dropdown.d.ts.map +1 -1
  116. package/dist/esm/components/Dropdown/Dropdown.js +16 -11
  117. package/dist/esm/components/Dropdown/Dropdown.js.map +1 -1
  118. package/dist/esm/components/Menu/Menu.js +2 -2
  119. package/dist/esm/components/Menu/Menu.js.map +1 -1
  120. package/dist/esm/components/Menu/MenuContainer.d.ts +2 -0
  121. package/dist/esm/components/Menu/MenuContainer.d.ts.map +1 -1
  122. package/dist/esm/components/Menu/MenuContainer.js +17 -12
  123. package/dist/esm/components/Menu/MenuContainer.js.map +1 -1
  124. package/dist/esm/components/MenuToggle/MenuToggle.d.ts +6 -0
  125. package/dist/esm/components/MenuToggle/MenuToggle.d.ts.map +1 -1
  126. package/dist/esm/components/MenuToggle/MenuToggle.js +8 -2
  127. package/dist/esm/components/MenuToggle/MenuToggle.js.map +1 -1
  128. package/dist/esm/components/Select/Select.d.ts.map +1 -1
  129. package/dist/esm/components/Select/Select.js +16 -11
  130. package/dist/esm/components/Select/Select.js.map +1 -1
  131. package/dist/js/components/Dropdown/Dropdown.d.ts.map +1 -1
  132. package/dist/js/components/Dropdown/Dropdown.js +16 -11
  133. package/dist/js/components/Dropdown/Dropdown.js.map +1 -1
  134. package/dist/js/components/Menu/Menu.js +2 -2
  135. package/dist/js/components/Menu/Menu.js.map +1 -1
  136. package/dist/js/components/Menu/MenuContainer.d.ts +2 -0
  137. package/dist/js/components/Menu/MenuContainer.d.ts.map +1 -1
  138. package/dist/js/components/Menu/MenuContainer.js +17 -12
  139. package/dist/js/components/Menu/MenuContainer.js.map +1 -1
  140. package/dist/js/components/MenuToggle/MenuToggle.d.ts +6 -0
  141. package/dist/js/components/MenuToggle/MenuToggle.d.ts.map +1 -1
  142. package/dist/js/components/MenuToggle/MenuToggle.js +9 -3
  143. package/dist/js/components/MenuToggle/MenuToggle.js.map +1 -1
  144. package/dist/js/components/Select/Select.d.ts.map +1 -1
  145. package/dist/js/components/Select/Select.js +16 -11
  146. package/dist/js/components/Select/Select.js.map +1 -1
  147. package/dist/umd/assets/{output-oMCjf7ay.css → output-CIrjpuGJ.css} +7022 -7022
  148. package/dist/umd/react-core.min.js +3 -3
  149. package/helpers/package.json +1 -1
  150. package/layouts/package.json +1 -1
  151. package/next/package.json +1 -1
  152. package/package.json +2 -2
  153. package/src/components/Breadcrumb/examples/BreadcrumbDropdown.tsx +1 -0
  154. package/src/components/Dropdown/Dropdown.tsx +16 -10
  155. package/src/components/Menu/Menu.tsx +2 -2
  156. package/src/components/Menu/MenuContainer.tsx +20 -11
  157. package/src/components/MenuToggle/MenuToggle.tsx +10 -0
  158. package/src/components/MenuToggle/__tests__/MenuToggle.test.tsx +13 -6
  159. package/src/components/MenuToggle/examples/MenuToggle.md +9 -1
  160. package/src/components/MenuToggle/examples/MenuToggleSmall.tsx +4 -0
  161. package/src/components/Select/Select.tsx +14 -8
@@ -1 +1 @@
1
- {"name":"@patternfly/react-core-helpers","main":"../dist/js/helpers/index.js","module":"../dist/esm/helpers/index.js","typings":"../dist/esm/helpers/index.d.ts","version":"6.0.0-alpha.96","private":true}
1
+ {"name":"@patternfly/react-core-helpers","main":"../dist/js/helpers/index.js","module":"../dist/esm/helpers/index.js","typings":"../dist/esm/helpers/index.d.ts","version":"6.0.0-alpha.98","private":true}
@@ -1 +1 @@
1
- {"name":"@patternfly/react-core-layouts","main":"../dist/js/layouts/index.js","module":"../dist/esm/layouts/index.js","typings":"../dist/esm/layouts/index.d.ts","version":"6.0.0-alpha.96","private":true}
1
+ {"name":"@patternfly/react-core-layouts","main":"../dist/js/layouts/index.js","module":"../dist/esm/layouts/index.js","typings":"../dist/esm/layouts/index.d.ts","version":"6.0.0-alpha.98","private":true}
package/next/package.json CHANGED
@@ -1 +1 @@
1
- {"name":"@patternfly/react-core-next","main":"../dist/js/next/index.js","module":"../dist/esm/next/index.js","typings":"../dist/esm/next/index.d.ts","version":"6.0.0-alpha.96","private":true}
1
+ {"name":"@patternfly/react-core-next","main":"../dist/js/next/index.js","module":"../dist/esm/next/index.js","typings":"../dist/esm/next/index.d.ts","version":"6.0.0-alpha.98","private":true}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@patternfly/react-core",
3
- "version": "6.0.0-alpha.97",
3
+ "version": "6.0.0-alpha.99",
4
4
  "description": "This library provides a set of common React components for use with the PatternFly reference implementation.",
5
5
  "main": "dist/js/index.js",
6
6
  "module": "dist/esm/index.js",
@@ -64,5 +64,5 @@
64
64
  "react": "^17 || ^18",
65
65
  "react-dom": "^17 || ^18"
66
66
  },
67
- "gitHead": "5e19008b3872fc1fb2cdea963253d3d48e6cd329"
67
+ "gitHead": "a74cdba65be61e9f94424de4381af804050c409f"
68
68
  }
@@ -66,6 +66,7 @@ export const BreadcrumbDropdown: React.FunctionComponent = () => {
66
66
  onOpenChange={(isOpen: boolean) => setIsOpen(isOpen)}
67
67
  toggle={(toggleRef: React.Ref<MenuToggleElement>) => (
68
68
  <MenuToggle
69
+ size="sm"
69
70
  badge={
70
71
  <Badge isRead screenReaderText="additional items">
71
72
  {dropdownItems.length}
@@ -104,6 +104,22 @@ const DropdownBase: React.FunctionComponent<DropdownProps> = ({
104
104
  ? localToggleRef
105
105
  : (toggle?.toggleRef as React.RefObject<HTMLButtonElement>);
106
106
 
107
+ const prevIsOpen = React.useRef<boolean>(isOpen);
108
+ React.useEffect(() => {
109
+ // menu was opened, focus on first menu item
110
+ if (prevIsOpen.current === false && isOpen === true && shouldFocusFirstItemOnOpen) {
111
+ setTimeout(() => {
112
+ const firstElement = menuRef?.current?.querySelector(
113
+ 'li button:not(:disabled),li input:not(:disabled),li a:not([aria-disabled="true"])'
114
+ );
115
+ firstElement && (firstElement as HTMLElement).focus();
116
+ }, 0);
117
+ }
118
+
119
+ prevIsOpen.current = isOpen;
120
+ // eslint-disable-next-line react-hooks/exhaustive-deps
121
+ }, [isOpen]);
122
+
107
123
  React.useEffect(() => {
108
124
  const handleMenuKeys = (event: KeyboardEvent) => {
109
125
  // Close the menu on tab or escape if onOpenChange is provided
@@ -120,16 +136,6 @@ const DropdownBase: React.FunctionComponent<DropdownProps> = ({
120
136
  };
121
137
 
122
138
  const handleClick = (event: MouseEvent) => {
123
- // toggle was opened, focus on first menu item
124
- if (isOpen && shouldFocusFirstItemOnOpen && toggleRef.current?.contains(event.target as Node)) {
125
- setTimeout(() => {
126
- const firstElement = menuRef?.current?.querySelector(
127
- 'li button:not(:disabled),li input:not(:disabled),li a:not([aria-disabled="true"])'
128
- );
129
- firstElement && (firstElement as HTMLElement).focus();
130
- }, 0);
131
- }
132
-
133
139
  // If the event is not on the toggle and onOpenChange callback is provided, close the menu
134
140
  if (isOpen && onOpenChange && !toggleRef?.current?.contains(event.target as Node)) {
135
141
  if (isOpen && !menuRef.current?.contains(event.target as Node)) {
@@ -119,7 +119,7 @@ class MenuBase extends React.Component<MenuProps, MenuState> {
119
119
  if (this.context) {
120
120
  this.setState({ disableHover: this.context.disableHover });
121
121
  }
122
- if (canUseDOM) {
122
+ if (canUseDOM && this.props.containsDrilldown) {
123
123
  window.addEventListener('transitionend', this.props.isRootMenu ? this.handleDrilldownTransition : null);
124
124
  }
125
125
 
@@ -127,7 +127,7 @@ class MenuBase extends React.Component<MenuProps, MenuState> {
127
127
  }
128
128
 
129
129
  componentWillUnmount() {
130
- if (canUseDOM) {
130
+ if (canUseDOM && this.props.containsDrilldown) {
131
131
  window.removeEventListener('transitionend', this.handleDrilldownTransition);
132
132
  }
133
133
  }
@@ -37,6 +37,8 @@ export interface MenuContainerProps {
37
37
  zIndex?: number;
38
38
  /** Additional properties to pass to the Popper */
39
39
  popperProps?: MenuPopperProps;
40
+ /** @beta Flag indicating the first menu item should be focused after opening the dropdown. */
41
+ shouldFocusFirstItemOnOpen?: boolean;
40
42
  }
41
43
 
42
44
  /**
@@ -51,8 +53,25 @@ export const MenuContainer: React.FunctionComponent<MenuContainerProps> = ({
51
53
  onOpenChange,
52
54
  zIndex = 9999,
53
55
  popperProps,
54
- onOpenChangeKeys = ['Escape', 'Tab']
56
+ onOpenChangeKeys = ['Escape', 'Tab'],
57
+ shouldFocusFirstItemOnOpen = true
55
58
  }: MenuContainerProps) => {
59
+ const prevIsOpen = React.useRef<boolean>(isOpen);
60
+ React.useEffect(() => {
61
+ // menu was opened, focus on first menu item
62
+ if (prevIsOpen.current === false && isOpen === true && shouldFocusFirstItemOnOpen) {
63
+ setTimeout(() => {
64
+ const firstElement = menuRef?.current?.querySelector(
65
+ 'li button:not(:disabled),li input:not(:disabled),li a:not([aria-disabled="true"])'
66
+ );
67
+ firstElement && (firstElement as HTMLElement).focus();
68
+ }, 0);
69
+ }
70
+
71
+ prevIsOpen.current = isOpen;
72
+ // eslint-disable-next-line react-hooks/exhaustive-deps
73
+ }, [isOpen]);
74
+
56
75
  React.useEffect(() => {
57
76
  const handleMenuKeys = (event: KeyboardEvent) => {
58
77
  // Close the menu on tab or escape if onOpenChange is provided
@@ -68,16 +87,6 @@ export const MenuContainer: React.FunctionComponent<MenuContainerProps> = ({
68
87
  };
69
88
 
70
89
  const handleClick = (event: MouseEvent) => {
71
- // toggle was opened, focus on first menu item
72
- if (isOpen && toggleRef.current?.contains(event.target as Node)) {
73
- setTimeout(() => {
74
- const firstElement = menuRef?.current?.querySelector(
75
- 'li button:not(:disabled),li input:not(:disabled),li a:not([aria-disabled="true"])'
76
- );
77
- firstElement && (firstElement as HTMLElement).focus();
78
- }, 0);
79
- }
80
-
81
90
  // If the event is not on the toggle and onOpenChange callback is provided, close the menu
82
91
  if (isOpen && onOpenChange && !toggleRef?.current?.contains(event.target as Node)) {
83
92
  if (isOpen && !menuRef.current?.contains(event.target as Node)) {
@@ -14,6 +14,11 @@ export enum MenuToggleStatus {
14
14
  warning = 'warning'
15
15
  }
16
16
 
17
+ export enum MenuToggleSize {
18
+ default = 'default',
19
+ sm = 'sm'
20
+ }
21
+
17
22
  export type MenuToggleElement = HTMLDivElement | HTMLButtonElement;
18
23
 
19
24
  export interface SplitButtonOptions {
@@ -58,6 +63,8 @@ export interface MenuToggleProps
58
63
  icon?: React.ReactNode;
59
64
  /** Optional badge rendered inside the toggle, after the children content */
60
65
  badge?: BadgeProps | React.ReactNode;
66
+ /** Adds styling which affects the size of the menu toggle */
67
+ size?: 'default' | 'sm';
61
68
  /** @hide Forwarded ref */
62
69
  innerRef?: React.Ref<MenuToggleElement>;
63
70
  /** Value to overwrite the randomly generated data-ouia-component-id. It will always target the toggle button. */
@@ -78,6 +85,7 @@ class MenuToggleBase extends React.Component<MenuToggleProps, MenuToggleState> {
78
85
  isDisabled: false,
79
86
  isFullWidth: false,
80
87
  isFullHeight: false,
88
+ size: 'default',
81
89
  ouiaSafe: true
82
90
  };
83
91
 
@@ -104,6 +112,7 @@ class MenuToggleBase extends React.Component<MenuToggleProps, MenuToggleState> {
104
112
  'aria-label': ariaLabel,
105
113
  ouiaId,
106
114
  ouiaSafe,
115
+ size,
107
116
  ...otherProps
108
117
  } = this.props;
109
118
  const isPlain = variant === 'plain';
@@ -170,6 +179,7 @@ class MenuToggleBase extends React.Component<MenuToggleProps, MenuToggleState> {
170
179
  isFullHeight && styles.modifiers.fullHeight,
171
180
  isFullWidth && styles.modifiers.fullWidth,
172
181
  isDisabled && styles.modifiers.disabled,
182
+ size === MenuToggleSize.sm && styles.modifiers.small,
173
183
  className
174
184
  );
175
185
 
@@ -6,6 +6,7 @@ import CogIcon from '@patternfly/react-icons/dist/esm/icons/cog-icon';
6
6
  import EllipsisVIcon from '@patternfly/react-icons/dist/esm/icons/ellipsis-v-icon';
7
7
  import userEvent from '@testing-library/user-event';
8
8
  import { render, screen } from '@testing-library/react';
9
+ import styles from '@patternfly/react-styles/css/components/MenuToggle/menu-toggle';
9
10
 
10
11
  describe('menu toggle', () => {
11
12
  test('renders successfully', () => {
@@ -53,19 +54,25 @@ describe('menu toggle', () => {
53
54
  expect(asFragment()).toMatchSnapshot();
54
55
  });
55
56
 
56
- test('shows success status', () => {
57
+ // Old snapshot tests end here; following tests should be kept when refactoring
58
+ test(`Renders with class ${styles.modifiers.small} when size="sm" is passed`, () => {
59
+ render(<MenuToggle size="sm">Toggle</MenuToggle>);
60
+ expect(screen.getByRole('button')).toHaveClass(styles.modifiers.small);
61
+ });
62
+
63
+ test(`Renders with class ${styles.modifiers.success} when status="success" is passed`, () => {
57
64
  render(<MenuToggle status="success">Toggle</MenuToggle>);
58
- expect(screen.getByRole('button')).toHaveClass('pf-m-success');
65
+ expect(screen.getByRole('button')).toHaveClass(styles.modifiers.success);
59
66
  });
60
67
 
61
- test('shows warning status', () => {
68
+ test(`Renders with class ${styles.modifiers.warning} when status="success" is passed`, () => {
62
69
  render(<MenuToggle status="warning">Toggle</MenuToggle>);
63
- expect(screen.getByRole('button')).toHaveClass('pf-m-warning');
70
+ expect(screen.getByRole('button')).toHaveClass(styles.modifiers.warning);
64
71
  });
65
72
 
66
- test('shows danger status', () => {
73
+ test(`Renders with class ${styles.modifiers.danger} when status="success" is passed`, () => {
67
74
  render(<MenuToggle status="danger">Toggle</MenuToggle>);
68
- expect(screen.getByRole('button')).toHaveClass('pf-m-danger');
75
+ expect(screen.getByRole('button')).toHaveClass(styles.modifiers.danger);
69
76
  });
70
77
 
71
78
  test('split toggle passes onClick', async () => {
@@ -39,6 +39,14 @@ import { MenuToggle } from '@patternfly/react-core';
39
39
 
40
40
  ```
41
41
 
42
+ ### Small toggle
43
+
44
+ You can pass `size="sm"` to a MenuToggle to style it as a small toggle, such as within a [breadcrumb](/components/breadcrumb).
45
+
46
+ ```ts file="./MenuToggleSmall.tsx"
47
+
48
+ ```
49
+
42
50
  ### Disabled toggle
43
51
 
44
52
  To disable the selection and expansion of a toggle, use the `isDisabled` property.
@@ -193,7 +201,7 @@ import { MenuToggle } from '@patternfly/react-core';
193
201
 
194
202
  ### Split toggle with checkbox
195
203
 
196
- To add a checkbox (or other action/control) to a menu toggle, use a split button.
204
+ To add a checkbox (or other action/control) to a menu toggle, use a split button.
197
205
 
198
206
  A `<MenuToggle>` can be rendered as a split button by adding a `splitButtonOptions` object. Elements to be displayed before the toggle button must be included in the `items` property of `splitButtonOptions`.
199
207
 
@@ -0,0 +1,4 @@
1
+ import React from 'react';
2
+ import { MenuToggle } from '@patternfly/react-core';
3
+
4
+ export const MenuToggleSmall: React.FunctionComponent = () => <MenuToggle size="sm">Small toggle</MenuToggle>;
@@ -110,6 +110,20 @@ const SelectBase: React.FunctionComponent<SelectProps & OUIAProps> = ({
110
110
  ? localToggleRef
111
111
  : (toggle?.toggleRef as React.RefObject<HTMLButtonElement>);
112
112
 
113
+ const prevIsOpen = React.useRef<boolean>(isOpen);
114
+ React.useEffect(() => {
115
+ // menu was opened, focus on first menu item
116
+ if (prevIsOpen.current === false && isOpen === true && shouldFocusFirstItemOnOpen) {
117
+ setTimeout(() => {
118
+ const firstElement = menuRef?.current?.querySelector('li button:not(:disabled),li input:not(:disabled)');
119
+ firstElement && (firstElement as HTMLElement).focus();
120
+ }, 0);
121
+ }
122
+
123
+ prevIsOpen.current = isOpen;
124
+ // eslint-disable-next-line react-hooks/exhaustive-deps
125
+ }, [isOpen]);
126
+
113
127
  React.useEffect(() => {
114
128
  const handleMenuKeys = (event: KeyboardEvent) => {
115
129
  // Close the menu on tab or escape if onOpenChange is provided
@@ -127,14 +141,6 @@ const SelectBase: React.FunctionComponent<SelectProps & OUIAProps> = ({
127
141
  };
128
142
 
129
143
  const handleClick = (event: MouseEvent) => {
130
- // toggle was opened, focus on first menu item
131
- if (isOpen && shouldFocusFirstItemOnOpen && toggleRef.current?.contains(event.target as Node)) {
132
- setTimeout(() => {
133
- const firstElement = menuRef?.current?.querySelector('li button:not(:disabled),li input:not(:disabled)');
134
- firstElement && (firstElement as HTMLElement).focus();
135
- }, 0);
136
- }
137
-
138
144
  // If the event is not on the toggle and onOpenChange callback is provided, close the menu
139
145
  if (isOpen && onOpenChange && !toggleRef?.current?.contains(event.target as Node)) {
140
146
  if (isOpen && !menuRef.current?.contains(event.target as Node)) {