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.5.0-prerelease.22",
"@patternfly/patternfly": "6.5.0-prerelease.26",
"case-anything": "^3.1.2",
"css": "^3.0.0",
"fs-extra": "^11.3.0"
Expand Down
18 changes: 18 additions & 0 deletions packages/react-core/src/components/Compass/CompassNavContent.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import styles from '@patternfly/react-styles/css/components/Compass/compass';
import { css } from '@patternfly/react-styles';
export interface CompassNavContentProps extends React.HTMLProps<HTMLDivElement> {
/** Content of the nav content wrapper. */
children: React.ReactNode;
}

export const CompassNavContent: React.FunctionComponent<CompassNavContentProps> = ({
children,
className,
...props
}) => (
<div className={css(styles.compassNavContent, className)} {...props}>
{children}
</div>
);

CompassNavContent.displayName = 'CompassNavContent';
61 changes: 61 additions & 0 deletions packages/react-core/src/components/Compass/CompassNavHome.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import styles from '@patternfly/react-styles/css/components/Compass/compass';
import { css } from '@patternfly/react-styles';
import { Button } from '../Button';
import { Tooltip } from '../Tooltip';

const CompassHomeIcon = () => (
<svg
width="1em"
height="1em"
className="pf-v6-svg"
viewBox="0 0 20 20"
fill="none"
xmlns="http://www.w3.org/2000/svg"
aria-hidden="true"
>
<path
d="M8.33268 13.334H11.666"
stroke="currentcolor"
strokeWidth="1.5"
strokeLinecap="round"
strokeLinejoin="round"
/>
<path
d="M1.66602 6.66602L9.73102 2.63351C9.89994 2.54905 10.0988 2.54905 10.2677 2.63351L18.3327 6.66602"
stroke="currentcolor"
strokeWidth="1.5"
strokeLinecap="round"
strokeLinejoin="round"
/>
<path
d="M16.6673 9.16602V15.4993C16.6673 16.6039 15.7719 17.4993 14.6673 17.4993H5.33398C4.22941 17.4993 3.33398 16.6039 3.33398 15.4993V9.16602"
stroke="currentcolor"
strokeWidth="1.5"
strokeLinecap="round"
strokeLinejoin="round"
/>
</svg>
);

export interface CompassNavHomeProps extends Omit<React.HTMLProps<HTMLDivElement>, 'onClick'> {
/** Content to display in the tooltip. Defaults to "Home". */
tooltipContent?: React.ReactNode;
/** Click handler for the home button. */
onClick?: React.MouseEventHandler<HTMLButtonElement>;
}

export const CompassNavHome: React.FunctionComponent<CompassNavHomeProps> = ({
'aria-label': ariaLabel = 'Home',
tooltipContent = 'Home',
className,
onClick,
...props
}) => (
<div className={css(styles.compassNav + '-home', className)} {...props}>
<Tooltip content={tooltipContent}>
<Button isCircle variant="plain" icon={<CompassHomeIcon />} aria-label={ariaLabel} onClick={onClick} />
</Tooltip>
</div>
);

CompassNavHome.displayName = 'CompassNavHome';
15 changes: 15 additions & 0 deletions packages/react-core/src/components/Compass/CompassNavMain.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import styles from '@patternfly/react-styles/css/components/Compass/compass';
import { css } from '@patternfly/react-styles';

export interface CompassNavMainProps extends React.HTMLProps<HTMLDivElement> {
/** Content of the nav main section (typically tabs). */
children: React.ReactNode;
}

export const CompassNavMain: React.FunctionComponent<CompassNavMainProps> = ({ children, className, ...props }) => (
<div className={css(styles.compassNavMain, className)} {...props}>
{children}
</div>
);

CompassNavMain.displayName = 'CompassNavMain';
54 changes: 54 additions & 0 deletions packages/react-core/src/components/Compass/CompassNavSearch.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import styles from '@patternfly/react-styles/css/components/Compass/compass';
import { css } from '@patternfly/react-styles';
import { Button } from '../Button';
import { Tooltip } from '../Tooltip';

const CompassSearchIcon = () => (
<svg
width="1em"
height="1em"
className="pf-v6-svg"
viewBox="0 0 20 20"
fill="none"
xmlns="http://www.w3.org/2000/svg"
aria-hidden="true"
>
<path
d="M14.166 14.166L17.4993 17.4993"
stroke="currentcolor"
strokeWidth="1.5"
strokeLinecap="round"
strokeLinejoin="round"
/>
<path
d="M2.5 9.16667C2.5 12.8486 5.48477 15.8333 9.16667 15.8333C11.0108 15.8333 12.6801 15.0846 13.887 13.8744C15.0897 12.6685 15.8333 11.0044 15.8333 9.16667C15.8333 5.48477 12.8486 2.5 9.16667 2.5C5.48477 2.5 2.5 5.48477 2.5 9.16667Z"
stroke="currentcolor"
strokeWidth="1.5"
strokeLinecap="round"
strokeLinejoin="round"
/>
</svg>
);

export interface CompassNavSearchProps extends Omit<React.HTMLProps<HTMLDivElement>, 'onClick'> {
/** Content to display in the tooltip. Defaults to "Search". */
tooltipContent?: React.ReactNode;
/** Click handler for the search button. */
onClick?: React.MouseEventHandler<HTMLButtonElement>;
}

export const CompassNavSearch: React.FunctionComponent<CompassNavSearchProps> = ({
'aria-label': ariaLabel = 'Search',
tooltipContent = 'Search',
className,
onClick,
...props
}) => (
<div className={css(styles.compassNav + '-search', className)} {...props}>
<Tooltip content={tooltipContent}>
<Button isCircle variant="plain" icon={<CompassSearchIcon />} aria-label={ariaLabel} onClick={onClick} />
</Tooltip>
</div>
);

CompassNavSearch.displayName = 'CompassNavSearch';
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
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(<CompassNavContent>Test content</CompassNavContent>);

expect(screen.getByText('Test content')).toBeVisible();
});

test('Renders with custom class name when className prop is provided', () => {
render(<CompassNavContent className="custom-class">Test</CompassNavContent>);

expect(screen.getByText('Test')).toHaveClass('custom-class');
});

test(`Renders with default ${styles.compassNavContent} class`, () => {
render(<CompassNavContent>Test</CompassNavContent>);

expect(screen.getByText('Test')).toHaveClass(styles.compassNavContent, { exact: true });
});

test('Renders with additional props spread to the component', () => {
render(<CompassNavContent aria-label="Test label">Test</CompassNavContent>);

expect(screen.getByText('Test')).toHaveAccessibleName('Test label');
});

test('Matches the snapshot', () => {
const { asFragment } = render(
<CompassNavContent>
<div>Nav content wrapper</div>
</CompassNavContent>
);

expect(asFragment()).toMatchSnapshot();
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { CompassNavHome } from '../CompassNavHome';
import styles from '@patternfly/react-styles/css/components/Compass/compass';

test('Renders with default aria-label', () => {
render(<CompassNavHome />);

expect(screen.getByRole('button', { name: 'Home' })).toBeVisible();
});

test('Renders with custom aria-label when provided', () => {
render(<CompassNavHome aria-label="Custom home" />);

expect(screen.getByRole('button', { name: 'Custom home' })).toBeVisible();
});

test('Renders with default tooltip content', async () => {
const user = userEvent.setup();

render(<CompassNavHome />);

const button = screen.getByRole('button');

user.hover(button);

await screen.findByRole('tooltip');

expect(screen.getByRole('tooltip')).toHaveTextContent('Home');
});

test('Renders with custom tooltip content when provided', async () => {
const user = userEvent.setup();

render(<CompassNavHome tooltipContent="Custom tooltip" />);

const button = screen.getByRole('button');

user.hover(button);

await screen.findByRole('tooltip');
expect(screen.getByRole('tooltip')).toHaveTextContent('Custom tooltip');
});

test('Renders with custom class name when className prop is provided', () => {
const { container } = render(<CompassNavHome className="custom-class" />);

expect(container.firstChild).toHaveClass('custom-class');
});

test(`Renders with default class`, () => {
const { container } = render(<CompassNavHome />);

expect(container.firstChild).toHaveClass(styles.compassNav + '-home', { exact: true });
});

test('Calls onClick handler when button is clicked', async () => {
const user = userEvent.setup();
const onClick = jest.fn();

render(<CompassNavHome onClick={onClick} />);

await user.click(screen.getByRole('button', { name: 'Home' }));

expect(onClick).toHaveBeenCalledTimes(1);
});

test('Renders button with plain variant and circle shape', () => {
render(<CompassNavHome />);

const button = screen.getByRole('button', { name: 'Home' });

expect(button).toHaveClass('pf-m-plain');
expect(button).toHaveClass('pf-m-circle');
});

test('Matches the snapshot', () => {
const { asFragment } = render(<CompassNavHome />);

expect(asFragment()).toMatchSnapshot();
});

test('Matches the snapshot with custom props', () => {
const { asFragment } = render(
<CompassNavHome aria-label="Custom home" tooltipContent="Go home" className="custom-class" />
);

expect(asFragment()).toMatchSnapshot();
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
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(<CompassNavMain>Test content</CompassNavMain>);

expect(screen.getByText('Test content')).toBeVisible();
});

test('Renders with custom class name when className prop is provided', () => {
render(<CompassNavMain className="custom-class">Test</CompassNavMain>);

expect(screen.getByText('Test')).toHaveClass('custom-class');
});

test(`Renders with default ${styles.compassNavMain} class`, () => {
render(<CompassNavMain>Test</CompassNavMain>);

expect(screen.getByText('Test')).toHaveClass(styles.compassNavMain, { exact: true });
});

test('Renders with additional props spread to the component', () => {
render(<CompassNavMain aria-label="Test label">Test</CompassNavMain>);

expect(screen.getByText('Test')).toHaveAccessibleName('Test label');
});

test('Matches the snapshot', () => {
const { asFragment } = render(
<CompassNavMain>
<div>Main tabs content</div>
</CompassNavMain>
);

expect(asFragment()).toMatchSnapshot();
});
Loading
Loading