@patternfly/react-docs 7.6.0-prerelease.7 → 7.6.0-prerelease.8
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/package.json +12 -13
- package/patternfly-docs/generated/components/about-modal/react.js +149 -0
- package/patternfly-docs/generated/components/accordion/react.js +262 -0
- package/patternfly-docs/generated/components/action-list/react.js +144 -0
- package/patternfly-docs/generated/components/alert/react-demos.js +56 -0
- package/patternfly-docs/generated/components/alert/react.js +1433 -0
- package/patternfly-docs/generated/components/avatar/react.js +166 -0
- package/patternfly-docs/generated/components/back-to-top/react-demos.js +60 -0
- package/patternfly-docs/generated/components/back-to-top/react.js +77 -0
- package/patternfly-docs/generated/components/backdrop/react.js +64 -0
- package/patternfly-docs/generated/components/background-image/react.js +62 -0
- package/patternfly-docs/generated/components/badge/react.js +97 -0
- package/patternfly-docs/generated/components/banner/react-demos.js +57 -0
- package/patternfly-docs/generated/components/banner/react.js +148 -0
- package/patternfly-docs/generated/components/brand/react.js +142 -0
- package/patternfly-docs/generated/components/breadcrumb/react.js +206 -0
- package/patternfly-docs/generated/components/button/react-demos.js +57 -0
- package/patternfly-docs/generated/components/button/react.js +826 -0
- package/patternfly-docs/generated/components/card/react-demos.js +201 -0
- package/patternfly-docs/generated/components/card/react.js +1015 -0
- package/patternfly-docs/generated/components/charts/area-chart/-Victory.js +1350 -0
- package/patternfly-docs/generated/components/charts/bar-chart/-Victory.js +1334 -0
- package/patternfly-docs/generated/components/charts/box-plot-chart/-Victory.js +1282 -0
- package/patternfly-docs/generated/components/charts/bullet-chart/-Victory.js +848 -0
- package/patternfly-docs/generated/components/charts/colors-for-charts/-Victory.js +192 -0
- package/patternfly-docs/generated/components/charts/donut-chart/-Victory.js +426 -0
- package/patternfly-docs/generated/components/charts/donut-utilization-chart/-Victory.js +804 -0
- package/patternfly-docs/generated/components/charts/legends/-Victory.js +3230 -0
- package/patternfly-docs/generated/components/charts/line-chart/-Victory.js +1178 -0
- package/patternfly-docs/generated/components/charts/line-chart/ECharts.js +525 -0
- package/patternfly-docs/generated/components/charts/patterns/-Victory.js +3382 -0
- package/patternfly-docs/generated/components/charts/pie-chart/-Victory.js +377 -0
- package/patternfly-docs/generated/components/charts/resize-observer/-Victory.js +2475 -0
- package/patternfly-docs/generated/components/charts/sankey-chart/ECharts.js +538 -0
- package/patternfly-docs/generated/components/charts/scatter-chart/-Victory.js +1551 -0
- package/patternfly-docs/generated/components/charts/skeletons/-Victory.js +4115 -0
- package/patternfly-docs/generated/components/charts/sparkline-chart/-Victory.js +955 -0
- package/patternfly-docs/generated/components/charts/stack-chart/-Victory.js +1173 -0
- package/patternfly-docs/generated/components/charts/threshold-chart/-Victory.js +1166 -0
- package/patternfly-docs/generated/components/charts/tooltips/-Victory.js +413 -0
- package/patternfly-docs/generated/components/chip/react-deprecated.js +323 -0
- package/patternfly-docs/generated/components/clipboard-copy/react.js +373 -0
- package/patternfly-docs/generated/components/code-block/react.js +148 -0
- package/patternfly-docs/generated/components/code-editor/react.js +659 -0
- package/patternfly-docs/generated/components/compass/react-demos.js +147 -0
- package/patternfly-docs/generated/components/compass/react.js +440 -0
- package/patternfly-docs/generated/components/content/react.js +248 -0
- package/patternfly-docs/generated/components/data-list/react-demos.js +90 -0
- package/patternfly-docs/generated/components/data-list/react.js +709 -0
- package/patternfly-docs/generated/components/date-and-time/calendar-month/react.js +283 -0
- package/patternfly-docs/generated/components/date-and-time/date-and-time-picker/react-demos.js +64 -0
- package/patternfly-docs/generated/components/date-and-time/date-picker/react-demos.js +83 -0
- package/patternfly-docs/generated/components/date-and-time/date-picker/react.js +395 -0
- package/patternfly-docs/generated/components/date-and-time/time-picker/react.js +241 -0
- package/patternfly-docs/generated/components/description-list/react-demos.js +58 -0
- package/patternfly-docs/generated/components/description-list/react.js +743 -0
- package/patternfly-docs/generated/components/divider/react.js +126 -0
- package/patternfly-docs/generated/components/drag-and-drop/react-demos.js +351 -0
- package/patternfly-docs/generated/components/drag-and-drop/react-deprecated.js +184 -0
- package/patternfly-docs/generated/components/drag-and-drop/react.js +137 -0
- package/patternfly-docs/generated/components/drawer/react.js +598 -0
- package/patternfly-docs/generated/components/dual-list-selector/react-deprecated.js +772 -0
- package/patternfly-docs/generated/components/dual-list-selector/react.js +594 -0
- package/patternfly-docs/generated/components/empty-state/react.js +199 -0
- package/patternfly-docs/generated/components/expandable-section/react-demos.js +65 -0
- package/patternfly-docs/generated/components/expandable-section/react.js +408 -0
- package/patternfly-docs/generated/components/file-upload/multiple-file-upload/react-demos.js +52 -0
- package/patternfly-docs/generated/components/file-upload/multiple-file-upload/react.js +398 -0
- package/patternfly-docs/generated/components/file-upload/simple-file-upload/react.js +749 -0
- package/patternfly-docs/generated/components/forms/checkbox/react.js +222 -0
- package/patternfly-docs/generated/components/forms/form/react.js +1106 -0
- package/patternfly-docs/generated/components/forms/form-select/react.js +208 -0
- package/patternfly-docs/generated/components/forms/radio/react.js +212 -0
- package/patternfly-docs/generated/components/forms/text-area/react.js +160 -0
- package/patternfly-docs/generated/components/forms/text-input/react.js +216 -0
- package/patternfly-docs/generated/components/helper-text/react-demos.js +180 -0
- package/patternfly-docs/generated/components/helper-text/react.js +164 -0
- package/patternfly-docs/generated/components/hero/react.js +88 -0
- package/patternfly-docs/generated/components/hint/react.js +169 -0
- package/patternfly-docs/generated/components/icon/react.js +215 -0
- package/patternfly-docs/generated/components/input-group/react.js +182 -0
- package/patternfly-docs/generated/components/jump-links/react-demos.js +154 -0
- package/patternfly-docs/generated/components/jump-links/react.js +212 -0
- package/patternfly-docs/generated/components/label/react-demos.js +57 -0
- package/patternfly-docs/generated/components/label/react.js +417 -0
- package/patternfly-docs/generated/components/list/react.js +175 -0
- package/patternfly-docs/generated/components/login-page/react.js +587 -0
- package/patternfly-docs/generated/components/masthead/react-demos.js +79 -0
- package/patternfly-docs/generated/components/masthead/react.js +291 -0
- package/patternfly-docs/generated/components/menus/application-launcher/react-demos.js +769 -0
- package/patternfly-docs/generated/components/menus/context-selector/react-demos.js +665 -0
- package/patternfly-docs/generated/components/menus/custom-menus/react-demos.js +187 -0
- package/patternfly-docs/generated/components/menus/dropdown/react-templates.js +163 -0
- package/patternfly-docs/generated/components/menus/dropdown/react.js +998 -0
- package/patternfly-docs/generated/components/menus/menu/react.js +1540 -0
- package/patternfly-docs/generated/components/menus/menu-toggle/react.js +747 -0
- package/patternfly-docs/generated/components/menus/options-menu/react-demos.js +508 -0
- package/patternfly-docs/generated/components/menus/select/react-templates.js +257 -0
- package/patternfly-docs/generated/components/menus/select/react.js +998 -0
- package/patternfly-docs/generated/components/modal/react-deprecated.js +554 -0
- package/patternfly-docs/generated/components/modal/react.js +597 -0
- package/patternfly-docs/generated/components/navigation/react-demos.js +356 -0
- package/patternfly-docs/generated/components/navigation/react.js +409 -0
- package/patternfly-docs/generated/components/notification-badge/react.js +196 -0
- package/patternfly-docs/generated/components/notification-drawer/react-demos.js +107 -0
- package/patternfly-docs/generated/components/notification-drawer/react.js +394 -0
- package/patternfly-docs/generated/components/number-input/react.js +210 -0
- package/patternfly-docs/generated/components/overflow-menu/react.js +274 -0
- package/patternfly-docs/generated/components/page/react-demos.js +149 -0
- package/patternfly-docs/generated/components/page/react.js +1352 -0
- package/patternfly-docs/generated/components/pagination/react.js +492 -0
- package/patternfly-docs/generated/components/panel/react.js +236 -0
- package/patternfly-docs/generated/components/popover/react.js +390 -0
- package/patternfly-docs/generated/components/progress/react-demos.js +59 -0
- package/patternfly-docs/generated/components/progress/react.js +283 -0
- package/patternfly-docs/generated/components/progress-stepper/react-demos.js +45 -0
- package/patternfly-docs/generated/components/progress-stepper/react.js +219 -0
- package/patternfly-docs/generated/components/search-input/react-demos.js +113 -0
- package/patternfly-docs/generated/components/search-input/react.js +263 -0
- package/patternfly-docs/generated/components/sidebar/react.js +236 -0
- package/patternfly-docs/generated/components/simple-list/react.js +200 -0
- package/patternfly-docs/generated/components/skeleton/react-demos.js +44 -0
- package/patternfly-docs/generated/components/skeleton/react.js +122 -0
- package/patternfly-docs/generated/components/skip-to-content/react.js +73 -0
- package/patternfly-docs/generated/components/slider/react.js +309 -0
- package/patternfly-docs/generated/components/spinner/react.js +111 -0
- package/patternfly-docs/generated/components/switch/react.js +163 -0
- package/patternfly-docs/generated/components/table/react-demos.js +355 -0
- package/patternfly-docs/generated/components/table/react-deprecated.js +1350 -0
- package/patternfly-docs/generated/components/table/react.js +3241 -0
- package/patternfly-docs/generated/components/tabs/react-demos.js +108 -0
- package/patternfly-docs/generated/components/tabs/react.js +1359 -0
- package/patternfly-docs/generated/components/text-input-group/react-demos.js +152 -0
- package/patternfly-docs/generated/components/text-input-group/react.js +278 -0
- package/patternfly-docs/generated/components/tile/react-deprecated.js +242 -0
- package/patternfly-docs/generated/components/timestamp/react.js +283 -0
- package/patternfly-docs/generated/components/title/react.js +94 -0
- package/patternfly-docs/generated/components/toggle-group/react.js +299 -0
- package/patternfly-docs/generated/components/toolbar/react-demos.js +66 -0
- package/patternfly-docs/generated/components/toolbar/react.js +932 -0
- package/patternfly-docs/generated/components/tooltip/react.js +241 -0
- package/patternfly-docs/generated/components/tree-view/react.js +429 -0
- package/patternfly-docs/generated/components/truncate/react.js +211 -0
- package/patternfly-docs/generated/components/wizard/react-demos.js +87 -0
- package/patternfly-docs/generated/components/wizard/react-deprecated.js +788 -0
- package/patternfly-docs/generated/components/wizard/react.js +986 -0
- package/patternfly-docs/generated/developer-guides/open-ui-automation/react.js +285 -0
- package/patternfly-docs/generated/foundations-and-styles/layouts/bullseye/react.js +70 -0
- package/patternfly-docs/generated/foundations-and-styles/layouts/flex/react.js +506 -0
- package/patternfly-docs/generated/foundations-and-styles/layouts/gallery/react.js +94 -0
- package/patternfly-docs/generated/foundations-and-styles/layouts/grid/react.js +272 -0
- package/patternfly-docs/generated/foundations-and-styles/layouts/level/react.js +87 -0
- package/patternfly-docs/generated/foundations-and-styles/layouts/split/react.js +124 -0
- package/patternfly-docs/generated/foundations-and-styles/layouts/stack/react.js +112 -0
- package/patternfly-docs/generated/index.js +1769 -0
- package/patternfly-docs/generated/patterns/card-view/react-demos.js +78 -0
- package/patternfly-docs/generated/patterns/filters/react-demos.js +141 -0
- package/patternfly-docs/generated/patterns/password-generator/react-demos.js +51 -0
- package/patternfly-docs/generated/patterns/password-strength/react-demos.js +61 -0
- package/patternfly-docs/generated/patterns/primary-detail/react-demos.js +124 -0
- package/patternfly-docs/generated/patterns/right-to-left/react-demos.js +81 -0
- package/LICENSE +0 -21
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { AutoLinkHeader, Example, Link as PatternflyThemeLink } from '@patternfly/documentation-framework/components';
|
|
3
|
+
import { cloneElement, Fragment, useEffect, useRef, useState } from 'react';
|
|
4
|
+
import RhUiSettingsFillIcon from '@patternfly/react-icons/dist/esm/icons/rh-ui-settings-fill-icon';
|
|
5
|
+
import RhUiBranchFillIcon from '@patternfly/react-icons/dist/esm/icons/rh-ui-branch-fill-icon';
|
|
6
|
+
import RhUiStorageDomainFillIcon from '@patternfly/react-icons/dist/esm/icons/rh-ui-storage-domain-fill-icon';
|
|
7
|
+
import RhUiServerStackFillIcon from '@patternfly/react-icons/dist/esm/icons/rh-ui-server-stack-fill-icon';
|
|
8
|
+
import CubeIcon from '@patternfly/react-icons/dist/esm/icons/cube-icon';
|
|
9
|
+
import RhUiMenuBarsIcon from '@patternfly/react-icons/dist/esm/icons/rh-ui-menu-bars-icon';
|
|
10
|
+
import RhUiClipboardFillIcon from '@patternfly/react-icons/dist/esm/icons/rh-ui-clipboard-fill-icon';
|
|
11
|
+
import RhUiNotificationFillIcon from '@patternfly/react-icons/dist/esm/icons/rh-ui-notification-fill-icon';
|
|
12
|
+
import RhUiThumbnailViewSmallFillIcon from '@patternfly/react-icons/dist/esm/icons/rh-ui-thumbnail-view-small-fill-icon';
|
|
13
|
+
import brandImg from '../../../../../../react-core/src/demos/CustomMenus/../assets/PF-IconLogo.svg';
|
|
14
|
+
import SearchIcon from '@patternfly/react-icons/dist/esm/icons/search-icon';
|
|
15
|
+
import RhMicronsCaretDownIcon from '@patternfly/react-icons/dist/esm/icons/rh-microns-caret-down-icon';
|
|
16
|
+
import RhMicronsCloseIcon from '@patternfly/react-icons/dist/esm/icons/rh-microns-close-icon';
|
|
17
|
+
import avatarImg from '../../../../../../react-core/src/demos/CustomMenus/../assets/avatarImg.svg';
|
|
18
|
+
import { css } from '@patternfly/react-styles';
|
|
19
|
+
import styles from '@patternfly/react-styles/css/components/Menu/menu';
|
|
20
|
+
import text from '@patternfly/react-styles/css/utilities/Text/text';
|
|
21
|
+
const pageData = {
|
|
22
|
+
"id": "Custom menus",
|
|
23
|
+
"section": "components",
|
|
24
|
+
"subsection": "menus",
|
|
25
|
+
"deprecated": false,
|
|
26
|
+
"template": false,
|
|
27
|
+
"beta": false,
|
|
28
|
+
"demo": false,
|
|
29
|
+
"newImplementationLink": false,
|
|
30
|
+
"source": "react-demos",
|
|
31
|
+
"tabName": null,
|
|
32
|
+
"slug": "/components/menus/custom-menus/react-demos",
|
|
33
|
+
"sourceLink": "https://github.com/patternfly/patternfly-react/blob/main/packages/react-core/src/demos/CustomMenus/CustomMenus.md",
|
|
34
|
+
"relPath": "packages/react-core/src/demos/CustomMenus/CustomMenus.md",
|
|
35
|
+
"examples": [
|
|
36
|
+
"With actions",
|
|
37
|
+
"With favorites",
|
|
38
|
+
"With drilldown",
|
|
39
|
+
"With inline search filter",
|
|
40
|
+
"Tree view menu",
|
|
41
|
+
"Flyout menu",
|
|
42
|
+
"Application launcher menu",
|
|
43
|
+
"Context selector menu",
|
|
44
|
+
"Date select menu"
|
|
45
|
+
]
|
|
46
|
+
};
|
|
47
|
+
pageData.liveContext = {
|
|
48
|
+
cloneElement,
|
|
49
|
+
Fragment,
|
|
50
|
+
useEffect,
|
|
51
|
+
useRef,
|
|
52
|
+
useState,
|
|
53
|
+
RhUiSettingsFillIcon,
|
|
54
|
+
RhUiBranchFillIcon,
|
|
55
|
+
RhUiStorageDomainFillIcon,
|
|
56
|
+
RhUiServerStackFillIcon,
|
|
57
|
+
CubeIcon,
|
|
58
|
+
RhUiMenuBarsIcon,
|
|
59
|
+
RhUiClipboardFillIcon,
|
|
60
|
+
RhUiNotificationFillIcon,
|
|
61
|
+
RhUiThumbnailViewSmallFillIcon,
|
|
62
|
+
brandImg,
|
|
63
|
+
SearchIcon,
|
|
64
|
+
RhMicronsCaretDownIcon,
|
|
65
|
+
RhMicronsCloseIcon,
|
|
66
|
+
avatarImg,
|
|
67
|
+
css,
|
|
68
|
+
styles,
|
|
69
|
+
text
|
|
70
|
+
};
|
|
71
|
+
pageData.examples = {
|
|
72
|
+
'With actions': props =>
|
|
73
|
+
<Example {...pageData} {...props} {...{"code":"import { useRef, useState } from 'react';\nimport { MenuToggle, MenuItemAction, Select, SelectGroup, SelectList, SelectOption } from '@patternfly/react-core';\nimport RhUiMenuBarsIcon from '@patternfly/react-icons/dist/esm/icons/rh-ui-menu-bars-icon';\nimport RhUiClipboardFillIcon from '@patternfly/react-icons/dist/esm/icons/rh-ui-clipboard-fill-icon';\nimport RhUiBranchFillIcon from '@patternfly/react-icons/dist/esm/icons/rh-ui-branch-fill-icon';\nimport RhUiNotificationFillIcon from '@patternfly/react-icons/dist/esm/icons/rh-ui-notification-fill-icon';\n\nexport const ActionsMenuDemo: React.FunctionComponent = () => {\n const [isOpen, setIsOpen] = useState<boolean>(false);\n const [selectedItems, setSelectedItems] = useState<number[]>([]);\n const menuRef = useRef<HTMLDivElement>(null);\n\n const onSelect = (event: React.MouseEvent | undefined, value: string | number | undefined) => {\n if (typeof value === 'string' || typeof value === 'undefined') {\n return;\n }\n\n if (selectedItems.includes(value)) {\n setSelectedItems(selectedItems.filter((id) => id !== value));\n } else {\n setSelectedItems([...selectedItems, value]);\n }\n };\n\n const onToggleClick = () => {\n setIsOpen(!isOpen);\n };\n\n return (\n <Select\n isOpen={isOpen}\n ref={menuRef}\n toggle={(toggleRef) => (\n <MenuToggle ref={toggleRef} onClick={onToggleClick} isExpanded={isOpen}>\n {isOpen ? 'Expanded' : 'Collapsed'}\n </MenuToggle>\n )}\n // eslint-disable-next-line no-console\n onActionClick={(event, value, actionId) => console.log(`clicked on ${value} - ${actionId}`)}\n onSelect={onSelect}\n onOpenChange={(isOpen) => setIsOpen(isOpen)}\n >\n <SelectGroup label=\"Actions\">\n <SelectList>\n <SelectOption\n isSelected={selectedItems.includes(0)}\n actions={\n <MenuItemAction\n icon={<RhUiBranchFillIcon />}\n actionId=\"code\"\n // eslint-disable-next-line no-console\n onClick={() => console.log('clicked on code icon')}\n aria-label=\"Code\"\n />\n }\n description=\"This is a description\"\n value={0}\n >\n Item 1\n </SelectOption>\n <SelectOption\n isDisabled\n isSelected={selectedItems.includes(1)}\n actions={<MenuItemAction icon={<RhUiNotificationFillIcon />} actionId=\"alert\" aria-label=\"Alert\" />}\n description=\"This is a description\"\n value={1}\n >\n Item 2\n </SelectOption>\n <SelectOption\n isSelected={selectedItems.includes(2)}\n actions={<MenuItemAction icon={<RhUiClipboardFillIcon />} actionId=\"copy\" aria-label=\"Copy\" />}\n value={2}\n >\n Item 3\n </SelectOption>\n <SelectOption\n isSelected={selectedItems.includes(3)}\n actions={<MenuItemAction icon={<RhUiMenuBarsIcon />} actionId=\"expand\" aria-label=\"Expand\" />}\n description=\"This is a description\"\n value={3}\n >\n Item 4\n </SelectOption>\n </SelectList>\n </SelectGroup>\n </Select>\n );\n};\n","title":"With actions","lang":"ts","className":""}}>
|
|
74
|
+
|
|
75
|
+
</Example>,
|
|
76
|
+
'With favorites': props =>
|
|
77
|
+
<Example {...pageData} {...props} {...{"code":"import { Fragment, useEffect, useRef, useState } from 'react';\nimport { MenuToggle, Divider, Dropdown, DropdownGroup, DropdownList, DropdownItem } from '@patternfly/react-core';\n\nexport const FavoritesDemo: React.FunctionComponent = () => {\n const [isOpen, setIsOpen] = useState<boolean>(false);\n const [favorites, setFavorites] = useState<string[]>([]);\n const menuRef = useRef<HTMLDivElement>(null);\n\n const onToggleClick = () => {\n setIsOpen(!isOpen);\n };\n\n const menuItems = [\n <DropdownGroup key=\"group1\" label=\"Group 1\">\n <DropdownList>\n <DropdownItem value=\"0\" id=\"0\" isFavorited={favorites.includes('0')}>\n Item 1\n </DropdownItem>\n <DropdownItem value=\"1\" id=\"1\" isFavorited={favorites.includes('1')}>\n Item 2\n </DropdownItem>\n <DropdownItem value=\"2\" id=\"2\" isFavorited={favorites.includes('2')}>\n Item 3\n </DropdownItem>\n <DropdownItem value=\"3\" id=\"3\" isFavorited={favorites.includes('3')}>\n Item 4\n </DropdownItem>\n </DropdownList>\n </DropdownGroup>,\n <Divider key=\"group1-divider\" />,\n <DropdownGroup key=\"group2\" label=\"Group 2\">\n <DropdownList>\n <DropdownItem value=\"4\" id=\"4\" isFavorited={favorites.includes('4')}>\n Item 5\n </DropdownItem>\n <DropdownItem value=\"5\" id=\"5\" isFavorited={favorites.includes('5')}>\n Item 6\n </DropdownItem>\n <DropdownItem value=\"6\" id=\"6\" isFavorited={favorites.includes('6')}>\n Item 7\n </DropdownItem>\n <DropdownItem value=\"7\" id=\"7\" isFavorited={favorites.includes('7')}>\n Item 8\n </DropdownItem>\n </DropdownList>\n </DropdownGroup>\n ];\n\n const createFavorites = (favIds: string[]) => {\n const favorites: React.JSX.Element[] = [];\n\n menuItems.forEach((item) => {\n if (item.type === DropdownList) {\n item.props.children.filter((child) => {\n if (favIds.includes(child.props.value)) {\n favorites.push(child);\n }\n });\n } else if (item.type === DropdownGroup) {\n item.props.children.props.children.filter((child) => {\n if (favIds.includes(child.props.value)) {\n favorites.push(child);\n }\n });\n } else {\n if (favIds.includes(item.props.value)) {\n favorites.push(item);\n }\n }\n });\n\n return favorites;\n };\n\n useEffect(() => {\n if (favorites.length === 0) {\n const firstElement = menuRef?.current?.querySelector('li > button:not(:disabled)');\n firstElement && (firstElement as HTMLElement).focus();\n }\n }, [favorites]);\n\n const onFavorite = (event: any, value: string, actionId: string) => {\n event.stopPropagation();\n if (actionId === 'fav') {\n const isFavorite = favorites.includes(value);\n if (isFavorite) {\n setFavorites(favorites.filter((fav) => fav !== value));\n } else {\n setFavorites([...favorites, value]);\n }\n }\n };\n\n return (\n <Dropdown\n isOpen={isOpen}\n onOpenChange={(isOpen) => setIsOpen(isOpen)}\n toggle={(toggleRef) => (\n <MenuToggle ref={toggleRef} onClick={onToggleClick} isExpanded={isOpen}>\n {isOpen ? 'Expanded' : 'Collapsed'}\n </MenuToggle>\n )}\n ref={menuRef}\n onActionClick={onFavorite}\n // eslint-disable-next-line no-console\n onSelect={(_ev, value) => console.log('selected', value)}\n >\n {favorites.length > 0 && (\n <Fragment>\n <DropdownGroup key=\"favorites-group\" label=\"Favorites\">\n <DropdownList>{createFavorites(favorites)}</DropdownList>\n </DropdownGroup>\n <Divider key=\"favorites-divider\" />\n </Fragment>\n )}\n {menuItems}\n </Dropdown>\n );\n};\n","title":"With favorites","lang":"ts","className":""}}>
|
|
78
|
+
|
|
79
|
+
</Example>,
|
|
80
|
+
'With drilldown': props =>
|
|
81
|
+
<Example {...pageData} {...props} {...{"code":"import { useRef, useState } from 'react';\nimport {\n MenuToggle,\n Menu,\n MenuContent,\n MenuList,\n MenuItem,\n DrilldownMenu,\n Divider,\n MenuContainer\n} from '@patternfly/react-core';\nimport RhUiBranchFillIcon from '@patternfly/react-icons/dist/esm/icons/rh-ui-branch-fill-icon';\nimport RhUiStorageDomainFillIcon from '@patternfly/react-icons/dist/esm/icons/rh-ui-storage-domain-fill-icon';\nimport RhUiServerStackFillIcon from '@patternfly/react-icons/dist/esm/icons/rh-ui-server-stack-fill-icon';\nimport CubeIcon from '@patternfly/react-icons/dist/esm/icons/cube-icon';\n\ninterface MenuHeightsType {\n [id: string]: number;\n}\n\nexport const DrilldownMenuDemo: React.FunctionComponent = () => {\n const [isOpen, setIsOpen] = useState<boolean>(false);\n const [activeMenu, setActiveMenu] = useState<string>('rootMenu');\n const [menuDrilledIn, setMenuDrilledIn] = useState<string[]>([]);\n const [drilldownPath, setDrilldownPath] = useState<string[]>([]);\n const [menuHeights, setMenuHeights] = useState<MenuHeightsType>({});\n const toggleRef = useRef<HTMLButtonElement>(null);\n const menuRef = useRef<HTMLDivElement>(null);\n\n const onToggleClick = () => {\n setIsOpen(!isOpen);\n setMenuDrilledIn([]);\n setDrilldownPath([]);\n setActiveMenu('rootMenu');\n };\n\n const drillIn = (\n _event: React.KeyboardEvent | React.MouseEvent,\n fromMenuId: string,\n toMenuId: string,\n pathId: string\n ) => {\n setMenuDrilledIn([...menuDrilledIn, fromMenuId]);\n setDrilldownPath([...drilldownPath, pathId]);\n setActiveMenu(toMenuId);\n };\n\n const drillOut = (_event: React.KeyboardEvent | React.MouseEvent, toMenuId: string) => {\n setMenuDrilledIn(menuDrilledIn.slice(0, menuDrilledIn.length - 1));\n setDrilldownPath(drilldownPath.slice(0, drilldownPath.length - 1));\n setActiveMenu(toMenuId);\n };\n\n const setHeight = (menuId: string, height: number) => {\n if (menuHeights[menuId] === undefined || (menuId !== 'rootMenu' && menuHeights[menuId] !== height)) {\n setMenuHeights({\n ...menuHeights,\n [menuId]: height\n });\n }\n };\n\n const toggle = (\n <MenuToggle ref={toggleRef} onClick={onToggleClick} isExpanded={isOpen}>\n {isOpen ? 'Expanded' : 'Collapsed'}\n </MenuToggle>\n );\n const menu = (\n <Menu\n id=\"rootMenu\"\n containsDrilldown\n drilldownItemPath={drilldownPath}\n drilledInMenus={menuDrilledIn}\n activeMenu={activeMenu}\n onDrillIn={drillIn}\n onDrillOut={drillOut}\n onGetMenuHeight={setHeight}\n ref={menuRef}\n >\n <MenuContent menuHeight={`${menuHeights[activeMenu]}px`}>\n <MenuList>\n <MenuItem\n itemId=\"group:start_rollout\"\n direction=\"down\"\n drilldownMenu={\n <DrilldownMenu id=\"drilldownMenuStart\">\n <MenuItem itemId=\"group:start_rollout_breadcrumb\" direction=\"up\">\n Start rollout\n </MenuItem>\n <Divider component=\"li\" />\n <MenuItem\n itemId=\"group:app_grouping\"\n description=\"Groups A-C\"\n direction=\"down\"\n drilldownMenu={\n <DrilldownMenu id=\"drilldownMenuStartGrouping\">\n <MenuItem itemId=\"group:app_grouping_breadcrumb\" direction=\"up\">\n Application Grouping\n </MenuItem>\n <Divider component=\"li\" />\n <MenuItem itemId=\"group_a\">Group A</MenuItem>\n <MenuItem itemId=\"group_b\">Group B</MenuItem>\n <MenuItem itemId=\"group_c\">Group C</MenuItem>\n </DrilldownMenu>\n }\n >\n Application Grouping\n </MenuItem>\n <MenuItem itemId=\"count\">Count</MenuItem>\n <MenuItem\n itemId=\"group:labels\"\n direction=\"down\"\n drilldownMenu={\n <DrilldownMenu id=\"drilldownMenuStartLabels\">\n <MenuItem itemId=\"group:labels_breadcrumb\" direction=\"up\">\n Labels\n </MenuItem>\n <Divider component=\"li\" />\n <MenuItem itemId=\"label_1\">Label 1</MenuItem>\n <MenuItem itemId=\"label_2\">Label 2</MenuItem>\n <MenuItem itemId=\"label_3\">Label 3</MenuItem>\n </DrilldownMenu>\n }\n >\n Labels\n </MenuItem>\n <MenuItem itemId=\"annotations\">Annotations</MenuItem>\n </DrilldownMenu>\n }\n >\n Start rollout\n </MenuItem>\n <MenuItem\n itemId=\"group:pause_rollout\"\n direction=\"down\"\n drilldownMenu={\n <DrilldownMenu id=\"drilldownMenuPause\">\n <MenuItem itemId=\"group:pause_rollout_breadcrumb\" direction=\"up\">\n Pause rollouts\n </MenuItem>\n <Divider component=\"li\" />\n <MenuItem\n itemId=\"group:app_grouping\"\n description=\"Groups A-C\"\n direction=\"down\"\n drilldownMenu={\n <DrilldownMenu id=\"drilldownMenuGrouping\">\n <MenuItem itemId=\"group:app_grouping_breadcrumb\" direction=\"up\">\n Application Grouping\n </MenuItem>\n <Divider component=\"li\" />\n <MenuItem itemId=\"group_a\">Group A</MenuItem>\n <MenuItem itemId=\"group_b\">Group B</MenuItem>\n <MenuItem itemId=\"group_c\">Group C</MenuItem>\n </DrilldownMenu>\n }\n >\n Application Grouping\n </MenuItem>\n <MenuItem itemId=\"count\">Count</MenuItem>\n <MenuItem\n itemId=\"group:labels\"\n direction=\"down\"\n drilldownMenu={\n <DrilldownMenu id=\"drilldownMenuLabels\">\n <MenuItem itemId=\"group:labels_breadcrumb\" direction=\"up\">\n Labels\n </MenuItem>\n <Divider component=\"li\" />\n <MenuItem itemId=\"label_1\">Label 1</MenuItem>\n <MenuItem itemId=\"label_2\">Label 2</MenuItem>\n <MenuItem itemId=\"label_3\">Label 3</MenuItem>\n </DrilldownMenu>\n }\n >\n Labels\n </MenuItem>\n <MenuItem itemId=\"annotations\">Annotations</MenuItem>\n </DrilldownMenu>\n }\n >\n Pause rollouts\n </MenuItem>\n <MenuItem\n itemId=\"group:storage\"\n icon={<RhUiStorageDomainFillIcon />}\n direction=\"down\"\n drilldownMenu={\n <DrilldownMenu id=\"drilldownMenuStorage\">\n <MenuItem itemId=\"group:storage_breadcrumb\" icon={<RhUiStorageDomainFillIcon />} direction=\"up\">\n Add storage\n </MenuItem>\n <Divider component=\"li\" />\n <MenuItem icon={<RhUiBranchFillIcon />} itemId=\"git\">\n From Git\n </MenuItem>\n <MenuItem icon={<RhUiServerStackFillIcon />} itemId=\"container\">\n Container Image\n </MenuItem>\n <MenuItem icon={<CubeIcon />} itemId=\"docker\">\n Docker File\n </MenuItem>\n </DrilldownMenu>\n }\n >\n Add storage\n </MenuItem>\n <MenuItem itemId=\"edit\">Edit</MenuItem>\n <MenuItem itemId=\"delete_deployment\">Delete deployment config</MenuItem>\n </MenuList>\n </MenuContent>\n </Menu>\n );\n return (\n <MenuContainer\n isOpen={isOpen}\n onOpenChange={(isOpen) => setIsOpen(isOpen)}\n menu={menu}\n menuRef={menuRef}\n toggle={toggle}\n toggleRef={toggleRef}\n />\n );\n};\n","title":"With drilldown","lang":"ts","className":""}}>
|
|
82
|
+
|
|
83
|
+
</Example>,
|
|
84
|
+
'With inline search filter': props =>
|
|
85
|
+
<Example {...pageData} {...props} {...{"code":"import { useRef, useState } from 'react';\nimport {\n Menu,\n MenuList,\n MenuContent,\n MenuSearch,\n MenuSearchInput,\n Divider,\n SearchInput,\n SelectOption,\n MenuToggle,\n MenuContainer\n} from '@patternfly/react-core';\n\nexport const InlineSearchFilterMenuDemo: React.FunctionComponent = () => {\n const [activeItem, setActiveItem] = useState(0);\n const [input, setInput] = useState('');\n const [isOpen, setIsOpen] = useState(false);\n const toggleRef = useRef<any>(undefined);\n const menuRef = useRef<any>(undefined);\n\n const onSelect = (_event: React.MouseEvent<Element, MouseEvent> | undefined, itemId: number | string | undefined) => {\n const item = itemId as number;\n // eslint-disable-next-line no-console\n console.log(`clicked ${itemId}`);\n setActiveItem(item);\n };\n\n const handleTextInputChange = (value: string) => {\n if (!isOpen) {\n setIsOpen(true);\n }\n setInput(value);\n };\n\n const menuListItemsText = [\n 'Action 1',\n 'Action 2',\n 'Action 3',\n 'My project',\n 'OpenShift cluster',\n 'Production Ansible',\n 'AWS',\n 'Azure',\n 'My project 2',\n 'OpenShift cluster ',\n 'Production Ansible 2 ',\n 'AWS 2',\n 'Azure 2'\n ];\n\n const menuListItems = menuListItemsText\n .filter((item) => !input || item.toLowerCase().includes(input.toString().toLowerCase()))\n .map((currentValue, index) => (\n <SelectOption key={currentValue} itemId={index}>\n {currentValue}\n </SelectOption>\n ));\n if (input && menuListItems.length === 0) {\n menuListItems.push(\n <SelectOption isDisabled key=\"no result\">\n No results found\n </SelectOption>\n );\n }\n\n const toggle = (\n <MenuToggle ref={toggleRef} onClick={() => setIsOpen(!isOpen)} isExpanded={isOpen}>\n {isOpen ? 'Expanded' : 'Collapsed'}\n </MenuToggle>\n );\n\n const menu = (\n <Menu ref={menuRef} onSelect={onSelect} activeItemId={activeItem} isScrollable>\n <MenuSearch>\n <MenuSearchInput>\n <SearchInput\n value={input}\n aria-label=\"Filter menu items\"\n onChange={(_event, value) => handleTextInputChange(value)}\n onClear={(event) => {\n event.stopPropagation();\n handleTextInputChange('');\n }}\n />\n </MenuSearchInput>\n </MenuSearch>\n <Divider />\n <MenuContent maxMenuHeight=\"200px\">\n <MenuList>{menuListItems}</MenuList>\n </MenuContent>\n </Menu>\n );\n\n return (\n <MenuContainer\n menu={menu}\n menuRef={menuRef}\n toggle={toggle}\n toggleRef={toggleRef}\n isOpen={isOpen}\n onOpenChange={(isOpen) => setIsOpen(isOpen)}\n onOpenChangeKeys={['Escape']}\n />\n );\n};\n","title":"With inline search filter","lang":"ts","className":""}}>
|
|
86
|
+
|
|
87
|
+
</Example>,
|
|
88
|
+
'Tree view menu': props =>
|
|
89
|
+
<Example {...pageData} {...props} {...{"code":"import { useRef, useState } from 'react';\nimport {\n MenuToggle,\n Panel,\n PanelMain,\n PanelMainBody,\n Title,\n MenuContainer,\n TreeView,\n TreeViewDataItem\n} from '@patternfly/react-core';\n\nexport const TreeViewMenuDemo: React.FunctionComponent = () => {\n const [isOpen, setIsOpen] = useState<boolean>(false);\n const [checkedItems, setCheckedItems] = useState<TreeViewDataItem[]>([]);\n const toggleRef = useRef<HTMLButtonElement>(null);\n const menuRef = useRef<HTMLDivElement>(undefined);\n\n const statusOptions: TreeViewDataItem[] = [\n {\n name: 'Ready',\n id: 'ready',\n checkProps: { checked: false },\n customBadgeContent: 1,\n children: [\n {\n name: 'Updated',\n id: 'updated',\n checkProps: { checked: false },\n customBadgeContent: 0\n },\n {\n name: 'Waiting to update',\n id: 'waiting',\n checkProps: { checked: false },\n customBadgeContent: 0\n },\n {\n name: 'Conditions degraded',\n id: 'degraded',\n checkProps: { checked: false },\n customBadgeContent: 1\n },\n {\n name: 'Approval required',\n id: 'approval',\n checkProps: { checked: false },\n customBadgeContent: 0\n }\n ]\n },\n {\n name: 'Not ready',\n id: 'nr',\n checkProps: { checked: false },\n customBadgeContent: 1,\n children: [\n {\n name: 'Conditions degraded',\n id: 'nr-degraded',\n checkProps: { checked: false },\n customBadgeContent: 1\n }\n ]\n },\n {\n name: 'Updating',\n id: 'updating',\n checkProps: { checked: false },\n customBadgeContent: 0\n }\n ];\n\n const roleOptions = [\n {\n name: 'Server',\n id: 'server',\n checkProps: { checked: false },\n customBadgeContent: 2\n },\n {\n name: 'Worker',\n id: 'worker',\n checkProps: { checked: false },\n customBadgeContent: 0\n }\n ];\n // Helper functions for tree\n const isChecked = (dataItem: TreeViewDataItem) => checkedItems.some((item) => item.id === dataItem.id);\n const areAllDescendantsChecked = (dataItem: TreeViewDataItem) =>\n dataItem.children ? dataItem.children.every((child) => areAllDescendantsChecked(child)) : isChecked(dataItem);\n const areSomeDescendantsChecked = (dataItem: TreeViewDataItem) =>\n dataItem.children ? dataItem.children.some((child) => areSomeDescendantsChecked(child)) : isChecked(dataItem);\n const flattenTree = (tree: TreeViewDataItem[]) => {\n let result: TreeViewDataItem[] = [];\n tree.forEach((item) => {\n result.push(item);\n if (item.children) {\n result = result.concat(flattenTree(item.children));\n }\n });\n return result;\n };\n\n const mapTree = (item: TreeViewDataItem) => {\n const hasCheck = areAllDescendantsChecked(item);\n item.checkProps = item.checkProps || {};\n // Reset checked properties to be updated\n item.checkProps.checked = false;\n\n if (hasCheck) {\n item.checkProps.checked = true;\n } else {\n const hasPartialCheck = areSomeDescendantsChecked(item);\n if (hasPartialCheck) {\n item.checkProps.checked = null;\n }\n }\n\n if (item.children) {\n return {\n ...item,\n children: item.children.map(mapTree)\n };\n }\n return item;\n };\n\n const filterItems = (item: TreeViewDataItem, checkedItem: TreeViewDataItem) => {\n if (item.id === checkedItem.id) {\n return true;\n }\n\n if (item.children) {\n return (\n (item.children = item.children\n .map((opt) => Object.assign({}, opt))\n .filter((child) => filterItems(child, checkedItem))).length > 0\n );\n }\n };\n\n const onCheck = (evt: React.ChangeEvent, treeViewItem: TreeViewDataItem, treeType: string) => {\n const checked = (evt.target as HTMLInputElement).checked;\n\n let options: TreeViewDataItem[] = [];\n switch (treeType) {\n case 'status':\n options = statusOptions;\n break;\n case 'role':\n options = roleOptions;\n break;\n default:\n break;\n }\n\n const checkedItemTree = options\n .map((opt) => Object.assign({}, opt))\n .filter((item) => filterItems(item, treeViewItem));\n const flatCheckedItems = flattenTree(checkedItemTree);\n setCheckedItems((prevCheckedItems) =>\n checked\n ? prevCheckedItems.concat(flatCheckedItems.filter((item) => !prevCheckedItems.some((i) => i.id === item.id)))\n : prevCheckedItems.filter((item) => !flatCheckedItems.some((i) => i.id === item.id))\n );\n };\n\n const onToggleClick = () => {\n setIsOpen(!isOpen);\n };\n\n const toggle = (\n <MenuToggle ref={toggleRef} onClick={onToggleClick} isExpanded={isOpen}>\n {isOpen ? 'Expanded' : 'Collapsed'}\n </MenuToggle>\n );\n const statusMapped = statusOptions.map(mapTree);\n const roleMapped = roleOptions.map(mapTree);\n const menu = (\n <Panel\n ref={menuRef}\n variant=\"raised\"\n style={{\n width: '300px'\n }}\n >\n <PanelMain>\n <section>\n <PanelMainBody style={{ paddingBottom: 0 }}>\n <Title headingLevel=\"h1\" size={'md'}>\n Status\n </Title>\n </PanelMainBody>\n <PanelMainBody style={{ padding: 0 }}>\n <TreeView\n data={statusMapped}\n hasBadges\n hasCheckboxes\n onCheck={(event, item) => onCheck(event, item, 'status')}\n />\n </PanelMainBody>\n </section>\n <section>\n <PanelMainBody style={{ paddingBottom: 0, paddingTop: 0 }}>\n <Title headingLevel=\"h1\" size={'md'}>\n Roles\n </Title>\n </PanelMainBody>\n <PanelMainBody style={{ padding: 0 }}>\n <TreeView\n data={roleMapped}\n hasBadges\n hasCheckboxes\n onCheck={(event, item) => onCheck(event, item, 'role')}\n />\n </PanelMainBody>\n </section>\n </PanelMain>\n </Panel>\n );\n\n return (\n <MenuContainer\n isOpen={isOpen}\n onOpenChange={(isOpen) => setIsOpen(isOpen)}\n onOpenChangeKeys={['Escape']}\n menu={menu}\n menuRef={menuRef}\n toggle={toggle}\n toggleRef={toggleRef}\n />\n );\n};\n","title":"Tree view menu","lang":"ts","className":""}}>
|
|
90
|
+
|
|
91
|
+
<p {...{"className":"pf-v6-c-content--p pf-m-editorial ws-p "}}>
|
|
92
|
+
{`When rendering a menu-like element that does not contain `}
|
|
93
|
+
|
|
94
|
+
<code {...{"className":"ws-code "}}>
|
|
95
|
+
{`<MenuItem>`}
|
|
96
|
+
</code>
|
|
97
|
+
{` components, `}
|
|
98
|
+
|
|
99
|
+
<PatternflyThemeLink {...{"to":"/components/panel","className":""}}>
|
|
100
|
+
{`panel`}
|
|
101
|
+
</PatternflyThemeLink>
|
|
102
|
+
{` allows more flexible control and customization.`}
|
|
103
|
+
</p>
|
|
104
|
+
</Example>,
|
|
105
|
+
'Flyout menu': props =>
|
|
106
|
+
<Example {...pageData} {...props} {...{"code":"import { useRef, useState } from 'react';\nimport { MenuToggle, Menu, MenuContent, MenuList, MenuItem, MenuContainer } from '@patternfly/react-core';\n\n/* eslint-disable no-console */\nconst onSelect = (event: React.MouseEvent | undefined, itemId: string | number | undefined) =>\n console.log('selected', itemId);\n/* eslint-enable no-console */\ninterface FlyoutMenuProps {\n children?: React.ReactElement<any>;\n depth: number;\n}\n\nconst FlyoutMenu: React.FunctionComponent<FlyoutMenuProps> = ({ depth, children }: FlyoutMenuProps) => (\n <Menu key={depth} containsFlyout id={`menu-${depth}`} onSelect={onSelect}>\n <MenuContent>\n <MenuList>\n <MenuItem flyoutMenu={children} itemId={`next-menu-${depth}`}>\n Next menu\n </MenuItem>\n {Array.from(new Array(15 - depth), (x, i) => i + 1).map((j) => (\n <MenuItem key={`${depth}-${j}`} itemId={`${depth}-${j}`}>\n Menu {depth} item {j}\n </MenuItem>\n ))}\n <MenuItem flyoutMenu={children} itemId={`next-menu-2-${depth}`}>\n Next menu\n </MenuItem>\n </MenuList>\n </MenuContent>\n </Menu>\n);\n\nexport const FlyoutDemo: React.FunctionComponent = () => {\n const [isOpen, setIsOpen] = useState<boolean>(false);\n const menuRef = useRef<HTMLDivElement>(null);\n const toggleRef = useRef<HTMLButtonElement>(null);\n\n let curFlyout = <FlyoutMenu depth={1} />;\n for (let i = 2; i < 14; i++) {\n curFlyout = <FlyoutMenu depth={i}>{curFlyout}</FlyoutMenu>;\n }\n\n const onToggleClick = () => {\n setIsOpen(!isOpen);\n };\n\n const toggle = (\n <MenuToggle ref={toggleRef} onClick={onToggleClick} isExpanded={isOpen}>\n {isOpen ? 'Expanded' : 'Collapsed'}\n </MenuToggle>\n );\n\n const menu = (\n <Menu ref={menuRef} containsFlyout onSelect={onSelect}>\n <MenuContent>\n <MenuList>\n <MenuItem itemId=\"start\">Start rollout</MenuItem>\n <MenuItem itemId=\"pause\">Pause rollouts</MenuItem>\n <MenuItem itemId=\"storage\">Add storage</MenuItem>\n <MenuItem description=\"Description\" flyoutMenu={curFlyout} itemId=\"next-menu-root\">\n Edit\n </MenuItem>\n <MenuItem itemId=\"delete\">Delete deployment config</MenuItem>\n </MenuList>\n </MenuContent>\n </Menu>\n );\n\n return (\n <MenuContainer\n isOpen={isOpen}\n onOpenChange={(isOpen) => setIsOpen(isOpen)}\n menu={menu}\n menuRef={menuRef}\n toggle={toggle}\n toggleRef={toggleRef}\n />\n );\n};\n","title":"Flyout menu","lang":"ts","className":""}}>
|
|
107
|
+
|
|
108
|
+
<p {...{"className":"pf-v6-c-content--p pf-m-editorial ws-p "}}>
|
|
109
|
+
{`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, `}
|
|
110
|
+
|
|
111
|
+
<PatternflyThemeLink {...{"to":"/components/popover","className":""}}>
|
|
112
|
+
{`popover`}
|
|
113
|
+
</PatternflyThemeLink>
|
|
114
|
+
{` or `}
|
|
115
|
+
|
|
116
|
+
<PatternflyThemeLink {...{"to":"/components/tooltip","className":""}}>
|
|
117
|
+
{`tooltip`}
|
|
118
|
+
</PatternflyThemeLink>
|
|
119
|
+
{`, since it may go over the side nav.`}
|
|
120
|
+
</p>
|
|
121
|
+
</Example>,
|
|
122
|
+
'Application launcher menu': props =>
|
|
123
|
+
<Example {...pageData} {...props} {...{"code":"import { cloneElement, Fragment, useRef, useState } from 'react';\nimport {\n MenuToggle,\n MenuSearch,\n MenuSearchInput,\n Tooltip,\n Divider,\n SearchInput,\n Dropdown,\n DropdownGroup,\n DropdownList,\n DropdownItem\n} from '@patternfly/react-core';\nimport RhUiThumbnailViewSmallFillIcon from '@patternfly/react-icons/dist/js/icons/rh-ui-thumbnail-view-small-fill-icon';\nimport brandImg from '@patternfly/react-core/src/demos/assets/PF-IconLogo.svg';\n\nconst MockLink: React.FunctionComponent = ({ to, ...props }: any) => <a href={to} {...props}></a>;\n\nexport const ApplicationLauncherDemo: React.FunctionComponent = () => {\n const [isOpen, setIsOpen] = useState<boolean>(false);\n const [refFullOptions, setRefFullOptions] = useState<Element[]>();\n const [favorites, setFavorites] = useState<string[]>([]);\n const [filteredIds, setFilteredIds] = useState<string[]>(['*']);\n const menuRef = useRef<HTMLDivElement>(null);\n\n const onToggleClick = () => {\n setTimeout(() => {\n if (menuRef.current) {\n const firstElement = menuRef.current.querySelector(\n 'li > button:not(:disabled), li > a:not(:disabled), input:not(:disabled)'\n );\n firstElement && (firstElement as HTMLElement).focus();\n setRefFullOptions(Array.from(menuRef.current.querySelectorAll('li:not(li[role=separator])>*:first-child')));\n }\n }, 0);\n setIsOpen(!isOpen);\n };\n\n const menuItems = [\n <DropdownGroup key=\"group1\" label=\"Group 1\">\n <DropdownList>\n <DropdownItem value=\"0\" id=\"0\" isFavorited={favorites.includes('0')}>\n Application 1\n </DropdownItem>\n <DropdownItem\n value=\"1\"\n id=\"1\"\n isFavorited={favorites.includes('1')}\n to=\"#default-link2\"\n onClick={(ev) => ev.preventDefault()}\n >\n Application 2\n </DropdownItem>\n </DropdownList>\n </DropdownGroup>,\n <Divider key=\"group1-divider\" />,\n <DropdownGroup key=\"group2\" label=\"Group 2\">\n <DropdownList>\n <DropdownItem\n value=\"2\"\n id=\"2\"\n isFavorited={favorites.includes('2')}\n component={(props) => <MockLink {...props} to=\"#router-link\" />}\n >\n Custom component (such as @reach/router Link)\n </DropdownItem>\n <DropdownItem\n value=\"3\"\n id=\"3\"\n isFavorited={favorites.includes('3')}\n isExternalLink\n icon={<img src={brandImg} alt=\"\" width={25} height={25} />}\n component={(props) => <MockLink {...props} to=\"#router-link2\" />}\n >\n Custom component with icon\n </DropdownItem>\n </DropdownList>\n </DropdownGroup>,\n <Divider key=\"group2-divider\" />,\n <DropdownList key=\"other-items\">\n <DropdownItem key=\"tooltip-app\" isFavorited={favorites.includes('4')} value=\"4\" id=\"4\">\n <Tooltip content={<div>Launch Application 3</div>} position=\"right\">\n <span>Application 3 with tooltip</span>\n </Tooltip>\n </DropdownItem>\n <DropdownItem key=\"disabled-app\" value=\"5\" id=\"5\" isDisabled>\n Unavailable Application\n </DropdownItem>\n </DropdownList>\n ];\n\n const createFavorites = (favIds: string[]) => {\n const favorites: unknown[] = [];\n\n menuItems.forEach((item) => {\n if (item.type === DropdownList) {\n item.props.children.filter((child) => {\n if (favIds.includes(child.props.value)) {\n favorites.push(child);\n }\n });\n } else if (item.type === DropdownGroup) {\n item.props.children.props.children.filter((child) => {\n if (favIds.includes(child.props.value)) {\n favorites.push(child);\n }\n });\n } else {\n if (favIds.includes(item.props.value)) {\n favorites.push(item);\n }\n }\n });\n\n return favorites;\n };\n\n const filterItems = (items: any[], filteredIds: string[]) => {\n if (filteredIds.length === 1 && filteredIds[0] === '*') {\n return items;\n }\n let keepDivider = false;\n const filteredCopy = items\n .map((group) => {\n if (group.type === DropdownGroup) {\n const filteredGroup = cloneElement(group, {\n children: cloneElement(group.props.children, {\n children: group.props.children.props.children.filter((child) => {\n if (filteredIds.includes(child.props.value)) {\n return child;\n }\n })\n })\n });\n const filteredList = filteredGroup.props.children;\n if (filteredList.props.children.length > 0) {\n keepDivider = true;\n return filteredGroup;\n } else {\n keepDivider = false;\n }\n } else if (group.type === DropdownList) {\n const filteredGroup = cloneElement(group, {\n children: group.props.children.filter((child) => {\n if (filteredIds.includes(child.props.value)) {\n return child;\n }\n })\n });\n if (filteredGroup.props.children.length > 0) {\n keepDivider = true;\n return filteredGroup;\n } else {\n keepDivider = false;\n }\n } else {\n if ((keepDivider && group.type === Divider) || filteredIds.includes(group.props.value)) {\n return group;\n }\n }\n })\n .filter((newGroup) => newGroup);\n\n if (filteredCopy.length > 0) {\n const lastGroup = filteredCopy.pop();\n if (lastGroup.type !== Divider) {\n filteredCopy.push(lastGroup);\n }\n }\n\n return filteredCopy;\n };\n\n const onTextChange = (textValue: string) => {\n if (textValue === '') {\n setFilteredIds(['*']);\n return;\n }\n\n const filteredIds =\n refFullOptions\n ?.filter((item) => (item as HTMLElement).innerText.toLowerCase().includes(textValue.toString().toLowerCase()))\n .map((item) => item.id) || [];\n setFilteredIds(filteredIds);\n };\n\n const onFavorite = (event: any, value: string, actionId: string) => {\n event.stopPropagation();\n if (actionId === 'fav') {\n const isFavorite = favorites.includes(value);\n if (isFavorite) {\n setFavorites(favorites.filter((fav) => fav !== value));\n } else {\n setFavorites([...favorites, value]);\n }\n }\n };\n\n const filteredFavorites = filterItems(createFavorites(favorites), filteredIds);\n const filteredItems = filterItems(menuItems, filteredIds);\n if (filteredItems.length === 0) {\n filteredItems.push(<DropdownItem key=\"no-items\">No results found</DropdownItem>);\n }\n\n return (\n <Dropdown\n isOpen={isOpen}\n onOpenChange={(isOpen) => setIsOpen(isOpen)}\n onOpenChangeKeys={['Escape']}\n toggle={(toggleRef) => (\n <MenuToggle\n aria-label=\"Toggle\"\n ref={toggleRef}\n variant=\"plain\"\n onClick={onToggleClick}\n isExpanded={isOpen}\n style={{ width: 'auto' }}\n icon={<RhUiThumbnailViewSmallFillIcon />}\n />\n )}\n ref={menuRef}\n onActionClick={onFavorite}\n // eslint-disable-next-line no-console\n onSelect={(_ev, value) => console.log('selected', value)}\n >\n <MenuSearch>\n <MenuSearchInput>\n <SearchInput aria-label=\"Filter menu items\" onChange={(_event, value) => onTextChange(value)} />\n </MenuSearchInput>\n </MenuSearch>\n <Divider />\n {filteredFavorites.length > 0 && (\n <Fragment>\n <DropdownGroup key=\"favorites-group\" label=\"Favorites\">\n <DropdownList>{filteredFavorites}</DropdownList>\n </DropdownGroup>\n <Divider key=\"favorites-divider\" />\n </Fragment>\n )}\n {filteredItems}\n </Dropdown>\n );\n};\n","title":"Application launcher menu","lang":"ts","className":""}}>
|
|
124
|
+
|
|
125
|
+
</Example>,
|
|
126
|
+
'Context selector menu': props =>
|
|
127
|
+
<Example {...pageData} {...props} {...{"code":"import { useRef, useState } from 'react';\nimport {\n MenuToggle,\n MenuFooter,\n MenuSearch,\n MenuSearchInput,\n Divider,\n InputGroup,\n InputGroupItem,\n Button,\n ButtonVariant,\n SearchInput,\n Dropdown,\n DropdownList,\n DropdownItem\n} from '@patternfly/react-core';\nimport SearchIcon from '@patternfly/react-icons/dist/esm/icons/search-icon';\n\ninterface ItemData {\n text: string;\n href?: string;\n isDisabled?: boolean | undefined;\n}\n\ntype ItemArrayType = (ItemData | string)[];\n\nexport const ContextSelectorDemo: React.FunctionComponent = () => {\n const items: ItemArrayType = [\n {\n text: 'Action'\n },\n {\n text: 'Link',\n href: '#'\n },\n {\n text: 'Disabled action',\n isDisabled: true\n },\n {\n text: 'Disabled link',\n href: '#',\n isDisabled: true\n },\n 'My project',\n 'OpenShift cluster',\n 'Production Ansible',\n 'AWS',\n 'Azure',\n 'My project 2',\n 'OpenShift cluster ',\n 'Production Ansible 2 ',\n 'AWS 2',\n 'Azure 2'\n ];\n const [isOpen, setIsOpen] = useState<boolean>(false);\n const [selected, setSelected] = useState(typeof items[0] === 'string' ? items[0] : items[0].text);\n const [filteredItems, setFilteredItems] = useState<ItemArrayType>(items);\n const [searchInputValue, setSearchInputValue] = useState<string>('');\n const menuRef = useRef<HTMLDivElement>(null);\n const menuFooterBtnRef = useRef<HTMLButtonElement>(null);\n\n const onToggleClick = () => {\n setIsOpen(!isOpen);\n };\n\n const onSelect = (ev: React.MouseEvent<Element, MouseEvent> | undefined, itemId: string | number | undefined) => {\n if (typeof itemId === 'number' || typeof itemId === 'undefined') {\n return;\n }\n setSelected(itemId.toString());\n setIsOpen(!isOpen);\n };\n\n const onSearchInputChange = (value: string) => {\n setSearchInputValue(value);\n };\n\n const onSearchButtonClick = () => {\n const filtered =\n searchInputValue === ''\n ? items\n : items.filter((item) => {\n const str = typeof item === 'string' ? item : item.text;\n return str.toLowerCase().indexOf(searchInputValue.toLowerCase()) !== -1;\n });\n\n setFilteredItems(filtered || []);\n setIsOpen(true); // Keep menu open after search executed\n };\n\n const onEnterPressed = (event: React.KeyboardEvent) => {\n if (event.key === 'Enter') {\n onSearchButtonClick();\n }\n };\n\n return (\n <Dropdown\n isOpen={isOpen}\n onOpenChange={(isOpen) => setIsOpen(isOpen)}\n onOpenChangeKeys={['Escape']}\n toggle={(toggleRef) => (\n <MenuToggle ref={toggleRef} onClick={onToggleClick} isExpanded={isOpen}>\n {selected}\n </MenuToggle>\n )}\n ref={menuRef}\n id=\"context-selector\"\n onSelect={onSelect}\n isScrollable\n >\n <MenuSearch>\n <MenuSearchInput>\n <InputGroup>\n <InputGroupItem isFill>\n <SearchInput\n value={searchInputValue}\n placeholder=\"Search\"\n onChange={(_event, value) => onSearchInputChange(value)}\n onKeyPress={onEnterPressed}\n aria-labelledby=\"pf-v6-context-selector-search-button-id-1\"\n />\n </InputGroupItem>\n <InputGroupItem>\n <Button\n variant={ButtonVariant.control}\n aria-label=\"Search menu items\"\n id=\"pf-v6-context-selector-search-button-id-1\"\n onClick={onSearchButtonClick}\n icon={<SearchIcon />}\n />\n </InputGroupItem>\n </InputGroup>\n </MenuSearchInput>\n </MenuSearch>\n <Divider />\n <DropdownList>\n {filteredItems.map((item, index) => {\n const [itemText, isDisabled, href] =\n typeof item === 'string' ? [item, null, null] : [item.text, item.isDisabled || null, item.href || null];\n return (\n <DropdownItem\n itemId={itemText}\n key={index}\n isDisabled={isDisabled as boolean | undefined}\n to={href as string | undefined}\n >\n {itemText}\n </DropdownItem>\n );\n })}\n </DropdownList>\n <MenuFooter>\n <Button ref={menuFooterBtnRef} variant=\"link\" isInline>\n Action\n </Button>\n </MenuFooter>\n </Dropdown>\n );\n};\n","title":"Context selector menu","lang":"ts","className":""}}>
|
|
128
|
+
|
|
129
|
+
</Example>,
|
|
130
|
+
'Date select menu': props =>
|
|
131
|
+
<Example {...pageData} {...props} {...{"code":"import { useRef, useState } from 'react';\nimport { MenuToggle, Select, SelectList, SelectOption, Timestamp } from '@patternfly/react-core';\n\nexport const DateSelectDemo: React.FunctionComponent = () => {\n const [isOpen, setIsOpen] = useState(false);\n const [selected, setSelected] = useState<number>(0);\n const menuRef = useRef<HTMLDivElement>(undefined);\n\n const onToggleClick = () => {\n setIsOpen(!isOpen);\n };\n\n const monthStrings = [\n 'January',\n 'February',\n 'March',\n 'April',\n 'May',\n 'June',\n 'July',\n 'August',\n 'September',\n 'October',\n 'November',\n 'December'\n ];\n\n const dateString = (date: Date) => `${monthStrings[date.getMonth()]} ${date.getDate()}, ${date.getFullYear()}`;\n\n const date = new Date();\n\n const toggleText = {\n 0: 'Today ',\n 1: 'Yesterday ',\n 2: 'Last 7 days ',\n 3: 'Last 14 days '\n };\n\n const getDateNDaysBefore = (date: Date, days: number) => new Date(new Date().setDate(date.getDate() - days));\n\n const dates = {\n 0: date,\n 1: getDateNDaysBefore(date, 1),\n 2: getDateNDaysBefore(date, 7),\n 3: getDateNDaysBefore(date, 14)\n };\n\n const dateText = {\n 0: <Timestamp date={dates[0]}>({dateString(dates[0])})</Timestamp>,\n 1: <Timestamp date={dates[1]}>({dateString(dates[1])})</Timestamp>,\n 2: (\n <>\n <Timestamp date={dates[2]}>\n ({dateString(dates[2])}\n - \n </Timestamp>\n <Timestamp date={date}>{dateString(date)})</Timestamp>\n </>\n ),\n 3: (\n <>\n <Timestamp date={dates[3]}>\n ({dateString(dates[3])}\n - \n </Timestamp>\n <Timestamp date={date}>{dateString(date)})</Timestamp>\n </>\n )\n };\n\n return (\n <Select\n isOpen={isOpen}\n onOpenChange={(isOpen) => setIsOpen(isOpen)}\n toggle={(toggleRef) => (\n <MenuToggle ref={toggleRef} onClick={onToggleClick} isExpanded={isOpen} style={{ minWidth: '250px' }}>\n <span style={{ verticalAlign: 'middle', marginRight: '8px' }}>{toggleText[selected]}</span>\n {dateText[selected]}\n </MenuToggle>\n )}\n ref={menuRef}\n onSelect={(_ev, value) => {\n setSelected(value as number);\n setIsOpen(false);\n }}\n selected={selected}\n >\n <SelectList>\n <SelectOption value={0}>Today</SelectOption>\n <SelectOption value={1}>Yesterday</SelectOption>\n <SelectOption value={2}>Last 7 days</SelectOption>\n <SelectOption value={3}>Last 14 days</SelectOption>\n </SelectList>\n </Select>\n );\n};\n","title":"Date select menu","lang":"ts","className":""}}>
|
|
132
|
+
|
|
133
|
+
</Example>
|
|
134
|
+
};
|
|
135
|
+
|
|
136
|
+
const Component = () => (
|
|
137
|
+
<React.Fragment>
|
|
138
|
+
<AutoLinkHeader {...{"id":"examples","headingLevel":"h2","className":"ws-title ws-h2"}}>
|
|
139
|
+
{`Examples`}
|
|
140
|
+
</AutoLinkHeader>
|
|
141
|
+
<p {...{"className":"pf-v6-c-content--p pf-m-editorial ws-p "}}>
|
|
142
|
+
{`Custom menus can be constructed using a composable approach by combining the `}
|
|
143
|
+
<PatternflyThemeLink {...{"to":"/components/menus/menu","className":""}}>
|
|
144
|
+
{`menu`}
|
|
145
|
+
</PatternflyThemeLink>
|
|
146
|
+
{` and `}
|
|
147
|
+
<PatternflyThemeLink {...{"to":"/components/menus/menu-toggle","className":""}}>
|
|
148
|
+
{`menu toggle`}
|
|
149
|
+
</PatternflyThemeLink>
|
|
150
|
+
{` components in unique ways. To handle basic keyboard inputs, `}
|
|
151
|
+
<PatternflyThemeLink {...{"to":"/components/menus/dropdown","className":""}}>
|
|
152
|
+
{`dropdown`}
|
|
153
|
+
</PatternflyThemeLink>
|
|
154
|
+
{`, `}
|
|
155
|
+
<PatternflyThemeLink {...{"to":"/components/menus/select","className":""}}>
|
|
156
|
+
{`select`}
|
|
157
|
+
</PatternflyThemeLink>
|
|
158
|
+
{`, or `}
|
|
159
|
+
<PatternflyThemeLink {...{"to":"/components/menus/menu#menucontainer","className":""}}>
|
|
160
|
+
<code {...{"className":"ws-code "}}>
|
|
161
|
+
{`<MenuContainer>`}
|
|
162
|
+
</code>
|
|
163
|
+
</PatternflyThemeLink>
|
|
164
|
+
{` components may be used in combination with menu components.`}
|
|
165
|
+
</p>
|
|
166
|
+
<p {...{"className":"pf-v6-c-content--p pf-m-editorial ws-p "}}>
|
|
167
|
+
{`Additionally, menu components may be connected to each other manually through our undocumented internal `}
|
|
168
|
+
<PatternflyThemeLink {...{"to":"https://popper.js.org/","className":""}}>
|
|
169
|
+
{`popper.js`}
|
|
170
|
+
</PatternflyThemeLink>
|
|
171
|
+
{` wrapper component called Popper.`}
|
|
172
|
+
</p>
|
|
173
|
+
{React.createElement(pageData.examples["With actions"])}
|
|
174
|
+
{React.createElement(pageData.examples["With favorites"])}
|
|
175
|
+
{React.createElement(pageData.examples["With drilldown"])}
|
|
176
|
+
{React.createElement(pageData.examples["With inline search filter"])}
|
|
177
|
+
{React.createElement(pageData.examples["Tree view menu"])}
|
|
178
|
+
{React.createElement(pageData.examples["Flyout menu"])}
|
|
179
|
+
{React.createElement(pageData.examples["Application launcher menu"])}
|
|
180
|
+
{React.createElement(pageData.examples["Context selector menu"])}
|
|
181
|
+
{React.createElement(pageData.examples["Date select menu"])}
|
|
182
|
+
</React.Fragment>
|
|
183
|
+
);
|
|
184
|
+
Component.displayName = 'ComponentsMenusCustomMenusReactDemosDocs';
|
|
185
|
+
Component.pageData = pageData;
|
|
186
|
+
|
|
187
|
+
export default Component;
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { AutoLinkHeader, Example, Link as PatternflyThemeLink } from '@patternfly/documentation-framework/components';
|
|
3
|
+
import { Fragment, useState, FunctionComponent } from 'react';
|
|
4
|
+
import { Checkbox, Flex, FlexItem } from '@patternfly/react-core';
|
|
5
|
+
import { SimpleDropdown } from '@patternfly/react-templates';
|
|
6
|
+
import RhUiEllipsisVerticalFillIcon from '@patternfly/react-icons/dist/esm/icons/rh-ui-ellipsis-vertical-fill-icon';
|
|
7
|
+
const pageData = {
|
|
8
|
+
"id": "Dropdown",
|
|
9
|
+
"section": "components",
|
|
10
|
+
"subsection": "menus",
|
|
11
|
+
"deprecated": false,
|
|
12
|
+
"template": true,
|
|
13
|
+
"beta": true,
|
|
14
|
+
"demo": false,
|
|
15
|
+
"newImplementationLink": false,
|
|
16
|
+
"source": "react-templates",
|
|
17
|
+
"tabName": null,
|
|
18
|
+
"slug": "/components/menus/dropdown/react-templates",
|
|
19
|
+
"sourceLink": "https://github.com/patternfly/patternfly-react/blob/main/packages/react-templates/src/components/Dropdown/examples/DropdownTemplates.md",
|
|
20
|
+
"relPath": "packages/react-templates/src/components/Dropdown/examples/DropdownTemplates.md",
|
|
21
|
+
"propComponents": [
|
|
22
|
+
{
|
|
23
|
+
"name": "SimpleDropdown",
|
|
24
|
+
"description": "",
|
|
25
|
+
"props": [
|
|
26
|
+
{
|
|
27
|
+
"name": "initialItems",
|
|
28
|
+
"type": "SimpleDropdownItem[]",
|
|
29
|
+
"description": "Initial items of the dropdown."
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
"name": "isDisabled",
|
|
33
|
+
"type": "boolean",
|
|
34
|
+
"description": "Flag indicating the dropdown should be disabled."
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
"name": "isToggleFullWidth",
|
|
38
|
+
"type": "boolean",
|
|
39
|
+
"description": "Flag indicated whether the dropdown toggle should take up the full width of its parent."
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
"name": "onSelect",
|
|
43
|
+
"type": "(event?: React.MouseEvent<Element, MouseEvent>, value?: SimpleDropdownItem['value']) => void",
|
|
44
|
+
"description": "Callback triggered when any dropdown item is clicked."
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
"name": "onToggle",
|
|
48
|
+
"type": "(nextIsOpen: boolean) => void",
|
|
49
|
+
"description": "Callback triggered when the dropdown toggle opens or closes."
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
"name": "shouldFocusToggleOnSelect",
|
|
53
|
+
"type": "boolean",
|
|
54
|
+
"description": "Flag indicating the dropdown toggle should be focused after a dropdown item is clicked."
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
"name": "toggleAriaLabel",
|
|
58
|
+
"type": "string",
|
|
59
|
+
"description": "Adds an accessible name to the dropdown toggle. Required when the dropdown toggle does not\nhave any text content."
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
"name": "toggleContent",
|
|
63
|
+
"type": "React.ReactNode",
|
|
64
|
+
"description": "Content of the toggle.",
|
|
65
|
+
"required": true
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
"name": "toggleProps",
|
|
69
|
+
"type": "MenuToggleProps",
|
|
70
|
+
"description": "Additional props passed to the toggle."
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
"name": "toggleVariant",
|
|
74
|
+
"type": "'default' | 'plain' | 'plainText'",
|
|
75
|
+
"description": "Variant style of the dropdown toggle."
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
"name": "toggleWidth",
|
|
79
|
+
"type": "string",
|
|
80
|
+
"description": "Width of the toggle."
|
|
81
|
+
}
|
|
82
|
+
]
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
"name": "SimpleDropdownItem",
|
|
86
|
+
"description": "",
|
|
87
|
+
"props": [
|
|
88
|
+
{
|
|
89
|
+
"name": "content",
|
|
90
|
+
"type": "React.ReactNode",
|
|
91
|
+
"description": "Content of the dropdown item. If the isDivider prop is true, this prop will be ignored."
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
"name": "isDivider",
|
|
95
|
+
"type": "boolean",
|
|
96
|
+
"description": "Flag indicating whether the dropdown item should render as a divider. If true, the item will be rendered without\nthe dropdown item wrapper."
|
|
97
|
+
},
|
|
98
|
+
{
|
|
99
|
+
"name": "onClick",
|
|
100
|
+
"type": "(event?: any) => void",
|
|
101
|
+
"description": "Callback for when the dropdown item is clicked."
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
"name": "to",
|
|
105
|
+
"type": "string",
|
|
106
|
+
"description": "URL to redirect to when the dropdown item is clicked."
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
"name": "value",
|
|
110
|
+
"type": "string | number",
|
|
111
|
+
"description": "Unique identifier for the dropdown item, which is used in the dropdown onSelect callback",
|
|
112
|
+
"required": true
|
|
113
|
+
}
|
|
114
|
+
]
|
|
115
|
+
}
|
|
116
|
+
],
|
|
117
|
+
"examples": [
|
|
118
|
+
"Simple"
|
|
119
|
+
]
|
|
120
|
+
};
|
|
121
|
+
pageData.liveContext = {
|
|
122
|
+
Fragment,
|
|
123
|
+
useState,
|
|
124
|
+
FunctionComponent,
|
|
125
|
+
Checkbox,
|
|
126
|
+
Flex,
|
|
127
|
+
FlexItem,
|
|
128
|
+
SimpleDropdown,
|
|
129
|
+
RhUiEllipsisVerticalFillIcon
|
|
130
|
+
};
|
|
131
|
+
pageData.examples = {
|
|
132
|
+
'Simple': props =>
|
|
133
|
+
<Example {...pageData} {...props} {...{"code":"import { Fragment, useState, FunctionComponent } from 'react';\nimport { Checkbox, Flex, FlexItem } from '@patternfly/react-core';\nimport { SimpleDropdown, SimpleDropdownItem } from '@patternfly/react-templates';\nimport RhUiEllipsisVerticalFillIcon from '@patternfly/react-icons/dist/esm/icons/rh-ui-ellipsis-vertical-fill-icon';\n\nexport const SimpleDropdownExample: FunctionComponent = () => {\n const [isDisabled, setIsDisabled] = useState(false);\n\n const items: SimpleDropdownItem[] = [\n // eslint-disable-next-line no-console\n { content: 'Action', value: 1, onClick: () => console.log('Action clicked') },\n // Prevent default click behavior on link for example purposes\n { content: 'Link', value: 2, to: '#', onClick: (event: any) => event.preventDefault() },\n { content: 'Disabled Action', value: 3, isDisabled: true },\n { value: 'separator', isDivider: true },\n // eslint-disable-next-line no-console\n { content: 'Second action', value: 4, onClick: () => console.log('Second action clicked') }\n ];\n\n return (\n <Fragment>\n <Checkbox\n id=\"simple-example-disabled-toggle\"\n label=\"Disable simple dropdown toggles\"\n isChecked={isDisabled}\n onChange={(_event: React.FormEvent<HTMLInputElement>, checked: boolean) => setIsDisabled(checked)}\n style={{ marginBottom: 20 }}\n />\n <Flex gap={{ default: 'gapLg' }}>\n <FlexItem>\n <SimpleDropdown initialItems={items} isDisabled={isDisabled} toggleContent=\"Dropdown\" />\n </FlexItem>\n <FlexItem>\n <SimpleDropdown\n toggleVariant=\"plainText\"\n initialItems={items}\n isDisabled={isDisabled}\n toggleContent=\"Dropdown with plainText styling\"\n />\n </FlexItem>\n <FlexItem>\n <SimpleDropdown\n toggleVariant=\"plain\"\n initialItems={items}\n isDisabled={isDisabled}\n toggleContent={<RhUiEllipsisVerticalFillIcon />}\n toggleAriaLabel=\"Plain dropdown toggle\"\n />\n </FlexItem>\n </Flex>\n </Fragment>\n );\n};\n","title":"Simple","lang":"ts","className":""}}>
|
|
134
|
+
|
|
135
|
+
</Example>
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
const Component = () => (
|
|
139
|
+
<React.Fragment>
|
|
140
|
+
<p {...{"className":"pf-v6-c-content--p pf-m-editorial ws-p "}}>
|
|
141
|
+
{`Note: Templates live in their own package at `}
|
|
142
|
+
<PatternflyThemeLink {...{"to":"https://www.npmjs.com/package/@patternfly/react-templates","className":""}}>
|
|
143
|
+
{`@patternfly/react-templates`}
|
|
144
|
+
</PatternflyThemeLink>
|
|
145
|
+
{`!`}
|
|
146
|
+
</p>
|
|
147
|
+
<p {...{"className":"pf-v6-c-content--p pf-m-editorial ws-p "}}>
|
|
148
|
+
{`For custom use cases, please see the dropdown component suite from `}
|
|
149
|
+
<PatternflyThemeLink {...{"to":"https://www.npmjs.com/package/@patternfly/react-core","className":""}}>
|
|
150
|
+
{`@patternfly/react-core`}
|
|
151
|
+
</PatternflyThemeLink>
|
|
152
|
+
{`.`}
|
|
153
|
+
</p>
|
|
154
|
+
<AutoLinkHeader {...{"id":"examples","headingLevel":"h2","className":"ws-title ws-h2"}}>
|
|
155
|
+
{`Examples`}
|
|
156
|
+
</AutoLinkHeader>
|
|
157
|
+
{React.createElement(pageData.examples["Simple"])}
|
|
158
|
+
</React.Fragment>
|
|
159
|
+
);
|
|
160
|
+
Component.displayName = 'ComponentsMenusDropdownReactTemplatesDocs';
|
|
161
|
+
Component.pageData = pageData;
|
|
162
|
+
|
|
163
|
+
export default Component;
|