@patternfly/react-docs 5.22.6 → 5.22.7
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 +8 -0
- package/package.json +11 -11
- package/src/generated/components/back-to-top/react-demos/using-name-selector.png +0 -0
- package/src/generated/components/backdrop/react/basic.png +0 -0
- package/src/generated/components/backdrop/react/with-spinner.png +0 -0
- package/src/generated/components/background-image/react/basic.png +0 -0
- package/src/generated/components/banner/react-demos/basic-sticky-banner.png +0 -0
- package/src/generated/components/banner/react-demos/top-and-bottom-banner.png +0 -0
- package/src/generated/components/drawer/react.js +0 -2
- package/src/generated/components/jump-links/react-demos/scrollspy-with-subsections.png +0 -0
- package/src/generated/components/login-page/react/basic.png +0 -0
- package/src/generated/components/login-page/react/showhide-password.png +0 -0
- package/src/generated/components/navigation/react-demos/default-nav.png +0 -0
- package/src/generated/components/navigation/react-demos/expandable-nav.png +0 -0
- package/src/generated/components/navigation/react-demos/grouped-nav.png +0 -0
- package/src/generated/components/navigation/react-demos/horizontal-nav-with-horizontal-subnav.png +0 -0
- package/src/generated/components/navigation/react-demos/horizontal-nav.png +0 -0
- package/src/generated/components/navigation/react-demos/horizontal-subnav.png +0 -0
- package/src/generated/components/navigation/react-demos/legacy-tertiary-nav.png +0 -0
- package/src/generated/components/navigation/react-demos/legacylight-nav.png +0 -0
- package/src/generated/components/navigation/react-demos/manual-nav.png +0 -0
- package/src/generated/components/notification-drawer/react-demos/basic.png +0 -0
- package/src/generated/components/notification-drawer/react-demos/grouped.png +0 -0
- package/src/generated/components/page/react-demos/sticky-section-group-alternate-syntax-and-using-pageheader.png +0 -0
- package/src/generated/components/page/react-demos/sticky-section-group-using-pageheader.png +0 -0
- package/src/generated/components/page/react-demos/sticky-section-group.png +0 -0
- package/src/generated/components/page/react-demos.js +27 -7
- package/src/generated/components/page/react.js +21 -9
- package/src/generated/components/pagination/react/sticky.png +0 -0
- package/src/generated/components/select/react.js +6 -0
- package/src/generated/components/skip-to-content/react/basic.png +0 -0
- package/src/generated/components/table/react-demos/sticky-header.png +0 -0
- package/src/generated/components/tabs/react.js +43 -0
- package/src/generated/components/toolbar/react-demos/console-log-viewer-toolbar-demo.png +0 -0
- package/src/generated/components/wizard/react-demos/in-modal.png +0 -0
- package/src/generated/components/wizard/react-demos/in-page.png +0 -0
- package/src/generated/demos/card-view/react-demos/card-view.png +0 -0
- package/src/generated/demos/composable-menu/react-demos.js +15 -9
- package/src/generated/demos/primary-detail/react-demos/primary-detail-card-view.png +0 -0
- package/src/generated/demos/primary-detail/react-demos/primary-detail-content-padding.png +0 -0
- package/src/generated/demos/primary-detail/react-demos/primary-detail-data-list-in-card.png +0 -0
- package/src/generated/demos/primary-detail/react-demos/primary-detail-full-page.png +0 -0
- package/src/generated/demos/primary-detail/react-demos/primary-detail-inline-modifier.png +0 -0
- package/src/generated/demos/primary-detail/react-demos/primary-detail-simple-list-in-card.png +0 -0
- package/src/generated/index.js +10 -10
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,14 @@
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
5
|
|
|
6
|
+
## [5.22.7](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-docs@5.22.6...@patternfly/react-docs@5.22.7) (2021-10-05)
|
|
7
|
+
|
|
8
|
+
**Note:** Version bump only for package @patternfly/react-docs
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
|
|
6
14
|
## [5.22.6](https://github.com/patternfly/patternfly-react/compare/@patternfly/react-docs@5.22.5...@patternfly/react-docs@5.22.6) (2021-10-05)
|
|
7
15
|
|
|
8
16
|
**Note:** Version bump only for package @patternfly/react-docs
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@patternfly/react-docs",
|
|
3
3
|
"description": "PatternFly React Docs",
|
|
4
|
-
"version": "5.22.
|
|
4
|
+
"version": "5.22.7",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public",
|
|
7
7
|
"tag": "prerelease-v4"
|
|
@@ -23,18 +23,18 @@
|
|
|
23
23
|
},
|
|
24
24
|
"dependencies": {
|
|
25
25
|
"@patternfly/patternfly": "4.139.2",
|
|
26
|
-
"@patternfly/react-catalog-view-extension": "^4.13.
|
|
26
|
+
"@patternfly/react-catalog-view-extension": "^4.13.5",
|
|
27
27
|
"@patternfly/react-charts": "^6.15.26",
|
|
28
|
-
"@patternfly/react-code-editor": "^4.3.
|
|
29
|
-
"@patternfly/react-core": "^4.
|
|
28
|
+
"@patternfly/react-code-editor": "^4.3.72",
|
|
29
|
+
"@patternfly/react-core": "^4.159.0",
|
|
30
30
|
"@patternfly/react-icons": "^4.12.1",
|
|
31
|
-
"@patternfly/react-inline-edit-extension": "^4.7.
|
|
32
|
-
"@patternfly/react-log-viewer": "^4.7.
|
|
31
|
+
"@patternfly/react-inline-edit-extension": "^4.7.96",
|
|
32
|
+
"@patternfly/react-log-viewer": "^4.7.8",
|
|
33
33
|
"@patternfly/react-styles": "^4.12.1",
|
|
34
|
-
"@patternfly/react-table": "^4.30.
|
|
34
|
+
"@patternfly/react-table": "^4.30.15",
|
|
35
35
|
"@patternfly/react-tokens": "^4.13.1",
|
|
36
|
-
"@patternfly/react-topology": "^4.9.
|
|
37
|
-
"@patternfly/react-virtualized-extension": "^4.9.
|
|
36
|
+
"@patternfly/react-topology": "^4.9.91",
|
|
37
|
+
"@patternfly/react-virtualized-extension": "^4.9.61"
|
|
38
38
|
},
|
|
39
39
|
"devDependencies": {
|
|
40
40
|
"@patternfly/patternfly-a11y": "4.2.1",
|
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
"react-dom": "^17.0.0",
|
|
45
45
|
"rimraf": "^2.6.3",
|
|
46
46
|
"shx": "^0.3.2",
|
|
47
|
-
"theme-patternfly-org": "0.7.
|
|
47
|
+
"theme-patternfly-org": "0.7.7"
|
|
48
48
|
},
|
|
49
49
|
"keywords": [
|
|
50
50
|
"gatsby"
|
|
@@ -53,5 +53,5 @@
|
|
|
53
53
|
"last 2 versions",
|
|
54
54
|
"not ie <= 11"
|
|
55
55
|
],
|
|
56
|
-
"gitHead": "
|
|
56
|
+
"gitHead": "86e7ecb47f3d2197cb664ce7237d3a25e18f8a48"
|
|
57
57
|
}
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -313,7 +313,6 @@ const pageData = {
|
|
|
313
313
|
"Inline panel on right",
|
|
314
314
|
"Inline panel on left",
|
|
315
315
|
"Stacked content body elements",
|
|
316
|
-
"Stacked content body elements",
|
|
317
316
|
"Modified content padding",
|
|
318
317
|
"Modified panel padding",
|
|
319
318
|
"Additional section above drawer content",
|
|
@@ -441,7 +440,6 @@ const Component = () => (
|
|
|
441
440
|
{React.createElement(pageData.examples["Inline panel on right"])}
|
|
442
441
|
{React.createElement(pageData.examples["Inline panel on left"])}
|
|
443
442
|
{React.createElement(pageData.examples["Stacked content body elements"])}
|
|
444
|
-
{React.createElement(pageData.examples["Stacked content body elements"])}
|
|
445
443
|
{React.createElement(pageData.examples["Modified content padding"])}
|
|
446
444
|
{React.createElement(pageData.examples["Modified panel padding"])}
|
|
447
445
|
{React.createElement(pageData.examples["Additional section above drawer content"])}
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/src/generated/components/navigation/react-demos/horizontal-nav-with-horizontal-subnav.png
CHANGED
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -4,15 +4,19 @@ import { css } from '@patternfly/react-styles';
|
|
|
4
4
|
import BellIcon from '@patternfly/react-icons/dist/esm/icons/bell-icon';
|
|
5
5
|
import CogIcon from '@patternfly/react-icons/dist/esm/icons/cog-icon';
|
|
6
6
|
import HelpIcon from '@patternfly/react-icons/dist/esm/icons/help-icon';
|
|
7
|
-
import imgBrand from '@patternfly/react-core/src/
|
|
7
|
+
import imgBrand from '@patternfly/react-core/src/demos/examples/pfColorLogo.svg';
|
|
8
8
|
import imgAvatar from '@patternfly/react-core/src/components/Avatar/examples/avatarImg.svg';
|
|
9
|
+
import BarsIcon from '@patternfly/react-icons/dist/esm/icons/bars-icon';
|
|
10
|
+
import AttentionBellIcon from '@patternfly/react-icons/dist/esm/icons/attention-bell-icon';
|
|
9
11
|
import srcImportdefaultnav from './react-demos/default-nav.png';
|
|
10
12
|
import srcImportexpandablenav from './react-demos/expandable-nav.png';
|
|
11
13
|
import srcImportgroupednav from './react-demos/grouped-nav.png';
|
|
12
14
|
import srcImporthorizontalnav from './react-demos/horizontal-nav.png';
|
|
13
15
|
import srcImportlegacylightnav from './react-demos/legacylight-nav.png';
|
|
14
16
|
import srcImportmanualnav from './react-demos/manual-nav.png';
|
|
17
|
+
import srcImportstickysectiongroupalternatesyntaxandusingpageheader from './react-demos/sticky-section-group-alternate-syntax-and-using-pageheader.png';
|
|
15
18
|
import srcImportstickysectiongroupalternatesyntax from './react-demos/sticky-section-group-alternate-syntax.png';
|
|
19
|
+
import srcImportstickysectiongroupusingpageheader from './react-demos/sticky-section-group-using-pageheader.png';
|
|
16
20
|
import srcImportstickysectiongroup from './react-demos/sticky-section-group.png';
|
|
17
21
|
import srcImporttertiarynav from './react-demos/tertiary-nav.png';
|
|
18
22
|
const pageData = {
|
|
@@ -23,7 +27,8 @@ const pageData = {
|
|
|
23
27
|
"sourceLink": "https://github.com/patternfly/patternfly-react/blob/main/packages/react-core/src/demos/Page/Page.md",
|
|
24
28
|
"fullscreenExamples": [
|
|
25
29
|
"Sticky section group",
|
|
26
|
-
"Sticky section group (
|
|
30
|
+
"Sticky section group (using PageHeader)",
|
|
31
|
+
"Sticky section group (alternate syntax and using PageHeader)"
|
|
27
32
|
]
|
|
28
33
|
};
|
|
29
34
|
pageData.liveContext = {
|
|
@@ -32,16 +37,30 @@ pageData.liveContext = {
|
|
|
32
37
|
CogIcon,
|
|
33
38
|
HelpIcon,
|
|
34
39
|
imgBrand,
|
|
35
|
-
imgAvatar
|
|
40
|
+
imgAvatar,
|
|
41
|
+
BarsIcon,
|
|
42
|
+
AttentionBellIcon
|
|
36
43
|
};
|
|
37
44
|
pageData.examples = {
|
|
38
45
|
'Sticky section group': props =>
|
|
39
|
-
<Example {...pageData} {...props} thumbnail={srcImportstickysectiongroup} {...{"code":"import React from 'react';\nimport {\n Avatar,\n Brand,\n Breadcrumb,\n BreadcrumbItem,\n Button,\n ButtonVariant,\n Card,\n CardBody,\n Dropdown,\n DropdownGroup,\n DropdownToggle,\n DropdownItem,\n DropdownSeparator,\n Gallery,\n GalleryItem,\n KebabToggle,\n Nav,\n NavItem,\n NavList,\n Page,\n
|
|
46
|
+
<Example {...pageData} {...props} thumbnail={srcImportstickysectiongroup} {...{"code":"import React from 'react';\nimport {\n Avatar,\n Brand,\n Breadcrumb,\n BreadcrumbItem,\n Button,\n ButtonVariant,\n Card,\n CardBody,\n Divider,\n Dropdown,\n DropdownGroup,\n DropdownToggle,\n DropdownItem,\n DropdownSeparator,\n Gallery,\n GalleryItem,\n KebabToggle,\n Masthead,\n MastheadBrand,\n MastheadContent,\n MastheadMain,\n MastheadToggle,\n Nav,\n NavItem,\n NavList,\n Page,\n PageSection,\n PageSectionVariants,\n PageSidebar,\n PageToggleButton,\n SkipToContent,\n TextContent,\n Text,\n Toolbar,\n ToolbarContent,\n ToolbarGroup,\n ToolbarItem\n} from '@patternfly/react-core';\nimport { css } from '@patternfly/react-styles';\nimport BellIcon from '@patternfly/react-icons/dist/esm/icons/bell-icon';\nimport CogIcon from '@patternfly/react-icons/dist/esm/icons/cog-icon';\nimport HelpIcon from '@patternfly/react-icons/dist/esm/icons/help-icon';\nimport AttentionBellIcon from '@patternfly/react-icons/dist/esm/icons/attention-bell-icon';\nimport BarsIcon from '@patternfly/react-icons/dist/js/icons/bars-icon';\nimport imgBrand from './imgBrand.svg';\nimport imgAvatar from './imgAvatar.svg';\n\nclass PageLayoutGrouped extends React.Component {\n constructor(props) {\n super(props);\n this.state = {\n isDropdownOpen: false,\n isKebabDropdownOpen: false,\n isFullKebabDropdownOpen: false,\n activeItem: 0\n };\n this.onDropdownToggle = isDropdownOpen => {\n this.setState({\n isDropdownOpen\n });\n };\n\n this.onDropdownSelect = event => {\n this.setState({\n isDropdownOpen: !this.state.isDropdownOpen\n });\n };\n\n this.onKebabDropdownToggle = isKebabDropdownOpen => {\n this.setState({\n isKebabDropdownOpen\n });\n };\n\n this.onKebabDropdownSelect = event => {\n this.setState({\n isKebabDropdownOpen: !this.state.isKebabDropdownOpen\n });\n };\n\n this.onNavSelect = result => {\n this.setState({\n activeItem: result.itemId\n });\n };\n\n this.onFullKebabToggle = isFullKebabDropdownOpen => {\n this.setState({\n isFullKebabDropdownOpen\n });\n };\n\n this.onFullKebabSelect = () => {\n this.setState({\n isFullKebabDropdownOpen: !this.state.isFullKebabDropdownOpen\n });\n };\n }\n\n render() {\n const { isDropdownOpen, isKebabDropdownOpen, activeItem, isFullKebabDropdownOpen } = this.state;\n\n const PageNav = (\n <Nav variant=\"tertiary\" onSelect={this.onNavSelect} aria-label=\"Nav\">\n <NavList>\n <NavItem href=\"#\" itemId={0} isActive={activeItem === 0}>\n System panel\n </NavItem>\n <NavItem href=\"#\" itemId={1} isActive={activeItem === 1}>\n Policy\n </NavItem>\n <NavItem href=\"#\" itemId={2} isActive={activeItem === 2}>\n Authentication\n </NavItem>\n <NavItem href=\"#\" itemId={3} isActive={activeItem === 3}>\n Network services\n </NavItem>\n <NavItem href=\"#\" itemId={4} isActive={activeItem === 4}>\n Server\n </NavItem>\n </NavList>\n </Nav>\n );\n\n const kebabDropdownItems = [\n <DropdownItem>\n <CogIcon /> Settings\n </DropdownItem>,\n <DropdownItem>\n <HelpIcon /> Help\n </DropdownItem>\n ];\n\n const userDropdownItems = [\n <DropdownGroup key=\"group 2\">\n <DropdownItem key=\"group 2 profile\">My profile</DropdownItem>\n <DropdownItem key=\"group 2 user\" component=\"button\">\n User management\n </DropdownItem>\n <DropdownItem key=\"group 2 logout\">Logout</DropdownItem>\n </DropdownGroup>\n ];\n\n const fullKebabItems = [\n <DropdownGroup key=\"group 2\">\n <DropdownItem key=\"group 2 profile\">My profile</DropdownItem>\n <DropdownItem key=\"group 2 user\" component=\"button\">\n User management\n </DropdownItem>\n <DropdownItem key=\"group 2 logout\">Logout</DropdownItem>\n </DropdownGroup>,\n <Divider key=\"divider\" />,\n <DropdownItem key=\"kebab-1\">\n <CogIcon /> Settings\n </DropdownItem>,\n <DropdownItem key=\"kebab-2\">\n <HelpIcon /> Help\n </DropdownItem>\n ];\n\n const headerToolbar = (\n <Toolbar id=\"toolbar\" isFullHeight isStatic>\n <ToolbarContent>\n <ToolbarGroup\n variant=\"icon-button-group\"\n alignment={{ default: 'alignRight' }}\n spacer={{ default: 'spacerNone', md: 'spacerMd' }}\n >\n <ToolbarItem>\n <Button aria-label=\"Notifications\" variant={ButtonVariant.plain}>\n <AttentionBellIcon />\n </Button>\n </ToolbarItem>\n <ToolbarGroup variant=\"icon-button-group\" visibility={{ default: 'hidden', lg: 'visible' }}>\n <ToolbarItem>\n <Button aria-label=\"Settings actions\" variant={ButtonVariant.plain}>\n <CogIcon />\n </Button>\n </ToolbarItem>\n <ToolbarItem>\n <Button aria-label=\"Help actions\" variant={ButtonVariant.plain}>\n <HelpIcon />\n </Button>\n </ToolbarItem>\n </ToolbarGroup>\n <ToolbarItem visibility={{ default: 'hidden', md: 'visible', lg: 'hidden' }}>\n <Dropdown\n isPlain\n position=\"right\"\n onSelect={this.onKebabDropdownSelect}\n toggle={<KebabToggle onToggle={this.onKebabDropdownToggle} />}\n isOpen={isKebabDropdownOpen}\n dropdownItems={kebabDropdownItems}\n />\n </ToolbarItem>\n <ToolbarItem visibility={{ default: 'visible', md: 'hidden', lg: 'hidden', xl: 'hidden', '2xl': 'hidden' }}>\n <Dropdown\n isPlain\n position=\"right\"\n onSelect={this.onFullKebabSelect}\n toggle={<KebabToggle onToggle={this.onFullKebabToggle} />}\n isOpen={isFullKebabDropdownOpen}\n dropdownItems={fullKebabItems}\n />\n </ToolbarItem>\n </ToolbarGroup>\n <ToolbarItem visibility={{ default: 'hidden', md: 'visible' }}>\n <Dropdown\n position=\"right\"\n onSelect={this.onDropdownSelect}\n isOpen={isDropdownOpen}\n toggle={\n <DropdownToggle icon={<Avatar src={imgAvatar} alt=\"Avatar\" />} onToggle={this.onDropdownToggle}>\n John Smith\n </DropdownToggle>\n }\n dropdownItems={userDropdownItems}\n />\n </ToolbarItem>\n </ToolbarContent>\n </Toolbar>\n );\n\n const Header = (\n <Masthead>\n <MastheadToggle>\n <PageToggleButton variant=\"plain\" aria-label=\"Global navigation\">\n <BarsIcon />\n </PageToggleButton>\n </MastheadToggle>\n <MastheadMain>\n <MastheadBrand>\n <Brand src={imgBrand} alt=\"Patternfly Logo\" />\n </MastheadBrand>\n </MastheadMain>\n <MastheadContent>{headerToolbar}</MastheadContent>\n </Masthead>\n );\n\n const pageId = 'main-content-page-layout-tertiary-nav';\n const PageSkipToContent = <SkipToContent href={`#${pageId}`}>Skip to content</SkipToContent>;\n\n const PageBreadcrumb = (\n <Breadcrumb>\n <BreadcrumbItem>Section home</BreadcrumbItem>\n <BreadcrumbItem to=\"#\">Section title</BreadcrumbItem>\n <BreadcrumbItem to=\"#\">Section title</BreadcrumbItem>\n <BreadcrumbItem to=\"#\" isActive>\n Section landing\n </BreadcrumbItem>\n </Breadcrumb>\n );\n\n return (\n <React.Fragment>\n <Page\n header={Header}\n breadcrumb={PageBreadcrumb}\n tertiaryNav={PageNav}\n isManagedSidebar\n isTertiaryNavWidthLimited\n isBreadcrumbWidthLimited\n skipToContent={PageSkipToContent}\n mainContainerId={pageId}\n isTertiaryNavGrouped\n isBreadcrumbGrouped\n additionalGroupedContent={\n <PageSection variant={PageSectionVariants.light}>\n <TextContent>\n <Text component=\"h1\">Main title</Text>\n <Text component=\"p\">\n Body text should be Overpass Regular at 16px. It should have leading of 24px because <br />\n of its relative line height of 1.5.\n </Text>\n </TextContent>\n </PageSection>\n }\n groupProps={{\n sticky: 'top'\n }}\n >\n <PageSection>\n <Gallery hasGutter>\n {Array.apply(0, Array(20)).map((x, i) => (\n <GalleryItem key={i}>\n <Card>\n <CardBody>This is a card</CardBody>\n </Card>\n </GalleryItem>\n ))}\n </Gallery>\n </PageSection>\n </Page>\n </React.Fragment>\n );\n }\n}","title":"Sticky section group","lang":"js","isFullscreen":true}}>
|
|
40
47
|
|
|
41
48
|
</Example>,
|
|
42
|
-
'Sticky section group (
|
|
43
|
-
<Example {...pageData} {...props} thumbnail={
|
|
49
|
+
'Sticky section group (using PageHeader)': props =>
|
|
50
|
+
<Example {...pageData} {...props} thumbnail={srcImportstickysectiongroupusingpageheader} {...{"code":"import React from 'react';\nimport {\n Avatar,\n Brand,\n Breadcrumb,\n BreadcrumbItem,\n Button,\n ButtonVariant,\n Card,\n CardBody,\n Dropdown,\n DropdownGroup,\n DropdownToggle,\n DropdownItem,\n DropdownSeparator,\n Gallery,\n GalleryItem,\n KebabToggle,\n Nav,\n NavItem,\n NavList,\n Page,\n PageHeader,\n PageSection,\n PageSectionVariants,\n PageSidebar,\n SkipToContent,\n TextContent,\n Text,\n PageHeaderTools,\n PageHeaderToolsGroup,\n PageHeaderToolsItem\n} from '@patternfly/react-core';\nimport { css } from '@patternfly/react-styles';\nimport BellIcon from '@patternfly/react-icons/dist/esm/icons/bell-icon';\nimport CogIcon from '@patternfly/react-icons/dist/esm/icons/cog-icon';\nimport HelpIcon from '@patternfly/react-icons/dist/esm/icons/help-icon';\nimport imgBrand from './imgBrand.svg';\nimport imgAvatar from './imgAvatar.svg';\n\nclass PageLayoutGrouped extends React.Component {\n constructor(props) {\n super(props);\n this.state = {\n isDropdownOpen: false,\n isKebabDropdownOpen: false,\n activeItem: 0\n };\n this.onDropdownToggle = isDropdownOpen => {\n this.setState({\n isDropdownOpen\n });\n };\n\n this.onDropdownSelect = event => {\n this.setState({\n isDropdownOpen: !this.state.isDropdownOpen\n });\n };\n\n this.onKebabDropdownToggle = isKebabDropdownOpen => {\n this.setState({\n isKebabDropdownOpen\n });\n };\n\n this.onKebabDropdownSelect = event => {\n this.setState({\n isKebabDropdownOpen: !this.state.isKebabDropdownOpen\n });\n };\n\n this.onNavSelect = result => {\n this.setState({\n activeItem: result.itemId\n });\n };\n }\n\n render() {\n const { isDropdownOpen, isKebabDropdownOpen, activeItem } = this.state;\n\n const PageNav = (\n <Nav variant=\"tertiary\" onSelect={this.onNavSelect} aria-label=\"Nav\">\n <NavList>\n <NavItem href=\"#\" itemId={0} isActive={activeItem === 0}>\n System panel\n </NavItem>\n <NavItem href=\"#\" itemId={1} isActive={activeItem === 1}>\n Policy\n </NavItem>\n <NavItem href=\"#\" itemId={2} isActive={activeItem === 2}>\n Authentication\n </NavItem>\n <NavItem href=\"#\" itemId={3} isActive={activeItem === 3}>\n Network services\n </NavItem>\n <NavItem href=\"#\" itemId={4} isActive={activeItem === 4}>\n Server\n </NavItem>\n </NavList>\n </Nav>\n );\n const kebabDropdownItems = [\n <DropdownItem>\n <CogIcon /> Settings\n </DropdownItem>,\n <DropdownItem>\n <HelpIcon /> Help\n </DropdownItem>\n ];\n const userDropdownItems = [\n <DropdownGroup key=\"group 2\">\n <DropdownItem key=\"group 2 profile\">My profile</DropdownItem>\n <DropdownItem key=\"group 2 user\" component=\"button\">\n User management\n </DropdownItem>\n <DropdownItem key=\"group 2 logout\">Logout</DropdownItem>\n </DropdownGroup>\n ];\n const headerTools = (\n <PageHeaderTools>\n <PageHeaderToolsGroup\n visibility={{\n default: 'hidden',\n lg: 'visible'\n }} /** the settings and help icon buttons are only visible on desktop sizes and replaced by a kebab dropdown for other sizes */\n >\n <PageHeaderToolsItem>\n <Button aria-label=\"Settings actions\" variant={ButtonVariant.plain}>\n <CogIcon />\n </Button>\n </PageHeaderToolsItem>\n <PageHeaderToolsItem>\n <Button aria-label=\"Help actions\" variant={ButtonVariant.plain}>\n <HelpIcon />\n </Button>\n </PageHeaderToolsItem>\n </PageHeaderToolsGroup>\n <PageHeaderToolsGroup>\n <PageHeaderToolsItem\n visibility={{\n lg: 'hidden'\n }} /** this kebab dropdown replaces the icon buttons and is hidden for desktop sizes */\n >\n <Dropdown\n isPlain\n position=\"right\"\n onSelect={this.onKebabDropdownSelect}\n toggle={<KebabToggle onToggle={this.onKebabDropdownToggle} />}\n isOpen={isKebabDropdownOpen}\n dropdownItems={kebabDropdownItems}\n />\n </PageHeaderToolsItem>\n <PageHeaderToolsItem\n visibility={{ default: 'hidden', md: 'visible' }} /** this user dropdown is hidden on mobile sizes */\n >\n <Dropdown\n isPlain\n position=\"right\"\n onSelect={this.onDropdownSelect}\n isOpen={isDropdownOpen}\n toggle={<DropdownToggle onToggle={this.onDropdownToggle}>John Smith</DropdownToggle>}\n dropdownItems={userDropdownItems}\n />\n </PageHeaderToolsItem>\n </PageHeaderToolsGroup>\n <Avatar src={imgAvatar} alt=\"Avatar image\" />\n </PageHeaderTools>\n );\n\n const Header = (\n <PageHeader logo={<Brand src={imgBrand} alt=\"Patternfly Logo\" />} headerTools={headerTools} showNavToggle />\n );\n const pageId = 'main-content-page-layout-tertiary-nav';\n const PageSkipToContent = <SkipToContent href={`#${pageId}`}>Skip to content</SkipToContent>;\n\n const PageBreadcrumb = (\n <Breadcrumb>\n <BreadcrumbItem>Section home</BreadcrumbItem>\n <BreadcrumbItem to=\"#\">Section title</BreadcrumbItem>\n <BreadcrumbItem to=\"#\">Section title</BreadcrumbItem>\n <BreadcrumbItem to=\"#\" isActive>\n Section landing\n </BreadcrumbItem>\n </Breadcrumb>\n );\n\n return (\n <React.Fragment>\n <Page\n header={Header}\n breadcrumb={PageBreadcrumb}\n tertiaryNav={PageNav}\n isManagedSidebar\n isTertiaryNavWidthLimited\n isBreadcrumbWidthLimited\n skipToContent={PageSkipToContent}\n mainContainerId={pageId}\n isTertiaryNavGrouped\n isBreadcrumbGrouped\n additionalGroupedContent={\n <PageSection variant={PageSectionVariants.light}>\n <TextContent>\n <Text component=\"h1\">Main title</Text>\n <Text component=\"p\">\n Body text should be Overpass Regular at 16px. It should have leading of 24px because <br />\n of its relative line height of 1.5.\n </Text>\n </TextContent>\n </PageSection>\n }\n groupProps={{\n sticky: 'top'\n }}\n >\n <PageSection>\n <Gallery hasGutter>\n {Array.apply(0, Array(20)).map((x, i) => (\n <GalleryItem key={i}>\n <Card>\n <CardBody>This is a card</CardBody>\n </Card>\n </GalleryItem>\n ))}\n </Gallery>\n </PageSection>\n </Page>\n </React.Fragment>\n );\n }\n}","title":"Sticky section group (using PageHeader)","lang":"js","isFullscreen":true}}>
|
|
44
51
|
|
|
52
|
+
<p {...{"className":"ws-p"}}>
|
|
53
|
+
{`This demo is provided becuase PageHeader and PageHeaderTools are still in use; however, going forward Masthead and Toolbar should be used to make headers rather than PageHeader and PageHeaderTools.`}
|
|
54
|
+
</p>
|
|
55
|
+
</Example>,
|
|
56
|
+
'Sticky section group (alternate syntax and using PageHeader)': props =>
|
|
57
|
+
<Example {...pageData} {...props} thumbnail={srcImportstickysectiongroupalternatesyntaxandusingpageheader} {...{"code":"import React from 'react';\nimport {\n Avatar,\n Brand,\n Breadcrumb,\n BreadcrumbItem,\n Button,\n ButtonVariant,\n Card,\n CardBody,\n Dropdown,\n DropdownGroup,\n DropdownToggle,\n DropdownItem,\n DropdownSeparator,\n Gallery,\n GalleryItem,\n KebabToggle,\n Nav,\n NavItem,\n NavList,\n Page,\n PageHeader,\n PageSection,\n PageSectionVariants,\n PageSidebar,\n PageGroup,\n PageBreadcrumb,\n PageNavigation,\n SkipToContent,\n TextContent,\n Text,\n PageHeaderTools,\n PageHeaderToolsGroup,\n PageHeaderToolsItem\n} from '@patternfly/react-core';\nimport { css } from '@patternfly/react-styles';\nimport BellIcon from '@patternfly/react-icons/dist/esm/icons/bell-icon';\nimport CogIcon from '@patternfly/react-icons/dist/esm/icons/cog-icon';\nimport HelpIcon from '@patternfly/react-icons/dist/esm/icons/help-icon';\nimport imgBrand from './imgBrand.svg';\nimport imgAvatar from './imgAvatar.svg';\n\nclass PageLayoutGroupedAlt extends React.Component {\n constructor(props) {\n super(props);\n this.state = {\n isDropdownOpen: false,\n isKebabDropdownOpen: false,\n activeItem: 0\n };\n this.onDropdownToggle = isDropdownOpen => {\n this.setState({\n isDropdownOpen\n });\n };\n\n this.onDropdownSelect = event => {\n this.setState({\n isDropdownOpen: !this.state.isDropdownOpen\n });\n };\n\n this.onKebabDropdownToggle = isKebabDropdownOpen => {\n this.setState({\n isKebabDropdownOpen\n });\n };\n\n this.onKebabDropdownSelect = event => {\n this.setState({\n isKebabDropdownOpen: !this.state.isKebabDropdownOpen\n });\n };\n\n this.onNavSelect = result => {\n this.setState({\n activeItem: result.itemId\n });\n };\n }\n\n render() {\n const { isDropdownOpen, isKebabDropdownOpen, activeItem } = this.state;\n\n const kebabDropdownItems = [\n <DropdownItem>\n <CogIcon /> Settings\n </DropdownItem>,\n <DropdownItem>\n <HelpIcon /> Help\n </DropdownItem>\n ];\n const userDropdownItems = [\n <DropdownGroup key=\"group 2\">\n <DropdownItem key=\"group 2 profile\">My profile</DropdownItem>\n <DropdownItem key=\"group 2 user\" component=\"button\">\n User management\n </DropdownItem>\n <DropdownItem key=\"group 2 logout\">Logout</DropdownItem>\n </DropdownGroup>\n ];\n const headerTools = (\n <PageHeaderTools>\n <PageHeaderToolsGroup\n visibility={{\n default: 'hidden',\n lg: 'visible'\n }} /** the settings and help icon buttons are only visible on desktop sizes and replaced by a kebab dropdown for other sizes */\n >\n <PageHeaderToolsItem>\n <Button aria-label=\"Settings actions\" variant={ButtonVariant.plain}>\n <CogIcon />\n </Button>\n </PageHeaderToolsItem>\n <PageHeaderToolsItem>\n <Button aria-label=\"Help actions\" variant={ButtonVariant.plain}>\n <HelpIcon />\n </Button>\n </PageHeaderToolsItem>\n </PageHeaderToolsGroup>\n <PageHeaderToolsGroup>\n <PageHeaderToolsItem\n visibility={{\n lg: 'hidden'\n }} /** this kebab dropdown replaces the icon buttons and is hidden for desktop sizes */\n >\n <Dropdown\n isPlain\n position=\"right\"\n onSelect={this.onKebabDropdownSelect}\n toggle={<KebabToggle onToggle={this.onKebabDropdownToggle} />}\n isOpen={isKebabDropdownOpen}\n dropdownItems={kebabDropdownItems}\n />\n </PageHeaderToolsItem>\n <PageHeaderToolsItem\n visibility={{ default: 'hidden', md: 'visible' }} /** this user dropdown is hidden on mobile sizes */\n >\n <Dropdown\n isPlain\n position=\"right\"\n onSelect={this.onDropdownSelect}\n isOpen={isDropdownOpen}\n toggle={<DropdownToggle onToggle={this.onDropdownToggle}>John Smith</DropdownToggle>}\n dropdownItems={userDropdownItems}\n />\n </PageHeaderToolsItem>\n </PageHeaderToolsGroup>\n <Avatar src={imgAvatar} alt=\"Avatar image\" />\n </PageHeaderTools>\n );\n\n const Header = (\n <PageHeader logo={<Brand src={imgBrand} alt=\"Patternfly Logo\" />} headerTools={headerTools} showNavToggle />\n );\n const pageId = 'main-content-page-layout-tertiary-nav';\n const PageSkipToContent = <SkipToContent href={`#${pageId}`}>Skip to content</SkipToContent>;\n\n return (\n <React.Fragment>\n <Page header={Header} isManagedSidebar skipToContent={PageSkipToContent} mainContainerId={pageId}>\n <PageGroup sticky=\"top\">\n <PageNavigation isWidthLimited>\n <Nav variant=\"tertiary\" onSelect={this.onNavSelect} aria-label=\"Nav\">\n <NavList>\n <NavItem href=\"#\" itemId={0} isActive={activeItem === 0}>\n System panel\n </NavItem>\n <NavItem href=\"#\" itemId={1} isActive={activeItem === 1}>\n Policy\n </NavItem>\n <NavItem href=\"#\" itemId={2} isActive={activeItem === 2}>\n Authentication\n </NavItem>\n <NavItem href=\"#\" itemId={3} isActive={activeItem === 3}>\n Network services\n </NavItem>\n <NavItem href=\"#\" itemId={4} isActive={activeItem === 4}>\n Server\n </NavItem>\n </NavList>\n </Nav>\n </PageNavigation>\n <PageBreadcrumb>\n <Breadcrumb>\n <BreadcrumbItem>Section home</BreadcrumbItem>\n <BreadcrumbItem to=\"#\">Section title</BreadcrumbItem>\n <BreadcrumbItem to=\"#\">Section title</BreadcrumbItem>\n <BreadcrumbItem to=\"#\" isActive>\n Section landing\n </BreadcrumbItem>\n </Breadcrumb>\n </PageBreadcrumb>\n <PageSection variant={PageSectionVariants.light}>\n <TextContent>\n <Text component=\"h1\">Main title</Text>\n <Text component=\"p\">\n Body text should be Overpass Regular at 16px. It should have leading of 24px because <br />\n of its relative line height of 1.5.\n </Text>\n </TextContent>\n </PageSection>{' '}\n </PageGroup>\n <PageSection>\n <Gallery hasGutter>\n {Array.apply(0, Array(20)).map((x, i) => (\n <GalleryItem key={i}>\n <Card>\n <CardBody>This is a card</CardBody>\n </Card>\n </GalleryItem>\n ))}\n </Gallery>\n </PageSection>\n </Page>\n </React.Fragment>\n );\n }\n}","title":"Sticky section group (alternate syntax and using PageHeader)","lang":"js","isFullscreen":true}}>
|
|
58
|
+
|
|
59
|
+
<p {...{"className":"ws-p"}}>
|
|
60
|
+
{`Please see `}
|
|
61
|
+
<a href="#sticky-section-group-using-pageheader">{`this`}</a>
|
|
62
|
+
{` note regarding PageHeader.`}
|
|
63
|
+
</p>
|
|
45
64
|
</Example>
|
|
46
65
|
};
|
|
47
66
|
|
|
@@ -88,7 +107,8 @@ const Component = () => (
|
|
|
88
107
|
{`This demonstrates a variety of navigation patterns in the context of a full page layout. These can be used as a basis for choosing the most appropriate page template for your application.`}
|
|
89
108
|
</p>
|
|
90
109
|
{React.createElement(pageData.examples["Sticky section group"])}
|
|
91
|
-
{React.createElement(pageData.examples["Sticky section group (
|
|
110
|
+
{React.createElement(pageData.examples["Sticky section group (using PageHeader)"])}
|
|
111
|
+
{React.createElement(pageData.examples["Sticky section group (alternate syntax and using PageHeader)"])}
|
|
92
112
|
</React.Fragment>
|
|
93
113
|
);
|
|
94
114
|
Component.displayName = 'ComponentsPageReactDemosDocs';
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { AutoLinkHeader, Example, Link as PatternflyThemeLink } from 'theme-patternfly-org/components';
|
|
3
|
-
|
|
3
|
+
import BarsIcon from '@patternfly/react-icons/dist/js/icons/bars-icon';
|
|
4
4
|
const pageData = {
|
|
5
5
|
"id": "Page",
|
|
6
6
|
"section": "components",
|
|
@@ -556,37 +556,48 @@ const pageData = {
|
|
|
556
556
|
"Main Section Padding",
|
|
557
557
|
"With or without fill",
|
|
558
558
|
"Uncontrolled nav",
|
|
559
|
-
"Group section"
|
|
559
|
+
"Group section",
|
|
560
|
+
"Vertical nav using PageHeader component"
|
|
560
561
|
]
|
|
561
562
|
};
|
|
563
|
+
pageData.liveContext = {
|
|
564
|
+
BarsIcon
|
|
565
|
+
};
|
|
562
566
|
pageData.examples = {
|
|
563
567
|
'Vertical nav': props =>
|
|
564
|
-
<Example {...pageData} {...props} {...{"code":"import React from 'react';\nimport {\n Page,\n
|
|
568
|
+
<Example {...pageData} {...props} {...{"code":"import React from 'react';\nimport {\n Page,\n Masthead,\n MastheadToggle,\n MastheadMain,\n MastheadBrand,\n MastheadContent,\n PageSidebar,\n PageSection,\n PageSectionVariants,\n PageToggleButton,\n Toolbar,\n ToolbarContent,\n ToolbarItem\n} from '@patternfly/react-core';\nimport BarsIcon from '@patternfly/react-icons/dist/esm/icons/bars-icon';\n\nclass VerticalPage extends React.Component {\n constructor(props) {\n super(props);\n this.state = {\n isNavOpen: true\n };\n this.onNavToggle = () => {\n this.setState({\n isNavOpen: !this.state.isNavOpen\n });\n };\n }\n\n render() {\n const { isNavOpen } = this.state;\n\n const headerToolbar = (\n <Toolbar id=\"toolbar\">\n <ToolbarContent>\n <ToolbarItem>header-tools</ToolbarItem>\n </ToolbarContent>\n </Toolbar>\n );\n\n const Header = (\n <Masthead>\n <MastheadToggle>\n <PageToggleButton\n variant=\"plain\"\n aria-label=\"Global navigation\"\n isNavOpen={isNavOpen}\n onNavToggle={this.onNavToggle}\n >\n <BarsIcon />\n </PageToggleButton>\n </MastheadToggle>\n <MastheadMain>\n <MastheadBrand href=\"https://patternfly.org\" onClick={() => console.log('clicked logo')} target=\"_blank\">\n Logo\n </MastheadBrand>\n </MastheadMain>\n <MastheadContent>{headerToolbar}</MastheadContent>\n </Masthead>\n );\n const Sidebar = <PageSidebar nav=\"Navigation\" isNavOpen={isNavOpen} />;\n\n return (\n <Page header={Header} sidebar={Sidebar}>\n <PageSection variant={PageSectionVariants.darker}>Section with darker background</PageSection>\n <PageSection variant={PageSectionVariants.dark}>Section with dark background</PageSection>\n <PageSection variant={PageSectionVariants.light}>Section with light background</PageSection>\n </Page>\n );\n }\n}","title":"Vertical nav","lang":"js"}}>
|
|
565
569
|
|
|
566
570
|
</Example>,
|
|
567
571
|
'Horizontal nav': props =>
|
|
568
|
-
<Example {...pageData} {...props} {...{"code":"import React from 'react';\nimport {\n Page,\n
|
|
572
|
+
<Example {...pageData} {...props} {...{"code":"import React from 'react';\nimport {\n Page,\n Masthead,\n MastheadMain,\n MastheadBrand,\n MastheadContent,\n PageSection,\n PageSectionVariants,\n Toolbar,\n ToolbarContent,\n ToolbarItem\n} from '@patternfly/react-core';\n\nHorizontalPage = () => {\n const headerToolbar = (\n <Toolbar id=\"toolbar\">\n <ToolbarContent>\n <ToolbarItem>Navigation</ToolbarItem>\n <ToolbarItem>header-tools</ToolbarItem>\n </ToolbarContent>\n </Toolbar>\n );\n\n const Header = (\n <Masthead display={{ default: 'stack' }} inset={{ default: 'insetXs' }}>\n <MastheadMain>\n <MastheadBrand href=\"https://patternfly.org\" onClick={() => console.log('clicked logo')} target=\"_blank\">\n Logo\n </MastheadBrand>\n </MastheadMain>\n <MastheadContent>{headerToolbar}</MastheadContent>\n </Masthead>\n );\n\n return (\n <Page header={Header}>\n <PageSection variant={PageSectionVariants.darker}>Section with darker background</PageSection>\n <PageSection variant={PageSectionVariants.dark}>Section with dark background</PageSection>\n <PageSection variant={PageSectionVariants.light}>Section with light background</PageSection>\n </Page>\n );\n};","title":"Horizontal nav","lang":"js"}}>
|
|
569
573
|
|
|
570
574
|
</Example>,
|
|
571
575
|
'Tertiary nav': props =>
|
|
572
|
-
<Example {...pageData} {...props} {...{"code":"import React from 'react';\nimport {\n Page,\n
|
|
576
|
+
<Example {...pageData} {...props} {...{"code":"import React from 'react';\nimport {\n Page,\n Masthead,\n MastheadMain,\n MastheadBrand,\n MastheadContent,\n PageSection,\n PageSectionVariants,\n Toolbar,\n ToolbarContent,\n ToolbarItem\n} from '@patternfly/react-core';\n\nTertiaryPage = () => {\n const headerToolbar = (\n <Toolbar id=\"toolbar\">\n <ToolbarContent>\n <ToolbarItem>header-tools</ToolbarItem>\n </ToolbarContent>\n </Toolbar>\n );\n\n const Header = (\n <Masthead display={{ default: 'stack' }} inset={{ default: 'insetXs' }}>\n <MastheadMain>\n <MastheadBrand href=\"https://patternfly.org\" onClick={() => console.log('clicked logo')} target=\"_blank\">\n Logo\n </MastheadBrand>\n </MastheadMain>\n <MastheadContent>{headerToolbar}</MastheadContent>\n </Masthead>\n );\n\n return (\n <Page header={Header} tertiaryNav=\"Navigation\">\n <PageSection variant={PageSectionVariants.darker}>Section with darker background</PageSection>\n <PageSection variant={PageSectionVariants.dark}>Section with dark background</PageSection>\n <PageSection variant={PageSectionVariants.light}>Section with light background</PageSection>\n </Page>\n );\n};","title":"Tertiary nav","lang":"js"}}>
|
|
573
577
|
|
|
574
578
|
</Example>,
|
|
575
579
|
'Main Section Padding': props =>
|
|
576
|
-
<Example {...pageData} {...props} {...{"code":"import React from 'react';\nimport {\n Page,\n
|
|
580
|
+
<Example {...pageData} {...props} {...{"code":"import React from 'react';\nimport {\n Page,\n Masthead,\n MastheadToggle,\n MastheadMain,\n MastheadBrand,\n MastheadContent,\n PageSidebar,\n PageSection,\n PageSectionVariants,\n PageToggleButton,\n Toolbar,\n ToolbarContent,\n ToolbarItem\n} from '@patternfly/react-core';\nimport BarsIcon from '@patternfly/react-icons/dist/esm/icons/bars-icon';\n\nclass VerticalPage extends React.Component {\n constructor(props) {\n super(props);\n this.state = {\n isNavOpen: true\n };\n this.onNavToggle = () => {\n this.setState({\n isNavOpen: !this.state.isNavOpen\n });\n };\n }\n\n render() {\n const { isNavOpen } = this.state;\n\n const headerToolbar = (\n <Toolbar id=\"toolbar\">\n <ToolbarContent>\n <ToolbarItem>header-tools</ToolbarItem>\n </ToolbarContent>\n </Toolbar>\n );\n\n const Header = (\n <Masthead>\n <MastheadToggle>\n <PageToggleButton\n variant=\"plain\"\n aria-label=\"Global navigation\"\n isNavOpen={isNavOpen}\n onNavToggle={this.onNavToggle}\n >\n <BarsIcon />\n </PageToggleButton>\n </MastheadToggle>\n <MastheadMain>\n <MastheadBrand href=\"https://patternfly.org\" onClick={() => console.log('clicked logo')} target=\"_blank\">\n Logo\n </MastheadBrand>\n </MastheadMain>\n <MastheadContent>{headerToolbar}</MastheadContent>\n </Masthead>\n );\n const Sidebar = <PageSidebar nav=\"Navigation\" isNavOpen={isNavOpen} />;\n\n return (\n <Page header={Header} sidebar={Sidebar}>\n <PageSection>Section with default padding</PageSection>\n <PageSection variant={PageSectionVariants.light} padding={{ default: 'noPadding' }}>\n Section with no padding\n </PageSection>\n <PageSection padding={{ default: 'noPadding', md: 'padding', lg: 'padding' }}>\n Section with padding only on medium/large\n </PageSection>\n <PageSection variant={PageSectionVariants.light} padding={{ md: 'noPadding' }}>\n Section with no padding on medium\n </PageSection>\n </Page>\n );\n }\n}","title":"Main Section Padding","lang":"js"}}>
|
|
577
581
|
|
|
578
582
|
</Example>,
|
|
579
583
|
'With or without fill': props =>
|
|
580
|
-
<Example {...pageData} {...props} {...{"code":"import React from 'react';\nimport {\n Page,\n
|
|
584
|
+
<Example {...pageData} {...props} {...{"code":"import React from 'react';\nimport {\n Page,\n Masthead,\n MastheadToggle,\n MastheadMain,\n MastheadBrand,\n MastheadContent,\n PageSidebar,\n PageSection,\n PageToggleButton,\n Toolbar,\n ToolbarContent,\n ToolbarItem\n} from '@patternfly/react-core';\nimport BarsIcon from '@patternfly/react-icons/dist/esm/icons/bars-icon';\n\nclass FillPage extends React.Component {\n constructor(props) {\n super(props);\n this.state = {\n isNavOpen: true\n };\n this.onNavToggle = () => {\n this.setState({\n isNavOpen: !this.state.isNavOpen\n });\n };\n }\n\n render() {\n const { isNavOpen } = this.state;\n\n const headerToolbar = (\n <Toolbar id=\"toolbar\">\n <ToolbarContent>\n <ToolbarItem>header-tools</ToolbarItem>\n </ToolbarContent>\n </Toolbar>\n );\n\n const Header = (\n <Masthead>\n <MastheadToggle>\n <PageToggleButton\n variant=\"plain\"\n aria-label=\"Global navigation\"\n isNavOpen={isNavOpen}\n onNavToggle={this.onNavToggle}\n >\n <BarsIcon />\n </PageToggleButton>\n </MastheadToggle>\n <MastheadMain>\n <MastheadBrand href=\"https://patternfly.org\" onClick={() => console.log('clicked logo')} target=\"_blank\">\n Logo\n </MastheadBrand>\n </MastheadMain>\n <MastheadContent>{headerToolbar}</MastheadContent>\n </Masthead>\n );\n const Sidebar = <PageSidebar nav=\"Navigation\" isNavOpen={isNavOpen} />;\n\n return (\n <Page header={Header} sidebar={Sidebar}>\n <PageSection style={{ height: '10em' }}>This section is set to the default fill variant</PageSection>\n <PageSection style={{ height: '10em' }} isFilled={true}>\n This section fills the available space.\n </PageSection>\n <PageSection style={{ height: '10em' }} isFilled={false}>\n {' '}\n This section does not fill the available space.\n </PageSection>\n </Page>\n );\n }\n}","title":"With or without fill","lang":"js"}}>
|
|
581
585
|
|
|
582
586
|
</Example>,
|
|
583
587
|
'Uncontrolled nav': props =>
|
|
584
|
-
<Example {...pageData} {...props} {...{"code":"import React from 'react';\nimport {\n Page,\n
|
|
588
|
+
<Example {...pageData} {...props} {...{"code":"import React from 'react';\nimport {\n Page,\n Masthead,\n MastheadToggle,\n MastheadMain,\n MastheadBrand,\n MastheadContent,\n PageSidebar,\n PageSection,\n PageSectionVariants,\n PageToggleButton,\n Toolbar,\n ToolbarContent,\n ToolbarItem\n} from '@patternfly/react-core';\nimport BarsIcon from '@patternfly/react-icons/dist/esm/icons/bars-icon';\n\nclass UncontrolledNavPage extends React.Component {\n render() {\n const headerToolbar = (\n <Toolbar id=\"toolbar\">\n <ToolbarContent>\n <ToolbarItem>header-tools</ToolbarItem>\n </ToolbarContent>\n </Toolbar>\n );\n\n const Header = (\n <Masthead>\n <MastheadToggle>\n <PageToggleButton variant=\"plain\" aria-label=\"Global navigation\">\n <BarsIcon />\n </PageToggleButton>\n </MastheadToggle>\n <MastheadMain>\n <MastheadBrand href=\"https://patternfly.org\" onClick={() => console.log('clicked logo')} target=\"_blank\">\n Logo\n </MastheadBrand>\n </MastheadMain>\n <MastheadContent>{headerToolbar}</MastheadContent>\n </Masthead>\n );\n const Sidebar = <PageSidebar nav=\"Navigation\" />;\n\n return (\n <Page isManagedSidebar header={Header} sidebar={Sidebar}>\n <PageSection variant={PageSectionVariants.darker}>Section with darker background</PageSection>\n <PageSection variant={PageSectionVariants.dark}>Section with dark background</PageSection>\n <PageSection variant={PageSectionVariants.light}>Section with light background</PageSection>\n </Page>\n );\n }\n}","title":"Uncontrolled nav","lang":"js"}}>
|
|
585
589
|
|
|
586
590
|
</Example>,
|
|
587
591
|
'Group section': props =>
|
|
588
|
-
<Example {...pageData} {...props} {...{"code":"import React from 'react';\nimport {\n Page,\n
|
|
592
|
+
<Example {...pageData} {...props} {...{"code":"import React from 'react';\nimport {\n Page,\n Masthead,\n MastheadToggle,\n MastheadMain,\n MastheadBrand,\n MastheadContent,\n PageSidebar,\n PageSection,\n PageGroup,\n PageBreadcrumb,\n PageNavigation,\n PageSectionVariants,\n PageToggleButton,\n Breadcrumb,\n BreadcrumbItem,\n Nav,\n NavList,\n NavItem,\n Toolbar,\n ToolbarContent,\n ToolbarItem\n} from '@patternfly/react-core';\nimport BarsIcon from '@patternfly/react-icons/dist/esm/icons/bars-icon';\n\nclass GroupPage extends React.Component {\n constructor(props) {\n super(props);\n this.state = {\n isNavOpen: true\n };\n this.onNavToggle = () => {\n this.setState({\n isNavOpen: !this.state.isNavOpen\n });\n };\n }\n\n render() {\n const { isNavOpen } = this.state;\n\n const headerToolbar = (\n <Toolbar id=\"toolbar\">\n <ToolbarContent>\n <ToolbarItem>header-tools</ToolbarItem>\n </ToolbarContent>\n </Toolbar>\n );\n\n const Header = (\n <Masthead>\n <MastheadToggle>\n <PageToggleButton\n variant=\"plain\"\n aria-label=\"Global navigation\"\n isNavOpen={isNavOpen}\n onNavToggle={this.onNavToggle}\n >\n <BarsIcon />\n </PageToggleButton>\n </MastheadToggle>\n <MastheadMain>\n <MastheadBrand href=\"https://patternfly.org\" onClick={() => console.log('clicked logo')} target=\"_blank\">\n Logo\n </MastheadBrand>\n </MastheadMain>\n <MastheadContent>{headerToolbar}</MastheadContent>\n </Masthead>\n );\n const Sidebar = <PageSidebar nav=\"Navigation\" isNavOpen={isNavOpen} />;\n\n return (\n <Page header={Header} sidebar={Sidebar}>\n <PageGroup>\n <PageNavigation>\n <Nav aria-label=\"Nav\" variant=\"tertiary\">\n <NavList>\n <NavItem itemId={0} isActive>\n System panel\n </NavItem>\n <NavItem itemId={1}>Policy</NavItem>\n <NavItem itemId={2}>Authentication</NavItem>\n <NavItem itemId={3}>Network services</NavItem>\n <NavItem itemId={4}>Server</NavItem>\n </NavList>\n </Nav>\n </PageNavigation>\n <PageBreadcrumb>\n <Breadcrumb>\n <BreadcrumbItem>Section home</BreadcrumbItem>\n <BreadcrumbItem to=\"#\">Section title</BreadcrumbItem>\n <BreadcrumbItem to=\"#\">Section title</BreadcrumbItem>\n <BreadcrumbItem to=\"#\" isActive>\n Section landing\n </BreadcrumbItem>\n </Breadcrumb>\n </PageBreadcrumb>\n <PageSection variant={PageSectionVariants.light}>Grouped section</PageSection>\n </PageGroup>\n <PageSection variant={PageSectionVariants.dark}>Section 1</PageSection>\n <PageSection variant={PageSectionVariants.dark}>Section 2</PageSection>\n </Page>\n );\n }\n}","title":"Group section","lang":"js"}}>
|
|
593
|
+
|
|
594
|
+
</Example>,
|
|
595
|
+
'Vertical nav using PageHeader component': props =>
|
|
596
|
+
<Example {...pageData} {...props} {...{"code":"import React from 'react';\nimport {\n Page,\n PageHeader,\n PageHeaderTools,\n PageSidebar,\n PageSection,\n PageSectionVariants\n} from '@patternfly/react-core';\n\nclass VerticalPage extends React.Component {\n constructor(props) {\n super(props);\n this.state = {\n isNavOpen: true\n };\n this.onNavToggle = () => {\n this.setState({\n isNavOpen: !this.state.isNavOpen\n });\n };\n }\n\n render() {\n const { isNavOpen } = this.state;\n\n const logoProps = {\n href: 'https://patternfly.org',\n onClick: () => console.log('clicked logo'),\n target: '_blank'\n };\n const Header = (\n <PageHeader\n logo=\"Logo\"\n logoProps={logoProps}\n headerTools={<PageHeaderTools>header-tools</PageHeaderTools>}\n showNavToggle\n isNavOpen={isNavOpen}\n onNavToggle={this.onNavToggle}\n />\n );\n const Sidebar = <PageSidebar nav=\"Navigation\" isNavOpen={isNavOpen} />;\n\n return (\n <Page header={Header} sidebar={Sidebar}>\n <PageSection variant={PageSectionVariants.darker}>Section with darker background</PageSection>\n <PageSection variant={PageSectionVariants.dark}>Section with dark background</PageSection>\n <PageSection variant={PageSectionVariants.light}>Section with light background</PageSection>\n </Page>\n );\n }\n}","title":"Vertical nav using PageHeader component","lang":"js"}}>
|
|
589
597
|
|
|
598
|
+
<p {...{"className":"ws-p"}}>
|
|
599
|
+
{`This example is provided becuase PageHeader and PageHeaderTools are still in use; however, going forward Masthead and Toolbar should be used to make headers rather than PageHeader and PageHeaderTools.`}
|
|
600
|
+
</p>
|
|
590
601
|
</Example>
|
|
591
602
|
};
|
|
592
603
|
|
|
@@ -602,6 +613,7 @@ const Component = () => (
|
|
|
602
613
|
{React.createElement(pageData.examples["With or without fill"])}
|
|
603
614
|
{React.createElement(pageData.examples["Uncontrolled nav"])}
|
|
604
615
|
{React.createElement(pageData.examples["Group section"])}
|
|
616
|
+
{React.createElement(pageData.examples["Vertical nav using PageHeader component"])}
|
|
605
617
|
</React.Fragment>
|
|
606
618
|
);
|
|
607
619
|
Component.displayName = 'ComponentsPageReactDocs';
|
|
Binary file
|
|
@@ -239,6 +239,12 @@ const pageData = {
|
|
|
239
239
|
"description": "Title text of Select",
|
|
240
240
|
"defaultValue": "''"
|
|
241
241
|
},
|
|
242
|
+
{
|
|
243
|
+
"name": "position",
|
|
244
|
+
"type": "SelectPosition | 'right' | 'left'",
|
|
245
|
+
"description": "Indicates where menu will be aligned horizontally",
|
|
246
|
+
"defaultValue": "SelectPosition.left"
|
|
247
|
+
},
|
|
242
248
|
{
|
|
243
249
|
"name": "removeSelectionAriaLabel",
|
|
244
250
|
"type": "string",
|
|
Binary file
|
|
Binary file
|
|
@@ -50,6 +50,16 @@ const pageData = {
|
|
|
50
50
|
"type": "number | string",
|
|
51
51
|
"description": "The index of the default active tab. Set this for uncontrolled Tabs"
|
|
52
52
|
},
|
|
53
|
+
{
|
|
54
|
+
"name": "defaultIsExpanded",
|
|
55
|
+
"type": "boolean",
|
|
56
|
+
"description": "Flag indicating the default expanded state for uncontrolled expand/collapse of"
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
"name": "expandable",
|
|
60
|
+
"type": "{\n default?: 'expandable' | 'nonExpandable';\n sm?: 'expandable' | 'nonExpandable';\n md?: 'expandable' | 'nonExpandable';\n lg?: 'expandable' | 'nonExpandable';\n xl?: 'expandable' | 'nonExpandable';\n '2xl'?: 'expandable' | 'nonExpandable';\n}",
|
|
61
|
+
"description": "Enable expandable vertical tabs at various breakpoints. (isVertical should be set to true for this to work)"
|
|
62
|
+
},
|
|
53
63
|
{
|
|
54
64
|
"name": "id",
|
|
55
65
|
"type": "string",
|
|
@@ -66,6 +76,11 @@ const pageData = {
|
|
|
66
76
|
"description": "Enables box styling to the tab component",
|
|
67
77
|
"defaultValue": "false"
|
|
68
78
|
},
|
|
79
|
+
{
|
|
80
|
+
"name": "isExpanded",
|
|
81
|
+
"type": "boolean",
|
|
82
|
+
"description": "Flag to indicate if the vertical tabs are expanded"
|
|
83
|
+
},
|
|
69
84
|
{
|
|
70
85
|
"name": "isFilled",
|
|
71
86
|
"type": "boolean",
|
|
@@ -102,6 +117,12 @@ const pageData = {
|
|
|
102
117
|
"description": "Callback to handle tab selection",
|
|
103
118
|
"defaultValue": "() => undefined as any"
|
|
104
119
|
},
|
|
120
|
+
{
|
|
121
|
+
"name": "onToggle",
|
|
122
|
+
"type": "(isExpanded: boolean) => void",
|
|
123
|
+
"description": "Callback function to toggle the expandable tabs.",
|
|
124
|
+
"defaultValue": "(isExpanded): void => undefined"
|
|
125
|
+
},
|
|
105
126
|
{
|
|
106
127
|
"name": "ouiaSafe",
|
|
107
128
|
"type": "No type info",
|
|
@@ -113,6 +134,16 @@ const pageData = {
|
|
|
113
134
|
"description": "Aria-label for the right scroll button",
|
|
114
135
|
"defaultValue": "'Scroll right'"
|
|
115
136
|
},
|
|
137
|
+
{
|
|
138
|
+
"name": "toggleAriaLabel",
|
|
139
|
+
"type": "string",
|
|
140
|
+
"description": "Aria-label for the left expandable toggle"
|
|
141
|
+
},
|
|
142
|
+
{
|
|
143
|
+
"name": "toggleText",
|
|
144
|
+
"type": "string",
|
|
145
|
+
"description": "Text that appears in the expandable toggle"
|
|
146
|
+
},
|
|
116
147
|
{
|
|
117
148
|
"name": "unmountOnExit",
|
|
118
149
|
"type": "boolean",
|
|
@@ -293,6 +324,8 @@ const pageData = {
|
|
|
293
324
|
"Box light variation",
|
|
294
325
|
"Default overflow",
|
|
295
326
|
"Vertical",
|
|
327
|
+
"Vertical expandable",
|
|
328
|
+
"Vertical expandable uncontrolled",
|
|
296
329
|
"Inset",
|
|
297
330
|
"Page Insets",
|
|
298
331
|
"Icons and text",
|
|
@@ -335,6 +368,14 @@ pageData.examples = {
|
|
|
335
368
|
'Vertical': props =>
|
|
336
369
|
<Example {...pageData} {...props} {...{"code":"import React from 'react';\nimport { Tabs, Tab, TabTitleText, Checkbox, Tooltip } from '@patternfly/react-core';\n\nclass VerticalTabs extends React.Component {\n constructor(props) {\n super(props);\n this.state = {\n activeTabKey: 0,\n isBox: false\n };\n // Toggle currently active tab\n this.handleTabClick = (event, tabIndex) => {\n this.setState({\n activeTabKey: tabIndex\n });\n };\n\n this.toggleBox = checked => {\n this.setState({\n isBox: checked\n });\n };\n }\n\n render() {\n const {activeTabKey, isBox} = this.state;\n const tooltipRef = React.createRef();\n return (\n <div>\n <Tabs activeKey={activeTabKey} onSelect={this.handleTabClick} isVertical isBox={isBox}>\n <Tab eventKey={0} title={<TabTitleText>Users</TabTitleText>}>\n Users\n </Tab>\n <Tab eventKey={1} title={<TabTitleText>Containers</TabTitleText>}>\n Containers\n </Tab>\n <Tab eventKey={2} title={<TabTitleText>Database</TabTitleText>}>\n Database\n </Tab>\n <Tab eventKey={3} title={<TabTitleText>Disabled</TabTitleText>} isDisabled>\n Disabled\n </Tab>\n <Tab eventKey={4} title={<TabTitleText>ARIA Disabled</TabTitleText>} isAriaDisabled>\n ARIA Disabled\n </Tab>\n <Tab eventKey={5} title={<TabTitleText>ARIA Disabled (Tooltip)</TabTitleText>} isAriaDisabled ref={tooltipRef}>\n ARIA Disabled (Tooltip)\n </Tab>\n </Tabs>\n <Tooltip content=\"Aria-disabled tabs are like disabled tabs, but focusable. Allows for tooltip support.\" reference={tooltipRef} position=\"right\" />\n <div style={{marginTop: \"20px\"}}>\n <Checkbox\n label=\"isBox\"\n isChecked={isBox}\n onChange={this.toggleBox}\n aria-label=\"show box variation checkbox with vertical\"\n id=\"toggle-box-vertical\"\n name=\"toggle-box-vertical\"\n />\n </div>\n </div>\n );\n }\n}","title":"Vertical","lang":"js"}}>
|
|
337
370
|
|
|
371
|
+
</Example>,
|
|
372
|
+
'Vertical expandable': props =>
|
|
373
|
+
<Example {...pageData} {...props} {...{"code":"import React from 'react';\nimport { Tabs, Tab, TabTitleText, Checkbox } from '@patternfly/react-core';\nclass VerticalExpandableTabs extends React.Component {\n constructor(props) {\n super(props);\n this.state = {\n activeTabKey: 0,\n isExpanded: false\n };\n // Toggle currently active tab\n this.handleTabClick = (event, tabIndex) => {\n this.setState({\n activeTabKey: tabIndex\n });\n };\n this.onToggle = isExpanded => {\n this.setState({\n isExpanded\n });\n };\n }\n render() {\n const {activeTabKey, isExpanded} = this.state;\n return (\n <Tabs activeKey={activeTabKey} onSelect={this.handleTabClick} isVertical expandable={{default: 'expandable', md: 'nonExpandable', lg: 'expandable'}} isExpanded={isExpanded} onToggle={this.onToggle} toggleText=\"Containers\">\n <Tab eventKey={0} title={<TabTitleText>Users</TabTitleText>}>\n Users\n </Tab>\n <Tab eventKey={1} title={<TabTitleText>Containers</TabTitleText>}>\n Containers\n </Tab>\n <Tab eventKey={2} title={<TabTitleText>Database</TabTitleText>}>\n Database\n </Tab>\n <Tab eventKey={3} title={<TabTitleText>Server</TabTitleText>}>\n Server\n </Tab>\n <Tab eventKey={4} title={<TabTitleText>System</TabTitleText>}>\n System\n </Tab>\n <Tab eventKey={6} title={<TabTitleText>Network</TabTitleText>}>\n Network\n </Tab>\n </Tabs>\n );\n }\n}","title":"Vertical expandable","lang":"js"}}>
|
|
374
|
+
|
|
375
|
+
</Example>,
|
|
376
|
+
'Vertical expandable uncontrolled': props =>
|
|
377
|
+
<Example {...pageData} {...props} {...{"code":"import React from 'react';\nimport { Tabs, Tab, TabTitleText, Checkbox } from '@patternfly/react-core';\nclass VerticalExpandableUncontrolledTabs extends React.Component {\n constructor(props) {\n super(props);\n this.state = {\n activeTabKey: 0\n };\n // Toggle currently active tab\n this.handleTabClick = (event, tabIndex) => {\n this.setState({\n activeTabKey: tabIndex\n });\n };\n }\n render() {\n const {activeTabKey} = this.state;\n return (\n <Tabs activeKey={activeTabKey} onSelect={this.handleTabClick} isVertical expandable={{default: 'expandable', md: 'nonExpandable', lg: 'expandable'}} defaultIsExpanded={false} toggleText=\"Containers\">\n <Tab eventKey={0} title={<TabTitleText>Users</TabTitleText>}>\n Users\n </Tab>\n <Tab eventKey={1} title={<TabTitleText>Containers</TabTitleText>}>\n Containers\n </Tab>\n <Tab eventKey={2} title={<TabTitleText>Database</TabTitleText>}>\n Database\n </Tab>\n <Tab eventKey={3} title={<TabTitleText>Server</TabTitleText>}>\n Server\n </Tab>\n <Tab eventKey={4} title={<TabTitleText>System</TabTitleText>}>\n System\n </Tab>\n <Tab eventKey={6} title={<TabTitleText>Network</TabTitleText>}>\n Network\n </Tab>\n </Tabs>\n );\n }\n}","title":"Vertical expandable uncontrolled","lang":"js"}}>
|
|
378
|
+
|
|
338
379
|
</Example>,
|
|
339
380
|
'Inset': props =>
|
|
340
381
|
<Example {...pageData} {...props} {...{"code":"import React from 'react';\nimport { Tabs, Tab, TabTitleText, Checkbox } from '@patternfly/react-core';\n\nclass InsetTabs extends React.Component {\n constructor(props) {\n super(props);\n this.state = {\n activeTabKey: 0,\n isBox: false\n };\n // Toggle currently active tab\n this.handleTabClick = (event, tabIndex) => {\n this.setState({\n activeTabKey: tabIndex\n });\n };\n\n this.toggleBox = checked => {\n this.setState({\n isBox: checked\n });\n };\n }\n\n render() {\n const {activeTabKey, isBox} = this.state;\n return (\n <div>\n <Tabs activeKey={activeTabKey} onSelect={this.handleTabClick} inset={{\n default: 'insetNone',\n md: 'insetSm',\n xl: 'inset2xl',\n '2xl': 'insetLg'\n }}\n isBox={isBox}>\n <Tab eventKey={0} title={<TabTitleText>Users</TabTitleText>}>\n Users\n </Tab>\n <Tab eventKey={1} title={<TabTitleText>Containers</TabTitleText>}>\n Containers\n </Tab>\n <Tab eventKey={2} title={<TabTitleText>Database</TabTitleText>}>\n Database\n </Tab>\n <Tab eventKey={3} title={<TabTitleText>Server</TabTitleText>}>\n Server\n </Tab>\n <Tab eventKey={4} title={<TabTitleText>System</TabTitleText>}>\n System\n </Tab>\n <Tab eventKey={6} title={<TabTitleText>Network</TabTitleText>}>\n Network\n </Tab>\n </Tabs>\n <div style={{marginTop: \"20px\"}}>\n <Checkbox\n label=\"isBox\"\n isChecked={isBox}\n onChange={this.toggleBox}\n aria-label=\"show box variation checkbox with inset\"\n id=\"toggle-box-inset\"\n name=\"toggle-box-inset\"\n />\n </div>\n </div>\n );\n }\n}","title":"Inset","lang":"js"}}>
|
|
@@ -401,6 +442,8 @@ Similarly the 'Tab content light variation' checkbox affects the TabContent back
|
|
|
401
442
|
{React.createElement(pageData.examples["Box light variation"])}
|
|
402
443
|
{React.createElement(pageData.examples["Default overflow"])}
|
|
403
444
|
{React.createElement(pageData.examples["Vertical"])}
|
|
445
|
+
{React.createElement(pageData.examples["Vertical expandable"])}
|
|
446
|
+
{React.createElement(pageData.examples["Vertical expandable uncontrolled"])}
|
|
404
447
|
{React.createElement(pageData.examples["Inset"])}
|
|
405
448
|
{React.createElement(pageData.examples["Page Insets"])}
|
|
406
449
|
{React.createElement(pageData.examples["Icons and text"])}
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -30,7 +30,8 @@ const pageData = {
|
|
|
30
30
|
"Filter tree menu",
|
|
31
31
|
"Flyout",
|
|
32
32
|
"Application launcher using menu components",
|
|
33
|
-
"Context selector using menu components"
|
|
33
|
+
"Context selector using menu components",
|
|
34
|
+
"Options menu using menu components"
|
|
34
35
|
]
|
|
35
36
|
};
|
|
36
37
|
pageData.liveContext = {
|
|
@@ -51,27 +52,27 @@ pageData.liveContext = {
|
|
|
51
52
|
};
|
|
52
53
|
pageData.examples = {
|
|
53
54
|
'Basic menu with toggle': props =>
|
|
54
|
-
<Example {...pageData} {...props} {...{"code":"import React from 'react';\nimport { MenuToggle, Menu, MenuContent, MenuList, MenuItem, Popper } from '@patternfly/react-core';\n\nBasicComposableMenu = () => {\n const [isOpen, setIsOpen] = React.useState(false);\n const toggleRef = React.useRef();\n const menuRef = React.useRef();\n\n const handleMenuKeys = event => {\n if (!isOpen) {\n return;\n }\n if (menuRef.current.contains(event.target) || toggleRef.current.contains(event.target)) {\n if (event.key === 'Escape' || event.key === 'Tab') {\n setIsOpen(!isOpen);\n toggleRef.current.focus();\n }\n }\n };\n\n const handleClickOutside = event => {\n if (isOpen && !menuRef.current.contains(event.target)) {\n setIsOpen(false);\n }\n };\n\n React.useEffect(() => {\n window.addEventListener('keydown', handleMenuKeys);\n window.addEventListener('click', handleClickOutside);\n return () => {\n window.removeEventListener('keydown', handleMenuKeys);\n window.removeEventListener('click', handleClickOutside);\n };\n }, [isOpen, menuRef]);\n\n const onToggleClick = ev => {\n ev.stopPropagation(); // Stop handleClickOutside from handling\n setTimeout(() => {\n const firstElement = menuRef.current.querySelector('li > button:not(:disabled)');\n
|
|
55
|
+
<Example {...pageData} {...props} {...{"code":"import React from 'react';\nimport { MenuToggle, Menu, MenuContent, MenuList, MenuItem, Popper } from '@patternfly/react-core';\n\nBasicComposableMenu = () => {\n const [isOpen, setIsOpen] = React.useState(false);\n const toggleRef = React.useRef();\n const menuRef = React.useRef();\n\n const handleMenuKeys = event => {\n if (!isOpen) {\n return;\n }\n if (menuRef.current.contains(event.target) || toggleRef.current.contains(event.target)) {\n if (event.key === 'Escape' || event.key === 'Tab') {\n setIsOpen(!isOpen);\n toggleRef.current.focus();\n }\n }\n };\n\n const handleClickOutside = event => {\n if (isOpen && !menuRef.current.contains(event.target)) {\n setIsOpen(false);\n }\n };\n\n React.useEffect(() => {\n window.addEventListener('keydown', handleMenuKeys);\n window.addEventListener('click', handleClickOutside);\n return () => {\n window.removeEventListener('keydown', handleMenuKeys);\n window.removeEventListener('click', handleClickOutside);\n };\n }, [isOpen, menuRef]);\n\n const onToggleClick = ev => {\n ev.stopPropagation(); // Stop handleClickOutside from handling\n setTimeout(() => {\n if (menuRef.current) {\n const firstElement = menuRef.current.querySelector('li > button:not(:disabled)');\n firstElement && firstElement.focus();\n }\n }, 0);\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 menu = (\n <Menu ref={menuRef} onSelect={(_ev, itemId) => console.log('selected', itemId)}>\n <MenuContent>\n <MenuList>\n <MenuItem itemId={0}>Action</MenuItem>\n <MenuItem itemId={1} to=\"#default-link2\" onClick={ev => ev.preventDefault()}>\n Link\n </MenuItem>\n <MenuItem isDisabled>Disabled Action</MenuItem>\n <MenuItem isDisabled to=\"#default-link4\">\n Disabled Link\n </MenuItem>\n </MenuList>\n </MenuContent>\n </Menu>\n );\n return <Popper trigger={toggle} popper={menu} isVisible={isOpen} />;\n};","title":"Basic menu with toggle","lang":"js"}}>
|
|
55
56
|
|
|
56
57
|
</Example>,
|
|
57
58
|
'Menu with actions': props =>
|
|
58
|
-
<Example {...pageData} {...props} {...{"code":"import React from 'react';\nimport {\n MenuToggle,\n Menu,\n MenuContent,\n MenuList,\n MenuItem,\n MenuGroup,\n MenuItemAction,\n Popper\n} from '@patternfly/react-core';\nimport BarsIcon from '@patternfly/react-icons/dist/esm/icons/bars-icon';\nimport ClipboardIcon from '@patternfly/react-icons/dist/esm/icons/clipboard-icon';\nimport CodeBranchIcon from '@patternfly/react-icons/dist/esm/icons/code-branch-icon';\nimport LayerGroupIcon from '@patternfly/react-icons/dist/esm/icons/layer-group-icon';\nimport CubeIcon from '@patternfly/react-icons/dist/esm/icons/cube-icon';\nimport TableIcon from '@patternfly/react-icons/dist/esm/icons/table-icon';\nimport BellIcon from '@patternfly/react-icons/dist/esm/icons/bell-icon';\n\nActionComposableMenu = () => {\n const [isOpen, setIsOpen] = React.useState(false);\n const [selectedItems, setSelectedItems] = React.useState([]);\n const toggleRef = React.useRef();\n const menuRef = React.useRef();\n\n const handleMenuKeys = event => {\n if (isOpen && menuRef.current.contains(event.target)) {\n if (event.key === 'Escape' || event.key === 'Tab') {\n setIsOpen(!isOpen);\n toggleRef.current.focus();\n }\n }\n };\n\n const handleClickOutside = event => {\n if (isOpen && !menuRef.current.contains(event.target)) {\n setIsOpen(false);\n }\n };\n\n React.useEffect(() => {\n window.addEventListener('keydown', handleMenuKeys);\n window.addEventListener('click', handleClickOutside);\n return () => {\n window.removeEventListener('keydown', handleMenuKeys);\n window.removeEventListener('click', handleClickOutside);\n };\n }, [isOpen, menuRef]);\n\n const onSelect = (event, itemId) => {\n if (selectedItems.includes(itemId)) {\n setSelectedItems(selectedItems.filter(id => id !== itemId));\n } else {\n setSelectedItems([...selectedItems, itemId]);\n }\n };\n\n const onToggleClick = ev => {\n ev.stopPropagation(); // Stop handleClickOutside from handling\n setTimeout(() => {\n const firstElement = menuRef.current.querySelector('li > button:not(:disabled)');\n
|
|
59
|
+
<Example {...pageData} {...props} {...{"code":"import React from 'react';\nimport {\n MenuToggle,\n Menu,\n MenuContent,\n MenuList,\n MenuItem,\n MenuGroup,\n MenuItemAction,\n Popper\n} from '@patternfly/react-core';\nimport BarsIcon from '@patternfly/react-icons/dist/esm/icons/bars-icon';\nimport ClipboardIcon from '@patternfly/react-icons/dist/esm/icons/clipboard-icon';\nimport CodeBranchIcon from '@patternfly/react-icons/dist/esm/icons/code-branch-icon';\nimport LayerGroupIcon from '@patternfly/react-icons/dist/esm/icons/layer-group-icon';\nimport CubeIcon from '@patternfly/react-icons/dist/esm/icons/cube-icon';\nimport TableIcon from '@patternfly/react-icons/dist/esm/icons/table-icon';\nimport BellIcon from '@patternfly/react-icons/dist/esm/icons/bell-icon';\n\nActionComposableMenu = () => {\n const [isOpen, setIsOpen] = React.useState(false);\n const [selectedItems, setSelectedItems] = React.useState([]);\n const toggleRef = React.useRef();\n const menuRef = React.useRef();\n\n const handleMenuKeys = event => {\n if (isOpen && menuRef.current.contains(event.target)) {\n if (event.key === 'Escape' || event.key === 'Tab') {\n setIsOpen(!isOpen);\n toggleRef.current.focus();\n }\n }\n };\n\n const handleClickOutside = event => {\n if (isOpen && !menuRef.current.contains(event.target)) {\n setIsOpen(false);\n }\n };\n\n React.useEffect(() => {\n window.addEventListener('keydown', handleMenuKeys);\n window.addEventListener('click', handleClickOutside);\n return () => {\n window.removeEventListener('keydown', handleMenuKeys);\n window.removeEventListener('click', handleClickOutside);\n };\n }, [isOpen, menuRef]);\n\n const onSelect = (event, itemId) => {\n if (selectedItems.includes(itemId)) {\n setSelectedItems(selectedItems.filter(id => id !== itemId));\n } else {\n setSelectedItems([...selectedItems, itemId]);\n }\n };\n\n const onToggleClick = ev => {\n ev.stopPropagation(); // Stop handleClickOutside from handling\n setTimeout(() => {\n if (menuRef.current) {\n const firstElement = menuRef.current.querySelector('li > button:not(:disabled)');\n firstElement && firstElement.focus();\n }\n }, 0);\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 menu = (\n <Menu\n ref={menuRef}\n onActionClick={(event, itemId, actionId) => console.log(`clicked on ${itemId} - ${actionId}`)}\n onSelect={onSelect}\n >\n <MenuGroup label=\"Actions\">\n <MenuList>\n <MenuItem\n isSelected={selectedItems.includes(0)}\n actions={\n <MenuItemAction\n icon={<CodeBranchIcon aria-hidden />}\n actionId=\"code\"\n onClick={() => console.log('clicked on code icon')}\n aria-label=\"Code\"\n />\n }\n description=\"This is a description\"\n itemId={0}\n >\n Item 1\n </MenuItem>\n <MenuItem\n isDisabled\n isSelected={selectedItems.includes(1)}\n actions={<MenuItemAction icon={<BellIcon aria-hidden />} actionId=\"alert\" aria-label=\"Alert\" />}\n description=\"This is a description\"\n itemId={1}\n >\n Item 2\n </MenuItem>\n <MenuItem\n isSelected={selectedItems.includes(2)}\n actions={<MenuItemAction icon={<ClipboardIcon aria-hidden />} actionId=\"copy\" aria-label=\"Copy\" />}\n itemId={2}\n >\n Item 3\n </MenuItem>\n <MenuItem\n isSelected={selectedItems.includes(3)}\n actions={<MenuItemAction icon={<BarsIcon aria-hidden />} actionId=\"expand\" aria-label=\"Expand\" />}\n description=\"This is a description\"\n itemId={3}\n >\n Item 4\n </MenuItem>\n </MenuList>\n </MenuGroup>\n </Menu>\n );\n\n return <Popper trigger={toggle} popper={menu} isVisible={isOpen} />;\n};","title":"Menu with actions","lang":"js"}}>
|
|
59
60
|
|
|
60
61
|
</Example>,
|
|
61
62
|
'Select menu': props =>
|
|
62
|
-
<Example {...pageData} {...props} {...{"code":"import React from 'react';\nimport { MenuToggle, Menu, MenuContent, MenuList, MenuItem, Popper } from '@patternfly/react-core';\nimport TableIcon from '@patternfly/react-icons/dist/esm/icons/table-icon';\n\nSelectComposableMenu = () => {\n const [isOpen, setIsOpen] = React.useState(false);\n const [selected, setSelected] = React.useState('Select a value');\n const toggleRef = React.useRef();\n const menuRef = React.useRef();\n\n const handleMenuKeys = event => {\n if (isOpen && menuRef.current.contains(event.target)) {\n if (event.key === 'Escape' || event.key === 'Tab') {\n setIsOpen(!isOpen);\n toggleRef.current.focus();\n }\n }\n };\n\n const handleClickOutside = event => {\n if (isOpen && !menuRef.current.contains(event.target)) {\n setIsOpen(false);\n }\n };\n\n React.useEffect(() => {\n window.addEventListener('keydown', handleMenuKeys);\n window.addEventListener('click', handleClickOutside);\n return () => {\n window.removeEventListener('keydown', handleMenuKeys);\n window.removeEventListener('click', handleClickOutside);\n };\n }, [isOpen, menuRef]);\n\n const onToggleClick = ev => {\n ev.stopPropagation(); // Stop handleClickOutside from handling\n setTimeout(() => {\n const firstElement = menuRef.current.querySelector('li > button:not(:disabled)');\n
|
|
63
|
+
<Example {...pageData} {...props} {...{"code":"import React from 'react';\nimport { MenuToggle, Menu, MenuContent, MenuList, MenuItem, Popper } from '@patternfly/react-core';\nimport TableIcon from '@patternfly/react-icons/dist/esm/icons/table-icon';\n\nSelectComposableMenu = () => {\n const [isOpen, setIsOpen] = React.useState(false);\n const [selected, setSelected] = React.useState('Select a value');\n const toggleRef = React.useRef();\n const menuRef = React.useRef();\n\n const handleMenuKeys = event => {\n if (isOpen && menuRef.current.contains(event.target)) {\n if (event.key === 'Escape' || event.key === 'Tab') {\n setIsOpen(!isOpen);\n toggleRef.current.focus();\n }\n }\n };\n\n const handleClickOutside = event => {\n if (isOpen && !menuRef.current.contains(event.target)) {\n setIsOpen(false);\n }\n };\n\n React.useEffect(() => {\n window.addEventListener('keydown', handleMenuKeys);\n window.addEventListener('click', handleClickOutside);\n return () => {\n window.removeEventListener('keydown', handleMenuKeys);\n window.removeEventListener('click', handleClickOutside);\n };\n }, [isOpen, menuRef]);\n\n const onToggleClick = ev => {\n ev.stopPropagation(); // Stop handleClickOutside from handling\n setTimeout(() => {\n if (menuRef.current) {\n const firstElement = menuRef.current.querySelector('li > button:not(:disabled)');\n firstElement && firstElement.focus();\n }\n }, 0);\n setIsOpen(!isOpen);\n };\n\n const toggle = (\n <MenuToggle ref={toggleRef} onClick={onToggleClick} isExpanded={isOpen}>\n {selected}\n </MenuToggle>\n );\n const menu = (\n <Menu ref={menuRef} id=\"select-menu\" onSelect={(_ev, itemId) => setSelected(itemId)} selected={selected}>\n <MenuContent>\n <MenuList>\n <MenuItem itemId=\"Option 1\">Option 1</MenuItem>\n <MenuItem itemId=\"Option 2\">Option 2</MenuItem>\n <MenuItem itemId=\"Option 3\" icon={<TableIcon aria-hidden />}>\n Option 3\n </MenuItem>\n </MenuList>\n </MenuContent>\n </Menu>\n );\n return <Popper trigger={toggle} popper={menu} isVisible={isOpen} />;\n};","title":"Select menu","lang":"js"}}>
|
|
63
64
|
|
|
64
65
|
</Example>,
|
|
65
66
|
'Drilldown menu with toggle': props =>
|
|
66
|
-
<Example {...pageData} {...props} {...{"code":"import React from 'react';\nimport {\n MenuToggle,\n Menu,\n MenuContent,\n MenuList,\n MenuItem,\n DrilldownMenu,\n Divider,\n Popper\n} from '@patternfly/react-core';\nimport StorageDomainIcon from '@patternfly/react-icons/dist/esm/icons/storage-domain-icon';\nimport CodeBranchIcon from '@patternfly/react-icons/dist/esm/icons/code-branch-icon';\nimport LayerGroupIcon from '@patternfly/react-icons/dist/esm/icons/layer-group-icon';\nimport CubeIcon from '@patternfly/react-icons/dist/esm/icons/cube-icon';\n\nDrilldownComposableMenu = () => {\n const [isOpen, setIsOpen] = React.useState(false);\n const [activeMenu, setActiveMenu] = React.useState('rootMenu');\n const [menuDrilledIn, setMenuDrilledIn] = React.useState([]);\n const [drilldownPath, setDrilldownPath] = React.useState([]);\n const [menuHeights, setMenuHeights] = React.useState({});\n const toggleRef = React.useRef();\n const menuRef = React.useRef();\n\n const handleMenuKeys = event => {\n if (isOpen && menuRef.current.contains(event.target)) {\n if (event.key === 'Escape' || event.key === 'Tab') {\n setIsOpen(!isOpen);\n toggleRef.current.focus();\n }\n }\n };\n\n const handleClickOutside = event => {\n if (isOpen && !menuRef.current.contains(event.target)) {\n setIsOpen(false);\n }\n };\n\n React.useEffect(() => {\n window.addEventListener('keydown', handleMenuKeys);\n window.addEventListener('click', handleClickOutside);\n return () => {\n window.removeEventListener('keydown', handleMenuKeys);\n window.removeEventListener('click', handleClickOutside);\n };\n }, [isOpen, menuRef]);\n\n const onToggleClick = ev => {\n ev.stopPropagation(); // Stop handleClickOutside from handling\n setTimeout(() => {\n const firstElement = menuRef.current.querySelector('li > button:not(:disabled)');\n
|
|
67
|
+
<Example {...pageData} {...props} {...{"code":"import React from 'react';\nimport {\n MenuToggle,\n Menu,\n MenuContent,\n MenuList,\n MenuItem,\n DrilldownMenu,\n Divider,\n Popper\n} from '@patternfly/react-core';\nimport StorageDomainIcon from '@patternfly/react-icons/dist/esm/icons/storage-domain-icon';\nimport CodeBranchIcon from '@patternfly/react-icons/dist/esm/icons/code-branch-icon';\nimport LayerGroupIcon from '@patternfly/react-icons/dist/esm/icons/layer-group-icon';\nimport CubeIcon from '@patternfly/react-icons/dist/esm/icons/cube-icon';\n\nDrilldownComposableMenu = () => {\n const [isOpen, setIsOpen] = React.useState(false);\n const [activeMenu, setActiveMenu] = React.useState('rootMenu');\n const [menuDrilledIn, setMenuDrilledIn] = React.useState([]);\n const [drilldownPath, setDrilldownPath] = React.useState([]);\n const [menuHeights, setMenuHeights] = React.useState({});\n const toggleRef = React.useRef();\n const menuRef = React.useRef();\n\n const handleMenuKeys = event => {\n if (isOpen && menuRef.current.contains(event.target)) {\n if (event.key === 'Escape' || event.key === 'Tab') {\n setIsOpen(!isOpen);\n toggleRef.current.focus();\n }\n }\n };\n\n const handleClickOutside = event => {\n if (isOpen && !menuRef.current.contains(event.target)) {\n setIsOpen(false);\n }\n };\n\n React.useEffect(() => {\n window.addEventListener('keydown', handleMenuKeys);\n window.addEventListener('click', handleClickOutside);\n return () => {\n window.removeEventListener('keydown', handleMenuKeys);\n window.removeEventListener('click', handleClickOutside);\n };\n }, [isOpen, menuRef]);\n\n const onToggleClick = ev => {\n ev.stopPropagation(); // Stop handleClickOutside from handling\n setTimeout(() => {\n if (menuRef.current) {\n const firstElement = menuRef.current.querySelector('li > button:not(:disabled)');\n firstElement && firstElement.focus();\n }\n }, 0);\n setIsOpen(!isOpen);\n setMenuDrilledIn([]);\n setDrilldownPath([]);\n setActiveMenu('rootMenu');\n };\n\n const drillIn = (fromMenuId, toMenuId, pathId) => {\n setMenuDrilledIn([...menuDrilledIn, fromMenuId]);\n setDrilldownPath([...drilldownPath, pathId]);\n setActiveMenu(toMenuId);\n };\n\n const drillOut = toMenuId => {\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, height) => {\n if (!menuHeights[menuId]) {\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\" 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\" 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\" 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\" 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\" 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\" 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={<StorageDomainIcon aria-hidden />}\n direction=\"down\"\n drilldownMenu={\n <DrilldownMenu id=\"drilldownMenuStorage\">\n <MenuItem itemId=\"group:storage\" icon={<StorageDomainIcon aria-hidden />} direction=\"up\">\n Add storage\n </MenuItem>\n <Divider component=\"li\" />\n <MenuItem icon={<CodeBranchIcon aria-hidden />} itemId=\"git\">\n From Git\n </MenuItem>\n <MenuItem icon={<LayerGroupIcon aria-hidden />} itemId=\"container\">\n Container Image\n </MenuItem>\n <MenuItem icon={<CubeIcon aria-hidden />} 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 <Popper trigger={toggle} popper={menu} isVisible={isOpen} />;\n};","title":"Drilldown menu with toggle","lang":"js"}}>
|
|
67
68
|
|
|
68
69
|
</Example>,
|
|
69
70
|
'Filter tree menu': props =>
|
|
70
|
-
<Example {...pageData} {...props} {...{"code":"import React from 'react';\nimport { MenuToggle, Menu, MenuContent, MenuGroup, MenuList, MenuItem, Popper, TreeView } from '@patternfly/react-core';\n\nFilterTreeComposableMenu = () => {\n const [isOpen, setIsOpen] = React.useState(false);\n const [checkedItems, setCheckedItems] = React.useState([]);\n const toggleRef = React.useRef();\n const menuRef = React.useRef();\n\n const statusOptions = [\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\n const isChecked = dataItem => checkedItems.some(item => item.id === dataItem.id);\n const areAllDescendantsChecked = dataItem =>\n dataItem.children ? dataItem.children.every(child => areAllDescendantsChecked(child)) : isChecked(dataItem);\n const areSomeDescendantsChecked = dataItem =>\n dataItem.children ? dataItem.children.some(child => areSomeDescendantsChecked(child)) : isChecked(dataItem);\n const flattenTree = tree => {\n var result = [];\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 mapTree = item => {\n const hasCheck = areAllDescendantsChecked(item);\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 filterItems = (item, checkedItem) => {\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, treeViewItem, tree) => {\n const checked = evt.target.checked;\n\n let options = [];\n switch (tree) {\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.map(opt => Object.assign({}, opt)).filter(item => filterItems(item, treeViewItem));\n const flatCheckedItems = flattenTree(checkedItemTree);\n\n setCheckedItems(\n prevState =>\n checked\n ? prevState.checkedItems.concat(\n flatCheckedItems.filter(item => !prevState.checkedItems.some(i => i.id === item.id))\n )\n : prevState.checkedItems.filter(item => !flatCheckedItems.some(i => i.id === item.id)),\n () => {\n console.log('Checked items: ', checkedItems);\n }\n );\n };\n\n const handleMenuKeys = event => {\n if (!isOpen) {\n return;\n }\n if (menuRef.current.contains(event.target) || toggleRef.current.contains(event.target)) {\n if (event.key === 'Escape' || event.key === 'Tab') {\n setIsOpen(!isOpen);\n toggleRef.current.focus();\n }\n }\n };\n\n const handleClickOutside = event => {\n if (isOpen && !menuRef.current.contains(event.target)) {\n setIsOpen(false);\n }\n };\n\n React.useEffect(() => {\n window.addEventListener('keydown', handleMenuKeys);\n window.addEventListener('click', handleClickOutside);\n return () => {\n window.removeEventListener('keydown', handleMenuKeys);\n window.removeEventListener('click', handleClickOutside);\n };\n }, [isOpen, menuRef]);\n\n const onToggleClick = ev => {\n ev.stopPropagation(); // Stop handleClickOutside from handling\n setTimeout(() => {\n
|
|
71
|
+
<Example {...pageData} {...props} {...{"code":"import React from 'react';\nimport { MenuToggle, Menu, MenuContent, MenuGroup, MenuList, MenuItem, Popper, TreeView } from '@patternfly/react-core';\n\nFilterTreeComposableMenu = () => {\n const [isOpen, setIsOpen] = React.useState(false);\n const [checkedItems, setCheckedItems] = React.useState([]);\n const toggleRef = React.useRef();\n const menuRef = React.useRef();\n\n const statusOptions = [\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\n const isChecked = dataItem => checkedItems.some(item => item.id === dataItem.id);\n const areAllDescendantsChecked = dataItem =>\n dataItem.children ? dataItem.children.every(child => areAllDescendantsChecked(child)) : isChecked(dataItem);\n const areSomeDescendantsChecked = dataItem =>\n dataItem.children ? dataItem.children.some(child => areSomeDescendantsChecked(child)) : isChecked(dataItem);\n const flattenTree = tree => {\n var result = [];\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 mapTree = item => {\n const hasCheck = areAllDescendantsChecked(item);\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 filterItems = (item, checkedItem) => {\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, treeViewItem, tree) => {\n const checked = evt.target.checked;\n\n let options = [];\n switch (tree) {\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.map(opt => Object.assign({}, opt)).filter(item => filterItems(item, treeViewItem));\n const flatCheckedItems = flattenTree(checkedItemTree);\n\n setCheckedItems(\n prevState =>\n checked\n ? prevState.checkedItems.concat(\n flatCheckedItems.filter(item => !prevState.checkedItems.some(i => i.id === item.id))\n )\n : prevState.checkedItems.filter(item => !flatCheckedItems.some(i => i.id === item.id)),\n () => {\n console.log('Checked items: ', checkedItems);\n }\n );\n };\n\n const handleMenuKeys = event => {\n if (!isOpen) {\n return;\n }\n if (menuRef.current.contains(event.target) || toggleRef.current.contains(event.target)) {\n if (event.key === 'Escape' || event.key === 'Tab') {\n setIsOpen(!isOpen);\n toggleRef.current.focus();\n }\n }\n };\n\n const handleClickOutside = event => {\n if (isOpen && !menuRef.current.contains(event.target)) {\n setIsOpen(false);\n }\n };\n\n React.useEffect(() => {\n window.addEventListener('keydown', handleMenuKeys);\n window.addEventListener('click', handleClickOutside);\n return () => {\n window.removeEventListener('keydown', handleMenuKeys);\n window.removeEventListener('click', handleClickOutside);\n };\n }, [isOpen, menuRef]);\n\n const onToggleClick = ev => {\n ev.stopPropagation(); // Stop handleClickOutside from handling\n setTimeout(() => {\n if (menuRef.current) {\n const firstElement = menuRef.current.querySelector('li > button:not(:disabled)');\n firstElement && firstElement.focus();\n }\n }, 0);\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 <Menu ref={menuRef} onSelect={(_ev, itemId) => console.log('selected', itemId)}>\n <MenuContent>\n <MenuList>\n <MenuGroup label=\"Status\">\n <TreeView\n data={statusMapped}\n hasBadges\n hasChecks\n onCheck={(event, item, parentItem) => onCheck(event, item, 'status')}\n />\n </MenuGroup>\n <MenuGroup label=\"Role\">\n <TreeView\n data={roleMapped}\n hasBadges\n hasChecks\n onCheck={(event, item, parentItem) => onCheck(event, item, 'role')}\n />\n </MenuGroup>\n </MenuList>\n </MenuContent>\n </Menu>\n );\n return <Popper trigger={toggle} popper={menu} isVisible={isOpen} />;\n};","title":"Filter tree menu","lang":"js"}}>
|
|
71
72
|
|
|
72
73
|
</Example>,
|
|
73
74
|
'Flyout': props =>
|
|
74
|
-
<Example {...pageData} {...props} {...{"code":"import React from 'react';\nimport { MenuToggle, Menu, MenuContent, MenuGroup, MenuList, MenuItem, Popper } from '@patternfly/react-core';\n\nMenuWithFlyout = () => {\n const [isOpen, setIsOpen] = React.useState(false);\n const menuRef = React.useRef();\n\n const handleMenuKeys = event => {\n if (!isOpen) {\n return;\n }\n if (menuRef.current.contains(event.target) || toggleRef.current.contains(event.target)) {\n if (event.key === 'Escape' || event.key === 'Tab') {\n setIsOpen(!isOpen);\n toggleRef.current.focus();\n }\n }\n };\n\n const handleClickOutside = event => {\n if (isOpen && !menuRef.current.contains(event.target)) {\n setIsOpen(false);\n }\n };\n\n React.useEffect(() => {\n window.addEventListener('keydown', handleMenuKeys);\n window.addEventListener('click', handleClickOutside);\n return () => {\n window.removeEventListener('keydown', handleMenuKeys);\n window.removeEventListener('click', handleClickOutside);\n };\n }, [isOpen, menuRef]);\n\n const onSelect = itemId => console.log('selected', itemId);\n\n const numFlyouts = 15;\n const FlyoutMenu = ({ depth, children }) => (\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(numFlyouts - depth).keys()].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 let curFlyout = <FlyoutMenu depth={1} />;\n for (let i = 2; i < numFlyouts - 1; i++) {\n curFlyout = <FlyoutMenu depth={i}>{curFlyout}</FlyoutMenu>;\n }\n\n const onToggleClick = ev => {\n ev.stopPropagation(); // Stop handleClickOutside from handling\n setTimeout(() => {\n const firstElement = menuRef.current.querySelector('li > button:not(:disabled)');\n
|
|
75
|
+
<Example {...pageData} {...props} {...{"code":"import React from 'react';\nimport { MenuToggle, Menu, MenuContent, MenuGroup, MenuList, MenuItem, Popper } from '@patternfly/react-core';\n\nMenuWithFlyout = () => {\n const [isOpen, setIsOpen] = React.useState(false);\n const menuRef = React.useRef();\n\n const handleMenuKeys = event => {\n if (!isOpen) {\n return;\n }\n if (menuRef.current.contains(event.target) || toggleRef.current.contains(event.target)) {\n if (event.key === 'Escape' || event.key === 'Tab') {\n setIsOpen(!isOpen);\n toggleRef.current.focus();\n }\n }\n };\n\n const handleClickOutside = event => {\n if (isOpen && !menuRef.current.contains(event.target)) {\n setIsOpen(false);\n }\n };\n\n React.useEffect(() => {\n window.addEventListener('keydown', handleMenuKeys);\n window.addEventListener('click', handleClickOutside);\n return () => {\n window.removeEventListener('keydown', handleMenuKeys);\n window.removeEventListener('click', handleClickOutside);\n };\n }, [isOpen, menuRef]);\n\n const onSelect = itemId => console.log('selected', itemId);\n\n const numFlyouts = 15;\n const FlyoutMenu = ({ depth, children }) => (\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(numFlyouts - depth).keys()].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 let curFlyout = <FlyoutMenu depth={1} />;\n for (let i = 2; i < numFlyouts - 1; i++) {\n curFlyout = <FlyoutMenu depth={i}>{curFlyout}</FlyoutMenu>;\n }\n\n const onToggleClick = ev => {\n ev.stopPropagation(); // Stop handleClickOutside from handling\n setTimeout(() => {\n if (menuRef.current) {\n const firstElement = menuRef.current.querySelector('li > button:not(:disabled)');\n firstElement && firstElement.focus();\n }\n }, 0);\n setIsOpen(!isOpen);\n };\n\n const toggle = (\n <MenuToggle 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 <Popper trigger={toggle} popper={menu} isVisible={isOpen} popperMatchesTriggerWidth={false} />;\n};","title":"Flyout","lang":"js"}}>
|
|
75
76
|
|
|
76
77
|
<p {...{"className":"ws-p"}}>
|
|
77
78
|
{`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, `}
|
|
@@ -88,11 +89,15 @@ pageData.examples = {
|
|
|
88
89
|
</p>
|
|
89
90
|
</Example>,
|
|
90
91
|
'Application launcher using menu components': props =>
|
|
91
|
-
<Example {...pageData} {...props} {...{"code":"import React from 'react';\nimport {\n MenuToggle,\n Menu,\n MenuContent,\n MenuList,\n MenuItem,\n MenuGroup,\n MenuInput,\n Popper,\n Tooltip,\n Divider,\n TextInput\n} from '@patternfly/react-core';\nimport { Link } from '@reach/router';\nimport ThIcon from '@patternfly/react-icons/dist/js/icons/th-icon';\nimport pfIcon from './examples/pf-logo-small.svg';\n\nMenuAppLauncher = () => {\n const [isOpen, setIsOpen] = React.useState(false);\n const [refFullOptions, setRefFullOptions] = React.useState();\n const [favorites, setFavorites] = React.useState([]);\n const [filteredIds, setFilteredIds] = React.useState(['*']);\n const toggleRef = React.useRef();\n const menuRef = React.useRef();\n const containerRef = React.useRef();\n\n const handleMenuKeys = event => {\n if (!isOpen) {\n return;\n }\n if (menuRef.current.contains(event.target) || toggleRef.current.contains(event.target)) {\n if (event.key === 'Escape') {\n setIsOpen(!isOpen);\n toggleRef.current.focus();\n }\n }\n };\n\n const handleClickOutside = event => {\n if (isOpen && !menuRef.current.contains(event.target)) {\n setIsOpen(false);\n }\n };\n\n const onToggleClick = ev => {\n ev.stopPropagation(); // Stop handleClickOutside from handling\n setTimeout(() => {\n
|
|
92
|
+
<Example {...pageData} {...props} {...{"code":"import React from 'react';\nimport {\n MenuToggle,\n Menu,\n MenuContent,\n MenuList,\n MenuItem,\n MenuGroup,\n MenuInput,\n Popper,\n Tooltip,\n Divider,\n TextInput\n} from '@patternfly/react-core';\nimport { Link } from '@reach/router';\nimport ThIcon from '@patternfly/react-icons/dist/js/icons/th-icon';\nimport pfIcon from './examples/pf-logo-small.svg';\n\nMenuAppLauncher = () => {\n const [isOpen, setIsOpen] = React.useState(false);\n const [refFullOptions, setRefFullOptions] = React.useState();\n const [favorites, setFavorites] = React.useState([]);\n const [filteredIds, setFilteredIds] = React.useState(['*']);\n const toggleRef = React.useRef();\n const menuRef = React.useRef();\n const containerRef = React.useRef();\n\n const handleMenuKeys = event => {\n if (!isOpen) {\n return;\n }\n if (menuRef.current.contains(event.target) || toggleRef.current.contains(event.target)) {\n if (event.key === 'Escape') {\n setIsOpen(!isOpen);\n toggleRef.current.focus();\n }\n }\n };\n\n const handleClickOutside = event => {\n if (isOpen && !menuRef.current.contains(event.target)) {\n setIsOpen(false);\n }\n };\n\n const onToggleClick = ev => {\n ev.stopPropagation(); // Stop handleClickOutside from handling\n setTimeout(() => {\n if (menuRef.current) {\n const firstElement = menuRef.current.querySelector('li > button,input:not(:disabled)');\n firstElement && firstElement.focus();\n setRefFullOptions(Array.from(menuRef.current.querySelectorAll('li:not(li[role=separator])')));\n }\n }, 0);\n setIsOpen(!isOpen);\n };\n\n React.useEffect(() => {\n window.addEventListener('keydown', handleMenuKeys);\n window.addEventListener('click', handleClickOutside);\n\n return () => {\n window.removeEventListener('keydown', handleMenuKeys);\n window.removeEventListener('click', handleClickOutside);\n };\n }, [isOpen, menuRef]);\n\n const toggle = (\n <MenuToggle\n aria-label=\"Toggle\"\n ref={toggleRef}\n variant=\"plain\"\n onClick={onToggleClick}\n isExpanded={isOpen}\n style={{ width: 'auto' }}\n >\n <ThIcon />\n </MenuToggle>\n );\n\n const menuItems = [\n <MenuGroup key=\"group1\" label=\"Group 1\">\n <MenuList>\n <MenuItem itemId=\"0\" id=\"0\" isFavorited={favorites.includes('0')}>\n Application 1\n </MenuItem>\n <MenuItem\n itemId=\"1\"\n id=\"1\"\n isFavorited={favorites.includes('1')}\n to=\"#default-link2\"\n onClick={ev => ev.preventDefault()}\n >\n Application 2\n </MenuItem>\n </MenuList>\n </MenuGroup>,\n <Divider key=\"group1-divider\" />,\n <MenuGroup key=\"group2\" label=\"Group 2\">\n <MenuList>\n <MenuItem\n itemId=\"2\"\n id=\"2\"\n isFavorited={favorites.includes('2')}\n component={props => <Link {...props} to=\"#router-link\" />}\n >\n @reach/router Link\n </MenuItem>\n <MenuItem\n itemId=\"3\"\n id=\"3\"\n isFavorited={favorites.includes('3')}\n isExternalLink\n icon={<img src={pfIcon} />}\n component={props => <Link {...props} to=\"#router-link2\" />}\n >\n @reach/router Link with icon\n </MenuItem>\n </MenuList>\n </MenuGroup>,\n <Divider key=\"group2-divider\" />,\n <MenuList key=\"other-items\">\n <MenuItem key=\"tooltip-app\" isFavorited={favorites.includes('4')} itemId=\"4\" id=\"4\">\n <Tooltip content={<div>Launch Application 3</div>} position=\"right\">\n <span>Application 3 with tooltip</span>\n </Tooltip>\n </MenuItem>\n <MenuItem key=\"disabled-app\" itemId=\"5\" id=\"5\" isDisabled>\n Unavailable Application\n </MenuItem>\n </MenuList>\n ];\n\n const createFavorites = favIds => {\n let favorites = [];\n\n menuItems.forEach(item => {\n if (item.type === MenuList) {\n item.props.children.filter(child => {\n if (favIds.includes(child.props.itemId)) {\n favorites.push(child);\n }\n });\n } else if (item.type === MenuGroup) {\n item.props.children.props.children.filter(child => {\n if (favIds.includes(child.props.itemId)) {\n favorites.push(child);\n }\n });\n } else {\n if (favIds.includes(item.props.itemId)) {\n favorites.push(item);\n }\n }\n });\n\n return favorites;\n };\n\n const filterItems = (items, filteredIds) => {\n if (filteredIds.length === 1 && filteredIds[0] === '*') {\n return items;\n }\n let keepDivider = false;\n let filteredCopy = items\n .map(group => {\n if (group.type === MenuGroup) {\n let filteredGroup = React.cloneElement(group, {\n children: React.cloneElement(group.props.children, {\n children: group.props.children.props.children.filter(child => {\n if (filteredIds.includes(child.props.itemId)) {\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 === MenuList) {\n let filteredGroup = React.cloneElement(group, {\n children: group.props.children.filter(child => {\n if (filteredIds.includes(child.props.itemId)) {\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.itemId)) {\n return group;\n }\n }\n })\n .filter(newGroup => newGroup);\n\n if (filteredCopy.length > 0) {\n let lastGroup = filteredCopy.pop();\n if (lastGroup.type !== Divider) {\n filteredCopy.push(lastGroup);\n }\n }\n\n return filteredCopy;\n };\n\n const onTextChange = textValue => {\n if (textValue === '') {\n setFilteredIds(['*']);\n return;\n }\n\n const filteredIds = refFullOptions\n .filter(item => item.innerText.toLowerCase().includes(textValue.toString().toLowerCase()))\n .map(item => item.id);\n setFilteredIds(filteredIds);\n };\n\n const onFavorite = (event, itemId, actionId) => {\n event.stopPropagation();\n if (actionId === 'fav') {\n const isFavorite = favorites.includes(itemId);\n if (isFavorite) {\n setFavorites(favorites.filter(fav => fav !== itemId));\n } else {\n setFavorites([...favorites, itemId]);\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(<MenuItem key=\"no-items\">No results found</MenuItem>);\n }\n\n const menu = (\n <Menu ref={menuRef} onActionClick={onFavorite} onSelect={(_ev, itemId) => console.log('selected', itemId)}>\n <MenuInput>\n <TextInput\n aria-label=\"Filter menu items\"\n iconVariant=\"search\"\n type=\"search\"\n onChange={value => onTextChange(value)}\n />\n </MenuInput>\n <Divider />\n <MenuContent>\n {filteredFavorites.length > 0 && (\n <React.Fragment>\n <MenuGroup key=\"favorites-group\" label=\"Favorites\">\n <MenuList>{filteredFavorites}</MenuList>\n </MenuGroup>\n <Divider key=\"favorites-divider\" />\n </React.Fragment>\n )}\n {filteredItems}\n </MenuContent>\n </Menu>\n );\n return (\n <div ref={containerRef}>\n <Popper\n trigger={toggle}\n popper={menu}\n isVisible={isOpen}\n popperMatchesTriggerWidth={false}\n appendTo={containerRef.current}\n />\n </div>\n );\n};","title":"Application launcher using menu components","lang":"js"}}>
|
|
92
93
|
|
|
93
94
|
</Example>,
|
|
94
95
|
'Context selector using menu components': props =>
|
|
95
|
-
<Example {...pageData} {...props} {...{"code":"import React from 'react';\nimport {\n MenuToggle,\n Menu,\n MenuContent,\n MenuFooter,\n MenuList,\n MenuItem,\n MenuGroup,\n MenuInput,\n Popper,\n Tooltip,\n Divider,\n TextInput,\n InputGroup,\n Button\n} from '@patternfly/react-core';\nimport { Link } from '@reach/router';\nimport SearchIcon from '@patternfly/react-icons/dist/esm/icons/search-icon';\nimport pfIcon from './examples/pf-logo-small.svg';\n\nMenuContextSelector = () => {\n const items = [\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] = React.useState(false);\n const [selected, setSelected] = React.useState(items[0]);\n const [filteredItems, setFilteredItems] = React.useState(items);\n const [searchInputValue, setSearchInputValue] = React.useState('');\n const toggleRef = React.useRef();\n const menuRef = React.useRef();\n const menuFooterBtnRef = React.useRef();\n\n const handleMenuKeys = event => {\n if (!isOpen) {\n return;\n }\n if (menuFooterBtnRef.current.contains(event.target)) {\n if (event.key === 'Tab') {\n if (event.shiftKey) {\n return;\n }\n setIsOpen(!isOpen);\n toggleRef.current.focus();\n }\n }\n if (menuRef.current.contains(event.target)) {\n if (event.key === 'Escape') {\n setIsOpen(!isOpen);\n toggleRef.current.focus();\n }\n }\n };\n\n const handleClickOutside = event => {\n if (isOpen && !menuRef.current.contains(event.target)) {\n setIsOpen(false);\n }\n };\n\n React.useEffect(() => {\n window.addEventListener('keydown', handleMenuKeys);\n window.addEventListener('click', handleClickOutside);\n\n return () => {\n window.removeEventListener('keydown', handleMenuKeys);\n window.removeEventListener('click', handleClickOutside);\n };\n }, [isOpen, menuRef]);\n\n const onToggleClick = ev => {\n ev.stopPropagation(); // Stop handleClickOutside from handling\n setTimeout(() => {\n const firstElement = menuRef.current.querySelector('li > button,input:not(:disabled)');\n
|
|
96
|
+
<Example {...pageData} {...props} {...{"code":"import React from 'react';\nimport {\n MenuToggle,\n Menu,\n MenuContent,\n MenuFooter,\n MenuList,\n MenuItem,\n MenuGroup,\n MenuInput,\n Popper,\n Tooltip,\n Divider,\n TextInput,\n InputGroup,\n Button\n} from '@patternfly/react-core';\nimport { Link } from '@reach/router';\nimport SearchIcon from '@patternfly/react-icons/dist/esm/icons/search-icon';\nimport pfIcon from './examples/pf-logo-small.svg';\n\nMenuContextSelector = () => {\n const items = [\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] = React.useState(false);\n const [selected, setSelected] = React.useState(items[0]);\n const [filteredItems, setFilteredItems] = React.useState(items);\n const [searchInputValue, setSearchInputValue] = React.useState('');\n const toggleRef = React.useRef();\n const menuRef = React.useRef();\n const menuFooterBtnRef = React.useRef();\n\n const handleMenuKeys = event => {\n if (!isOpen) {\n return;\n }\n if (menuFooterBtnRef.current.contains(event.target)) {\n if (event.key === 'Tab') {\n if (event.shiftKey) {\n return;\n }\n setIsOpen(!isOpen);\n toggleRef.current.focus();\n }\n }\n if (menuRef.current.contains(event.target)) {\n if (event.key === 'Escape') {\n setIsOpen(!isOpen);\n toggleRef.current.focus();\n }\n }\n };\n\n const handleClickOutside = event => {\n if (isOpen && !menuRef.current.contains(event.target)) {\n setIsOpen(false);\n }\n };\n\n React.useEffect(() => {\n window.addEventListener('keydown', handleMenuKeys);\n window.addEventListener('click', handleClickOutside);\n\n return () => {\n window.removeEventListener('keydown', handleMenuKeys);\n window.removeEventListener('click', handleClickOutside);\n };\n }, [isOpen, menuRef]);\n\n const onToggleClick = ev => {\n ev.stopPropagation(); // Stop handleClickOutside from handling\n setTimeout(() => {\n if (menuRef.current) {\n const firstElement = menuRef.current.querySelector('li > button,input:not(:disabled)');\n firstElement && firstElement.focus();\n }\n }, 0);\n setIsOpen(!isOpen);\n };\n\n const toggle = (\n <MenuToggle ref={toggleRef} onClick={onToggleClick} isExpanded={isOpen}>\n {selected}\n </MenuToggle>\n );\n\n const onSelect = (event, itemId) => {\n setSelected(itemId);\n setIsOpen(!isOpen);\n };\n\n const onSearchInputChange = value => {\n setSearchInputValue(value);\n };\n\n const onSearchButtonClick = event => {\n const filtered =\n searchInputValue === ''\n ? items\n : items.filter(str => str.toLowerCase().indexOf(searchInputValue.toLowerCase()) !== -1);\n\n setFilteredItems(filtered || []);\n setIsOpen(true); // Keep menu open after search executed\n };\n\n const onEnterPressed = event => {\n if (event.key === 'Enter') {\n onSearchButtonClick(event);\n }\n };\n\n const menu = (\n <Menu ref={menuRef} id=\"context-selector\" onSelect={onSelect}>\n <MenuInput>\n <InputGroup>\n <TextInput\n value={searchInputValue}\n type=\"search\"\n placeholder=\"Search\"\n onChange={onSearchInputChange}\n onKeyPress={onEnterPressed}\n aria-labelledby=\"pf-context-selector-search-button-id-1\"\n />\n <Button\n variant={ButtonVariant.control}\n aria-label=\"Search menu items\"\n id=\"pf-context-selector-search-button-id-1\"\n onClick={onSearchButtonClick}\n >\n <SearchIcon aria-hidden=\"true\" />\n </Button>\n </InputGroup>\n </MenuInput>\n <Divider />\n <MenuContent maxMenuHeight=\"200px\">\n <MenuList>\n {filteredItems.map((item, index) => (\n <MenuItem itemId={item} key={index}>\n {item}\n </MenuItem>\n ))}\n </MenuList>\n </MenuContent>\n <MenuFooter>\n <Button ref={menuFooterBtnRef} variant=\"link\" isInline>\n Action\n </Button>\n </MenuFooter>\n </Menu>\n );\n return <Popper trigger={toggle} popper={menu} isVisible={isOpen} />;\n};","title":"Context selector using menu components","lang":"js"}}>
|
|
97
|
+
|
|
98
|
+
</Example>,
|
|
99
|
+
'Options menu using menu components': props =>
|
|
100
|
+
<Example {...pageData} {...props} {...{"code":"import React from 'react';\nimport {\n MenuToggle,\n Menu,\n MenuContent,\n MenuList,\n MenuItem,\n MenuGroup,\n Popper,\n Divider\n} from '@patternfly/react-core';\n\nMenuOptionsMenu = () => {\n\n const [isOpen, setIsOpen] = React.useState(false);\n const [selected, setSelected] = React.useState(undefined);\n const toggleRef = React.useRef();\n const menuRef = React.useRef();\n\n const handleMenuKeys = event => {\n if (isOpen && menuRef.current.contains(event.target)) {\n if (event.key === 'Escape' || event.key === 'Tab') {\n setIsOpen(!isOpen);\n toggleRef.current.focus();\n }\n }\n };\n\n const handleClickOutside = event => {\n if (isOpen && !menuRef.current.contains(event.target)) {\n setIsOpen(false);\n }\n };\n\n React.useEffect(() => {\n window.addEventListener('keydown', handleMenuKeys);\n window.addEventListener('click', handleClickOutside);\n\n return () => {\n window.removeEventListener('keydown', handleMenuKeys);\n window.removeEventListener('click', handleClickOutside);\n };\n }, [isOpen, menuRef]);\n\n const onToggleClick = ev => {\n ev.stopPropagation(); // Stop handleClickOutside from handling\n setTimeout(() => {\n if (menuRef.current) {\n const firstElement = menuRef.current.querySelector('li > button,input:not(:disabled)');\n firstElement && firstElement.focus();\n }\n }, 0);\n setIsOpen(!isOpen);\n };\n\n const toggle = (\n <MenuToggle ref={toggleRef} onClick={onToggleClick} isExpanded={isOpen}>\n Options menu\n </MenuToggle>\n );\n\n const menu = (\n <Menu ref={menuRef} id=\"options-menu\" selected={selected} onSelect={(_ev, itemId) => setSelected(itemId)}>\n <MenuContent>\n <MenuList>\n <MenuItem itemId={0}>Option 1</MenuItem>\n <MenuItem itemId={1} isDisabled>Disabled Option</MenuItem>\n <Divider key=\"group1-divider\" />\n <MenuGroup label=\"Group 1\">\n <MenuList>\n <MenuItem itemId={2}>Option 1</MenuItem>\n <MenuItem itemId={3}>Option 2</MenuItem>\n </MenuList>\n </MenuGroup>\n <Divider key=\"group2-divider\" />\n <MenuGroup label=\"Group 2\">\n <MenuList>\n <MenuItem itemId={4}>Option 1</MenuItem>\n <MenuItem itemId={5}>Option 2</MenuItem>\n </MenuList>\n </MenuGroup>\n </MenuList>\n </MenuContent>\n </Menu>\n );\n return <Popper trigger={toggle} popper={menu} isVisible={isOpen} />;\n};","title":"Options menu using menu components","lang":"js"}}>
|
|
96
101
|
|
|
97
102
|
</Example>
|
|
98
103
|
};
|
|
@@ -121,6 +126,7 @@ const Component = () => (
|
|
|
121
126
|
{React.createElement(pageData.examples["Flyout"])}
|
|
122
127
|
{React.createElement(pageData.examples["Application launcher using menu components"])}
|
|
123
128
|
{React.createElement(pageData.examples["Context selector using menu components"])}
|
|
129
|
+
{React.createElement(pageData.examples["Options menu using menu components"])}
|
|
124
130
|
</React.Fragment>
|
|
125
131
|
);
|
|
126
132
|
Component.displayName = 'DemosComposableMenuReactDemosDocs';
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/src/generated/demos/primary-detail/react-demos/primary-detail-simple-list-in-card.png
CHANGED
|
Binary file
|
package/src/generated/index.js
CHANGED
|
@@ -253,8 +253,8 @@ module.exports = {
|
|
|
253
253
|
'/components/drawer/react': {
|
|
254
254
|
id: "Drawer",
|
|
255
255
|
title: "Drawer",
|
|
256
|
-
toc: [{"text":"Examples"},[{"text":"Basic"},{"text":"Panel on right"},{"text":"Panel on left"},{"text":"Panel on bottom"},{"text":"Basic inline"},{"text":"Inline panel on right"},{"text":"Inline panel on left"},{"text":"Stacked content body elements"},{"text":"
|
|
257
|
-
examples: ["Basic","Panel on right","Panel on left","Panel on bottom","Basic inline","Inline panel on right","Inline panel on left","Stacked content body elements","
|
|
256
|
+
toc: [{"text":"Examples"},[{"text":"Basic"},{"text":"Panel on right"},{"text":"Panel on left"},{"text":"Panel on bottom"},{"text":"Basic inline"},{"text":"Inline panel on right"},{"text":"Inline panel on left"},{"text":"Stacked content body elements"},{"text":"Modified content padding"},{"text":"Modified panel padding"},{"text":"Additional section above drawer content"},{"text":"Static drawer"},{"text":"Breakpoint"},{"text":"Resizable on right"},{"text":"Resizable on left"},{"text":"Resizable on bottom"},{"text":"Resizable on inline"},{"text":"Panel with light-200 background"}]],
|
|
257
|
+
examples: ["Basic","Panel on right","Panel on left","Panel on bottom","Basic inline","Inline panel on right","Inline panel on left","Stacked content body elements","Modified content padding","Modified panel padding","Additional section above drawer content","Static drawer","Breakpoint","Resizable on right","Resizable on left","Resizable on bottom","Resizable on inline","Panel with light-200 background"],
|
|
258
258
|
section: "components",
|
|
259
259
|
source: "react",
|
|
260
260
|
Component: () => import(/* webpackChunkName: "components/drawer/react/index" */ './components/drawer/react')
|
|
@@ -487,8 +487,8 @@ module.exports = {
|
|
|
487
487
|
'/components/page/react': {
|
|
488
488
|
id: "Page",
|
|
489
489
|
title: "Page",
|
|
490
|
-
toc: [{"text":"Examples"},[{"text":"Vertical nav"},{"text":"Horizontal nav"},{"text":"Tertiary nav"},{"text":"Main Section Padding"},{"text":"With or without fill"},{"text":"Uncontrolled nav"},{"text":"Group section"}]],
|
|
491
|
-
examples: ["Vertical nav","Horizontal nav","Tertiary nav","Main Section Padding","With or without fill","Uncontrolled nav","Group section"],
|
|
490
|
+
toc: [{"text":"Examples"},[{"text":"Vertical nav"},{"text":"Horizontal nav"},{"text":"Tertiary nav"},{"text":"Main Section Padding"},{"text":"With or without fill"},{"text":"Uncontrolled nav"},{"text":"Group section"},{"text":"Vertical nav using PageHeader component"}]],
|
|
491
|
+
examples: ["Vertical nav","Horizontal nav","Tertiary nav","Main Section Padding","With or without fill","Uncontrolled nav","Group section","Vertical nav using PageHeader component"],
|
|
492
492
|
section: "components",
|
|
493
493
|
source: "react",
|
|
494
494
|
Component: () => import(/* webpackChunkName: "components/page/react/index" */ './components/page/react')
|
|
@@ -614,8 +614,8 @@ module.exports = {
|
|
|
614
614
|
'/components/tabs/react': {
|
|
615
615
|
id: "Tabs",
|
|
616
616
|
title: "Tabs",
|
|
617
|
-
toc: [{"text":"Examples"},[{"text":"Default"},{"text":"Uncontrolled"},{"text":"Box light variation"},{"text":"Default overflow"},{"text":"Vertical"},{"text":"Inset"},{"text":"Page Insets"},{"text":"Icons and text"},{"text":"Tabs with sub tabs"},{"text":"Filled"},{"text":"Filled with icons"},{"text":"Using the nav element"},{"text":"Sub nav using the nav element"},{"text":"Separate content"},{"text":"Children mounting on click"},{"text":"Unmounting invisible children"},{"text":"Toggled separate content"}]],
|
|
618
|
-
examples: ["Default","Uncontrolled","Box light variation","Default overflow","Vertical","Inset","Page Insets","Icons and text","Tabs with sub tabs","Filled","Filled with icons","Using the nav element","Sub nav using the nav element","Separate content","Children mounting on click","Unmounting invisible children","Toggled separate content"],
|
|
617
|
+
toc: [{"text":"Examples"},[{"text":"Default"},{"text":"Uncontrolled"},{"text":"Box light variation"},{"text":"Default overflow"},{"text":"Vertical"},{"text":"Vertical expandable"},{"text":"Vertical expandable uncontrolled"},{"text":"Inset"},{"text":"Page Insets"},{"text":"Icons and text"},{"text":"Tabs with sub tabs"},{"text":"Filled"},{"text":"Filled with icons"},{"text":"Using the nav element"},{"text":"Sub nav using the nav element"},{"text":"Separate content"},{"text":"Children mounting on click"},{"text":"Unmounting invisible children"},{"text":"Toggled separate content"}]],
|
|
618
|
+
examples: ["Default","Uncontrolled","Box light variation","Default overflow","Vertical","Vertical expandable","Vertical expandable uncontrolled","Inset","Page Insets","Icons and text","Tabs with sub tabs","Filled","Filled with icons","Using the nav element","Sub nav using the nav element","Separate content","Children mounting on click","Unmounting invisible children","Toggled separate content"],
|
|
619
619
|
section: "components",
|
|
620
620
|
source: "react",
|
|
621
621
|
Component: () => import(/* webpackChunkName: "components/tabs/react/index" */ './components/tabs/react')
|
|
@@ -821,8 +821,8 @@ module.exports = {
|
|
|
821
821
|
'/demos/composable-menu/react-demos': {
|
|
822
822
|
id: "Composable menu",
|
|
823
823
|
title: "Composable menu",
|
|
824
|
-
toc: [{"text":"Demos"},[{"text":"Basic menu with toggle"},{"text":"Menu with actions"},{"text":"Select menu"},{"text":"Drilldown menu with toggle"},{"text":"Filter tree menu"},{"text":"Flyout"},{"text":"Application launcher using menu components"},{"text":"Context selector using menu components"}]],
|
|
825
|
-
examples: ["Basic menu with toggle","Menu with actions","Select menu","Drilldown menu with toggle","Filter tree menu","Flyout","Application launcher using menu components","Context selector using menu components"],
|
|
824
|
+
toc: [{"text":"Demos"},[{"text":"Basic menu with toggle"},{"text":"Menu with actions"},{"text":"Select menu"},{"text":"Drilldown menu with toggle"},{"text":"Filter tree menu"},{"text":"Flyout"},{"text":"Application launcher using menu components"},{"text":"Context selector using menu components"},{"text":"Options menu using menu components"}]],
|
|
825
|
+
examples: ["Basic menu with toggle","Menu with actions","Select menu","Drilldown menu with toggle","Filter tree menu","Flyout","Application launcher using menu components","Context selector using menu components","Options menu using menu components"],
|
|
826
826
|
section: "demos",
|
|
827
827
|
source: "react-demos",
|
|
828
828
|
Component: () => import(/* webpackChunkName: "demos/composable-menu/react-demos/index" */ './demos/composable-menu/react-demos')
|
|
@@ -884,8 +884,8 @@ module.exports = {
|
|
|
884
884
|
'/components/page/react-demos': {
|
|
885
885
|
id: "Page",
|
|
886
886
|
title: "Page",
|
|
887
|
-
toc: [{"text":"Layouts"},[{"text":"Sticky section group"},{"text":"Sticky section group (alternate syntax)"}]],
|
|
888
|
-
fullscreenExamples: ["Sticky section group","Sticky section group (alternate syntax)"],
|
|
887
|
+
toc: [{"text":"Layouts"},[{"text":"Sticky section group"},{"text":"Sticky section group (using PageHeader)"},{"text":"Sticky section group (alternate syntax and using PageHeader)"}]],
|
|
888
|
+
fullscreenExamples: ["Sticky section group","Sticky section group (using PageHeader)","Sticky section group (alternate syntax and using PageHeader)"],
|
|
889
889
|
section: "components",
|
|
890
890
|
source: "react-demos",
|
|
891
891
|
Component: () => import(/* webpackChunkName: "components/page/react-demos/index" */ './components/page/react-demos')
|