UNPKG

@patternfly/react-core

Version:

This library provides a set of common React components for use with the PatternFly reference implementation.

1,263 lines (1,201 loc) • 47.4 kB
--- id: Notification drawer section: components beta: true --- import BellIcon from '@patternfly/react-icons/dist/esm/icons/bell-icon'; import CogIcon from '@patternfly/react-icons/dist/esm/icons/cog-icon'; import BarsIcon from '@patternfly/react-icons/dist/js/icons/bars-icon'; import HelpIcon from '@patternfly/react-icons/dist/esm/icons/help-icon'; import QuestionCircleIcon from '@patternfly/react-icons/dist/esm/icons/question-circle-icon'; import SearchIcon from '@patternfly/react-icons/dist/esm/icons/search-icon'; import imgBrand from '@patternfly/react-core/src/components/Brand/examples/pfLogo.svg'; import imgAvatar from '@patternfly/react-core/src/components/Avatar/examples/avatarImg.svg'; import AttentionBellIcon from '@patternfly/react-icons/dist/esm/icons/attention-bell-icon'; ## Demos - Focus must be manually managed when the NotificationDrawer component is opened: 1. Create a React `ref` and pass it into the NotificationDrawer component's `ref` attribute 2. Pass in a function to the `onNotificationDrawerExpand` prop of the Page component that will place focus on the first interact-able element inside the NotificationDrawer component via the previously created `ref` ### Basic ```js isFullscreen import React from 'react'; import { Avatar, Brand, Breadcrumb, BreadcrumbItem, Button, ButtonVariant, Card, CardBody, Drawer, DrawerContent, DrawerContentBody, Dropdown, DropdownGroup, DropdownToggle, DropdownItem, DropdownSeparator, EmptyState, EmptyStateBody, EmptyStateIcon, EmptyStatePrimary, Gallery, GalleryItem, KebabToggle, Nav, NavItem, NavList, NotificationBadge, NotificationDrawer, NotificationDrawerBody, NotificationDrawerHeader, NotificationDrawerList, NotificationDrawerListItem, NotificationDrawerListItemBody, NotificationDrawerListItemHeader, Page, PageSection, PageSectionVariants, PageSidebar, SkipToContent, TextContent, Text, Title, PageToggleButton, Masthead, MastheadMain, MastheadToggle, MastheadContent, MastheadBrand, Toolbar, ToolbarItem, ToolbarGroup, ToolbarContent } 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 QuestionCircleIcon from '@patternfly/react-icons/dist/esm/icons/question-circle-icon'; import BarsIcon from '@patternfly/react-icons/dist/js/icons/bars-icon'; import imgBrand from '@patternfly/react-core/src/components/Brand/examples/pfLogo.svg'; import imgAvatar from '@patternfly/react-core/src/components/Avatar/examples/avatarImg.svg'; import { Table, TableHeader, TableBody } from '@patternfly/react-table'; class BasicNotificationDrawer extends React.Component { constructor(props) { super(props); this.drawerRef = React.createRef(); this.state = { isDropdownOpen: false, isKebabDropdownOpen: false, activeItem: 0, isDrawerExpanded: false, isUnreadMap: { 'notification-1': true, 'notification-2': true }, showNotifications: true, isActionsMenuOpen: null }; this.onDropdownToggle = isDropdownOpen => { this.setState({ isDropdownOpen }); }; this.onDropdownSelect = event => { this.setState({ isDropdownOpen: !this.state.isDropdownOpen }); }; this.onKebabDropdownToggle = isKebabDropdownOpen => { this.setState({ isKebabDropdownOpen }); }; this.onKebabDropdownSelect = event => { this.setState({ isKebabDropdownOpen: !this.state.isKebabDropdownOpen }); }; this.onNavSelect = result => { this.setState({ activeItem: result.itemId }); }; this.onCloseNotificationDrawer = () => { this.setState(prevState => { return { isDrawerExpanded: !prevState.isDrawerExpanded }; }); }; this.onToggle = (id, isOpen) => { this.setState({ isActionsMenuOpen: { [id]: isOpen } }); }; this.onSelect = event => { this.setState({ isActionsMenuOpen: null }); }; this.onListItemClick = id => { this.setState(prevState => { if (!prevState.isUnreadMap) return; prevState.isUnreadMap[id] = false; return { isUnreadMap: prevState.isUnreadMap }; }); }; this.getNumberUnread = () => { const { isUnreadMap } = this.state; if (isUnreadMap === null) return 0; return Object.keys(isUnreadMap).reduce((count, id) => { return isUnreadMap[id] ? count + 1 : count; }, 0); }; this.markAllRead = () => { this.setState({ isUnreadMap: null }); }; this.showNotifications = showNotifications => { this.setState({ isUnreadMap: null, showNotifications: showNotifications }); }; this.focusDrawer = () => { const firstTabbableItem = this.drawerRef.current.querySelector('a, button'); firstTabbableItem.focus(); }; } render() { const { isDropdownOpen, isKebabDropdownOpen, activeItem, res, isDrawerExpanded, isActionsMenuOpen, isUnreadMap, showNotifications } = this.state; const PageNav = ( <Nav onSelect={this.onNavSelect} aria-label="Nav"> <NavList> <NavItem itemId={0} isActive={activeItem === 0}> System Panel </NavItem> <NavItem itemId={1} isActive={activeItem === 1}> Policy </NavItem> <NavItem itemId={2} isActive={activeItem === 2}> Authentication </NavItem> <NavItem itemId={3} isActive={activeItem === 3}> Network Services </NavItem> <NavItem itemId={4} isActive={activeItem === 4}> Server </NavItem> </NavList> </Nav> ); const kebabDropdownItems = [ <DropdownItem> <CogIcon /> Settings </DropdownItem>, <DropdownItem> <HelpIcon /> Help </DropdownItem> ]; const userDropdownItems = [ <DropdownGroup key="group 2"> <DropdownItem key="group 2 profile">My profile</DropdownItem> <DropdownItem key="group 2 user" component="button"> User management </DropdownItem> <DropdownItem key="group 2 logout">Logout</DropdownItem> </DropdownGroup> ]; const headerToolbar = ( <Toolbar> <ToolbarContent> <ToolbarGroup spaceItems={{ default: 'spacerNone' }} alignment={{ default: 'alignRight' }}> <ToolbarGroup variant="icon-button-group"> <ToolbarItem visibility={{ default: 'visible' }} isSelected={isDrawerExpanded}> <NotificationBadge variant={this.getNumberUnread() === 0 ? 'read' : 'unread'} onClick={this.onCloseNotificationDrawer} aria-label="Notifications" > <BellIcon /> </NotificationBadge> </ToolbarItem> <ToolbarGroup variant="icon-button-group" visibility={{ default: 'hidden', lg: 'visible' }} /** the settings and help icon buttons are only visible on desktop sizes and replaced by a kebab dropdown for other sizes */ > <ToolbarItem> <Button aria-label="Settings actions" variant={ButtonVariant.plain}> <CogIcon /> </Button> </ToolbarItem> <ToolbarItem> <Button aria-label="Help actions" variant={ButtonVariant.plain}> <QuestionCircleIcon /> </Button> </ToolbarItem> </ToolbarGroup> </ToolbarGroup> <ToolbarGroup> <ToolbarItem visibility={{ lg: 'hidden' }} /** this kebab dropdown replaces the icon buttons and is hidden for desktop sizes */ > <Dropdown isPlain position="right" onSelect={this.onKebabDropdownSelect} toggle={<KebabToggle onToggle={this.onKebabDropdownToggle} />} isOpen={isKebabDropdownOpen} dropdownItems={kebabDropdownItems} /> </ToolbarItem> <ToolbarItem visibility={{ default: 'hidden', md: 'visible' }} /** this user dropdown is hidden on mobile sizes */ > <Dropdown position="right" onSelect={this.onDropdownSelect} isOpen={isDropdownOpen} toggle={ <DropdownToggle icon={<Avatar src={imgAvatar} alt="Avatar" />} onToggle={this.onDropdownToggle}> John Smith </DropdownToggle> } dropdownItems={userDropdownItems} /> </ToolbarItem> </ToolbarGroup> </ToolbarGroup> </ToolbarContent> </Toolbar> ); const Header = ( <Masthead> <MastheadToggle> <PageToggleButton variant="plain" aria-label="Global navigation"> <BarsIcon /> </PageToggleButton> </MastheadToggle> <MastheadMain> <MastheadBrand> <Brand src={imgBrand} alt="Patternfly logo" /> </MastheadBrand> </MastheadMain> <MastheadContent>{headerToolbar}</MastheadContent> </Masthead> ); const Sidebar = <PageSidebar nav={PageNav} />; const pageId = 'main-content-page-layout-default-nav'; const PageSkipToContent = <SkipToContent href={`#${pageId}`}>Skip to content</SkipToContent>; const PageBreadcrumb = ( <Breadcrumb> <BreadcrumbItem>Section home</BreadcrumbItem> <BreadcrumbItem to="#">Section title</BreadcrumbItem> <BreadcrumbItem to="#">Section title</BreadcrumbItem> <BreadcrumbItem to="#" isActive> Section landing </BreadcrumbItem> </Breadcrumb> ); const drawerContent = 'Panel content'; const notificationDrawerActions = [ <DropdownItem key="markAllRead" onClick={this.markAllRead} component="button"> Mark all read </DropdownItem>, <DropdownItem key="clearAll" onClick={() => this.showNotifications(false)} component="button"> Clear all </DropdownItem>, <DropdownItem key="unclearLast" onClick={() => this.showNotifications(true)} component="button"> Unclear last </DropdownItem>, <DropdownItem key="settings" component="button"> Settings </DropdownItem> ]; const notificationDrawerDropdownItems = [ <DropdownItem key="link">Link</DropdownItem>, <DropdownItem key="action" component="button"> Action </DropdownItem>, <DropdownSeparator key="separator" />, <DropdownItem key="disabled link" isDisabled> Disabled Link </DropdownItem> ]; const notificationDrawer = ( <NotificationDrawer ref={this.drawerRef}> <NotificationDrawerHeader count={this.getNumberUnread()} onClose={this.onCloseNotificationDrawer}> <Dropdown onSelect={this.onSelect} toggle={<KebabToggle onToggle={isOpen => this.onToggle('toggle-id-0', isOpen)} id="toggle-id-0" />} isOpen={isActionsMenuOpen && isActionsMenuOpen['toggle-id-0']} isPlain dropdownItems={notificationDrawerActions} id="notification-0" position={DropdownPosition.right} /> </NotificationDrawerHeader> <NotificationDrawerBody> {showNotifications && ( <NotificationDrawerList> <NotificationDrawerListItem variant="info" onClick={() => this.onListItemClick('notification-1')} isRead={isUnreadMap === null || !isUnreadMap['notification-1']} > <NotificationDrawerListItemHeader variant="info" title="Unread info notification title" srTitle="Info notification:" > <Dropdown position={DropdownPosition.right} onSelect={this.onSelect} toggle={<KebabToggle onToggle={isOpen => this.onToggle('toggle-id-1', isOpen)} id="toggle-id-1" />} isOpen={isActionsMenuOpen && isActionsMenuOpen['toggle-id-1']} isPlain dropdownItems={notificationDrawerDropdownItems} id="notification-1" /> </NotificationDrawerListItemHeader> <NotificationDrawerListItemBody timestamp="5 minutes ago"> This is an info notification description. </NotificationDrawerListItemBody> </NotificationDrawerListItem> <NotificationDrawerListItem variant="danger" onClick={() => this.onListItemClick('notification-2')} isRead={isUnreadMap === null || !isUnreadMap['notification-2']} > <NotificationDrawerListItemHeader variant="danger" title="Unread danger notification title. This is a long title to show how the title will wrap if it is long and wraps to multiple lines." srTitle="Danger notification:" > <Dropdown position={DropdownPosition.right} onSelect={this.onSelect} toggle={<KebabToggle onToggle={isOpen => this.onToggle('toggle-id-2', isOpen)} id="toggle-id-2" />} isOpen={isActionsMenuOpen && isActionsMenuOpen['toggle-id-2']} isPlain dropdownItems={notificationDrawerDropdownItems} id="notification-2" /> </NotificationDrawerListItemHeader> <NotificationDrawerListItemBody timestamp="10 minutes ago"> This is a danger notification description. This is a long description to show how the title will wrap if it is long and wraps to multiple lines. </NotificationDrawerListItemBody> </NotificationDrawerListItem> <NotificationDrawerListItem variant="warning" onClick={() => this.onListItemClick('notification-3')} isRead={isUnreadMap === null || !isUnreadMap['notification-3']} > <NotificationDrawerListItemHeader variant="warning" title="Read warning notification title" srTitle="Warning notification:" > <Dropdown position={DropdownPosition.right} onSelect={this.onSelect} toggle={<KebabToggle onToggle={isOpen => this.onToggle('toggle-id-3', isOpen)} id="toggle-id-3" />} isOpen={isActionsMenuOpen && isActionsMenuOpen['toggle-id-3']} isPlain dropdownItems={notificationDrawerDropdownItems} id="notification-3" /> </NotificationDrawerListItemHeader> <NotificationDrawerListItemBody timestamp="20 minutes ago"> This is a warning notification description. </NotificationDrawerListItemBody> </NotificationDrawerListItem> <NotificationDrawerListItem variant="success" onClick={() => this.onListItemClick('notification-4')} isRead={isUnreadMap === null || !isUnreadMap['notification-4']} > <NotificationDrawerListItemHeader variant="success" title="Read success notification title" srTitle="Success notification:" > <Dropdown position={DropdownPosition.right} direction={DropdownDirection.up} onSelect={this.onSelect} toggle={<KebabToggle onToggle={isOpen => this.onToggle('toggle-id-4', isOpen)} id="toggle-id-4" />} isOpen={isActionsMenuOpen && isActionsMenuOpen['toggle-id-4']} isPlain dropdownItems={notificationDrawerDropdownItems} id="notification-4" /> </NotificationDrawerListItemHeader> <NotificationDrawerListItemBody timestamp="30 minutes ago"> This is a success notification description. </NotificationDrawerListItemBody> </NotificationDrawerListItem> </NotificationDrawerList> )} {!showNotifications && ( <EmptyState variant={EmptyStateVariant.full}> <EmptyStateIcon icon={SearchIcon} /> <Title headingLevel="h2" size="lg"> No alerts found </Title> <EmptyStateBody> There are currently no alerts. There may be silenced critical alerts however. </EmptyStateBody> <EmptyStatePrimary> <Button variant="link">Action</Button> </EmptyStatePrimary> </EmptyState> )} </NotificationDrawerBody> </NotificationDrawer> ); return ( <React.Fragment> <Page header={Header} sidebar={Sidebar} isManagedSidebar notificationDrawer={notificationDrawer} onNotificationDrawerExpand={this.focusDrawer} isNotificationDrawerExpanded={isDrawerExpanded} skipToContent={PageSkipToContent} breadcrumb={PageBreadcrumb} mainContainerId={pageId} > <PageSection variant={PageSectionVariants.light}> <TextContent> <Text component="h1">Main title</Text> <Text component="p"> Body text should be Overpass Regular at 16px. It should have leading of 24px because <br /> of its relative line height of 1.5. </Text> </TextContent> </PageSection> <PageSection variant={PageSectionVariants.light} noPadding={true}> Panel section content </PageSection> </Page> </React.Fragment> ); } } ``` ### Grouped When using the NotificationDrawerGroupList and related components, the function that is passed in to the `onNotificationDrawerExpand` prop on the Page component must also ensure the NotificationDrawer component only receives focus when it is initially opened. Otherwise any time a drawer group item is opened the NotificationDrawer component will receive focus, which would be unexpected behavior for users. ```js isFullscreen import React from 'react'; import { Avatar, Brand, Breadcrumb, BreadcrumbItem, Button, ButtonVariant, Card, CardBody, Drawer, DrawerContent, DrawerContentBody, Dropdown, DropdownGroup, DropdownToggle, DropdownItem, DropdownSeparator, EmptyState, EmptyStateBody, EmptyStateIcon, EmptyStatePrimary, Gallery, GalleryItem, KebabToggle, Nav, NavItem, NavList, NotificationBadge, NotificationDrawer, NotificationDrawerBody, NotificationDrawerGroup, NotificationDrawerGroupList, NotificationDrawerHeader, NotificationDrawerList, NotificationDrawerListItem, NotificationDrawerListItemBody, NotificationDrawerListItemHeader, Page, PageSection, PageSectionVariants, PageSidebar, SkipToContent, Title, TextContent, Text, PageToggleButton, Masthead, MastheadMain, MastheadToggle, MastheadContent, MastheadBrand, Toolbar, ToolbarItem, ToolbarGroup, ToolbarContent } 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 AttentionBellIcon from '@patternfly/react-icons/dist/esm/icons/attention-bell-icon'; import BarsIcon from '@patternfly/react-icons/dist/esm/icons/bars-icon'; import HelpIcon from '@patternfly/react-icons/dist/esm/icons/help-icon'; import QuestionCircleIcon from '@patternfly/react-icons/dist/esm/icons/question-circle-icon'; import imgBrand from '@patternfly/react-core/src/components/Brand/examples/pfLogo.svg'; import imgAvatar from '@patternfly/react-core/src/components/Avatar/examples/avatarImg.svg'; import { Table, TableHeader, TableBody } from '@patternfly/react-table'; class GroupedNotificationDrawer extends React.Component { constructor(props) { super(props); this.drawerRef = React.createRef(); this.state = { isDropdownOpen: false, isKebabDropdownOpen: false, activeItem: 0, isDrawerExpanded: false, firstDrawerGroupExpanded: false, secondDrawerGroupExpanded: true, thirdDrawerGroupExpanded: false, isActionsMenuOpen: null, showNotifications: true, isUnreadMap: { 'group-1': { 'notification-5': true, 'notification-6': true }, 'group-2': { 'notification-9': true, 'notification-10': true }, 'group-3': null } }; this.onDropdownToggle = isDropdownOpen => { this.setState({ isDropdownOpen }); }; this.onDropdownSelect = event => { this.setState({ isDropdownOpen: !this.state.isDropdownOpen }); }; this.onKebabDropdownToggle = isKebabDropdownOpen => { this.setState({ isKebabDropdownOpen }); }; this.onKebabDropdownSelect = event => { this.setState({ isKebabDropdownOpen: !this.state.isKebabDropdownOpen }); }; this.onNavSelect = result => { this.setState({ activeItem: result.itemId }); }; this.onCloseNotificationDrawer = () => { this.setState(prevState => { return { isDrawerExpanded: !prevState.isDrawerExpanded }; }); }; this.onToggle = (id, isOpen) => { this.setState({ isActionsMenuOpen: { [id]: isOpen } }); }; this.onSelect = event => { this.setState({ isActionsMenuOpen: null }); }; this.onListItemClick = (groupId, id) => { this.setState(prevState => { if (!prevState.isUnreadMap || !prevState.isUnreadMap[groupId]) return; console.log(prevState.isUnreadMap); prevState.isUnreadMap[groupId][id] = false; return { isUnreadMap: prevState.isUnreadMap }; }); }; this.isUnread = (groupId, id) => { const { isUnreadMap } = this.state; return isUnreadMap && isUnreadMap[groupId] && isUnreadMap[groupId][id]; }; this.getNumberUnread = groupId => { const { isUnreadMap } = this.state; if (isUnreadMap === null) return 0; if (groupId) { if (isUnreadMap[groupId] === null) return 0; return Object.keys(isUnreadMap[groupId]).reduce((count, id) => { return isUnreadMap[groupId][id] ? count + 1 : count; }, 0); } return Object.keys(isUnreadMap).reduce((count, groupId) => { if (isUnreadMap[groupId] === null) return count; return Object.keys(isUnreadMap[groupId]).reduce((groupCount, id) => { return isUnreadMap[groupId][id] ? groupCount + 1 : groupCount; }, count); }, 0); }; this.markAllRead = () => { this.setState({ isUnreadMap: null }); }; this.showNotifications = showNotifications => { this.setState({ isUnreadMap: null, showNotifications: showNotifications }); }; this.toggleFirstDrawer = (event, value) => { this.setState({ firstDrawerGroupExpanded: value }); }; this.toggleSecondDrawer = (event, value) => { this.setState({ secondDrawerGroupExpanded: value }); }; this.toggleThirdDrawer = (event, value) => { this.setState({ thirdDrawerGroupExpanded: value }); }; this.focusDrawer = () => { // Prevent the NotificationDrawer from receiving focus if a drawer group item is opened if (!document.activeElement.closest(`.${this.drawerRef.current.className}`)) { const firstTabbableItem = this.drawerRef.current.querySelector('a, button'); firstTabbableItem.focus(); } }; } render() { const { isDropdownOpen, isKebabDropdownOpen, activeItem, res, isDrawerExpanded, isActionsMenuOpen, isUnreadMap, showNotifications, firstDrawerGroupExpanded, secondDrawerGroupExpanded, thirdDrawerGroupExpanded } = this.state; const PageNav = ( <Nav onSelect={this.onNavSelect} aria-label="Nav"> <NavList> <NavItem itemId={0} isActive={activeItem === 0}> System Panel </NavItem> <NavItem itemId={1} isActive={activeItem === 1}> Policy </NavItem> <NavItem itemId={2} isActive={activeItem === 2}> Authentication </NavItem> <NavItem itemId={3} isActive={activeItem === 3}> Network Services </NavItem> <NavItem itemId={4} isActive={activeItem === 4}> Server </NavItem> </NavList> </Nav> ); const kebabDropdownItems = [ <DropdownItem> <CogIcon /> Settings </DropdownItem>, <DropdownItem> <HelpIcon /> Help </DropdownItem> ]; const userDropdownItems = [ <DropdownGroup key="group 2"> <DropdownItem key="group 2 profile">My profile</DropdownItem> <DropdownItem key="group 2 user" component="button"> User management </DropdownItem> <DropdownItem key="group 2 logout">Logout</DropdownItem> </DropdownGroup> ]; const headerToolbar = ( <Toolbar> <ToolbarContent> <ToolbarGroup spaceItems={{ default: 'spacerNone' }} alignment={{ default: 'alignRight' }}> <ToolbarGroup variant="icon-button-group"> <ToolbarItem visibility={{ default: 'visible' }} isSelected={isDrawerExpanded}> <NotificationBadge variant={this.getNumberUnread() === 0 ? 'read' : 'unread'} onClick={this.onCloseNotificationDrawer} aria-label="Notifications" > <BellIcon /> </NotificationBadge> </ToolbarItem> <ToolbarGroup variant="icon-button-group" visibility={{ default: 'hidden', lg: 'visible' }} /** the settings and help icon buttons are only visible on desktop sizes and replaced by a kebab dropdown for other sizes */ > <ToolbarItem> <Button aria-label="Settings actions" variant={ButtonVariant.plain}> <CogIcon /> </Button> </ToolbarItem> <ToolbarItem> <Button aria-label="Help actions" variant={ButtonVariant.plain}> <QuestionCircleIcon /> </Button> </ToolbarItem> </ToolbarGroup> </ToolbarGroup> <ToolbarGroup> <ToolbarItem visibility={{ lg: 'hidden' }} /** this kebab dropdown replaces the icon buttons and is hidden for desktop sizes */ > <Dropdown isPlain position="right" onSelect={this.onKebabDropdownSelect} toggle={<KebabToggle onToggle={this.onKebabDropdownToggle} />} isOpen={isKebabDropdownOpen} dropdownItems={kebabDropdownItems} /> </ToolbarItem> <ToolbarItem visibility={{ default: 'hidden', md: 'visible' }} /** this user dropdown is hidden on mobile sizes */ > <Dropdown position="right" onSelect={this.onDropdownSelect} isOpen={isDropdownOpen} toggle={ <DropdownToggle icon={<Avatar src={imgAvatar} alt="Avatar" />} onToggle={this.onDropdownToggle}> John Smith </DropdownToggle> } dropdownItems={userDropdownItems} /> </ToolbarItem> </ToolbarGroup> </ToolbarGroup> </ToolbarContent> </Toolbar> ); const Header = ( <Masthead> <MastheadToggle> <PageToggleButton variant="plain" aria-label="Global navigation"> <BarsIcon /> </PageToggleButton> </MastheadToggle> <MastheadMain> <MastheadBrand> <Brand src={imgBrand} alt="Patternfly logo" /> </MastheadBrand> </MastheadMain> <MastheadContent>{headerToolbar}</MastheadContent> </Masthead> ); const Sidebar = <PageSidebar nav={PageNav} />; const pageId = 'main-content-page-layout-default-nav'; const PageSkipToContent = <SkipToContent href={`#${pageId}`}>Skip to content</SkipToContent>; const PageBreadcrumb = ( <Breadcrumb> <BreadcrumbItem>Section home</BreadcrumbItem> <BreadcrumbItem to="#">Section title</BreadcrumbItem> <BreadcrumbItem to="#">Section title</BreadcrumbItem> <BreadcrumbItem to="#" isActive> Section landing </BreadcrumbItem> </Breadcrumb> ); const drawerContent = 'Panel content'; const notificationDrawerDropdownItems = [ <DropdownItem key="link">Link</DropdownItem>, <DropdownItem key="action" component="button"> Action </DropdownItem>, <DropdownSeparator key="separator" />, <DropdownItem key="disabled link" isDisabled> Disabled Link </DropdownItem> ]; const notificationDrawerActions = [ <DropdownItem key="markAllRead" onClick={this.markAllRead} component="button"> Mark all read </DropdownItem>, <DropdownItem key="clearAll" onClick={() => this.showNotifications(false)} component="button"> Clear all </DropdownItem>, <DropdownItem key="unclearLast" onClick={() => this.showNotifications(true)} component="button"> Unclear last </DropdownItem>, <DropdownItem key="settings" component="button"> Settings </DropdownItem> ]; const notificationDrawer = ( <NotificationDrawer ref={this.drawerRef}> <NotificationDrawerHeader count={this.getNumberUnread()} onClose={this.onCloseNotificationDrawer}> <Dropdown onSelect={this.onSelect} toggle={<KebabToggle onToggle={isOpen => this.onToggle('toggle-id-0', isOpen)} id="toggle-id-0" />} isOpen={isActionsMenuOpen && isActionsMenuOpen['toggle-id-0']} isPlain dropdownItems={notificationDrawerActions} id="notification-0" position={DropdownPosition.right} /> </NotificationDrawerHeader> <NotificationDrawerBody> {showNotifications && ( <NotificationDrawerGroupList> <NotificationDrawerGroup title="First notification group" isExpanded={firstDrawerGroupExpanded} count={this.getNumberUnread('group-1')} onExpand={this.toggleFirstDrawer} > <NotificationDrawerList isHidden={!firstDrawerGroupExpanded}> <NotificationDrawerListItem variant="info" onClick={() => this.onListItemClick('group-1', 'notification-5')} isRead={!this.isUnread('group-1', 'notification-5')} > <NotificationDrawerListItemHeader variant="info" title="Unread info notification title" srTitle="Info notification:" > <Dropdown position={DropdownPosition.right} onSelect={this.onSelect} toggle={ <KebabToggle onToggle={isOpen => this.onToggle('toggle-id-5', isOpen)} id="toggle-id-5" /> } isOpen={isActionsMenuOpen && isActionsMenuOpen['toggle-id-5']} isPlain dropdownItems={notificationDrawerDropdownItems} id="notification-5" /> </NotificationDrawerListItemHeader> <NotificationDrawerListItemBody timestamp="5 minutes ago"> This is an info notification description. </NotificationDrawerListItemBody> </NotificationDrawerListItem> <NotificationDrawerListItem variant="danger" onClick={() => this.onListItemClick('group-1', 'notification-6')} isRead={!this.isUnread('group-1', 'notification-6')} > <NotificationDrawerListItemHeader variant="danger" title="Unread danger notification title. This is a long title to show how the title will wrap if it is long and wraps to multiple lines." srTitle="Danger notification:" > <Dropdown position={DropdownPosition.right} onSelect={this.onSelect} toggle={ <KebabToggle onToggle={isOpen => this.onToggle('toggle-id-6', isOpen)} id="toggle-id-6" /> } isOpen={isActionsMenuOpen && isActionsMenuOpen['toggle-id-6']} isPlain dropdownItems={notificationDrawerDropdownItems} id="notification-6" /> </NotificationDrawerListItemHeader> <NotificationDrawerListItemBody timestamp="10 minutes ago"> This is a danger notification description. This is a long description to show how the title will wrap if it is long and wraps to multiple lines. </NotificationDrawerListItemBody> </NotificationDrawerListItem> <NotificationDrawerListItem variant="warning" onClick={() => this.onListItemClick('group-1', 'notification-7')} isRead={!this.isUnread('group-1', 'notification-7')} > <NotificationDrawerListItemHeader variant="warning" title="Read warning notification title" srTitle="Warning notification:" > <Dropdown position={DropdownPosition.right} onSelect={this.onSelect} toggle={ <KebabToggle onToggle={isOpen => this.onToggle('toggle-id-7', isOpen)} id="toggle-id-7" /> } isOpen={isActionsMenuOpen && isActionsMenuOpen['toggle-id-7']} isPlain dropdownItems={notificationDrawerDropdownItems} id="notification-7" /> </NotificationDrawerListItemHeader> <NotificationDrawerListItemBody timestamp="20 minutes ago"> This is a warning notification description. </NotificationDrawerListItemBody> </NotificationDrawerListItem> <NotificationDrawerListItem variant="success" onClick={() => this.onListItemClick('group-1', 'notification-8')} isRead={!this.isUnread('group-1', 'notification-8')} > <NotificationDrawerListItemHeader variant="success" title="Read success notification title" srTitle="Success notification:" > <Dropdown position={DropdownPosition.right} direction={DropdownDirection.up} onSelect={this.onSelect} toggle={ <KebabToggle onToggle={isOpen => this.onToggle('toggle-id-8', isOpen)} id="toggle-id-8" /> } isOpen={isActionsMenuOpen && isActionsMenuOpen['toggle-id-8']} isPlain dropdownItems={notificationDrawerDropdownItems} id="notification-8" /> </NotificationDrawerListItemHeader> <NotificationDrawerListItemBody timestamp="30 minutes ago"> This is a success notification description. </NotificationDrawerListItemBody> </NotificationDrawerListItem> </NotificationDrawerList> </NotificationDrawerGroup> <NotificationDrawerGroup title="Second notification group" isExpanded={secondDrawerGroupExpanded} count={this.getNumberUnread('group-2')} onExpand={this.toggleSecondDrawer} > <NotificationDrawerList isHidden={!secondDrawerGroupExpanded}> <NotificationDrawerListItem variant="info" onClick={() => this.onListItemClick('group-2', 'notification-9')} isRead={!this.isUnread('group-2', 'notification-9')} > <NotificationDrawerListItemHeader variant="info" title="Unread info notification title" srTitle="Info notification:" > <Dropdown position={DropdownPosition.right} onSelect={this.onSelect} toggle={ <KebabToggle onToggle={isOpen => this.onToggle('toggle-id-9', isOpen)} id="toggle-id-9" /> } isOpen={isActionsMenuOpen && isActionsMenuOpen['toggle-id-9']} isPlain dropdownItems={notificationDrawerDropdownItems} id="notification-9" /> </NotificationDrawerListItemHeader> <NotificationDrawerListItemBody timestamp="5 minutes ago"> This is an info notification description. </NotificationDrawerListItemBody> </NotificationDrawerListItem> <NotificationDrawerListItem variant="danger" onClick={() => this.onListItemClick('group-2', 'notification-10')} isRead={!this.isUnread('group-2', 'notification-10')} > <NotificationDrawerListItemHeader variant="danger" title="Unread danger notification title. This is a long title to show how the title will wrap if it is long and wraps to multiple lines." srTitle="Danger notification:" > <Dropdown position={DropdownPosition.right} onSelect={this.onSelect} toggle={ <KebabToggle onToggle={isOpen => this.onToggle('toggle-id-10', isOpen)} id="toggle-id-10" /> } isOpen={isActionsMenuOpen && isActionsMenuOpen['toggle-id-10']} isPlain dropdownItems={notificationDrawerDropdownItems} id="notification-10" /> </NotificationDrawerListItemHeader> <NotificationDrawerListItemBody timestamp="10 minutes ago"> This is a danger notification description. This is a long description to show how the title will wrap if it is long and wraps to multiple lines. </NotificationDrawerListItemBody> </NotificationDrawerListItem> <NotificationDrawerListItem variant="warning" onClick={() => this.onListItemClick('group-2', 'notification-11')} isRead={!this.isUnread('group-2', 'notification-11')} > <NotificationDrawerListItemHeader variant="warning" title="Read warning notification title" srTitle="Warning notification:" > <Dropdown position={DropdownPosition.right} onSelect={this.onSelect} toggle={ <KebabToggle onToggle={isOpen => this.onToggle('toggle-id-11', isOpen)} id="toggle-id-11" /> } isOpen={isActionsMenuOpen && isActionsMenuOpen['toggle-id-11']} isPlain dropdownItems={notificationDrawerDropdownItems} id="notification-11" /> </NotificationDrawerListItemHeader> <NotificationDrawerListItemBody timestamp="20 minutes ago"> This is a warning notification description. </NotificationDrawerListItemBody> </NotificationDrawerListItem> <NotificationDrawerListItem variant="success" onClick={() => this.onListItemClick('group-2', 'notification-12')} isRead={!this.isUnread('group-2', 'notification-12')} > <NotificationDrawerListItemHeader variant="success" title="Read success notification title" srTitle="Success notification:" > <Dropdown position={DropdownPosition.right} direction={DropdownDirection.up} onSelect={this.onSelect} toggle={ <KebabToggle onToggle={isOpen => this.onToggle('toggle-id-12', isOpen)} id="toggle-id-12" /> } isOpen={isActionsMenuOpen && isActionsMenuOpen['toggle-id-12']} isPlain dropdownItems={notificationDrawerDropdownItems} id="notification-12" /> </NotificationDrawerListItemHeader> <NotificationDrawerListItemBody timestamp="30 minutes ago"> This is a success notification description. </NotificationDrawerListItemBody> </NotificationDrawerListItem> </NotificationDrawerList> </NotificationDrawerGroup> <NotificationDrawerGroup title="Third notification group" isExpanded={thirdDrawerGroupExpanded} count={this.getNumberUnread('group-3')} onExpand={this.toggleThirdDrawer} > <NotificationDrawerList isHidden={!thirdDrawerGroupExpanded}> <EmptyState variant={EmptyStateVariant.full}> <EmptyStateIcon icon={SearchIcon} /> <Title headingLevel="h2" size="lg"> No alerts found </Title> <EmptyStateBody> There are currently no critical alerts firing. There may be firing alerts of other severities or silenced critical alerts however. </EmptyStateBody> <EmptyStatePrimary> <Button variant="link">Action</Button> </EmptyStatePrimary> </EmptyState> </NotificationDrawerList> </NotificationDrawerGroup> </NotificationDrawerGroupList> )} {!showNotifications && ( <EmptyState variant={EmptyStateVariant.full}> <EmptyStateIcon icon={SearchIcon} /> <Title headingLevel="h2" size="lg"> No alerts found </Title> <EmptyStateBody> There are currently no alerts. There may be silenced critical alerts however. </EmptyStateBody> <EmptyStatePrimary> <Button variant="link">Action</Button> </EmptyStatePrimary> </EmptyState> )} </NotificationDrawerBody> </NotificationDrawer> ); return ( <React.Fragment> <Page header={Header} sidebar={Sidebar} isManagedSidebar notificationDrawer={notificationDrawer} isNotificationDrawerExpanded={isDrawerExpanded} onNotificationDrawerExpand={this.focusDrawer} skipToContent={PageSkipToContent} breadcrumb={PageBreadcrumb} mainContainerId={pageId} > <PageSection variant={PageSectionVariants.light}> <TextContent> <Text component="h1">Main title</Text> <Text component="p"> Body text should be Overpass Regular at 16px. It should have leading of 24px because <br /> of its relative line height of 1.5. </Text> </TextContent> </PageSection> <PageSection variant={PageSectionVariants.light} noPadding={true}> Panel section content </PageSection> </Page> </React.Fragment> ); } } ```