Skip to content

Commit 8da87a2

Browse files
feat(Hero): added component (#12131)
* feat(Hero): added component * Added example description * Added snapshots * Austin and Erin feedback * Updated to bake-in HeroBody in main Hero component * Removed HeroBody instances, example verbiage updated * Exported all compass interfaces --------- Co-authored-by: Eric Olkowski <git.eric@thatblindgeye.dev>
1 parent 7f37467 commit 8da87a2

File tree

22 files changed

+369
-225
lines changed

22 files changed

+369
-225
lines changed

packages/react-core/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@
5454
"tslib": "^2.8.1"
5555
},
5656
"devDependencies": {
57-
"@patternfly/patternfly": "6.5.0-prerelease.19",
57+
"@patternfly/patternfly": "6.5.0-prerelease.21",
5858
"case-anything": "^3.1.2",
5959
"css": "^3.0.0",
6060
"fs-extra": "^11.3.0"

packages/react-core/src/components/Compass/CompassContent.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { Drawer, DrawerContent, DrawerProps } from '../Drawer';
22
import styles from '@patternfly/react-styles/css/components/Compass/compass';
33
import { css } from '@patternfly/react-styles';
44

5-
interface CompassContentProps extends React.HTMLProps<HTMLDivElement> {
5+
export interface CompassContentProps extends React.HTMLProps<HTMLDivElement> {
66
/** Content of the main compass area. Typically one or more CompassPanel components. */
77
children: React.ReactNode;
88
/** Additional classes added to the CompassContent */

packages/react-core/src/components/Compass/CompassHeader.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import styles from '@patternfly/react-styles/css/components/Compass/compass';
22
import { css } from '@patternfly/react-styles';
33

4-
interface CompassHeaderProps {
4+
export interface CompassHeaderProps {
55
/** Content of the logo area */
66
logo?: React.ReactNode;
77
/** Content of the navigation area */
Lines changed: 7 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -1,87 +1,18 @@
11
import styles from '@patternfly/react-styles/css/components/Compass/compass';
22
import { css } from '@patternfly/react-styles';
33

4-
import compassHeroBackgroundImageLight from '@patternfly/react-tokens/dist/esm/c_compass__hero_BackgroundImage_light';
5-
import compassHeroBackgroundImageDark from '@patternfly/react-tokens/dist/esm/c_compass__hero_BackgroundImage_dark';
6-
import compassHeroGradientStop1Light from '@patternfly/react-tokens/dist/esm/c_compass__hero_gradient_stop_1_light';
7-
import compassHeroGradientStop2Light from '@patternfly/react-tokens/dist/esm/c_compass__hero_gradient_stop_2_light';
8-
import compassHeroGradientStop3Light from '@patternfly/react-tokens/dist/esm/c_compass__hero_gradient_stop_3_light';
9-
import compassHeroGradientStop1Dark from '@patternfly/react-tokens/dist/esm/c_compass__hero_gradient_stop_1_dark';
10-
import compassHeroGradientStop2Dark from '@patternfly/react-tokens/dist/esm/c_compass__hero_gradient_stop_2_dark';
11-
import compassHeroGradientStop3Dark from '@patternfly/react-tokens/dist/esm/c_compass__hero_gradient_stop_3_dark';
12-
13-
interface CompassHeroProps extends Omit<React.HTMLProps<HTMLDivElement>, 'content'> {
4+
/** A wrapper component to pass a PatternFly Hero component into. */
5+
export interface CompassHeroProps extends Omit<React.HTMLProps<HTMLDivElement>, 'content'> {
146
/** Content of the hero */
157
children?: React.ReactNode;
168
/** Additional classes added to the hero */
179
className?: string;
18-
/** Light theme background image path of the hero */
19-
backgroundSrcLight?: string;
20-
/** Dark theme background image path of the hero */
21-
backgroundSrcDark?: string;
22-
/** Light theme gradient of the hero */
23-
gradientLight?: {
24-
stop1?: string;
25-
stop2?: string;
26-
stop3?: string;
27-
};
28-
/** Dark theme gradient of the hero */
29-
gradientDark?: {
30-
stop1?: string;
31-
stop2?: string;
32-
stop3?: string;
33-
};
3410
}
3511

36-
export const CompassHero: React.FunctionComponent<CompassHeroProps> = ({
37-
className,
38-
children,
39-
backgroundSrcLight,
40-
backgroundSrcDark,
41-
gradientLight,
42-
gradientDark,
43-
...props
44-
}) => {
45-
const backgroundImageStyles: { [key: string]: string } = {};
46-
if (backgroundSrcLight) {
47-
backgroundImageStyles[compassHeroBackgroundImageLight.name] = `url(${backgroundSrcLight})`;
48-
}
49-
if (backgroundSrcDark) {
50-
backgroundImageStyles[compassHeroBackgroundImageDark.name] = `url(${backgroundSrcDark})`;
51-
}
52-
53-
if (gradientLight) {
54-
if (gradientLight.stop1) {
55-
backgroundImageStyles[compassHeroGradientStop1Light.name] = gradientLight.stop1;
56-
}
57-
if (gradientLight.stop2) {
58-
backgroundImageStyles[compassHeroGradientStop2Light.name] = gradientLight.stop2;
59-
}
60-
if (gradientLight.stop3) {
61-
backgroundImageStyles[compassHeroGradientStop3Light.name] = gradientLight.stop3;
62-
}
63-
}
64-
if (gradientDark) {
65-
if (gradientDark.stop1) {
66-
backgroundImageStyles[compassHeroGradientStop1Dark.name] = gradientDark.stop1;
67-
}
68-
if (gradientDark.stop2) {
69-
backgroundImageStyles[compassHeroGradientStop2Dark.name] = gradientDark.stop2;
70-
}
71-
if (gradientDark.stop3) {
72-
backgroundImageStyles[compassHeroGradientStop3Dark.name] = gradientDark.stop3;
73-
}
74-
}
75-
76-
return (
77-
<div
78-
className={css(styles.compassPanel, styles.compassHero, className)}
79-
style={{ ...props.style, ...backgroundImageStyles }}
80-
{...props}
81-
>
82-
<div className={css(styles.compassHeroBody)}>{children}</div>
83-
</div>
84-
);
85-
};
12+
export const CompassHero: React.FunctionComponent<CompassHeroProps> = ({ className, children, ...props }) => (
13+
<div className={css(`${styles.compass}__hero`, className)} {...props}>
14+
{children}
15+
</div>
16+
);
8617

8718
CompassHero.displayName = 'CompassHero';

packages/react-core/src/components/Compass/CompassMainHeader.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { CompassPanel } from './CompassPanel';
33
import styles from '@patternfly/react-styles/css/components/Compass/compass';
44
import { css } from '@patternfly/react-styles';
55

6-
interface CompassMainHeaderProps extends Omit<React.HTMLProps<HTMLDivElement>, 'title'> {
6+
export interface CompassMainHeaderProps extends Omit<React.HTMLProps<HTMLDivElement>, 'title'> {
77
/** Additional classes added to the main header */
88
className?: string;
99
/** Styled title. If title or toolbar is provided, the children will be ignored. */

packages/react-core/src/components/Compass/CompassMessageBar.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import styles from '@patternfly/react-styles/css/components/Compass/compass';
22
import { css } from '@patternfly/react-styles';
33

4-
interface CompassMessageBarProps extends React.HTMLProps<HTMLDivElement> {
4+
export interface CompassMessageBarProps extends React.HTMLProps<HTMLDivElement> {
55
/** Content of the message bar. Typically a @patternfly/chatbot MessageBar component. */
66
children?: React.ReactNode;
77
/** Additional classes added to the message bar */

packages/react-core/src/components/Compass/CompassPanel.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import styles from '@patternfly/react-styles/css/components/Compass/compass';
22
import { css } from '@patternfly/react-styles';
33

4-
interface CompassPanelProps extends React.HTMLProps<HTMLDivElement> {
4+
export interface CompassPanelProps extends React.HTMLProps<HTMLDivElement> {
55
/** Content of the panel. */
66
children: React.ReactNode;
77
/** Additional classes added to the panel. */

packages/react-core/src/components/Compass/__tests__/CompassHero.test.tsx

Lines changed: 7 additions & 119 deletions
Original file line numberDiff line numberDiff line change
@@ -16,135 +16,23 @@ test('Renders with children', () => {
1616
expect(screen.getByText('Test content')).toBeVisible();
1717
});
1818

19-
test('Renders with custom class name when className prop is provided', () => {
20-
render(<CompassHero className="custom-class">Test</CompassHero>);
21-
expect(screen.getByText('Test').parentElement).toHaveClass('custom-class');
22-
});
23-
24-
test(`Renders with default ${styles.compassPanel} and ${styles.compassHero} classes on the hero and ${styles.compassHeroBody} class on the hero body`, () => {
19+
test(`Renders with ${styles.compass}__hero class by defaulty`, () => {
2520
render(<CompassHero>Test</CompassHero>);
26-
const heroBodyElement = screen.getByText('Test');
27-
expect(heroBodyElement).toHaveClass(styles.compassHeroBody);
28-
29-
const heroElement = heroBodyElement.parentElement;
30-
expect(heroElement).toHaveClass(styles.compassPanel);
31-
expect(heroElement).toHaveClass(styles.compassHero);
32-
});
33-
34-
test('Renders with light background image style when backgroundSrcLight is provided', () => {
35-
const backgroundSrc = 'light-bg.jpg';
36-
render(<CompassHero backgroundSrcLight={backgroundSrc}>Test</CompassHero>);
37-
expect(screen.getByText('Test').parentElement).toHaveStyle(
38-
`--pf-v6-c-compass__hero--BackgroundImage--light: url(${backgroundSrc})`
39-
);
40-
});
41-
42-
test('Renders with dark background image style when backgroundSrcDark is provided', () => {
43-
const backgroundSrc = 'dark-bg.jpg';
44-
render(<CompassHero backgroundSrcDark={backgroundSrc}>Test</CompassHero>);
45-
expect(screen.getByText('Test').parentElement).toHaveStyle(
46-
`--pf-v6-c-compass__hero--BackgroundImage--dark: url(${backgroundSrc})`
47-
);
48-
});
49-
50-
test('Renders with both light and dark background image styles when both are provided', () => {
51-
const lightSrc = 'light-bg.jpg';
52-
const darkSrc = 'dark-bg.jpg';
53-
render(
54-
<CompassHero backgroundSrcLight={lightSrc} backgroundSrcDark={darkSrc}>
55-
Test
56-
</CompassHero>
57-
);
58-
const heroElement = screen.getByText('Test').parentElement;
59-
expect(heroElement).toHaveStyle(`--pf-v6-c-compass__hero--BackgroundImage--light: url(${lightSrc})`);
60-
expect(heroElement).toHaveStyle(`--pf-v6-c-compass__hero--BackgroundImage--dark: url(${darkSrc})`);
61-
});
62-
63-
test('Renders with light gradient styles when gradientLight is provided', () => {
64-
const gradient = {
65-
stop1: '#ff0000',
66-
stop2: '#00ff00',
67-
stop3: '#0000ff'
68-
};
69-
render(<CompassHero gradientLight={gradient}>Test</CompassHero>);
70-
const heroElement = screen.getByText('Test').parentElement;
71-
expect(heroElement).toHaveStyle(`--pf-v6-c-compass__hero--gradient--stop-1--light: ${gradient.stop1}`);
72-
expect(heroElement).toHaveStyle(`--pf-v6-c-compass__hero--gradient--stop-2--light: ${gradient.stop2}`);
73-
expect(heroElement).toHaveStyle(`--pf-v6-c-compass__hero--gradient--stop-3--light: ${gradient.stop3}`);
74-
});
7521

76-
test('Renders with dark gradient styles when gradientDark is provided', () => {
77-
const gradient = {
78-
stop1: '#ff0000',
79-
stop2: '#00ff00',
80-
stop3: '#0000ff'
81-
};
82-
render(<CompassHero gradientDark={gradient}>Test</CompassHero>);
83-
const heroElement = screen.getByText('Test').parentElement;
84-
expect(heroElement).toHaveStyle(`--pf-v6-c-compass__hero--gradient--stop-1--dark: ${gradient.stop1}`);
85-
expect(heroElement).toHaveStyle(`--pf-v6-c-compass__hero--gradient--stop-2--dark: ${gradient.stop2}`);
86-
expect(heroElement).toHaveStyle(`--pf-v6-c-compass__hero--gradient--stop-3--dark: ${gradient.stop3}`);
87-
});
88-
89-
test('Renders with both light and dark gradient styles when both are provided', () => {
90-
const lightGradient = {
91-
stop1: '#ff0000',
92-
stop2: '#00ff00',
93-
stop3: '#0000ff'
94-
};
95-
const darkGradient = {
96-
stop1: '#000000',
97-
stop2: '#ffffff',
98-
stop3: '#808080'
99-
};
100-
render(
101-
<CompassHero gradientLight={lightGradient} gradientDark={darkGradient}>
102-
Test
103-
</CompassHero>
104-
);
105-
const heroElement = screen.getByText('Test').parentElement;
106-
expect(heroElement).toHaveStyle(`--pf-v6-c-compass__hero--gradient--stop-1--light: ${lightGradient.stop1}`);
107-
expect(heroElement).toHaveStyle(`--pf-v6-c-compass__hero--gradient--stop-1--dark: ${darkGradient.stop1}`);
22+
expect(screen.getByText('Test')).toHaveClass(`${styles.compass}__hero`, { exact: true });
10823
});
10924

110-
test('Renders with both background images and gradient styles when both are provided', () => {
111-
const lightSrc = 'light-bg.jpg';
112-
const darkSrc = 'dark-bg.jpg';
113-
const lightGradient = { stop1: '#ff0000' };
114-
const darkGradient = { stop1: '#000000' };
115-
116-
render(
117-
<CompassHero
118-
backgroundSrcLight={lightSrc}
119-
backgroundSrcDark={darkSrc}
120-
gradientLight={lightGradient}
121-
gradientDark={darkGradient}
122-
>
123-
Test
124-
</CompassHero>
125-
);
126-
const heroElement = screen.getByText('Test').parentElement;
127-
expect(heroElement).toHaveStyle(`--pf-v6-c-compass__hero--BackgroundImage--light: url(${lightSrc})`);
128-
expect(heroElement).toHaveStyle(`--pf-v6-c-compass__hero--BackgroundImage--dark: url(${darkSrc})`);
129-
expect(heroElement).toHaveStyle(`--pf-v6-c-compass__hero--gradient--stop-1--light: ${lightGradient.stop1}`);
130-
expect(heroElement).toHaveStyle(`--pf-v6-c-compass__hero--gradient--stop-1--dark: ${darkGradient.stop1}`);
25+
test('Renders with custom class name when className prop is provided', () => {
26+
render(<CompassHero className="custom-class">Test</CompassHero>);
27+
expect(screen.getByText('Test')).toHaveClass('custom-class');
13128
});
13229

13330
test('Renders with additional props spread to the component', () => {
13431
render(<CompassHero aria-label="Test label">Test</CompassHero>);
135-
expect(screen.getByText('Test').parentElement).toHaveAccessibleName('Test label');
32+
expect(screen.getByText('Test')).toHaveAccessibleName('Test label');
13633
});
13734

13835
test('Matches the snapshot', () => {
139-
const { asFragment } = render(
140-
<CompassHero
141-
backgroundSrcLight="light.jpg"
142-
backgroundSrcDark="dark.jpg"
143-
gradientLight={{ stop1: '#ff0000', stop2: '#00ff00', stop3: '#0000ff' }}
144-
gradientDark={{ stop1: '#000000', stop2: '#ffffff', stop3: '#808080' }}
145-
>
146-
<div>Hero content</div>
147-
</CompassHero>
148-
);
36+
const { asFragment } = render(<CompassHero>Hero content</CompassHero>);
14937
expect(asFragment()).toMatchSnapshot();
15038
});

packages/react-core/src/components/Compass/__tests__/__snapshots__/CompassHero.test.tsx.snap

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,9 @@
33
exports[`Matches the snapshot 1`] = `
44
<DocumentFragment>
55
<div
6-
class="pf-v6-c-compass__panel pf-v6-c-compass__hero"
7-
style="--pf-v6-c-compass__hero--BackgroundImage--light: url(light.jpg); --pf-v6-c-compass__hero--BackgroundImage--dark: url(dark.jpg); --pf-v6-c-compass__hero--gradient--stop-1--light: #ff0000; --pf-v6-c-compass__hero--gradient--stop-2--light: #00ff00; --pf-v6-c-compass__hero--gradient--stop-3--light: #0000ff; --pf-v6-c-compass__hero--gradient--stop-1--dark: #000000; --pf-v6-c-compass__hero--gradient--stop-2--dark: #ffffff; --pf-v6-c-compass__hero--gradient--stop-3--dark: #808080;"
6+
class="pf-v6-c-compass__hero"
87
>
9-
<div
10-
class="pf-v6-c-compass__hero-body"
11-
>
12-
<div>
13-
Hero content
14-
</div>
15-
</div>
8+
Hero content
169
</div>
1710
</DocumentFragment>
1811
`;

packages/react-core/src/components/Compass/examples/CompassDemo.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import {
77
CompassMainHeader,
88
CompassPanel,
99
CompassMessageBar,
10+
Hero,
1011
Tabs,
1112
TabsComponent,
1213
Tab,
@@ -119,8 +120,8 @@ export const CompassBasic: React.FunctionComponent = () => {
119120
const sidebarStartContent = sidebarContent;
120121
const mainContent = (
121122
<>
122-
<CompassHero gradientDark={{ stop1: '#000', stop2: '#1b0d33', stop3: '#3d2785' }}>
123-
<div>Hero</div>
123+
<CompassHero>
124+
<Hero gradientDark={{ stop1: '#000', stop2: '#1b0d33', stop3: '#3d2785' }}>Hero</Hero>
124125
</CompassHero>
125126
<CompassMainHeader title={<Title headingLevel="h1">Content title</Title>} />
126127
<CompassContent>

0 commit comments

Comments
 (0)