Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages/react-core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@
"tslib": "^2.8.1"
},
"devDependencies": {
"@patternfly/patternfly": "6.6.0-prerelease.20",
"@patternfly/patternfly": "6.6.0-prerelease.37",
"case-anything": "^3.1.2",
"css": "^3.0.0",
"fs-extra": "^11.3.3"
Expand Down
4 changes: 4 additions & 0 deletions packages/react-core/src/components/Compass/Compass.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ export interface CompassProps extends React.HTMLProps<HTMLDivElement> {
dock?: React.ReactNode;
/** @beta Flag indicating the docked nav is expanded on mobile. Only applies when dock content is passed. */
isDockExpanded?: boolean;
/** @beta Flag indicating a docked nav is expanded as an overlay, triggered by expandable nav children. Only applies when dock content is passed. */
isDockExpandableExpanded?: boolean;
/** @beta Flag indicating the docked nav should display text on desktop. Only applies when dock content is passed, and
* will handle toggling the visibility of the text in individual isDocked components.
*/
Expand Down Expand Up @@ -45,6 +47,7 @@ export const Compass: React.FunctionComponent<CompassProps> = ({
masthead,
dock,
isDockExpanded,
isDockExpandableExpanded,
isDockTextExpanded,
header,
isHeaderExpanded = true,
Expand All @@ -69,6 +72,7 @@ export const Compass: React.FunctionComponent<CompassProps> = ({
className={css(
`${styles.compass}__dock`,
isDockExpanded && styles.modifiers.expanded,
isDockExpandableExpanded && styles.modifiers.expandableExpanded,
isDockTextExpanded && styles.modifiers.textExpanded
)}
>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,21 @@ test('Renders footer without expanded class and with inert when isFooterExpanded
expect(footerElement).toHaveAttribute('inert');
});

test(`Renders with ${styles.modifiers.expandableExpanded} class when isDockExpandableExpanded is true`, () => {
render(<Compass dock={<div>Dock content</div>} isDockExpandableExpanded />);
expect(screen.getByText('Dock content').parentElement).toHaveClass(styles.modifiers.expandableExpanded);
});

test(`Does not render with ${styles.modifiers.expandableExpanded} class when isDockExpandableExpanded is false`, () => {
render(<Compass dock={<div>Dock content</div>} isDockExpandableExpanded={false} />);
expect(screen.getByText('Dock content').parentElement).not.toHaveClass(styles.modifiers.expandableExpanded);
});

test(`Does not render with ${styles.modifiers.expandableExpanded} class by default`, () => {
render(<Compass dock={<div>Dock content</div>} />);
expect(screen.getByText('Dock content').parentElement).not.toHaveClass(styles.modifiers.expandableExpanded);
});

test('Renders with drawer when drawerContent is provided', () => {
render(<Compass drawerContent={<div>Drawer content</div>} />);
expect(screen.getByText('Drawer content')).toBeVisible();
Expand Down
14 changes: 12 additions & 2 deletions packages/react-core/src/components/Nav/NavExpandable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { PickOptional } from '../../helpers/typeUtils';
import { getOUIAProps, OUIAProps } from '../../helpers';
import { SSRSafeIds } from '../../helpers/SSRSafeIds/SSRSafeIds';
import { IS_INERT } from '../../helpers/inert';
import RhUiEllipsisHorizontalFillIcon from '@patternfly/react-icons/dist/esm/icons/rh-ui-ellipsis-horizontal-fill-icon';

export interface NavExpandableProps
extends Omit<React.DetailedHTMLProps<React.LiHTMLAttributes<HTMLLIElement>, HTMLLIElement>, 'title'>, OUIAProps {
Expand All @@ -17,6 +18,8 @@ export interface NavExpandableProps
srText?: string;
/** Boolean to pragmatically expand or collapse section */
isExpanded?: boolean;
/** Adds an expandable icon to indicate the section is expandable */
hasExpandableIcon?: boolean;
/** Anything that can be rendered inside of the expandable list */
children?: React.ReactNode;
/** Additional classes added to the container */
Expand Down Expand Up @@ -50,7 +53,8 @@ class NavExpandable extends Component<NavExpandableProps, NavExpandableState> {
className: '',
groupId: null as string,
isActive: false,
id: ''
id: '',
hasExpandableIcon: false
};

state = {
Expand Down Expand Up @@ -100,6 +104,7 @@ class NavExpandable extends Component<NavExpandableProps, NavExpandableState> {
id,
// eslint-disable-next-line @typescript-eslint/no-unused-vars
isExpanded,
hasExpandableIcon,
buttonProps,
// eslint-disable-next-line @typescript-eslint/no-unused-vars
onExpand,
Expand Down Expand Up @@ -137,7 +142,12 @@ class NavExpandable extends Component<NavExpandableProps, NavExpandableState> {
{...buttonProps}
>
{icon && <span className={css(styles.navLinkIcon)}>{icon}</span>}
{typeof title !== 'string' ? <span className={css(styles.navLinkText)}>{title}</span> : title}
{hasExpandableIcon && (
<span className={css(styles.navLinkExpandableIcon)}>
<RhUiEllipsisHorizontalFillIcon />
</span>
)}
<span className={css(styles.navLinkText)}>{title}</span>
<span className={css(styles.navToggle)}>
<span className={css(styles.navToggleIcon)}>
<RhMicronsCaretDownIcon />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,11 @@ exports[`NavExpandable should match snapshot (auto-generated) 1`] = `
aria-expanded="false"
class="pf-v6-c-nav__link"
>
string
<span
class="pf-v6-c-nav__link-text"
>
string
</span>
<span
class="pf-v6-c-nav__toggle"
>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,24 @@ test('Does not render nav link icon wrapper when icon prop is not provided', ()
const button = screen.getByRole('button', { name: 'NavExpandable' });
expect(button.querySelector('.pf-v6-c-nav__link-icon')).not.toBeInTheDocument();
});

test(`Renders with expandable icon when hasExpandableIcon is true`, () => {
render(<NavExpandable id="grp-1" title="NavExpandable" hasExpandableIcon={true}></NavExpandable>);

const button = screen.getByRole('button', { name: 'NavExpandable' });
expect(button.querySelector('.pf-v6-c-nav__link-expandable-icon')).toBeInTheDocument();
});

test(`Does not render expandable icon when hasExpandableIcon is false`, () => {
render(<NavExpandable id="grp-1" title="NavExpandable" hasExpandableIcon={false}></NavExpandable>);

const button = screen.getByRole('button', { name: 'NavExpandable' });
expect(button.querySelector('.pf-v6-c-nav__link-expandable-icon')).not.toBeInTheDocument();
});

test(`Does not render expandable icon by default`, () => {
render(<NavExpandable id="grp-1" title="NavExpandable"></NavExpandable>);

const button = screen.getByRole('button', { name: 'NavExpandable' });
expect(button.querySelector('.pf-v6-c-nav__link-expandable-icon')).not.toBeInTheDocument();
});
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,11 @@ exports[`Nav Expandable Nav List - Trigger toggle 1`] = `
class="pf-v6-c-nav__link"
id="grp-1"
>
Section 1
<span
class="pf-v6-c-nav__link-text"
>
Section 1
</span>
<span
class="pf-v6-c-nav__toggle"
>
Expand Down Expand Up @@ -329,7 +333,11 @@ exports[`Nav Expandable Nav List 1`] = `
class="pf-v6-c-nav__link"
id="grp-1"
>
Section 1
<span
class="pf-v6-c-nav__link-text"
>
Section 1
</span>
<span
class="pf-v6-c-nav__toggle"
>
Expand Down Expand Up @@ -461,7 +469,11 @@ exports[`Nav Expandable Nav List with aria label 1`] = `
aria-expanded="false"
class="pf-v6-c-nav__link"
>
Section 1
<span
class="pf-v6-c-nav__link-text"
>
Section 1
</span>
<span
class="pf-v6-c-nav__toggle"
>
Expand Down
21 changes: 17 additions & 4 deletions packages/react-core/src/components/Nav/examples/Nav.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,12 @@ ouia: true
import { useState } from 'react';
import './nav.css';
import RhMicronsCaretRightIcon from '@patternfly/react-icons/dist/esm/icons/rh-microns-caret-right-icon';
import CubeIcon from '@patternfly/react-icons/dist/esm/icons/cube-icon';
import RhUiFolderFillIcon from '@patternfly/react-icons/dist/esm/icons/rh-ui-folder-fill-icon';
import RhUiFolderOpenFillIcon from '@patternfly/react-icons/dist/esm/icons/rh-ui-folder-open-fill-icon';
import RhUiCloudFillIcon from '@patternfly/react-icons/dist/esm/icons/rh-ui-cloud-fill-icon';
import RhUiCubesIcon from '@patternfly/react-icons/dist/esm/icons/rh-ui-cubes-icon';
import RhUiFolderIcon from '@patternfly/react-icons/dist/esm/icons/rh-ui-folder-icon';
import RhUiFolderOpenIcon from '@patternfly/react-icons/dist/esm/icons/rh-ui-folder-open-icon';
import RhUiCloudIcon from '@patternfly/react-icons/dist/esm/icons/rh-ui-cloud-icon';
import RhUiLinkIcon from '@patternfly/react-icons/dist/esm/icons/rh-ui-link-icon';
import RhUiCodeIcon from '@patternfly/react-icons/dist/esm/icons/rh-ui-code-icon';

## Examples

Expand Down Expand Up @@ -81,6 +82,18 @@ A flyout should be a `Menu` component. Press `space` or `right arrow` to open a

```

### Docked

The docked variant of `Navigation` displays only icons passed to child `NavItems` or `NavExpandable`. Text becomes visible when `.pf-m-text-expanded` or `.pf-m-expandable-expanded` are applied to an outer page or compass dock.

`NavExpandable` items should include the `hasExpandableIcon` prop to indicate their expandable nature while in the collapsed state of the docked nav as the caret will not be rendered.

See the [docked nav demo](/components/navigation/react-demos#docked-nav) for a fully functional example.

```ts file="./NavDocked.tsx"

```

## Types

### NavSelectClickHandler
Expand Down
97 changes: 97 additions & 0 deletions packages/react-core/src/components/Nav/examples/NavDocked.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
import { useState } from 'react';
import { Nav, NavItem, NavList, NavExpandable } from '@patternfly/react-core';
import RhUiCubesIcon from '@patternfly/react-icons/dist/esm/icons/rh-ui-cubes-icon';
import RhUiFolderIcon from '@patternfly/react-icons/dist/esm/icons/rh-ui-folder-icon';
import RhUiCodeIcon from '@patternfly/react-icons/dist/esm/icons/rh-ui-code-icon';
import RhUiCloudIcon from '@patternfly/react-icons/dist/esm/icons/rh-ui-cloud-icon';

export const NavDocked: React.FunctionComponent = () => {
const [activeItem, setActiveItem] = useState(0);
const [isGroupExpanded, setIsGroupExpanded] = useState(false);

const onSelect = (_event: React.FormEvent<HTMLInputElement>, result: { itemId: number | string }) => {
setActiveItem(result.itemId as number);
};

const onToggle = (
_event: React.MouseEvent<HTMLButtonElement>,
result: { groupId: number | string; isExpanded: boolean }
) => {
setIsGroupExpanded(result.isExpanded);
};

return (
<Nav variant="docked" onSelect={onSelect} onToggle={onToggle} aria-label="Default global" ouiaId="DefaultNav">
<NavList>
<NavItem
icon={<RhUiCubesIcon />}
preventDefault
id="nav-default-link1"
to="#nav-default-link1"
itemId={0}
isActive={activeItem === 0}
>
Default Link 1
</NavItem>
<NavItem
icon={<RhUiCloudIcon />}
preventDefault
id="nav-default-link2"
to="#nav-default-link2"
itemId={1}
isActive={activeItem === 1}
>
Default Link 2
</NavItem>
<NavItem
icon={<RhUiCodeIcon />}
preventDefault
id="nav-default-link3"
to="#nav-default-link3"
itemId={2}
isActive={activeItem === 2}
>
Default Link 3
</NavItem>
<NavExpandable
title="Expandable Group 1"
groupId="nav-expandable-group-1"
icon={<RhUiFolderIcon />}
isExpanded={isGroupExpanded}
hasExpandableIcon
>
<NavItem
preventDefault
id="expandable-1"
to="#expandable-1"
groupId="nav-expandable-group-1"
itemId={3}
isActive={activeItem === 3}
>
Subnav 1 Link 1
</NavItem>
<NavItem
preventDefault
id="expandable-2"
to="#expandable-2"
groupId="nav-expandable-group-1"
itemId={4}
isActive={activeItem === 4}
>
Subnav 1 Link 2
</NavItem>
<NavItem
preventDefault
id="expandable-3"
to="#expandable-3"
groupId="nav-expandable-group-1"
itemId={5}
isActive={activeItem === 5}
>
Subnav 1 Link 3
</NavItem>
</NavExpandable>
</NavList>
</Nav>
);
};
16 changes: 8 additions & 8 deletions packages/react-core/src/components/Nav/examples/NavIcons.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { useState } from 'react';
import { Nav, NavExpandable, NavItem, NavList } from '@patternfly/react-core';
import CubeIcon from '@patternfly/react-icons/dist/esm/icons/cube-icon';
import RhUiFolderFillIcon from '@patternfly/react-icons/dist/esm/icons/rh-ui-folder-fill-icon';
import RhUiFolderOpenFillIcon from '@patternfly/react-icons/dist/esm/icons/rh-ui-folder-open-fill-icon';
import RhUiCloudFillIcon from '@patternfly/react-icons/dist/esm/icons/rh-ui-cloud-fill-icon';
import RhUiCubesIcon from '@patternfly/react-icons/dist/esm/icons/rh-ui-cubes-icon';
import RhUiFolderIcon from '@patternfly/react-icons/dist/esm/icons/rh-ui-folder-icon';
import RhUiFolderOpenIcon from '@patternfly/react-icons/dist/esm/icons/rh-ui-folder-open-icon';
import RhUiCloudIcon from '@patternfly/react-icons/dist/esm/icons/rh-ui-cloud-icon';
import RhUiLinkIcon from '@patternfly/react-icons/dist/esm/icons/rh-ui-link-icon';

export const NavIcons: React.FunctionComponent = () => {
Expand All @@ -22,7 +22,7 @@ export const NavIcons: React.FunctionComponent = () => {
to="#nav-icon-link1"
itemId={0}
isActive={activeItem === 0}
icon={<CubeIcon />}
icon={<RhUiCubesIcon />}
>
Link 1
</NavItem>
Expand All @@ -32,7 +32,7 @@ export const NavIcons: React.FunctionComponent = () => {
to="#nav-icon-link2"
itemId={1}
isActive={activeItem === 1}
icon={<RhUiFolderFillIcon />}
icon={<RhUiFolderIcon />}
>
Link 2
</NavItem>
Expand All @@ -42,7 +42,7 @@ export const NavIcons: React.FunctionComponent = () => {
to="#nav-icon-link3"
itemId={2}
isActive={activeItem === 2}
icon={<RhUiCloudFillIcon />}
icon={<RhUiCloudIcon />}
>
Link 3
</NavItem>
Expand All @@ -56,7 +56,7 @@ export const NavIcons: React.FunctionComponent = () => {
>
Link 4
</NavItem>
<NavExpandable title="Expandable" icon={<RhUiFolderOpenFillIcon />} groupId="nav-icon-expandable">
<NavExpandable title="Expandable" icon={<RhUiFolderOpenIcon />} groupId="nav-icon-expandable">
<NavItem
preventDefault
id="nav-icon-expandable-link1"
Expand Down
5 changes: 5 additions & 0 deletions packages/react-core/src/components/Page/Page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ export interface PageProps extends React.HTMLProps<HTMLDivElement> {
variant?: 'default' | 'docked';
/** @beta Flag indicating the docked nav is expanded on mobile. Only applies when variant is docked. */
isDockExpanded?: boolean;
/** @beta Flag indicating a docked nav is expanded as an overlay, triggered by expandable nav children. Only applies when dock content is passed. */
isDockExpandableExpanded?: boolean;
/** @beta Flag indicating the docked nav should display text on desktop. Only applies when variant is docked, and
* will handle toggling the visibility of the text in individual isDocked components.
*/
Expand Down Expand Up @@ -131,6 +133,7 @@ class Page extends Component<PageProps, PageState> {
defaultManagedSidebarIsOpen: true,
mainTabIndex: -1,
isNotificationDrawerExpanded: false,
isDockExpandableExpanded: false,
onNotificationDrawerExpand: () => null,
mainComponent: 'main',
getBreakpoint,
Expand Down Expand Up @@ -245,6 +248,7 @@ class Page extends Component<PageProps, PageState> {
variant,
isDockExpanded = false,
isDockTextExpanded = false,
isDockExpandableExpanded = false,
masthead,
dockContent,
sidebar,
Expand Down Expand Up @@ -371,6 +375,7 @@ class Page extends Component<PageProps, PageState> {
className={css(
styles.pageDock,
isDockExpanded && styles.modifiers.expanded,
isDockExpandableExpanded && styles.modifiers.expandableExpanded,
isDockTextExpanded && styles.modifiers.textExpanded
)}
>
Expand Down
Loading
Loading