@patternfly/react-core 5.0.0-alpha.109 → 5.0.0-alpha.110

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 (270) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/dist/esm/components/AboutModal/package.json +1 -1
  3. package/dist/esm/components/Accordion/package.json +1 -1
  4. package/dist/esm/components/ActionList/package.json +1 -1
  5. package/dist/esm/components/Alert/package.json +1 -1
  6. package/dist/esm/components/Avatar/package.json +1 -1
  7. package/dist/esm/components/BackToTop/package.json +1 -1
  8. package/dist/esm/components/Backdrop/package.json +1 -1
  9. package/dist/esm/components/BackgroundImage/package.json +1 -1
  10. package/dist/esm/components/Badge/package.json +1 -1
  11. package/dist/esm/components/Banner/package.json +1 -1
  12. package/dist/esm/components/Brand/package.json +1 -1
  13. package/dist/esm/components/Breadcrumb/package.json +1 -1
  14. package/dist/esm/components/Button/package.json +1 -1
  15. package/dist/esm/components/CalendarMonth/package.json +1 -1
  16. package/dist/esm/components/Card/package.json +1 -1
  17. package/dist/esm/components/Checkbox/package.json +1 -1
  18. package/dist/esm/components/Chip/package.json +1 -1
  19. package/dist/esm/components/ClipboardCopy/package.json +1 -1
  20. package/dist/esm/components/CodeBlock/package.json +1 -1
  21. package/dist/esm/components/DataList/package.json +1 -1
  22. package/dist/esm/components/DatePicker/package.json +1 -1
  23. package/dist/esm/components/DescriptionList/package.json +1 -1
  24. package/dist/esm/components/Divider/package.json +1 -1
  25. package/dist/esm/components/DragDrop/package.json +1 -1
  26. package/dist/esm/components/Drawer/package.json +1 -1
  27. package/dist/esm/components/Dropdown/Dropdown.d.ts +3 -1
  28. package/dist/esm/components/Dropdown/Dropdown.d.ts.map +1 -1
  29. package/dist/esm/components/Dropdown/Dropdown.js +3 -4
  30. package/dist/esm/components/Dropdown/Dropdown.js.map +1 -1
  31. package/dist/esm/components/Dropdown/package.json +1 -1
  32. package/dist/esm/components/DualListSelector/package.json +1 -1
  33. package/dist/esm/components/EmptyState/package.json +1 -1
  34. package/dist/esm/components/ExpandableSection/package.json +1 -1
  35. package/dist/esm/components/FileUpload/package.json +1 -1
  36. package/dist/esm/components/Form/package.json +1 -1
  37. package/dist/esm/components/FormSelect/package.json +1 -1
  38. package/dist/esm/components/HelperText/package.json +1 -1
  39. package/dist/esm/components/Hint/package.json +1 -1
  40. package/dist/esm/components/Icon/package.json +1 -1
  41. package/dist/esm/components/InputGroup/package.json +1 -1
  42. package/dist/esm/components/JumpLinks/package.json +1 -1
  43. package/dist/esm/components/Label/package.json +1 -1
  44. package/dist/esm/components/List/package.json +1 -1
  45. package/dist/esm/components/LoginPage/package.json +1 -1
  46. package/dist/esm/components/Masthead/package.json +1 -1
  47. package/dist/esm/components/Menu/Menu.js +7 -4
  48. package/dist/esm/components/Menu/Menu.js.map +1 -1
  49. package/dist/esm/components/Menu/MenuContainer.d.ts +42 -0
  50. package/dist/esm/components/Menu/MenuContainer.d.ts.map +1 -0
  51. package/dist/esm/components/Menu/MenuContainer.js +47 -0
  52. package/dist/esm/components/Menu/MenuContainer.js.map +1 -0
  53. package/dist/esm/components/Menu/index.d.ts +1 -0
  54. package/dist/esm/components/Menu/index.d.ts.map +1 -1
  55. package/dist/esm/components/Menu/index.js +1 -0
  56. package/dist/esm/components/Menu/index.js.map +1 -1
  57. package/dist/esm/components/Menu/package.json +1 -1
  58. package/dist/esm/components/MenuToggle/package.json +1 -1
  59. package/dist/esm/components/Modal/package.json +1 -1
  60. package/dist/esm/components/MultipleFileUpload/package.json +1 -1
  61. package/dist/esm/components/Nav/package.json +1 -1
  62. package/dist/esm/components/NotificationBadge/package.json +1 -1
  63. package/dist/esm/components/NotificationDrawer/package.json +1 -1
  64. package/dist/esm/components/NumberInput/package.json +1 -1
  65. package/dist/esm/components/OverflowMenu/package.json +1 -1
  66. package/dist/esm/components/Page/package.json +1 -1
  67. package/dist/esm/components/Pagination/package.json +1 -1
  68. package/dist/esm/components/Panel/package.json +1 -1
  69. package/dist/esm/components/Popover/package.json +1 -1
  70. package/dist/esm/components/Progress/package.json +1 -1
  71. package/dist/esm/components/ProgressStepper/package.json +1 -1
  72. package/dist/esm/components/Radio/package.json +1 -1
  73. package/dist/esm/components/SearchInput/package.json +1 -1
  74. package/dist/esm/components/Select/package.json +1 -1
  75. package/dist/esm/components/Sidebar/package.json +1 -1
  76. package/dist/esm/components/SimpleList/package.json +1 -1
  77. package/dist/esm/components/Skeleton/package.json +1 -1
  78. package/dist/esm/components/SkipToContent/package.json +1 -1
  79. package/dist/esm/components/Slider/package.json +1 -1
  80. package/dist/esm/components/Spinner/package.json +1 -1
  81. package/dist/esm/components/Switch/package.json +1 -1
  82. package/dist/esm/components/Tabs/package.json +1 -1
  83. package/dist/esm/components/Text/package.json +1 -1
  84. package/dist/esm/components/TextArea/package.json +1 -1
  85. package/dist/esm/components/TextInput/package.json +1 -1
  86. package/dist/esm/components/TextInputGroup/package.json +1 -1
  87. package/dist/esm/components/Tile/package.json +1 -1
  88. package/dist/esm/components/TimePicker/package.json +1 -1
  89. package/dist/esm/components/Timestamp/package.json +1 -1
  90. package/dist/esm/components/Title/package.json +1 -1
  91. package/dist/esm/components/ToggleGroup/package.json +1 -1
  92. package/dist/esm/components/Toolbar/package.json +1 -1
  93. package/dist/esm/components/Tooltip/package.json +1 -1
  94. package/dist/esm/components/TreeView/package.json +1 -1
  95. package/dist/esm/components/Truncate/package.json +1 -1
  96. package/dist/esm/components/Wizard/hooks/package.json +1 -1
  97. package/dist/esm/components/Wizard/package.json +1 -1
  98. package/dist/esm/components/package.json +1 -1
  99. package/dist/esm/deprecated/components/ApplicationLauncher/package.json +1 -1
  100. package/dist/esm/deprecated/components/ContextSelector/package.json +1 -1
  101. package/dist/esm/deprecated/components/Dropdown/package.json +1 -1
  102. package/dist/esm/deprecated/components/OptionsMenu/package.json +1 -1
  103. package/dist/esm/deprecated/components/PageHeader/package.json +1 -1
  104. package/dist/esm/deprecated/components/Select/package.json +1 -1
  105. package/dist/esm/deprecated/components/Wizard/package.json +1 -1
  106. package/dist/esm/deprecated/components/package.json +1 -1
  107. package/dist/esm/deprecated/package.json +1 -1
  108. package/dist/esm/helpers/Popper/thirdparty/popper-core/package.json +1 -1
  109. package/dist/esm/helpers/package.json +1 -1
  110. package/dist/esm/layouts/Bullseye/package.json +1 -1
  111. package/dist/esm/layouts/Flex/package.json +1 -1
  112. package/dist/esm/layouts/Gallery/package.json +1 -1
  113. package/dist/esm/layouts/Grid/package.json +1 -1
  114. package/dist/esm/layouts/Level/package.json +1 -1
  115. package/dist/esm/layouts/Split/package.json +1 -1
  116. package/dist/esm/layouts/Stack/package.json +1 -1
  117. package/dist/esm/layouts/package.json +1 -1
  118. package/dist/esm/next/components/package.json +1 -1
  119. package/dist/esm/next/package.json +1 -1
  120. package/dist/esm/package.json +1 -1
  121. package/dist/js/components/AboutModal/package.json +1 -1
  122. package/dist/js/components/Accordion/package.json +1 -1
  123. package/dist/js/components/ActionList/package.json +1 -1
  124. package/dist/js/components/Alert/package.json +1 -1
  125. package/dist/js/components/Avatar/package.json +1 -1
  126. package/dist/js/components/BackToTop/package.json +1 -1
  127. package/dist/js/components/Backdrop/package.json +1 -1
  128. package/dist/js/components/BackgroundImage/package.json +1 -1
  129. package/dist/js/components/Badge/package.json +1 -1
  130. package/dist/js/components/Banner/package.json +1 -1
  131. package/dist/js/components/Brand/package.json +1 -1
  132. package/dist/js/components/Breadcrumb/package.json +1 -1
  133. package/dist/js/components/Button/package.json +1 -1
  134. package/dist/js/components/CalendarMonth/package.json +1 -1
  135. package/dist/js/components/Card/package.json +1 -1
  136. package/dist/js/components/Checkbox/package.json +1 -1
  137. package/dist/js/components/Chip/package.json +1 -1
  138. package/dist/js/components/ClipboardCopy/package.json +1 -1
  139. package/dist/js/components/CodeBlock/package.json +1 -1
  140. package/dist/js/components/DataList/package.json +1 -1
  141. package/dist/js/components/DatePicker/package.json +1 -1
  142. package/dist/js/components/DescriptionList/package.json +1 -1
  143. package/dist/js/components/Divider/package.json +1 -1
  144. package/dist/js/components/DragDrop/package.json +1 -1
  145. package/dist/js/components/Drawer/package.json +1 -1
  146. package/dist/js/components/Dropdown/Dropdown.d.ts +3 -1
  147. package/dist/js/components/Dropdown/Dropdown.d.ts.map +1 -1
  148. package/dist/js/components/Dropdown/Dropdown.js +3 -4
  149. package/dist/js/components/Dropdown/Dropdown.js.map +1 -1
  150. package/dist/js/components/Dropdown/package.json +1 -1
  151. package/dist/js/components/DualListSelector/package.json +1 -1
  152. package/dist/js/components/EmptyState/package.json +1 -1
  153. package/dist/js/components/ExpandableSection/package.json +1 -1
  154. package/dist/js/components/FileUpload/package.json +1 -1
  155. package/dist/js/components/Form/package.json +1 -1
  156. package/dist/js/components/FormSelect/package.json +1 -1
  157. package/dist/js/components/HelperText/package.json +1 -1
  158. package/dist/js/components/Hint/package.json +1 -1
  159. package/dist/js/components/Icon/package.json +1 -1
  160. package/dist/js/components/InputGroup/package.json +1 -1
  161. package/dist/js/components/JumpLinks/package.json +1 -1
  162. package/dist/js/components/Label/package.json +1 -1
  163. package/dist/js/components/List/package.json +1 -1
  164. package/dist/js/components/LoginPage/package.json +1 -1
  165. package/dist/js/components/Masthead/package.json +1 -1
  166. package/dist/js/components/Menu/Menu.js +7 -4
  167. package/dist/js/components/Menu/Menu.js.map +1 -1
  168. package/dist/js/components/Menu/MenuContainer.d.ts +42 -0
  169. package/dist/js/components/Menu/MenuContainer.d.ts.map +1 -0
  170. package/dist/js/components/Menu/MenuContainer.js +52 -0
  171. package/dist/js/components/Menu/MenuContainer.js.map +1 -0
  172. package/dist/js/components/Menu/index.d.ts +1 -0
  173. package/dist/js/components/Menu/index.d.ts.map +1 -1
  174. package/dist/js/components/Menu/index.js +1 -0
  175. package/dist/js/components/Menu/index.js.map +1 -1
  176. package/dist/js/components/Menu/package.json +1 -1
  177. package/dist/js/components/MenuToggle/package.json +1 -1
  178. package/dist/js/components/Modal/package.json +1 -1
  179. package/dist/js/components/MultipleFileUpload/package.json +1 -1
  180. package/dist/js/components/Nav/package.json +1 -1
  181. package/dist/js/components/NotificationBadge/package.json +1 -1
  182. package/dist/js/components/NotificationDrawer/package.json +1 -1
  183. package/dist/js/components/NumberInput/package.json +1 -1
  184. package/dist/js/components/OverflowMenu/package.json +1 -1
  185. package/dist/js/components/Page/package.json +1 -1
  186. package/dist/js/components/Pagination/package.json +1 -1
  187. package/dist/js/components/Panel/package.json +1 -1
  188. package/dist/js/components/Popover/package.json +1 -1
  189. package/dist/js/components/Progress/package.json +1 -1
  190. package/dist/js/components/ProgressStepper/package.json +1 -1
  191. package/dist/js/components/Radio/package.json +1 -1
  192. package/dist/js/components/SearchInput/package.json +1 -1
  193. package/dist/js/components/Select/package.json +1 -1
  194. package/dist/js/components/Sidebar/package.json +1 -1
  195. package/dist/js/components/SimpleList/package.json +1 -1
  196. package/dist/js/components/Skeleton/package.json +1 -1
  197. package/dist/js/components/SkipToContent/package.json +1 -1
  198. package/dist/js/components/Slider/package.json +1 -1
  199. package/dist/js/components/Spinner/package.json +1 -1
  200. package/dist/js/components/Switch/package.json +1 -1
  201. package/dist/js/components/Tabs/package.json +1 -1
  202. package/dist/js/components/Text/package.json +1 -1
  203. package/dist/js/components/TextArea/package.json +1 -1
  204. package/dist/js/components/TextInput/package.json +1 -1
  205. package/dist/js/components/TextInputGroup/package.json +1 -1
  206. package/dist/js/components/Tile/package.json +1 -1
  207. package/dist/js/components/TimePicker/package.json +1 -1
  208. package/dist/js/components/Timestamp/package.json +1 -1
  209. package/dist/js/components/Title/package.json +1 -1
  210. package/dist/js/components/ToggleGroup/package.json +1 -1
  211. package/dist/js/components/Toolbar/package.json +1 -1
  212. package/dist/js/components/Tooltip/package.json +1 -1
  213. package/dist/js/components/TreeView/package.json +1 -1
  214. package/dist/js/components/Truncate/package.json +1 -1
  215. package/dist/js/components/Wizard/hooks/package.json +1 -1
  216. package/dist/js/components/Wizard/package.json +1 -1
  217. package/dist/js/components/package.json +1 -1
  218. package/dist/js/deprecated/components/ApplicationLauncher/package.json +1 -1
  219. package/dist/js/deprecated/components/ContextSelector/package.json +1 -1
  220. package/dist/js/deprecated/components/Dropdown/package.json +1 -1
  221. package/dist/js/deprecated/components/OptionsMenu/package.json +1 -1
  222. package/dist/js/deprecated/components/PageHeader/package.json +1 -1
  223. package/dist/js/deprecated/components/Select/package.json +1 -1
  224. package/dist/js/deprecated/components/Wizard/package.json +1 -1
  225. package/dist/js/deprecated/components/package.json +1 -1
  226. package/dist/js/deprecated/package.json +1 -1
  227. package/dist/js/helpers/Popper/thirdparty/popper-core/package.json +1 -1
  228. package/dist/js/helpers/package.json +1 -1
  229. package/dist/js/layouts/Bullseye/package.json +1 -1
  230. package/dist/js/layouts/Flex/package.json +1 -1
  231. package/dist/js/layouts/Gallery/package.json +1 -1
  232. package/dist/js/layouts/Grid/package.json +1 -1
  233. package/dist/js/layouts/Level/package.json +1 -1
  234. package/dist/js/layouts/Split/package.json +1 -1
  235. package/dist/js/layouts/Stack/package.json +1 -1
  236. package/dist/js/layouts/package.json +1 -1
  237. package/dist/js/next/components/package.json +1 -1
  238. package/dist/js/next/package.json +1 -1
  239. package/dist/js/package.json +1 -1
  240. package/dist/umd/react-core.min.js +2 -2
  241. package/package.json +2 -2
  242. package/src/components/Dropdown/Dropdown.tsx +6 -4
  243. package/src/components/Menu/Menu.tsx +2 -2
  244. package/src/components/Menu/MenuContainer.tsx +109 -0
  245. package/src/components/Menu/examples/Menu.md +13 -1
  246. package/src/components/Menu/index.ts +1 -0
  247. package/src/demos/CustomMenus/ApplicationLauncher.md +30 -0
  248. package/src/demos/CustomMenus/ContextSelector.md +30 -0
  249. package/src/demos/CustomMenus/CustomMenus.md +84 -0
  250. package/src/demos/CustomMenus/OptionsMenu.md +17 -0
  251. package/src/demos/{ComposableMenu/examples/ComposableActionsMenu.tsx → CustomMenus/examples/ActionsMenuDemo.tsx} +25 -57
  252. package/src/demos/{ComposableMenu/examples/ComposableApplicationLauncher.tsx → CustomMenus/examples/ApplicationLauncherDemo.tsx} +72 -99
  253. package/src/demos/{ComposableMenu/examples/ComposableContextSelector.tsx → CustomMenus/examples/ContextSelectorDemo.tsx} +43 -80
  254. package/src/demos/CustomMenus/examples/DateSelectDemo.tsx +84 -0
  255. package/src/demos/{ComposableMenu/examples/ComposableDrilldownMenu.tsx → CustomMenus/examples/DrilldownMenuDemo.tsx} +14 -36
  256. package/src/demos/CustomMenus/examples/FavoritesDemo.tsx +120 -0
  257. package/src/demos/{ComposableMenu/examples/ComposableFlyout.tsx → CustomMenus/examples/FlyoutDemo.tsx} +14 -39
  258. package/src/demos/CustomMenus/examples/OptionsMenuDemo.tsx +59 -0
  259. package/src/demos/{ComposableMenu/examples/ComposableTreeViewMenu.tsx → CustomMenus/examples/TreeViewMenuDemo.tsx} +15 -52
  260. package/src/demos/ComposableMenu/ComposableMenu.md +0 -118
  261. package/src/demos/ComposableMenu/examples/ComposableMultipleTypeaheadSelect.tsx +0 -253
  262. package/src/demos/ComposableMenu/examples/ComposableOptionsMenuVariants.tsx +0 -96
  263. package/src/demos/ComposableMenu/examples/ComposableSimpleCheckboxSelect.tsx +0 -101
  264. package/src/demos/ComposableMenu/examples/ComposableSimpleDropdown.tsx +0 -70
  265. package/src/demos/ComposableMenu/examples/ComposableSimpleSelect.tsx +0 -83
  266. package/src/demos/ComposableMenu/examples/ComposableTypeaheadSelect.tsx +0 -234
  267. /package/src/demos/{ComposableMenu → CustomMenus}/examples/ComposableDateSelect.tsx +0 -0
  268. /package/src/demos/{ComposableMenu → CustomMenus}/examples/ComposableDropdwnVariants.tsx +0 -0
  269. /package/src/demos/{ComposableMenu → CustomMenus}/examples/avatarImg.svg +0 -0
  270. /package/src/demos/{ComposableMenu → CustomMenus}/examples/pf-logo-small.svg +0 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@patternfly/react-core",
3
- "version": "5.0.0-alpha.109",
3
+ "version": "5.0.0-alpha.110",
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",
@@ -71,5 +71,5 @@
71
71
  "react": "^17 || ^18",
72
72
  "react-dom": "^17 || ^18"
73
73
  },
74
- "gitHead": "7f4932ede08af25736561cdeeeffcd110f225620"
74
+ "gitHead": "58f5dadf223b2b7b34f48f3dda3e1c3b06a925b8"
75
75
  }
@@ -43,8 +43,10 @@ export interface DropdownProps extends MenuProps, OUIAProps {
43
43
  /** Function callback called when user selects item. */
44
44
  onSelect?: (event?: React.MouseEvent<Element, MouseEvent>, itemId?: string | number) => void;
45
45
  /** Callback to allow the dropdown component to change the open state of the menu.
46
- * Triggered by clicking outside of the menu, or by pressing either tab or escape. */
46
+ * Triggered by clicking outside of the menu, or by pressing any keys specificed in onOpenChangeKeys. */
47
47
  onOpenChange?: (isOpen: boolean) => void;
48
+ /** @beta Keys that trigger onOpenChange, defaults to tab and escape. It is highly recommended to include Escape in the array, while Tab may be omitted if the menu contains non-menu items that are focusable. */
49
+ onOpenChangeKeys?: string[];
48
50
  /** Indicates if the menu should be without the outer box-shadow. */
49
51
  isPlain?: boolean;
50
52
  /** Indicates if the menu should be scrollable. */
@@ -76,6 +78,7 @@ const DropdownBase: React.FunctionComponent<DropdownProps> = ({
76
78
  ouiaSafe = true,
77
79
  zIndex = 9999,
78
80
  popperProps,
81
+ onOpenChangeKeys = ['Escape', 'Tab'],
79
82
  ...props
80
83
  }: DropdownProps) => {
81
84
  const localMenuRef = React.useRef<HTMLDivElement>();
@@ -96,8 +99,7 @@ const DropdownBase: React.FunctionComponent<DropdownProps> = ({
96
99
  onOpenChange &&
97
100
  (menuRef.current?.contains(event.target as Node) || toggleRef.current?.contains(event.target as Node))
98
101
  ) {
99
- if (event.key === 'Escape' || event.key === 'Tab') {
100
- event.preventDefault();
102
+ if (onOpenChangeKeys.includes(event.key)) {
101
103
  onOpenChange(false);
102
104
  toggleRef.current?.focus();
103
105
  }
@@ -130,7 +132,7 @@ const DropdownBase: React.FunctionComponent<DropdownProps> = ({
130
132
  window.removeEventListener('keydown', handleMenuKeys);
131
133
  window.removeEventListener('click', handleClick);
132
134
  };
133
- }, [isOpen, menuRef, toggleRef, onOpenChange]);
135
+ }, [isOpen, menuRef, toggleRef, onOpenChange, onOpenChangeKeys]);
134
136
 
135
137
  const menu = (
136
138
  <Menu
@@ -301,8 +301,8 @@ class MenuBase extends React.Component<MenuProps, MenuState> {
301
301
  (document.activeElement.closest('ol') && document.activeElement.closest('ol').firstChild === element)
302
302
  }
303
303
  getFocusableElement={(navigableElement: Element) =>
304
- (navigableElement.tagName === 'DIV' && navigableElement.querySelector('input')) || // for MenuSearchInput
305
- ((navigableElement.firstChild as Element).tagName === 'LABEL' &&
304
+ (navigableElement?.tagName === 'DIV' && navigableElement.querySelector('input')) || // for MenuSearchInput
305
+ ((navigableElement.firstChild as Element)?.tagName === 'LABEL' &&
306
306
  navigableElement.querySelector('input')) || // for MenuItem checkboxes
307
307
  (navigableElement.firstChild as Element)
308
308
  }
@@ -0,0 +1,109 @@
1
+ import React from 'react';
2
+ import { Popper } from '../../helpers/Popper/Popper';
3
+
4
+ export interface MenuPopperProps {
5
+ /** Vertical direction of the popper. If enableFlip is set to true, this will set the initial direction before the popper flips. */
6
+ direction?: 'up' | 'down';
7
+ /** Horizontal position of the popper */
8
+ position?: 'right' | 'left' | 'center';
9
+ /** Custom width of the popper. If the value is "trigger", it will set the width to the dropdown toggle's width */
10
+ width?: string | 'trigger';
11
+ /** Minimum width of the popper. If the value is "trigger", it will set the min width to the dropdown toggle's width */
12
+ minWidth?: string | 'trigger';
13
+ /** Maximum width of the popper. If the value is "trigger", it will set the max width to the dropdown toggle's width */
14
+ maxWidth?: string | 'trigger';
15
+ /** Enable to flip the popper when it reaches the boundary */
16
+ enableFlip?: boolean;
17
+ }
18
+ export interface MenuContainerProps {
19
+ /** Menu to be rendered */
20
+ menu: React.ReactElement<any, string | React.JSXElementConstructor<any>>;
21
+ /** Reference to the menu */
22
+ menuRef: React.RefObject<any>;
23
+ /** Toggle to be rendered */
24
+ toggle: React.ReactNode;
25
+ /** Reference to the toggle */
26
+ toggleRef: React.RefObject<any>;
27
+ /** Flag to indicate if menu is opened.*/
28
+ isOpen: boolean;
29
+ /** Callback to change the open state of the menu.
30
+ * Triggered by clicking outside of the menu, or by pressing any keys specificed in onOpenChangeKeys. */
31
+ onOpenChange?: (isOpen: boolean) => void;
32
+ /** Keys that trigger onOpenChange, defaults to tab and escape. It is highly recommended to include Escape in the array, while Tab may be omitted if the menu contains non-menu items that are focusable. */
33
+ onOpenChangeKeys?: string[];
34
+ /** z-index of the dropdown menu */
35
+ zIndex?: number;
36
+ /** Additional properties to pass to the Popper */
37
+ popperProps?: MenuPopperProps;
38
+ }
39
+
40
+ /**
41
+ * Container that links a menu and menu toggle together, to handle basic keyboard input and control the opening and closing of a menu.
42
+ * This component is currently in beta and is subject to change.
43
+ */
44
+ export const MenuContainer: React.FunctionComponent<MenuContainerProps> = ({
45
+ menu,
46
+ menuRef,
47
+ isOpen,
48
+ toggle,
49
+ toggleRef,
50
+ onOpenChange,
51
+ zIndex = 9999,
52
+ popperProps,
53
+ onOpenChangeKeys = ['Escape', 'Tab']
54
+ }: MenuContainerProps) => {
55
+ React.useEffect(() => {
56
+ const handleMenuKeys = (event: KeyboardEvent) => {
57
+ // Close the menu on tab or escape if onOpenChange is provided
58
+ if (
59
+ (isOpen && onOpenChange && menuRef.current?.contains(event.target as Node)) ||
60
+ toggleRef.current?.contains(event.target as Node)
61
+ ) {
62
+ if (onOpenChangeKeys.includes(event.key)) {
63
+ onOpenChange(false);
64
+ toggleRef.current?.focus();
65
+ }
66
+ }
67
+ };
68
+
69
+ const handleClick = (event: MouseEvent) => {
70
+ // toggle was clicked open via keyboard, focus on first menu item
71
+ if (isOpen && toggleRef.current?.contains(event.target as Node) && event.detail === 0) {
72
+ setTimeout(() => {
73
+ const firstElement = menuRef?.current?.querySelector(
74
+ 'li button:not(:disabled),li input:not(:disabled),li a:not([aria-disabled="true"])'
75
+ );
76
+ firstElement && (firstElement as HTMLElement).focus();
77
+ }, 0);
78
+ }
79
+
80
+ // If the event is not on the toggle and onOpenChange callback is provided, close the menu
81
+ if (isOpen && onOpenChange && !toggleRef?.current?.contains(event.target as Node)) {
82
+ if (isOpen && !menuRef.current?.contains(event.target as Node)) {
83
+ onOpenChange(false);
84
+ }
85
+ }
86
+ };
87
+
88
+ window.addEventListener('keydown', handleMenuKeys);
89
+ window.addEventListener('click', handleClick);
90
+
91
+ return () => {
92
+ window.removeEventListener('keydown', handleMenuKeys);
93
+ window.removeEventListener('click', handleClick);
94
+ };
95
+ }, [isOpen, menuRef, onOpenChange, onOpenChangeKeys, toggleRef]);
96
+
97
+ return (
98
+ <Popper
99
+ trigger={toggle}
100
+ triggerRef={toggleRef}
101
+ popper={menu}
102
+ popperRef={menuRef}
103
+ isVisible={isOpen}
104
+ zIndex={zIndex}
105
+ {...popperProps}
106
+ />
107
+ );
108
+ };
109
+ MenuContainer.displayName = 'MenuContainer';
@@ -3,7 +3,19 @@ id: Menu
3
3
  section: components
4
4
  subsection: menus
5
5
  cssPrefix: pf-c-menu
6
- propComponents: ['Menu', 'MenuList', 'MenuItem', 'MenuItemAction', 'MenuContent', 'MenuSearch', 'MenuSearchInput', 'MenuGroup']
6
+ propComponents:
7
+ [
8
+ 'Menu',
9
+ 'MenuList',
10
+ 'MenuItem',
11
+ 'MenuItemAction',
12
+ 'MenuContent',
13
+ 'MenuSearch',
14
+ 'MenuSearchInput',
15
+ 'MenuGroup',
16
+ 'MenuContainer',
17
+ 'MenuPopperProps'
18
+ ]
7
19
  ouia: true
8
20
  ---
9
21
 
@@ -9,3 +9,4 @@ export * from './MenuList';
9
9
  export * from './MenuItemAction';
10
10
  export * from './DrilldownMenu';
11
11
  export * from './MenuBreadcrumb';
12
+ export * from './MenuContainer';
@@ -0,0 +1,30 @@
1
+ ---
2
+ id: Application launcher
3
+ section: components
4
+ subsection: menus
5
+ source: react-demos
6
+ propComponents:
7
+ [
8
+ 'MenuToggle',
9
+ 'MenuSearch',
10
+ 'MenuSearchInput',
11
+ 'Tooltip',
12
+ 'Divider',
13
+ 'SearchInput',
14
+ 'Dropdown',
15
+ 'DropdownGroup',
16
+ 'DropdownList',
17
+ 'DropdownItem'
18
+ ]
19
+ ---
20
+
21
+ import ThIcon from '@patternfly/react-icons/dist/esm/icons/th-icon';
22
+ import pfIcon from './examples/pf-logo-small.svg';
23
+
24
+ As the application launcher component is now deprecated, an application launcher may now be built using the new suite of menu components. This is showcased in the following demo, which uses the new [dropdown](/components/menus/dropdown) component that is built off of menu.
25
+
26
+ ### Application launcher menu
27
+
28
+ ```ts file="./examples/ApplicationLauncherDemo.tsx"
29
+
30
+ ```
@@ -0,0 +1,30 @@
1
+ ---
2
+ id: Context selector
3
+ section: components
4
+ subsection: menus
5
+ source: react-demos
6
+ propComponents:
7
+ [
8
+ 'MenuToggle',
9
+ 'MenuFooter',
10
+ 'MenuSearch',
11
+ 'MenuSearchInput',
12
+ 'Divider',
13
+ 'InputGroup',
14
+ 'SearchInput',
15
+ 'Dropdown',
16
+ 'DropdownGroup',
17
+ 'DropdownList',
18
+ 'DropdownItem'
19
+ ]
20
+ ---
21
+
22
+ import SearchIcon from '@patternfly/react-icons/dist/esm/icons/search-icon';
23
+
24
+ As the context selector component is now deprecated, a context selector may now be built using the new suite of menu components. This is showcased in the following demo, which uses the new [dropdown](/components/menus/dropdown) component that is built off of menu.
25
+
26
+ ### Context selector menu
27
+
28
+ ```ts file="./examples/ContextSelectorDemo.tsx"
29
+
30
+ ```
@@ -0,0 +1,84 @@
1
+ ---
2
+ id: Custom menus
3
+ section: components
4
+ subsection: menus
5
+ ---
6
+
7
+ import { Link } from '@reach/router';
8
+
9
+ import CogIcon from '@patternfly/react-icons/dist/esm/icons/cog-icon';
10
+ import EllipsisVIcon from '@patternfly/react-icons/dist/esm/icons/ellipsis-v-icon';
11
+ import TableIcon from '@patternfly/react-icons/dist/esm/icons/table-icon';
12
+ import StorageDomainIcon from '@patternfly/react-icons/dist/esm/icons/storage-domain-icon';
13
+ import CodeBranchIcon from '@patternfly/react-icons/dist/esm/icons/code-branch-icon';
14
+ import LayerGroupIcon from '@patternfly/react-icons/dist/esm/icons/layer-group-icon';
15
+ import CubeIcon from '@patternfly/react-icons/dist/esm/icons/cube-icon';
16
+ import BarsIcon from '@patternfly/react-icons/dist/esm/icons/bars-icon';
17
+ import ClipboardIcon from '@patternfly/react-icons/dist/esm/icons/clipboard-icon';
18
+ import BellIcon from '@patternfly/react-icons/dist/esm/icons/bell-icon';
19
+ import ThIcon from '@patternfly/react-icons/dist/esm/icons/th-icon';
20
+ import pfIcon from './examples/pf-logo-small.svg';
21
+ import SearchIcon from '@patternfly/react-icons/dist/esm/icons/search-icon';
22
+ import CaretDownIcon from '@patternfly/react-icons/dist/esm/icons/caret-down-icon';
23
+ import TimesIcon from '@patternfly/react-icons/dist/esm/icons/times-icon';
24
+ import avatarImg from './examples/avatarImg.svg';
25
+ import { css } from '@patternfly/react-styles';
26
+ import styles from '@patternfly/react-styles/css/components/Menu/menu';
27
+
28
+ ## Examples
29
+
30
+ Custom menus can be constructed using a composable approach by combining the [menu](/components/menus/menu) and [menu toggle](/components/menus/menu-toggle) components in unique ways. To handle basic keyboard inputs, [dropdown](/components/menus/dropdown), [select](/components/menus/select), or [`<MenuContainer>`](/components/menus/menu#menucontainer) components may be used in combination with menu components.
31
+
32
+ Additionally, menu components may be connected to each other manually through our undocumented internal [popper.js](https://popper.js.org/) wrapper component called Popper.
33
+
34
+ ### With actions
35
+
36
+ ```ts file="./examples/ActionsMenuDemo.tsx"
37
+
38
+ ```
39
+
40
+ ### With favorites
41
+
42
+ ```ts file="./examples/FavoritesDemo.tsx"
43
+
44
+ ```
45
+
46
+ ### With drilldown
47
+
48
+ ```ts isBeta file="./examples/DrilldownMenuDemo.tsx"
49
+
50
+ ```
51
+
52
+ ### Tree view menu
53
+
54
+ When rendering a menu-like element that does not contain `<MenuItem>` components, [panel](/components/panel) allows more flexible control and customization.
55
+
56
+ ```ts file="./examples/TreeViewMenuDemo.tsx"
57
+
58
+ ```
59
+
60
+ ### Flyout menu
61
+
62
+ The flyout will automatically position to the left or top if it would otherwise go outside the window. The menu must be placed in a container outside the main content like Popper, [popover](/components/popover) or [tooltip](/components/tooltip), since it may go over the side nav.
63
+
64
+ ```ts isBeta file="./examples/FlyoutDemo.tsx"
65
+
66
+ ```
67
+
68
+ ### Application launcher menu
69
+
70
+ ```ts file="./examples/ApplicationLauncherDemo.tsx"
71
+
72
+ ```
73
+
74
+ ### Context selector menu
75
+
76
+ ```ts file="./examples/ContextSelectorDemo.tsx"
77
+
78
+ ```
79
+
80
+ ### Date select menu
81
+
82
+ ```ts file="./examples/DateSelectDemo.tsx"
83
+
84
+ ```
@@ -0,0 +1,17 @@
1
+ ---
2
+ id: Options menu
3
+ section: components
4
+ subsection: menus
5
+ source: react-demos
6
+ propComponents: ['MenuToggle', 'Divider', 'Select', 'SelectList', 'SelectOption', 'SelectGroup']
7
+ ---
8
+
9
+ import SearchIcon from '@patternfly/react-icons/dist/esm/icons/search-icon';
10
+
11
+ As the `<OptionsMenu>` component is now deprecated, an options menu may now be built using the new suite of menu components. This is showcased in the following demo, which uses the new [select](/components/menus/select) component that is built off of menu.
12
+
13
+ ### Options menu
14
+
15
+ ```ts file="./examples/OptionsMenuDemo.tsx"
16
+
17
+ ```
@@ -1,40 +1,15 @@
1
1
  import React from 'react';
2
- import { MenuToggle, Menu, MenuList, MenuItem, MenuGroup, MenuItemAction, Popper } from '@patternfly/react-core';
2
+ import { MenuToggle, MenuItemAction, Select, SelectGroup, SelectList, SelectOption } from '@patternfly/react-core';
3
3
  import BarsIcon from '@patternfly/react-icons/dist/esm/icons/bars-icon';
4
4
  import ClipboardIcon from '@patternfly/react-icons/dist/esm/icons/clipboard-icon';
5
5
  import CodeBranchIcon from '@patternfly/react-icons/dist/esm/icons/code-branch-icon';
6
6
  import BellIcon from '@patternfly/react-icons/dist/esm/icons/bell-icon';
7
7
 
8
- export const ComposableActionsMenu: React.FunctionComponent = () => {
8
+ export const ActionsMenuDemo: React.FunctionComponent = () => {
9
9
  const [isOpen, setIsOpen] = React.useState<boolean>(false);
10
10
  const [selectedItems, setSelectedItems] = React.useState<number[]>([]);
11
- const toggleRef = React.useRef<HTMLButtonElement>(null);
12
11
  const menuRef = React.useRef<HTMLDivElement>(null);
13
12
 
14
- const handleMenuKeys = (event: KeyboardEvent) => {
15
- if (isOpen && menuRef.current?.contains(event.target as Node)) {
16
- if (event.key === 'Escape' || event.key === 'Tab') {
17
- setIsOpen(!isOpen);
18
- toggleRef.current?.focus();
19
- }
20
- }
21
- };
22
-
23
- const handleClickOutside = (event: MouseEvent) => {
24
- if (isOpen && !menuRef.current?.contains(event.target as Node)) {
25
- setIsOpen(false);
26
- }
27
- };
28
-
29
- React.useEffect(() => {
30
- window.addEventListener('keydown', handleMenuKeys);
31
- window.addEventListener('click', handleClickOutside);
32
- return () => {
33
- window.removeEventListener('keydown', handleMenuKeys);
34
- window.removeEventListener('click', handleClickOutside);
35
- };
36
- }, [isOpen, menuRef]);
37
-
38
13
  const onSelect = (event: React.MouseEvent | undefined, itemId: string | number | undefined) => {
39
14
  if (typeof itemId === 'string' || typeof itemId === 'undefined') {
40
15
  return;
@@ -47,32 +22,27 @@ export const ComposableActionsMenu: React.FunctionComponent = () => {
47
22
  }
48
23
  };
49
24
 
50
- const onToggleClick = (ev: React.MouseEvent) => {
51
- ev.stopPropagation(); // Stop handleClickOutside from handling
52
- setTimeout(() => {
53
- if (menuRef.current) {
54
- const firstElement = menuRef.current.querySelector('li > button:not(:disabled), li > a:not(:disabled)');
55
- firstElement && (firstElement as HTMLElement).focus();
56
- }
57
- }, 0);
25
+ const onToggleClick = () => {
58
26
  setIsOpen(!isOpen);
59
27
  };
60
28
 
61
- const toggle = (
62
- <MenuToggle ref={toggleRef} onClick={onToggleClick} isExpanded={isOpen}>
63
- {isOpen ? 'Expanded' : 'Collapsed'}
64
- </MenuToggle>
65
- );
66
- const menu = (
67
- <Menu
29
+ return (
30
+ <Select
31
+ isOpen={isOpen}
68
32
  ref={menuRef}
33
+ toggle={(toggleRef) => (
34
+ <MenuToggle ref={toggleRef} onClick={onToggleClick} isExpanded={isOpen}>
35
+ {isOpen ? 'Expanded' : 'Collapsed'}
36
+ </MenuToggle>
37
+ )}
69
38
  // eslint-disable-next-line no-console
70
39
  onActionClick={(event, itemId, actionId) => console.log(`clicked on ${itemId} - ${actionId}`)}
71
40
  onSelect={onSelect}
41
+ onOpenChange={(isOpen) => setIsOpen(isOpen)}
72
42
  >
73
- <MenuGroup label="Actions">
74
- <MenuList>
75
- <MenuItem
43
+ <SelectGroup label="Actions">
44
+ <SelectList>
45
+ <SelectOption
76
46
  isSelected={selectedItems.includes(0)}
77
47
  actions={
78
48
  <MenuItemAction
@@ -87,8 +57,8 @@ export const ComposableActionsMenu: React.FunctionComponent = () => {
87
57
  itemId={0}
88
58
  >
89
59
  Item 1
90
- </MenuItem>
91
- <MenuItem
60
+ </SelectOption>
61
+ <SelectOption
92
62
  isDisabled
93
63
  isSelected={selectedItems.includes(1)}
94
64
  actions={<MenuItemAction icon={<BellIcon aria-hidden />} actionId="alert" aria-label="Alert" />}
@@ -96,26 +66,24 @@ export const ComposableActionsMenu: React.FunctionComponent = () => {
96
66
  itemId={1}
97
67
  >
98
68
  Item 2
99
- </MenuItem>
100
- <MenuItem
69
+ </SelectOption>
70
+ <SelectOption
101
71
  isSelected={selectedItems.includes(2)}
102
72
  actions={<MenuItemAction icon={<ClipboardIcon aria-hidden />} actionId="copy" aria-label="Copy" />}
103
73
  itemId={2}
104
74
  >
105
75
  Item 3
106
- </MenuItem>
107
- <MenuItem
76
+ </SelectOption>
77
+ <SelectOption
108
78
  isSelected={selectedItems.includes(3)}
109
79
  actions={<MenuItemAction icon={<BarsIcon aria-hidden />} actionId="expand" aria-label="Expand" />}
110
80
  description="This is a description"
111
81
  itemId={3}
112
82
  >
113
83
  Item 4
114
- </MenuItem>
115
- </MenuList>
116
- </MenuGroup>
117
- </Menu>
84
+ </SelectOption>
85
+ </SelectList>
86
+ </SelectGroup>
87
+ </Select>
118
88
  );
119
-
120
- return <Popper trigger={toggle} triggerRef={toggleRef} popper={menu} popperRef={menuRef} isVisible={isOpen} />;
121
89
  };