Skip to content

Commit

Permalink
feat(PageSidebar): added SidebarBody component
Browse files Browse the repository at this point in the history
  • Loading branch information
thatblindgeye committed Apr 12, 2023
1 parent d92de5c commit 524c19f
Show file tree
Hide file tree
Showing 36 changed files with 433 additions and 305 deletions.
4 changes: 2 additions & 2 deletions packages/react-core/src/components/Nav/NavExpandable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -125,13 +125,13 @@ export class NavExpandable extends React.Component<NavExpandableProps, NavExpand
{...props}
>
<PageSidebarContext.Consumer>
{({ isNavOpen }) => (
{({ isSidebarOpen }) => (
<button
className={styles.navLink}
id={srText ? null : this.id}
onClick={(event) => this.onExpand(event, context.onToggle)}
aria-expanded={expandedState}
tabIndex={isNavOpen ? null : -1}
tabIndex={isSidebarOpen ? null : -1}
{...buttonProps}
>
{title}
Expand Down
4 changes: 2 additions & 2 deletions packages/react-core/src/components/Nav/NavItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ export const NavItem: React.FunctionComponent<NavItemProps> = ({
...props
}: NavItemProps) => {
const { flyoutRef, setFlyoutRef, navRef } = React.useContext(NavContext);
const { isNavOpen } = React.useContext(PageSidebarContext);
const { isSidebarOpen } = React.useContext(PageSidebarContext);
const [flyoutTarget, setFlyoutTarget] = React.useState(null);
const [isHovered, setIsHovered] = React.useState(false);
const ref = React.useRef<HTMLLIElement>();
Expand Down Expand Up @@ -166,7 +166,7 @@ export const NavItem: React.FunctionComponent<NavItemProps> = ({
'aria-expanded': flyoutVisible
};

const tabIndex = isNavOpen ? null : -1;
const tabIndex = isSidebarOpen ? null : -1;

const renderDefaultLink = (context: any): React.ReactNode => {
const preventLinkDefault = preventDefault || !to;
Expand Down
6 changes: 3 additions & 3 deletions packages/react-core/src/components/Nav/NavList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -108,15 +108,15 @@ export class NavList extends React.Component<NavListProps> {
<NavContext.Consumer>
{({ isHorizontal }) => (
<PageSidebarContext.Consumer>
{({ isNavOpen }) => (
{({ isSidebarOpen }) => (
<React.Fragment>
{isHorizontal && (
<button
className={css(styles.navScrollButton)}
aria-label={ariaLeftScroll}
onClick={this.scrollLeft}
disabled={scrollViewAtStart}
tabIndex={isNavOpen ? null : -1}
tabIndex={isSidebarOpen ? null : -1}
>
<AngleLeftIcon />
</button>
Expand All @@ -136,7 +136,7 @@ export class NavList extends React.Component<NavListProps> {
aria-label={ariaRightScroll}
onClick={this.scrollRight}
disabled={scrollViewAtEnd}
tabIndex={isNavOpen ? null : -1}
tabIndex={isSidebarOpen ? null : -1}
>
<AngleRightIcon />
</button>
Expand Down
36 changes: 18 additions & 18 deletions packages/react-core/src/components/Page/Page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,8 @@ export interface PageProps extends React.HTMLProps<HTMLDivElement> {
/** tabIndex to use for the [role="main"] element, null to unset it */
mainTabIndex?: number | null;
/**
* If true, manages the sidebar open/close state and there is no need to pass the isNavOpen boolean into
* the sidebar component or add a callback onNavToggle function into the Masthead component
* If true, manages the sidebar open/close state and there is no need to pass the isSidebarOpen boolean into
* the sidebar component or add a callback onSidebarToggle function into the Masthead component
*/
isManagedSidebar?: boolean;
/** Flag indicating if tertiary nav width should be limited */
Expand All @@ -51,7 +51,7 @@ export interface PageProps extends React.HTMLProps<HTMLDivElement> {
*/
defaultManagedSidebarIsOpen?: boolean;
/**
* Can add callback to be notified when resize occurs, for example to set the sidebar isNav prop to false for a width < 768px
* Can add callback to be notified when resize occurs, for example to set the sidebar isSidebarOpen prop to false for a width < 768px
* Returns object { mobileView: boolean, windowSize: number }
*/
onPageResize?: ((object: any) => void) | null;
Expand Down Expand Up @@ -88,8 +88,8 @@ export interface PageProps extends React.HTMLProps<HTMLDivElement> {
}

export interface PageState {
desktopIsNavOpen: boolean;
mobileIsNavOpen: boolean;
desktopIsSidebarOpen: boolean;
mobileIsSidebarOpen: boolean;
mobileView: boolean;
width: number;
height: number;
Expand Down Expand Up @@ -117,8 +117,8 @@ export class Page extends React.Component<PageProps, PageState> {
const { isManagedSidebar, defaultManagedSidebarIsOpen } = props;
const managedSidebarOpen = !isManagedSidebar ? true : defaultManagedSidebarIsOpen;
this.state = {
desktopIsNavOpen: managedSidebarOpen,
mobileIsNavOpen: false,
desktopIsSidebarOpen: managedSidebarOpen,
mobileIsSidebarOpen: false,
mobileView: false,
width: null,
height: null
Expand Down Expand Up @@ -188,20 +188,20 @@ export class Page extends React.Component<PageProps, PageState> {
handleResize = debounce(this.resize, 250);

handleMainClick = () => {
if (this.isMobile() && this.state.mobileIsNavOpen && this.mainRef.current) {
this.setState({ mobileIsNavOpen: false });
if (this.isMobile() && this.state.mobileIsSidebarOpen && this.mainRef.current) {
this.setState({ mobileIsSidebarOpen: false });
}
};

onNavToggleMobile = () => {
this.setState(prevState => ({
mobileIsNavOpen: !prevState.mobileIsNavOpen
onSidebarToggleMobile = () => {
this.setState((prevState) => ({
mobileIsSidebarOpen: !prevState.mobileIsSidebarOpen
}));
};

onNavToggleDesktop = () => {
this.setState(prevState => ({
desktopIsNavOpen: !prevState.desktopIsNavOpen
onSidebarToggleDesktop = () => {
this.setState((prevState) => ({
desktopIsSidebarOpen: !prevState.desktopIsSidebarOpen
}));
};

Expand Down Expand Up @@ -237,12 +237,12 @@ export class Page extends React.Component<PageProps, PageState> {
breadcrumbProps,
...rest
} = this.props;
const { mobileView, mobileIsNavOpen, desktopIsNavOpen, width, height } = this.state;
const { mobileView, mobileIsSidebarOpen, desktopIsSidebarOpen, width, height } = this.state;

const context = {
isManagedSidebar,
onNavToggle: mobileView ? this.onNavToggleMobile : this.onNavToggleDesktop,
isNavOpen: mobileView ? mobileIsNavOpen : desktopIsNavOpen,
onSidebarToggle: mobileView ? this.onSidebarToggleMobile : this.onSidebarToggleDesktop,
isSidebarOpen: mobileView ? mobileIsSidebarOpen : desktopIsSidebarOpen,
width,
height,
getBreakpoint,
Expand Down
8 changes: 4 additions & 4 deletions packages/react-core/src/components/Page/PageContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ import { getBreakpoint, getVerticalBreakpoint } from '../../helpers/util';

export interface PageContextProps {
isManagedSidebar: boolean;
onNavToggle: () => void;
isNavOpen: boolean;
onSidebarToggle: () => void;
isSidebarOpen: boolean;
width: number;
height: number;
getBreakpoint: (width: number | null) => 'default' | 'sm' | 'md' | 'lg' | 'xl' | '2xl';
Expand All @@ -13,8 +13,8 @@ export interface PageContextProps {

export const pageContextDefaults: PageContextProps = {
isManagedSidebar: false,
isNavOpen: false,
onNavToggle: () => null,
isSidebarOpen: false,
onSidebarToggle: () => null,
width: null,
height: null,
getBreakpoint,
Expand Down
34 changes: 16 additions & 18 deletions packages/react-core/src/components/Page/PageSidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,57 +6,55 @@ import { PageContextConsumer } from './PageContext';
export interface PageSidebarProps extends React.HTMLProps<HTMLDivElement> {
/** Additional classes added to the page sidebar */
className?: string;
/** Component to render the side navigation (e.g. <Nav /> */
nav?: React.ReactNode;
/** Content rendered inside the page sidebar (e.g. <PageSidebarBody /> */
children?: React.ReactNode;
/**
* If true, manages the sidebar open/close state and there is no need to pass the isNavOpen boolean into
* the sidebar component or add a callback onNavToggle function into the PageHeader component
* If true, manages the sidebar open/close state and there is no need to pass the isSidebarOpen boolean into
* the sidebar component or add a callback onSidebarToggle function into the PageHeader component
*/
isManagedSidebar?: boolean;
/** Programmatically manage if the side nav is shown, if isManagedSidebar is set to true in the Page component, this prop is managed */
isNavOpen?: boolean;
/** Programmatically manage if the sidebar is shown, if isManagedSidebar is set to true in the Page component, this prop is managed */
isSidebarOpen?: boolean;
/** Indicates the color scheme of the sidebar */
theme?: 'dark' | 'light';
/** Sidebar id */
id?: string;
}

export interface PageSidebarContextProps {
isNavOpen: boolean;
isSidebarOpen: boolean;
}
export const pageSidebarContextDefaults: PageSidebarContextProps = {
isNavOpen: true
isSidebarOpen: true
};
export const PageSidebarContext = React.createContext<Partial<PageSidebarContextProps>>(pageSidebarContextDefaults);

export const PageSidebar: React.FunctionComponent<PageSidebarProps> = ({
className = '',
nav,
isNavOpen = true,
children,
isSidebarOpen = true,
theme = 'dark',
id = 'page-sidebar',
...props
}: PageSidebarProps) => (
<PageContextConsumer>
{({ isManagedSidebar, isNavOpen: managedIsNavOpen }: PageSidebarProps) => {
const navOpen = isManagedSidebar ? managedIsNavOpen : isNavOpen;
{({ isManagedSidebar, isSidebarOpen: managedIsNavOpen }: PageSidebarProps) => {
const sidebarOpen = isManagedSidebar ? managedIsNavOpen : isSidebarOpen;

return (
<div
id={id}
className={css(
styles.pageSidebar,
theme === 'light' && styles.modifiers.light,
navOpen && styles.modifiers.expanded,
!navOpen && styles.modifiers.collapsed,
sidebarOpen && styles.modifiers.expanded,
!sidebarOpen && styles.modifiers.collapsed,
className
)}
aria-hidden={!navOpen}
aria-hidden={!sidebarOpen}
{...props}
>
<div className={css(styles.pageSidebarBody)}>
<PageSidebarContext.Provider value={{ isNavOpen: navOpen }}>{nav}</PageSidebarContext.Provider>
</div>
<PageSidebarContext.Provider value={{ isSidebarOpen: sidebarOpen }}>{children}</PageSidebarContext.Provider>
</div>
);
}}
Expand Down
36 changes: 36 additions & 0 deletions packages/react-core/src/components/Page/PageSidebarBody.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import * as React from 'react';
import styles from '@patternfly/react-styles/css/components/Page/page';
import { css } from '@patternfly/react-styles';

export interface PageSidebarBodyProps extends React.HTMLProps<HTMLDivElement> {
/** Content rendered inside the page sidebar body */
children?: React.ReactNode;
/** Additional classes added to the page sidebar body */
className?: string;
/** Flag indicating that the page sidebar body should use page insets. */
usePageInsets?: boolean;
/** Flag indicating that the page sidebar body should fill the available vertical space. */
isFilled?: boolean;
}

export const PageSidebarBody: React.FunctionComponent<PageSidebarBodyProps> = ({
children,
className,
usePageInsets,
isFilled,
...props
}: PageSidebarBodyProps) => (
<div
className={css(
styles.pageSidebarBody,
usePageInsets && styles.modifiers.pageInsets,
isFilled === false && styles.modifiers.noFill,
isFilled === true && styles.modifiers.fill,
className
)}
{...props}
>
{children}
</div>
);
PageSidebarBody.displayName = 'PageSidebarBody';
26 changes: 15 additions & 11 deletions packages/react-core/src/components/Page/PageToggleButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,32 +6,36 @@ import { PageContextConsumer, PageContextProps } from './PageContext';
export interface PageToggleButtonProps extends ButtonProps {
/** Content of the page toggle button */
children?: React.ReactNode;
/** True if the side nav is shown */
isNavOpen?: boolean;
/** Callback function to handle the side nav toggle button, managed by the Page component if the Page isManagedSidebar prop is set to true */
onNavToggle?: () => void;
/** True if the sidebar is shown */
isSidebarOpen?: boolean;
/** Callback function to handle the sidebar toggle button, managed by the Page component if the Page isManagedSidebar prop is set to true */
onSidebarToggle?: () => void;
/** Button id */
id?: string;
}

export const PageToggleButton: React.FunctionComponent<PageToggleButtonProps> = ({
children,
isNavOpen = true,
onNavToggle = () => undefined as any,
isSidebarOpen = true,
onSidebarToggle = () => undefined as any,
id = 'nav-toggle',
...props
}: PageToggleButtonProps) => (
<PageContextConsumer>
{({ isManagedSidebar, onNavToggle: managedOnNavToggle, isNavOpen: managedIsNavOpen }: PageContextProps) => {
const navToggle = isManagedSidebar ? managedOnNavToggle : onNavToggle;
const navOpen = isManagedSidebar ? managedIsNavOpen : isNavOpen;
{({
isManagedSidebar,
onSidebarToggle: managedOnSidebarToggle,
isSidebarOpen: managedIsSidebarOpen
}: PageContextProps) => {
const sidebarToggle = isManagedSidebar ? managedOnSidebarToggle : onSidebarToggle;
const sidebarOpen = isManagedSidebar ? managedIsSidebarOpen : isSidebarOpen;

return (
<Button
id={id}
onClick={navToggle}
onClick={sidebarToggle}
aria-label="Side navigation toggle"
aria-expanded={navOpen ? 'true' : 'false'}
aria-expanded={sidebarOpen ? 'true' : 'false'}
variant={ButtonVariant.plain}
{...props}
>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@ import {} from '../..';

it('PageSidebar should match snapshot (auto-generated)', () => {
const { asFragment } = render(
<PageSidebar className={"''"} nav={<div>ReactNode</div>} isManagedSidebar={true} isNavOpen={true} theme={'dark'} />
<PageSidebar className={"''"} isManagedSidebar={true} isSidebarOpen={true} theme={'dark'}>
<div>ReactNode</div>
</PageSidebar>
);
expect(asFragment()).toMatchSnapshot();
});
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,8 @@ exports[`PageSidebar should match snapshot (auto-generated) 1`] = `
class="pf-c-page__sidebar pf-m-expanded ''"
id="page-sidebar"
>
<div
class="pf-c-page__sidebar-body"
>
<div>
ReactNode
</div>
<div>
ReactNode
</div>
</div>
</DocumentFragment>
Expand Down
Loading

0 comments on commit 524c19f

Please sign in to comment.