diff --git a/packages/react-core/src/components/Masthead/Masthead.tsx b/packages/react-core/src/components/Masthead/Masthead.tsx index 75c2f3795bf..11650d22d5f 100644 --- a/packages/react-core/src/components/Masthead/Masthead.tsx +++ b/packages/react-core/src/components/Masthead/Masthead.tsx @@ -2,6 +2,8 @@ import * as React from 'react'; import styles from '@patternfly/react-styles/css/components/Masthead/masthead'; import { css } from '@patternfly/react-styles'; import { formatBreakpointMods } from '../../helpers/util'; +import { PageContext } from '../Page/Page'; + export interface MastheadProps extends React.DetailedHTMLProps, HTMLDivElement> { /** Content rendered inside of the masthead */ children?: React.ReactNode; @@ -33,22 +35,27 @@ export const Masthead: React.FunctionComponent = ({ children, className, backgroundColor = 'dark', - display, + display = { + md: 'inline' + }, inset, ...props -}: MastheadProps) => ( -
- {children} -
-); +}: MastheadProps) => { + const { width, getBreakpoint } = React.useContext(PageContext); + return ( +
+ {children} +
+ ); +}; Masthead.displayName = 'Masthead'; diff --git a/packages/react-core/src/components/Masthead/__tests__/__snapshots__/Masthead.test.tsx.snap b/packages/react-core/src/components/Masthead/__tests__/__snapshots__/Masthead.test.tsx.snap index a7d4265f5bc..896fd364b0d 100644 --- a/packages/react-core/src/components/Masthead/__tests__/__snapshots__/Masthead.test.tsx.snap +++ b/packages/react-core/src/components/Masthead/__tests__/__snapshots__/Masthead.test.tsx.snap @@ -2,7 +2,7 @@ exports[`Masthead verify basic 1`] = `
test
@@ -13,7 +13,7 @@ exports[`Masthead verify custom class 1`] = ` className="custom-css" >
test
@@ -23,7 +23,7 @@ exports[`Masthead verify custom class 1`] = ` exports[`Masthead verify full structure 1`] = `
test
@@ -115,7 +115,7 @@ exports[`Masthead verify inset3xl inset breakpoints 1`] = ` } >
test
@@ -136,7 +136,7 @@ exports[`Masthead verify insetLg inset breakpoints 1`] = ` } >
test
@@ -157,7 +157,7 @@ exports[`Masthead verify insetMd inset breakpoints 1`] = ` } >
test
@@ -178,7 +178,7 @@ exports[`Masthead verify insetNone inset breakpoints 1`] = ` } >
test
@@ -199,7 +199,7 @@ exports[`Masthead verify insetSm inset breakpoints 1`] = ` } >
test
@@ -220,7 +220,7 @@ exports[`Masthead verify insetXl inset breakpoints 1`] = ` } >
test
@@ -241,7 +241,7 @@ exports[`Masthead verify insetXs inset breakpoints 1`] = ` } >
test
diff --git a/packages/react-core/src/components/Nav/Nav.tsx b/packages/react-core/src/components/Nav/Nav.tsx index d5400b21e21..aeb8d1f2ab9 100644 --- a/packages/react-core/src/components/Nav/Nav.tsx +++ b/packages/react-core/src/components/Nav/Nav.tsx @@ -38,7 +38,7 @@ export interface NavProps variant?: 'default' | 'horizontal' | 'tertiary' | 'horizontal-subnav'; } -export const NavContext = React.createContext<{ +export interface NavContextProps { onSelect?: ( event: React.FormEvent, groupId: number | string, @@ -57,7 +57,9 @@ export const NavContext = React.createContext<{ isHorizontal?: boolean; flyoutRef?: React.Ref; setFlyoutRef?: (ref: React.Ref) => void; -}>({}); +} +export const navContextDefaults = {}; +export const NavContext = React.createContext(navContextDefaults); export class Nav extends React.Component< NavProps, diff --git a/packages/react-core/src/components/Nav/NavList.tsx b/packages/react-core/src/components/Nav/NavList.tsx index 2dd7d1d3893..8c4f3905aba 100644 --- a/packages/react-core/src/components/Nav/NavList.tsx +++ b/packages/react-core/src/components/Nav/NavList.tsx @@ -6,7 +6,7 @@ import AngleRightIcon from '@patternfly/react-icons/dist/esm/icons/angle-right-i import { isElementInView } from '../../helpers/util'; import { NavContext } from './Nav'; import { PageSidebarContext } from '../Page/PageSidebar'; -import { canUseDOM } from '../../helpers/util'; +import { getResizeObserver } from '../../helpers/resizeObserver'; export interface NavListProps extends React.DetailedHTMLProps, HTMLUListElement> { @@ -35,6 +35,7 @@ export class NavList extends React.Component { }; navList = React.createRef(); + observer: any = () => {}; handleScrollButtons = () => { const container = this.navList.current; @@ -91,16 +92,12 @@ export class NavList extends React.Component { }; componentDidMount() { - if (canUseDOM) { - window.addEventListener('resize', this.handleScrollButtons, false); - } + this.observer = getResizeObserver(this.navList.current, this.handleScrollButtons); this.handleScrollButtons(); } componentWillUnmount() { - if (canUseDOM) { - window.removeEventListener('resize', this.handleScrollButtons, false); - } + this.observer(); } render() { diff --git a/packages/react-core/src/components/Page/Page.tsx b/packages/react-core/src/components/Page/Page.tsx index b97ca878f2b..81dd7e3f285 100644 --- a/packages/react-core/src/components/Page/Page.tsx +++ b/packages/react-core/src/components/Page/Page.tsx @@ -5,6 +5,8 @@ import globalBreakpointXl from '@patternfly/react-tokens/dist/esm/global_breakpo import { debounce, canUseDOM } from '../../helpers/util'; import { Drawer, DrawerContent, DrawerContentBody, DrawerPanelContent } from '../Drawer'; import { PageGroup, PageGroupProps } from './PageGroup'; +import { getResizeObserver } from '../../helpers/resizeObserver'; +import { getBreakpoint } from '../../helpers/util'; export enum PageLayouts { vertical = 'vertical', @@ -15,13 +17,17 @@ export interface PageContextProps { isManagedSidebar: boolean; onNavToggle: () => void; isNavOpen: boolean; + width: number; + getBreakpoint: (width: number | null) => 'default' | 'sm' | 'md' | 'lg' | 'xl' | '2xl'; } - -const PageContext = React.createContext({ +export const pageContextDefaults: PageContextProps = { isManagedSidebar: false, isNavOpen: false, - onNavToggle: () => null -}); + onNavToggle: () => null, + width: null, + getBreakpoint +}; +export const PageContext = React.createContext(pageContextDefaults); export const PageContextProvider = PageContext.Provider; export const PageContextConsumer = PageContext.Consumer; @@ -67,6 +73,13 @@ export interface PageProps extends React.HTMLProps { * Returns object { mobileView: boolean, windowSize: number } */ onPageResize?: (object: any) => void; + /** + * The page resize observer uses the breakpoints returned from this function when adding the pf-m-breakpoint-[default|sm|md|lg|xl|2xl] class + * You can override the default getBreakpoint function to return breakpoints at different sizes than the default + * You can view the default getBreakpoint function here: + * https://github.com/patternfly/patternfly-react/blob/main/packages/react-core/src/helpers/util.ts + */ + getBreakpoint?: (width: number | null) => 'default' | 'sm' | 'md' | 'lg' | 'xl' | '2xl'; /** Breadcrumb component for the page */ breadcrumb?: React.ReactNode; /** Tertiary nav component for the page */ @@ -87,6 +100,7 @@ export interface PageState { desktopIsNavOpen: boolean; mobileIsNavOpen: boolean; mobileView: boolean; + width: number; } export class Page extends React.Component { @@ -98,9 +112,12 @@ export class Page extends React.Component { onPageResize: (): void => null, mainTabIndex: -1, isNotificationDrawerExpanded: false, - onNotificationDrawerExpand: () => null + onNotificationDrawerExpand: () => null, + getBreakpoint }; mainRef = React.createRef(); + pageRef = React.createRef(); + observer: any = () => {}; constructor(props: PageProps) { super(props); @@ -110,16 +127,15 @@ export class Page extends React.Component { this.state = { desktopIsNavOpen: managedSidebarOpen, mobileIsNavOpen: false, - mobileView: false + mobileView: false, + width: null }; } componentDidMount() { const { isManagedSidebar, onPageResize } = this.props; if (isManagedSidebar || onPageResize) { - if (canUseDOM) { - window.addEventListener('resize', this.handleResize); - } + this.observer = getResizeObserver(this.pageRef.current, this.handleResize); const currentRef = this.mainRef.current; if (currentRef) { currentRef.addEventListener('mousedown', this.handleMainClick); @@ -133,9 +149,7 @@ export class Page extends React.Component { componentWillUnmount() { const { isManagedSidebar, onPageResize } = this.props; if (isManagedSidebar || onPageResize) { - if (canUseDOM) { - window.removeEventListener('resize', this.handleResize); - } + this.observer(); const currentRef = this.mainRef.current; if (currentRef) { currentRef.removeEventListener('mousedown', this.handleMainClick); @@ -144,7 +158,13 @@ export class Page extends React.Component { } } - getWindowWidth = () => (canUseDOM ? window.innerWidth : 1200); + getWindowWidth = () => { + if (canUseDOM) { + return this.pageRef.current ? this.pageRef.current.clientWidth : window.innerWidth; + } else { + return 1200; + } + }; isMobile = () => // eslint-disable-next-line radix @@ -159,6 +179,7 @@ export class Page extends React.Component { if (mobileView !== this.state.mobileView) { this.setState({ mobileView }); } + this.pageRef.current && this.setState({ width: this.pageRef.current.clientWidth }); }; handleResize = debounce(this.resize, 250); @@ -201,6 +222,7 @@ export class Page extends React.Component { defaultManagedSidebarIsOpen, // eslint-disable-next-line @typescript-eslint/no-unused-vars onPageResize, + getBreakpoint, mainAriaLabel, mainTabIndex, tertiaryNav, @@ -210,12 +232,14 @@ export class Page extends React.Component { groupProps, ...rest } = this.props; - const { mobileView, mobileIsNavOpen, desktopIsNavOpen } = this.state; + const { mobileView, mobileIsNavOpen, desktopIsNavOpen, width } = this.state; const context = { isManagedSidebar, onNavToggle: mobileView ? this.onNavToggleMobile : this.onNavToggleDesktop, - isNavOpen: mobileView ? mobileIsNavOpen : desktopIsNavOpen + isNavOpen: mobileView ? mobileIsNavOpen : desktopIsNavOpen, + width, + getBreakpoint }; let nav = null; @@ -270,7 +294,16 @@ export class Page extends React.Component { return ( -
+
{skipToContent} {header} {sidebar} diff --git a/packages/react-core/src/components/Page/PageHeaderToolsGroup.tsx b/packages/react-core/src/components/Page/PageHeaderToolsGroup.tsx index c74fa4a57dc..6c9f3962bb6 100644 --- a/packages/react-core/src/components/Page/PageHeaderToolsGroup.tsx +++ b/packages/react-core/src/components/Page/PageHeaderToolsGroup.tsx @@ -2,6 +2,7 @@ import * as React from 'react'; import styles from '@patternfly/react-styles/css/components/Page/page'; import { css } from '@patternfly/react-styles'; import { formatBreakpointMods } from '../../helpers/util'; +import { PageContext } from '../Page/Page'; export interface PageHeaderToolsGroupProps extends React.HTMLProps { /** Content rendered in the page header tools group */ @@ -24,9 +25,19 @@ export const PageHeaderToolsGroup: React.FunctionComponent ( -
- {children} -
-); +}: PageHeaderToolsGroupProps) => { + const { width, getBreakpoint } = React.useContext(PageContext); + return ( +
+ {children} +
+ ); +}; PageHeaderToolsGroup.displayName = 'PageHeaderToolsGroup'; diff --git a/packages/react-core/src/components/Page/PageHeaderToolsItem.tsx b/packages/react-core/src/components/Page/PageHeaderToolsItem.tsx index 961e3a95295..bba419c5563 100644 --- a/packages/react-core/src/components/Page/PageHeaderToolsItem.tsx +++ b/packages/react-core/src/components/Page/PageHeaderToolsItem.tsx @@ -2,6 +2,7 @@ import * as React from 'react'; import styles from '@patternfly/react-styles/css/components/Page/page'; import { css } from '@patternfly/react-styles'; import { formatBreakpointMods } from '../../helpers/util'; +import { PageContext } from '../Page/Page'; export interface PageHeaderToolsItemProps extends React.HTMLProps { /** Content rendered in page header tools item. */ @@ -28,18 +29,23 @@ export const PageHeaderToolsItem: React.FunctionComponent ( -
- {children} -
-); + isSelected, + ...props +}: PageHeaderToolsItemProps) => { + const { width, getBreakpoint } = React.useContext(PageContext); + return ( +
+ {children} +
+ ); +}; PageHeaderToolsItem.displayName = 'PageHeaderToolsItem'; diff --git a/packages/react-core/src/components/Page/PageSidebar.tsx b/packages/react-core/src/components/Page/PageSidebar.tsx index 206e421da3c..a748ca50531 100644 --- a/packages/react-core/src/components/Page/PageSidebar.tsx +++ b/packages/react-core/src/components/Page/PageSidebar.tsx @@ -22,10 +22,10 @@ export interface PageSidebarProps extends React.HTMLProps { export interface PageSidebarContextProps { isNavOpen: boolean; } - -export const PageSidebarContext = React.createContext>({ +export const pageSidebarContextDefaults: PageSidebarContextProps = { isNavOpen: true -}); +}; +export const PageSidebarContext = React.createContext>(pageSidebarContextDefaults); export const PageSidebar: React.FunctionComponent = ({ className = '', diff --git a/packages/react-core/src/components/Page/__tests__/Generated/__snapshots__/Page.test.tsx.snap b/packages/react-core/src/components/Page/__tests__/Generated/__snapshots__/Page.test.tsx.snap index 6eee9cd6f90..61054dc7758 100644 --- a/packages/react-core/src/components/Page/__tests__/Generated/__snapshots__/Page.test.tsx.snap +++ b/packages/react-core/src/components/Page/__tests__/Generated/__snapshots__/Page.test.tsx.snap @@ -4,9 +4,11 @@ exports[`Page should match snapshot (auto-generated) 1`] = ` diff --git a/packages/react-core/src/components/Page/__tests__/__snapshots__/Page.test.tsx.snap b/packages/react-core/src/components/Page/__tests__/__snapshots__/Page.test.tsx.snap index 63f1fdb5907..a689723142d 100644 --- a/packages/react-core/src/components/Page/__tests__/__snapshots__/Page.test.tsx.snap +++ b/packages/react-core/src/components/Page/__tests__/__snapshots__/Page.test.tsx.snap @@ -5,6 +5,7 @@ exports[`Check dark page against snapshot 1`] = ` aria-label="Page layout" className="my-page-class" defaultManagedSidebarIsOpen={true} + getBreakpoint={[Function]} header={
} className="my-page-class" defaultManagedSidebarIsOpen={true} + getBreakpoint={[Function]} header={
, OUIAProps { /** Optional callback for clearing all filters in the toolbar */ @@ -139,46 +140,50 @@ export class Toolbar extends React.Component { const showClearFiltersButton = numberOfFilters > 0; return ( -
+ {({ width, getBreakpoint }) => ( +
+ + {children} + + +
)} - id={randomId} - {...getOUIAProps(Toolbar.displayName, ouiaId !== undefined ? ouiaId : this.state.ouiaStateId)} - {...props} - > - - {children} - - -
+ ); }; diff --git a/packages/react-core/src/components/Toolbar/ToolbarContent.tsx b/packages/react-core/src/components/Toolbar/ToolbarContent.tsx index df0a2e0d9b7..6ccbd675170 100644 --- a/packages/react-core/src/components/Toolbar/ToolbarContent.tsx +++ b/packages/react-core/src/components/Toolbar/ToolbarContent.tsx @@ -4,6 +4,7 @@ import { css } from '@patternfly/react-styles'; import { ToolbarContentContext, ToolbarContext } from './ToolbarUtils'; import { formatBreakpointMods } from '../../helpers/util'; import { ToolbarExpandableContent } from './ToolbarExpandableContent'; +import { PageContext } from '../Page/Page'; export interface ToolbarContentProps extends React.HTMLProps { /** Classes applied to root element of the data toolbar content row */ @@ -81,47 +82,51 @@ export class ToolbarContent extends React.Component { } return ( -
+ {({ width, getBreakpoint }) => ( +
+ + {({ + clearAllFilters: clearAllFiltersContext, + clearFiltersButtonText: clearFiltersButtonContext, + showClearFiltersButton: showClearFiltersButtonContext, + toolbarId: toolbarIdContext + }) => { + const expandableContentId = `${toolbarId || + toolbarIdContext}-expandable-content-${ToolbarContent.currentId++}`; + return ( + +
{children}
+ +
+ ); + }} +
+
)} - {...props} - > - - {({ - clearAllFilters: clearAllFiltersContext, - clearFiltersButtonText: clearFiltersButtonContext, - showClearFiltersButton: showClearFiltersButtonContext, - toolbarId: toolbarIdContext - }) => { - const expandableContentId = `${toolbarId || - toolbarIdContext}-expandable-content-${ToolbarContent.currentId++}`; - return ( - -
{children}
- -
- ); - }} -
-
+ ); } } diff --git a/packages/react-core/src/components/Toolbar/ToolbarGroup.tsx b/packages/react-core/src/components/Toolbar/ToolbarGroup.tsx index 2d106d7e91d..a387885fa33 100644 --- a/packages/react-core/src/components/Toolbar/ToolbarGroup.tsx +++ b/packages/react-core/src/components/Toolbar/ToolbarGroup.tsx @@ -2,6 +2,7 @@ import * as React from 'react'; import styles from '@patternfly/react-styles/css/components/Toolbar/toolbar'; import { css } from '@patternfly/react-styles'; import { formatBreakpointMods, toCamel } from '../../helpers/util'; +import { PageContext } from '../Page/Page'; export enum ToolbarGroupVariant { 'filter-group' = 'filter-group', @@ -84,21 +85,25 @@ class ToolbarGroupWithRef extends React.Component { } return ( -
+ {({ width, getBreakpoint }) => ( +
+ {children} +
)} - {...props} - ref={innerRef} - > - {children} -
+ ); } } diff --git a/packages/react-core/src/components/Toolbar/ToolbarItem.tsx b/packages/react-core/src/components/Toolbar/ToolbarItem.tsx index 9be93a7d39d..1f1a1daf0e6 100644 --- a/packages/react-core/src/components/Toolbar/ToolbarItem.tsx +++ b/packages/react-core/src/components/Toolbar/ToolbarItem.tsx @@ -4,6 +4,7 @@ import { css } from '@patternfly/react-styles'; import { formatBreakpointMods, toCamel } from '../../helpers/util'; import { Divider } from '../Divider'; +import { PageContext } from '../Page/Page'; export enum ToolbarItemVariant { separator = 'separator', @@ -113,26 +114,36 @@ export const ToolbarItem: React.FunctionComponent = ({ } return ( -
+ {({ width, getBreakpoint }) => ( +
+ {children} +
)} - {...(variant === 'label' && { 'aria-hidden': true })} - id={id} - {...props} - {...(widths && { style: { ...widthStyles, ...props.style } as React.CSSProperties })} - > - {children} -
+ ); }; ToolbarItem.displayName = 'ToolbarItem'; diff --git a/packages/react-core/src/components/Toolbar/ToolbarToggleGroup.tsx b/packages/react-core/src/components/Toolbar/ToolbarToggleGroup.tsx index 32111a54f0f..70c37a351d5 100644 --- a/packages/react-core/src/components/Toolbar/ToolbarToggleGroup.tsx +++ b/packages/react-core/src/components/Toolbar/ToolbarToggleGroup.tsx @@ -6,7 +6,8 @@ import { ToolbarGroupProps } from './ToolbarGroup'; import { ToolbarContext, ToolbarContentContext } from './ToolbarUtils'; import { Button } from '../Button'; import globalBreakpointLg from '@patternfly/react-tokens/dist/esm/global_breakpoint_lg'; -import { formatBreakpointMods, toCamel, capitalize, canUseDOM } from '../../helpers/util'; +import { formatBreakpointMods, toCamel, canUseDOM } from '../../helpers/util'; +import { PageContext } from '../Page/Page'; export interface ToolbarToggleGroupProps extends ToolbarGroupProps { /** An icon to be rendered when the toggle group has collapsed down */ @@ -92,61 +93,67 @@ export class ToolbarToggleGroup extends React.Component } return ( - - {({ isExpanded, toggleIsExpanded }) => ( - - {({ expandableContentRef, expandableContentId }) => { - if (expandableContentRef.current && expandableContentRef.current.classList) { - if (isExpanded) { - expandableContentRef.current.classList.add(styles.modifiers.expanded); - } else { - expandableContentRef.current.classList.remove(styles.modifiers.expanded); - } - } + + {({ width, getBreakpoint }) => ( + + {({ isExpanded, toggleIsExpanded }) => ( + + {({ expandableContentRef, expandableContentId }) => { + if (expandableContentRef.current && expandableContentRef.current.classList) { + if (isExpanded) { + expandableContentRef.current.classList.add(styles.modifiers.expanded); + } else { + expandableContentRef.current.classList.remove(styles.modifiers.expanded); + } + } - return ( -
-
- -
- {isExpanded - ? ReactDOM.createPortal(children, expandableContentRef.current.firstElementChild) - : children} -
- ); - }} -
+
+ +
+ {isExpanded + ? ReactDOM.createPortal(children, expandableContentRef.current.firstElementChild) + : children} +
+ ); + }} + + )} + )} - + ); } } diff --git a/packages/react-core/src/components/Toolbar/__tests__/Generated/__snapshots__/Toolbar.test.tsx.snap b/packages/react-core/src/components/Toolbar/__tests__/Generated/__snapshots__/Toolbar.test.tsx.snap index 65e2a667afa..0349c1743ec 100644 --- a/packages/react-core/src/components/Toolbar/__tests__/Generated/__snapshots__/Toolbar.test.tsx.snap +++ b/packages/react-core/src/components/Toolbar/__tests__/Generated/__snapshots__/Toolbar.test.tsx.snap @@ -1,47 +1,7 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`Toolbar should match snapshot (auto-generated) 1`] = ` -
- -
- ReactNode -
- -
-
+ + + `; diff --git a/packages/react-core/src/components/Toolbar/__tests__/Generated/__snapshots__/ToolbarContent.test.tsx.snap b/packages/react-core/src/components/Toolbar/__tests__/Generated/__snapshots__/ToolbarContent.test.tsx.snap index 292de1a8bce..1375f7445c6 100644 --- a/packages/react-core/src/components/Toolbar/__tests__/Generated/__snapshots__/ToolbarContent.test.tsx.snap +++ b/packages/react-core/src/components/Toolbar/__tests__/Generated/__snapshots__/ToolbarContent.test.tsx.snap @@ -1,11 +1,7 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`ToolbarContent should match snapshot (auto-generated) 1`] = ` -
- - - -
+ + + `; diff --git a/packages/react-core/src/components/Toolbar/__tests__/Generated/__snapshots__/ToolbarItem.test.tsx.snap b/packages/react-core/src/components/Toolbar/__tests__/Generated/__snapshots__/ToolbarItem.test.tsx.snap index cb584c8321f..e39674109a9 100644 --- a/packages/react-core/src/components/Toolbar/__tests__/Generated/__snapshots__/ToolbarItem.test.tsx.snap +++ b/packages/react-core/src/components/Toolbar/__tests__/Generated/__snapshots__/ToolbarItem.test.tsx.snap @@ -1,12 +1,7 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`ToolbarItem should match snapshot (auto-generated) 1`] = ` -
-
- ReactNode -
-
+ + + `; diff --git a/packages/react-core/src/demos/Page/Page.md b/packages/react-core/src/demos/Page/Page.md index 20d55357553..1b1cdcbc9e5 100644 --- a/packages/react-core/src/demos/Page/Page.md +++ b/packages/react-core/src/demos/Page/Page.md @@ -11,6 +11,7 @@ import imgBrand from '@patternfly/react-core/src/demos/examples/pfColorLogo.svg' import imgAvatar from '@patternfly/react-core/src/components/Avatar/examples/avatarImg.svg'; import BarsIcon from '@patternfly/react-icons/dist/esm/icons/bars-icon'; import AttentionBellIcon from '@patternfly/react-icons/dist/esm/icons/attention-bell-icon'; +import LightbulbIcon from '@patternfly/react-icons/dist/esm/icons/lightbulb-icon'; - All but the last example set the `isManagedSidebar` prop on the Page component to have the sidebar automatically close for smaller screen widths. You can also manually control this behavior by not adding the `isManagedSidebar` prop and instead: @@ -38,6 +39,7 @@ import { ButtonVariant, Card, CardBody, + Checkbox, Divider, Dropdown, DropdownGroup, @@ -66,13 +68,21 @@ import { Toolbar, ToolbarContent, ToolbarGroup, - ToolbarItem + ToolbarItem, + Drawer, + DrawerPanelContent, + DrawerContent, + DrawerContentBody, + DrawerHead, + DrawerActions, + DrawerCloseButton, } from '@patternfly/react-core'; import { css } from '@patternfly/react-styles'; import BellIcon from '@patternfly/react-icons/dist/esm/icons/bell-icon'; import CogIcon from '@patternfly/react-icons/dist/esm/icons/cog-icon'; import HelpIcon from '@patternfly/react-icons/dist/esm/icons/help-icon'; import AttentionBellIcon from '@patternfly/react-icons/dist/esm/icons/attention-bell-icon'; +import LightbulbIcon from '@patternfly/react-icons/dist/esm/icons/lightbulb-icon'; import BarsIcon from '@patternfly/react-icons/dist/js/icons/bars-icon'; import imgBrand from './imgBrand.svg'; import imgAvatar from './imgAvatar.svg'; @@ -84,7 +94,8 @@ class PageLayoutGrouped extends React.Component { isDropdownOpen: false, isKebabDropdownOpen: false, isFullKebabDropdownOpen: false, - activeItem: 0 + activeItem: 0, + isDrawerExpanded: false }; this.onDropdownToggle = isDropdownOpen => { this.setState({ @@ -127,10 +138,23 @@ class PageLayoutGrouped extends React.Component { isFullKebabDropdownOpen: !this.state.isFullKebabDropdownOpen }); }; + + this.onDrawerToggle = () => { + const isDrawerExpanded = !this.state.isDrawerExpanded; + this.setState({ + isDrawerExpanded + }); + }; + + this.onDrawerClose = () => { + this.setState({ + isDrawerExpanded: false + }); + }; } render() { - const { isDropdownOpen, isKebabDropdownOpen, activeItem, isFullKebabDropdownOpen } = this.state; + const { isDropdownOpen, isKebabDropdownOpen, activeItem, isFullKebabDropdownOpen, isDrawerExpanded } = this.state; const PageNav = (