@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.
- package/CHANGELOG.md +6 -0
- package/dist/esm/components/AboutModal/package.json +1 -1
- package/dist/esm/components/Accordion/package.json +1 -1
- package/dist/esm/components/ActionList/package.json +1 -1
- package/dist/esm/components/Alert/package.json +1 -1
- package/dist/esm/components/Avatar/package.json +1 -1
- package/dist/esm/components/BackToTop/package.json +1 -1
- package/dist/esm/components/Backdrop/package.json +1 -1
- package/dist/esm/components/BackgroundImage/package.json +1 -1
- package/dist/esm/components/Badge/package.json +1 -1
- package/dist/esm/components/Banner/package.json +1 -1
- package/dist/esm/components/Brand/package.json +1 -1
- package/dist/esm/components/Breadcrumb/package.json +1 -1
- package/dist/esm/components/Button/package.json +1 -1
- package/dist/esm/components/CalendarMonth/package.json +1 -1
- package/dist/esm/components/Card/package.json +1 -1
- package/dist/esm/components/Checkbox/package.json +1 -1
- package/dist/esm/components/Chip/package.json +1 -1
- package/dist/esm/components/ClipboardCopy/package.json +1 -1
- package/dist/esm/components/CodeBlock/package.json +1 -1
- package/dist/esm/components/DataList/package.json +1 -1
- package/dist/esm/components/DatePicker/package.json +1 -1
- package/dist/esm/components/DescriptionList/package.json +1 -1
- package/dist/esm/components/Divider/package.json +1 -1
- package/dist/esm/components/DragDrop/package.json +1 -1
- package/dist/esm/components/Drawer/package.json +1 -1
- package/dist/esm/components/Dropdown/Dropdown.d.ts +3 -1
- package/dist/esm/components/Dropdown/Dropdown.d.ts.map +1 -1
- package/dist/esm/components/Dropdown/Dropdown.js +3 -4
- package/dist/esm/components/Dropdown/Dropdown.js.map +1 -1
- package/dist/esm/components/Dropdown/package.json +1 -1
- package/dist/esm/components/DualListSelector/package.json +1 -1
- package/dist/esm/components/EmptyState/package.json +1 -1
- package/dist/esm/components/ExpandableSection/package.json +1 -1
- package/dist/esm/components/FileUpload/package.json +1 -1
- package/dist/esm/components/Form/package.json +1 -1
- package/dist/esm/components/FormSelect/package.json +1 -1
- package/dist/esm/components/HelperText/package.json +1 -1
- package/dist/esm/components/Hint/package.json +1 -1
- package/dist/esm/components/Icon/package.json +1 -1
- package/dist/esm/components/InputGroup/package.json +1 -1
- package/dist/esm/components/JumpLinks/package.json +1 -1
- package/dist/esm/components/Label/package.json +1 -1
- package/dist/esm/components/List/package.json +1 -1
- package/dist/esm/components/LoginPage/package.json +1 -1
- package/dist/esm/components/Masthead/package.json +1 -1
- package/dist/esm/components/Menu/Menu.js +7 -4
- package/dist/esm/components/Menu/Menu.js.map +1 -1
- package/dist/esm/components/Menu/MenuContainer.d.ts +42 -0
- package/dist/esm/components/Menu/MenuContainer.d.ts.map +1 -0
- package/dist/esm/components/Menu/MenuContainer.js +47 -0
- package/dist/esm/components/Menu/MenuContainer.js.map +1 -0
- package/dist/esm/components/Menu/index.d.ts +1 -0
- package/dist/esm/components/Menu/index.d.ts.map +1 -1
- package/dist/esm/components/Menu/index.js +1 -0
- package/dist/esm/components/Menu/index.js.map +1 -1
- package/dist/esm/components/Menu/package.json +1 -1
- package/dist/esm/components/MenuToggle/package.json +1 -1
- package/dist/esm/components/Modal/package.json +1 -1
- package/dist/esm/components/MultipleFileUpload/package.json +1 -1
- package/dist/esm/components/Nav/package.json +1 -1
- package/dist/esm/components/NotificationBadge/package.json +1 -1
- package/dist/esm/components/NotificationDrawer/package.json +1 -1
- package/dist/esm/components/NumberInput/package.json +1 -1
- package/dist/esm/components/OverflowMenu/package.json +1 -1
- package/dist/esm/components/Page/package.json +1 -1
- package/dist/esm/components/Pagination/package.json +1 -1
- package/dist/esm/components/Panel/package.json +1 -1
- package/dist/esm/components/Popover/package.json +1 -1
- package/dist/esm/components/Progress/package.json +1 -1
- package/dist/esm/components/ProgressStepper/package.json +1 -1
- package/dist/esm/components/Radio/package.json +1 -1
- package/dist/esm/components/SearchInput/package.json +1 -1
- package/dist/esm/components/Select/package.json +1 -1
- package/dist/esm/components/Sidebar/package.json +1 -1
- package/dist/esm/components/SimpleList/package.json +1 -1
- package/dist/esm/components/Skeleton/package.json +1 -1
- package/dist/esm/components/SkipToContent/package.json +1 -1
- package/dist/esm/components/Slider/package.json +1 -1
- package/dist/esm/components/Spinner/package.json +1 -1
- package/dist/esm/components/Switch/package.json +1 -1
- package/dist/esm/components/Tabs/package.json +1 -1
- package/dist/esm/components/Text/package.json +1 -1
- package/dist/esm/components/TextArea/package.json +1 -1
- package/dist/esm/components/TextInput/package.json +1 -1
- package/dist/esm/components/TextInputGroup/package.json +1 -1
- package/dist/esm/components/Tile/package.json +1 -1
- package/dist/esm/components/TimePicker/package.json +1 -1
- package/dist/esm/components/Timestamp/package.json +1 -1
- package/dist/esm/components/Title/package.json +1 -1
- package/dist/esm/components/ToggleGroup/package.json +1 -1
- package/dist/esm/components/Toolbar/package.json +1 -1
- package/dist/esm/components/Tooltip/package.json +1 -1
- package/dist/esm/components/TreeView/package.json +1 -1
- package/dist/esm/components/Truncate/package.json +1 -1
- package/dist/esm/components/Wizard/hooks/package.json +1 -1
- package/dist/esm/components/Wizard/package.json +1 -1
- package/dist/esm/components/package.json +1 -1
- package/dist/esm/deprecated/components/ApplicationLauncher/package.json +1 -1
- package/dist/esm/deprecated/components/ContextSelector/package.json +1 -1
- package/dist/esm/deprecated/components/Dropdown/package.json +1 -1
- package/dist/esm/deprecated/components/OptionsMenu/package.json +1 -1
- package/dist/esm/deprecated/components/PageHeader/package.json +1 -1
- package/dist/esm/deprecated/components/Select/package.json +1 -1
- package/dist/esm/deprecated/components/Wizard/package.json +1 -1
- package/dist/esm/deprecated/components/package.json +1 -1
- package/dist/esm/deprecated/package.json +1 -1
- package/dist/esm/helpers/Popper/thirdparty/popper-core/package.json +1 -1
- package/dist/esm/helpers/package.json +1 -1
- package/dist/esm/layouts/Bullseye/package.json +1 -1
- package/dist/esm/layouts/Flex/package.json +1 -1
- package/dist/esm/layouts/Gallery/package.json +1 -1
- package/dist/esm/layouts/Grid/package.json +1 -1
- package/dist/esm/layouts/Level/package.json +1 -1
- package/dist/esm/layouts/Split/package.json +1 -1
- package/dist/esm/layouts/Stack/package.json +1 -1
- package/dist/esm/layouts/package.json +1 -1
- package/dist/esm/next/components/package.json +1 -1
- package/dist/esm/next/package.json +1 -1
- package/dist/esm/package.json +1 -1
- package/dist/js/components/AboutModal/package.json +1 -1
- package/dist/js/components/Accordion/package.json +1 -1
- package/dist/js/components/ActionList/package.json +1 -1
- package/dist/js/components/Alert/package.json +1 -1
- package/dist/js/components/Avatar/package.json +1 -1
- package/dist/js/components/BackToTop/package.json +1 -1
- package/dist/js/components/Backdrop/package.json +1 -1
- package/dist/js/components/BackgroundImage/package.json +1 -1
- package/dist/js/components/Badge/package.json +1 -1
- package/dist/js/components/Banner/package.json +1 -1
- package/dist/js/components/Brand/package.json +1 -1
- package/dist/js/components/Breadcrumb/package.json +1 -1
- package/dist/js/components/Button/package.json +1 -1
- package/dist/js/components/CalendarMonth/package.json +1 -1
- package/dist/js/components/Card/package.json +1 -1
- package/dist/js/components/Checkbox/package.json +1 -1
- package/dist/js/components/Chip/package.json +1 -1
- package/dist/js/components/ClipboardCopy/package.json +1 -1
- package/dist/js/components/CodeBlock/package.json +1 -1
- package/dist/js/components/DataList/package.json +1 -1
- package/dist/js/components/DatePicker/package.json +1 -1
- package/dist/js/components/DescriptionList/package.json +1 -1
- package/dist/js/components/Divider/package.json +1 -1
- package/dist/js/components/DragDrop/package.json +1 -1
- package/dist/js/components/Drawer/package.json +1 -1
- package/dist/js/components/Dropdown/Dropdown.d.ts +3 -1
- package/dist/js/components/Dropdown/Dropdown.d.ts.map +1 -1
- package/dist/js/components/Dropdown/Dropdown.js +3 -4
- package/dist/js/components/Dropdown/Dropdown.js.map +1 -1
- package/dist/js/components/Dropdown/package.json +1 -1
- package/dist/js/components/DualListSelector/package.json +1 -1
- package/dist/js/components/EmptyState/package.json +1 -1
- package/dist/js/components/ExpandableSection/package.json +1 -1
- package/dist/js/components/FileUpload/package.json +1 -1
- package/dist/js/components/Form/package.json +1 -1
- package/dist/js/components/FormSelect/package.json +1 -1
- package/dist/js/components/HelperText/package.json +1 -1
- package/dist/js/components/Hint/package.json +1 -1
- package/dist/js/components/Icon/package.json +1 -1
- package/dist/js/components/InputGroup/package.json +1 -1
- package/dist/js/components/JumpLinks/package.json +1 -1
- package/dist/js/components/Label/package.json +1 -1
- package/dist/js/components/List/package.json +1 -1
- package/dist/js/components/LoginPage/package.json +1 -1
- package/dist/js/components/Masthead/package.json +1 -1
- package/dist/js/components/Menu/Menu.js +7 -4
- package/dist/js/components/Menu/Menu.js.map +1 -1
- package/dist/js/components/Menu/MenuContainer.d.ts +42 -0
- package/dist/js/components/Menu/MenuContainer.d.ts.map +1 -0
- package/dist/js/components/Menu/MenuContainer.js +52 -0
- package/dist/js/components/Menu/MenuContainer.js.map +1 -0
- package/dist/js/components/Menu/index.d.ts +1 -0
- package/dist/js/components/Menu/index.d.ts.map +1 -1
- package/dist/js/components/Menu/index.js +1 -0
- package/dist/js/components/Menu/index.js.map +1 -1
- package/dist/js/components/Menu/package.json +1 -1
- package/dist/js/components/MenuToggle/package.json +1 -1
- package/dist/js/components/Modal/package.json +1 -1
- package/dist/js/components/MultipleFileUpload/package.json +1 -1
- package/dist/js/components/Nav/package.json +1 -1
- package/dist/js/components/NotificationBadge/package.json +1 -1
- package/dist/js/components/NotificationDrawer/package.json +1 -1
- package/dist/js/components/NumberInput/package.json +1 -1
- package/dist/js/components/OverflowMenu/package.json +1 -1
- package/dist/js/components/Page/package.json +1 -1
- package/dist/js/components/Pagination/package.json +1 -1
- package/dist/js/components/Panel/package.json +1 -1
- package/dist/js/components/Popover/package.json +1 -1
- package/dist/js/components/Progress/package.json +1 -1
- package/dist/js/components/ProgressStepper/package.json +1 -1
- package/dist/js/components/Radio/package.json +1 -1
- package/dist/js/components/SearchInput/package.json +1 -1
- package/dist/js/components/Select/package.json +1 -1
- package/dist/js/components/Sidebar/package.json +1 -1
- package/dist/js/components/SimpleList/package.json +1 -1
- package/dist/js/components/Skeleton/package.json +1 -1
- package/dist/js/components/SkipToContent/package.json +1 -1
- package/dist/js/components/Slider/package.json +1 -1
- package/dist/js/components/Spinner/package.json +1 -1
- package/dist/js/components/Switch/package.json +1 -1
- package/dist/js/components/Tabs/package.json +1 -1
- package/dist/js/components/Text/package.json +1 -1
- package/dist/js/components/TextArea/package.json +1 -1
- package/dist/js/components/TextInput/package.json +1 -1
- package/dist/js/components/TextInputGroup/package.json +1 -1
- package/dist/js/components/Tile/package.json +1 -1
- package/dist/js/components/TimePicker/package.json +1 -1
- package/dist/js/components/Timestamp/package.json +1 -1
- package/dist/js/components/Title/package.json +1 -1
- package/dist/js/components/ToggleGroup/package.json +1 -1
- package/dist/js/components/Toolbar/package.json +1 -1
- package/dist/js/components/Tooltip/package.json +1 -1
- package/dist/js/components/TreeView/package.json +1 -1
- package/dist/js/components/Truncate/package.json +1 -1
- package/dist/js/components/Wizard/hooks/package.json +1 -1
- package/dist/js/components/Wizard/package.json +1 -1
- package/dist/js/components/package.json +1 -1
- package/dist/js/deprecated/components/ApplicationLauncher/package.json +1 -1
- package/dist/js/deprecated/components/ContextSelector/package.json +1 -1
- package/dist/js/deprecated/components/Dropdown/package.json +1 -1
- package/dist/js/deprecated/components/OptionsMenu/package.json +1 -1
- package/dist/js/deprecated/components/PageHeader/package.json +1 -1
- package/dist/js/deprecated/components/Select/package.json +1 -1
- package/dist/js/deprecated/components/Wizard/package.json +1 -1
- package/dist/js/deprecated/components/package.json +1 -1
- package/dist/js/deprecated/package.json +1 -1
- package/dist/js/helpers/Popper/thirdparty/popper-core/package.json +1 -1
- package/dist/js/helpers/package.json +1 -1
- package/dist/js/layouts/Bullseye/package.json +1 -1
- package/dist/js/layouts/Flex/package.json +1 -1
- package/dist/js/layouts/Gallery/package.json +1 -1
- package/dist/js/layouts/Grid/package.json +1 -1
- package/dist/js/layouts/Level/package.json +1 -1
- package/dist/js/layouts/Split/package.json +1 -1
- package/dist/js/layouts/Stack/package.json +1 -1
- package/dist/js/layouts/package.json +1 -1
- package/dist/js/next/components/package.json +1 -1
- package/dist/js/next/package.json +1 -1
- package/dist/js/package.json +1 -1
- package/dist/umd/react-core.min.js +2 -2
- package/package.json +2 -2
- package/src/components/Dropdown/Dropdown.tsx +6 -4
- package/src/components/Menu/Menu.tsx +2 -2
- package/src/components/Menu/MenuContainer.tsx +109 -0
- package/src/components/Menu/examples/Menu.md +13 -1
- package/src/components/Menu/index.ts +1 -0
- package/src/demos/CustomMenus/ApplicationLauncher.md +30 -0
- package/src/demos/CustomMenus/ContextSelector.md +30 -0
- package/src/demos/CustomMenus/CustomMenus.md +84 -0
- package/src/demos/CustomMenus/OptionsMenu.md +17 -0
- package/src/demos/{ComposableMenu/examples/ComposableActionsMenu.tsx → CustomMenus/examples/ActionsMenuDemo.tsx} +25 -57
- package/src/demos/{ComposableMenu/examples/ComposableApplicationLauncher.tsx → CustomMenus/examples/ApplicationLauncherDemo.tsx} +72 -99
- package/src/demos/{ComposableMenu/examples/ComposableContextSelector.tsx → CustomMenus/examples/ContextSelectorDemo.tsx} +43 -80
- package/src/demos/CustomMenus/examples/DateSelectDemo.tsx +84 -0
- package/src/demos/{ComposableMenu/examples/ComposableDrilldownMenu.tsx → CustomMenus/examples/DrilldownMenuDemo.tsx} +14 -36
- package/src/demos/CustomMenus/examples/FavoritesDemo.tsx +120 -0
- package/src/demos/{ComposableMenu/examples/ComposableFlyout.tsx → CustomMenus/examples/FlyoutDemo.tsx} +14 -39
- package/src/demos/CustomMenus/examples/OptionsMenuDemo.tsx +59 -0
- package/src/demos/{ComposableMenu/examples/ComposableTreeViewMenu.tsx → CustomMenus/examples/TreeViewMenuDemo.tsx} +15 -52
- package/src/demos/ComposableMenu/ComposableMenu.md +0 -118
- package/src/demos/ComposableMenu/examples/ComposableMultipleTypeaheadSelect.tsx +0 -253
- package/src/demos/ComposableMenu/examples/ComposableOptionsMenuVariants.tsx +0 -96
- package/src/demos/ComposableMenu/examples/ComposableSimpleCheckboxSelect.tsx +0 -101
- package/src/demos/ComposableMenu/examples/ComposableSimpleDropdown.tsx +0 -70
- package/src/demos/ComposableMenu/examples/ComposableSimpleSelect.tsx +0 -83
- package/src/demos/ComposableMenu/examples/ComposableTypeaheadSelect.tsx +0 -234
- /package/src/demos/{ComposableMenu → CustomMenus}/examples/ComposableDateSelect.tsx +0 -0
- /package/src/demos/{ComposableMenu → CustomMenus}/examples/ComposableDropdwnVariants.tsx +0 -0
- /package/src/demos/{ComposableMenu → CustomMenus}/examples/avatarImg.svg +0 -0
- /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.
|
|
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": "
|
|
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
|
|
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 (
|
|
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
|
|
305
|
-
((navigableElement.firstChild as Element)
|
|
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:
|
|
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
|
|
|
@@ -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,
|
|
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
|
|
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 = (
|
|
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
|
-
|
|
62
|
-
<
|
|
63
|
-
{isOpen
|
|
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
|
-
<
|
|
74
|
-
<
|
|
75
|
-
<
|
|
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
|
-
</
|
|
91
|
-
<
|
|
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
|
-
</
|
|
100
|
-
<
|
|
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
|
-
</
|
|
107
|
-
<
|
|
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
|
-
</
|
|
115
|
-
</
|
|
116
|
-
</
|
|
117
|
-
</
|
|
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
|
};
|