From db5776efaf1d334fe420d01bcc34e130516da5fd Mon Sep 17 00:00:00 2001 From: Austin Sullivan Date: Thu, 13 Nov 2025 11:49:12 -0500 Subject: [PATCH 1/7] feat(Compass): add compass nav components --- packages/react-core/package.json | 2 +- .../components/Compass/CompassNavContent.tsx | 21 ++++ .../src/components/Compass/CompassNavHome.tsx | 17 +++ .../src/components/Compass/CompassNavMain.tsx | 17 +++ .../components/Compass/CompassNavSearch.tsx | 17 +++ .../__tests__/CompassNavContent.test.tsx | 32 ++++++ .../Compass/__tests__/CompassNavHome.test.tsx | 32 ++++++ .../Compass/__tests__/CompassNavMain.test.tsx | 32 ++++++ .../__tests__/CompassNavSearch.test.tsx | 32 ++++++ .../Compass/examples/CompassDemo.tsx | 100 +++++++++++------- .../src/components/Compass/index.ts | 4 + packages/react-docs/package.json | 2 +- packages/react-icons/package.json | 2 +- packages/react-styles/package.json | 2 +- packages/react-tokens/package.json | 2 +- 15 files changed, 270 insertions(+), 44 deletions(-) create mode 100644 packages/react-core/src/components/Compass/CompassNavContent.tsx create mode 100644 packages/react-core/src/components/Compass/CompassNavHome.tsx create mode 100644 packages/react-core/src/components/Compass/CompassNavMain.tsx create mode 100644 packages/react-core/src/components/Compass/CompassNavSearch.tsx create mode 100644 packages/react-core/src/components/Compass/__tests__/CompassNavContent.test.tsx create mode 100644 packages/react-core/src/components/Compass/__tests__/CompassNavHome.test.tsx create mode 100644 packages/react-core/src/components/Compass/__tests__/CompassNavMain.test.tsx create mode 100644 packages/react-core/src/components/Compass/__tests__/CompassNavSearch.test.tsx diff --git a/packages/react-core/package.json b/packages/react-core/package.json index 18fe134ecce..5f356e2e75b 100644 --- a/packages/react-core/package.json +++ b/packages/react-core/package.json @@ -54,7 +54,7 @@ "tslib": "^2.8.1" }, "devDependencies": { - "@patternfly/patternfly": "6.5.0-prerelease.19", + "@patternfly/patternfly": "6.5.0-prerelease.24", "case-anything": "^3.1.2", "css": "^3.0.0", "fs-extra": "^11.3.0" diff --git a/packages/react-core/src/components/Compass/CompassNavContent.tsx b/packages/react-core/src/components/Compass/CompassNavContent.tsx new file mode 100644 index 00000000000..e188652c146 --- /dev/null +++ b/packages/react-core/src/components/Compass/CompassNavContent.tsx @@ -0,0 +1,21 @@ +import styles from '@patternfly/react-styles/css/components/Compass/compass'; +import { css } from '@patternfly/react-styles'; + +interface CompassNavContentProps extends React.HTMLProps { + /** Content of the nav content wrapper. */ + children: React.ReactNode; + /** Additional classes added to the nav content. */ + className?: string; +} + +export const CompassNavContent: React.FunctionComponent = ({ + children, + className, + ...props +}) => ( +
+ {children} +
+); + +CompassNavContent.displayName = 'CompassNavContent'; diff --git a/packages/react-core/src/components/Compass/CompassNavHome.tsx b/packages/react-core/src/components/Compass/CompassNavHome.tsx new file mode 100644 index 00000000000..1c47b0b549c --- /dev/null +++ b/packages/react-core/src/components/Compass/CompassNavHome.tsx @@ -0,0 +1,17 @@ +import styles from '@patternfly/react-styles/css/components/Compass/compass'; +import { css } from '@patternfly/react-styles'; + +interface CompassNavHomeProps extends React.HTMLProps { + /** Content of the nav home section (typically a home button/icon). */ + children: React.ReactNode; + /** Additional classes added to the nav home section. */ + className?: string; +} + +export const CompassNavHome: React.FunctionComponent = ({ children, className, ...props }) => ( +
+ {children} +
+); + +CompassNavHome.displayName = 'CompassNavHome'; diff --git a/packages/react-core/src/components/Compass/CompassNavMain.tsx b/packages/react-core/src/components/Compass/CompassNavMain.tsx new file mode 100644 index 00000000000..7f4f56d24f0 --- /dev/null +++ b/packages/react-core/src/components/Compass/CompassNavMain.tsx @@ -0,0 +1,17 @@ +import styles from '@patternfly/react-styles/css/components/Compass/compass'; +import { css } from '@patternfly/react-styles'; + +interface CompassNavMainProps extends React.HTMLProps { + /** Content of the nav main section (typically tabs). */ + children: React.ReactNode; + /** Additional classes added to the nav main section. */ + className?: string; +} + +export const CompassNavMain: React.FunctionComponent = ({ children, className, ...props }) => ( +
+ {children} +
+); + +CompassNavMain.displayName = 'CompassNavMain'; diff --git a/packages/react-core/src/components/Compass/CompassNavSearch.tsx b/packages/react-core/src/components/Compass/CompassNavSearch.tsx new file mode 100644 index 00000000000..d83bc394357 --- /dev/null +++ b/packages/react-core/src/components/Compass/CompassNavSearch.tsx @@ -0,0 +1,17 @@ +import styles from '@patternfly/react-styles/css/components/Compass/compass'; +import { css } from '@patternfly/react-styles'; + +interface CompassNavSearchProps extends React.HTMLProps { + /** Content of the nav search section (typically a search button/icon). */ + children: React.ReactNode; + /** Additional classes added to the nav search section. */ + className?: string; +} + +export const CompassNavSearch: React.FunctionComponent = ({ children, className, ...props }) => ( +
+ {children} +
+); + +CompassNavSearch.displayName = 'CompassNavSearch'; diff --git a/packages/react-core/src/components/Compass/__tests__/CompassNavContent.test.tsx b/packages/react-core/src/components/Compass/__tests__/CompassNavContent.test.tsx new file mode 100644 index 00000000000..7672261680f --- /dev/null +++ b/packages/react-core/src/components/Compass/__tests__/CompassNavContent.test.tsx @@ -0,0 +1,32 @@ +import { render, screen } from '@testing-library/react'; +import { CompassNavContent } from '../CompassNavContent'; +import styles from '@patternfly/react-styles/css/components/Compass/compass'; + +test('Renders with children', () => { + render(Test content); + expect(screen.getByText('Test content')).toBeVisible(); +}); + +test('Renders with custom class name when className prop is provided', () => { + render(Test); + expect(screen.getByText('Test')).toHaveClass('custom-class'); +}); + +test(`Renders with default ${styles.compassNavContent} class`, () => { + render(Test); + expect(screen.getByText('Test')).toHaveClass(styles.compassNavContent); +}); + +test('Renders with additional props spread to the component', () => { + render(Test); + expect(screen.getByText('Test')).toHaveAccessibleName('Test label'); +}); + +test('Matches the snapshot', () => { + const { asFragment } = render( + +
Nav content wrapper
+
+ ); + expect(asFragment()).toMatchSnapshot(); +}); diff --git a/packages/react-core/src/components/Compass/__tests__/CompassNavHome.test.tsx b/packages/react-core/src/components/Compass/__tests__/CompassNavHome.test.tsx new file mode 100644 index 00000000000..2b04a24ba5b --- /dev/null +++ b/packages/react-core/src/components/Compass/__tests__/CompassNavHome.test.tsx @@ -0,0 +1,32 @@ +import { render, screen } from '@testing-library/react'; +import { CompassNavHome } from '../CompassNavHome'; +import styles from '@patternfly/react-styles/css/components/Compass/compass'; + +test('Renders with children', () => { + render(Test content); + expect(screen.getByText('Test content')).toBeVisible(); +}); + +test('Renders with custom class name when className prop is provided', () => { + render(Test); + expect(screen.getByText('Test')).toHaveClass('custom-class'); +}); + +test(`Renders with default ${styles.compassNavHome} class`, () => { + render(Test); + expect(screen.getByText('Test')).toHaveClass(styles.compassNavHome); +}); + +test('Renders with additional props spread to the component', () => { + render(Test); + expect(screen.getByText('Test')).toHaveAccessibleName('Test label'); +}); + +test('Matches the snapshot', () => { + const { asFragment } = render( + +
Home button
+
+ ); + expect(asFragment()).toMatchSnapshot(); +}); diff --git a/packages/react-core/src/components/Compass/__tests__/CompassNavMain.test.tsx b/packages/react-core/src/components/Compass/__tests__/CompassNavMain.test.tsx new file mode 100644 index 00000000000..76f0c309f28 --- /dev/null +++ b/packages/react-core/src/components/Compass/__tests__/CompassNavMain.test.tsx @@ -0,0 +1,32 @@ +import { render, screen } from '@testing-library/react'; +import { CompassNavMain } from '../CompassNavMain'; +import styles from '@patternfly/react-styles/css/components/Compass/compass'; + +test('Renders with children', () => { + render(Test content); + expect(screen.getByText('Test content')).toBeVisible(); +}); + +test('Renders with custom class name when className prop is provided', () => { + render(Test); + expect(screen.getByText('Test')).toHaveClass('custom-class'); +}); + +test(`Renders with default ${styles.compassNavMain} class`, () => { + render(Test); + expect(screen.getByText('Test')).toHaveClass(styles.compassNavMain); +}); + +test('Renders with additional props spread to the component', () => { + render(Test); + expect(screen.getByText('Test')).toHaveAccessibleName('Test label'); +}); + +test('Matches the snapshot', () => { + const { asFragment } = render( + +
Main tabs content
+
+ ); + expect(asFragment()).toMatchSnapshot(); +}); diff --git a/packages/react-core/src/components/Compass/__tests__/CompassNavSearch.test.tsx b/packages/react-core/src/components/Compass/__tests__/CompassNavSearch.test.tsx new file mode 100644 index 00000000000..ed159203d65 --- /dev/null +++ b/packages/react-core/src/components/Compass/__tests__/CompassNavSearch.test.tsx @@ -0,0 +1,32 @@ +import { render, screen } from '@testing-library/react'; +import { CompassNavSearch } from '../CompassNavSearch'; +import styles from '@patternfly/react-styles/css/components/Compass/compass'; + +test('Renders with children', () => { + render(Test content); + expect(screen.getByText('Test content')).toBeVisible(); +}); + +test('Renders with custom class name when className prop is provided', () => { + render(Test); + expect(screen.getByText('Test')).toHaveClass('custom-class'); +}); + +test(`Renders with default ${styles.compassNavSearch} class`, () => { + render(Test); + expect(screen.getByText('Test')).toHaveClass(styles.compassNavSearch); +}); + +test('Renders with additional props spread to the component', () => { + render(Test); + expect(screen.getByText('Test')).toHaveAccessibleName('Test label'); +}); + +test('Matches the snapshot', () => { + const { asFragment } = render( + +
Search button
+
+ ); + expect(asFragment()).toMatchSnapshot(); +}); diff --git a/packages/react-core/src/components/Compass/examples/CompassDemo.tsx b/packages/react-core/src/components/Compass/examples/CompassDemo.tsx index 735cbdf0e3f..049c1ffb59d 100644 --- a/packages/react-core/src/components/Compass/examples/CompassDemo.tsx +++ b/packages/react-core/src/components/Compass/examples/CompassDemo.tsx @@ -7,6 +7,10 @@ import { CompassMainHeader, CompassPanel, CompassMessageBar, + CompassNavContent, + CompassNavHome, + CompassNavMain, + CompassNavSearch, Tabs, TabsComponent, Tab, @@ -23,6 +27,8 @@ import PlayIcon from '@patternfly/react-icons/dist/esm/icons/play-icon'; import OutlinedPlusSquare from '@patternfly/react-icons/dist/esm/icons/outlined-plus-square-icon'; import OutlinedCopy from '@patternfly/react-icons/dist/esm/icons/outlined-copy-icon'; import OutlinedQuestionCircleIcon from '@patternfly/react-icons/dist/esm/icons/outlined-question-circle-icon'; +import HomeIcon from '@patternfly/react-icons/dist/esm/icons/home-icon'; +import SearchIcon from '@patternfly/react-icons/dist/esm/icons/search-icon'; export const CompassBasic: React.FunctionComponent = () => { const [activeTab, setActiveTab] = useState(0); @@ -32,48 +38,64 @@ export const CompassBasic: React.FunctionComponent = () => { const navContent = ( <> - setActiveTab(tabIndex as number)} - component={TabsComponent.nav} - aria-label="Compass navigation tabs" - inset={{ default: 'insetXl' }} - > - Tab 1} - aria-label="Compass tab with subtabs" - /> - Tab 2} /> - Tab 3} /> - Disabled Tab 4} isDisabled /> - + + + + + + + +`; + +exports[`Matches the snapshot with custom props 1`] = ` + +
+
+ +
+
+
+`; diff --git a/packages/react-core/src/components/Compass/__tests__/__snapshots__/CompassNavMain.test.tsx.snap b/packages/react-core/src/components/Compass/__tests__/__snapshots__/CompassNavMain.test.tsx.snap new file mode 100644 index 00000000000..53987fbf559 --- /dev/null +++ b/packages/react-core/src/components/Compass/__tests__/__snapshots__/CompassNavMain.test.tsx.snap @@ -0,0 +1,13 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Matches the snapshot 1`] = ` + +
+
+ Main tabs content +
+
+
+`; diff --git a/packages/react-core/src/components/Compass/__tests__/__snapshots__/CompassNavSearch.test.tsx.snap b/packages/react-core/src/components/Compass/__tests__/__snapshots__/CompassNavSearch.test.tsx.snap new file mode 100644 index 00000000000..d70bc7861fc --- /dev/null +++ b/packages/react-core/src/components/Compass/__tests__/__snapshots__/CompassNavSearch.test.tsx.snap @@ -0,0 +1,79 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Matches the snapshot 1`] = ` + + + +`; + +exports[`Matches the snapshot with custom props 1`] = ` + + + +`; diff --git a/packages/react-core/src/components/Compass/examples/CompassDemo.tsx b/packages/react-core/src/components/Compass/examples/CompassDemo.tsx index d0e87aae837..ca22b8e712d 100644 --- a/packages/react-core/src/components/Compass/examples/CompassDemo.tsx +++ b/packages/react-core/src/components/Compass/examples/CompassDemo.tsx @@ -1,3 +1,5 @@ +/* eslint-disable no-console */ + import { useRef, useState } from 'react'; import { Compass, @@ -28,8 +30,6 @@ import PlayIcon from '@patternfly/react-icons/dist/esm/icons/play-icon'; import OutlinedPlusSquare from '@patternfly/react-icons/dist/esm/icons/outlined-plus-square-icon'; import OutlinedCopy from '@patternfly/react-icons/dist/esm/icons/outlined-copy-icon'; import OutlinedQuestionCircleIcon from '@patternfly/react-icons/dist/esm/icons/outlined-question-circle-icon'; -import HomeIcon from '@patternfly/react-icons/dist/esm/icons/home-icon'; -import SearchIcon from '@patternfly/react-icons/dist/esm/icons/search-icon'; export const CompassBasic: React.FunctionComponent = () => { const [activeTab, setActiveTab] = useState(0); @@ -40,11 +40,7 @@ export const CompassBasic: React.FunctionComponent = () => { <> - - -