Skip to content

Commit 5ffe512

Browse files
committed
Updated to bake-in HeroBody in main Hero component
1 parent 213f6be commit 5ffe512

File tree

9 files changed

+80
-105
lines changed

9 files changed

+80
-105
lines changed

packages/react-core/src/components/Hero/Hero.tsx

Lines changed: 26 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ import heroGradientStop3Light from '@patternfly/react-tokens/dist/esm/c_hero_gra
88
import heroGradientStop1Dark from '@patternfly/react-tokens/dist/esm/c_hero_gradient_stop_1_dark';
99
import heroGradientStop2Dark from '@patternfly/react-tokens/dist/esm/c_hero_gradient_stop_2_dark';
1010
import heroGradientStop3Dark from '@patternfly/react-tokens/dist/esm/c_hero_gradient_stop_3_dark';
11+
import heroBodyWidth from '@patternfly/react-tokens/dist/esm/c_hero__body_Width';
12+
import heroBodyMaxWidth from '@patternfly/react-tokens/dist/esm/c_hero__body_MaxWidth';
1113

1214
/** The main Hero component that allows adjusting of its background images and gradients in different color modes (such as light and dark). */
1315

@@ -34,6 +36,10 @@ export interface HeroProps extends Omit<React.HTMLProps<HTMLDivElement>, 'conten
3436
};
3537
/** Flag indicating whether glass styles are removed from the hero when a glass theme is applied. */
3638
hasNoGlass?: boolean;
39+
/** Modifies the width of the hero body. */
40+
bodyWidth?: string;
41+
/** Modifies the max-width of the hero body. */
42+
bodyMaxWidth?: string;
3743
}
3844

3945
export const Hero: React.FunctionComponent<HeroProps> = ({
@@ -44,42 +50,51 @@ export const Hero: React.FunctionComponent<HeroProps> = ({
4450
gradientLight,
4551
gradientDark,
4652
hasNoGlass = false,
53+
bodyWidth,
54+
bodyMaxWidth,
4755
...props
4856
}) => {
49-
const backgroundImageStyles: { [key: string]: string } = {};
57+
const customStyles: { [key: string]: string } = {};
5058
if (backgroundSrcLight) {
51-
backgroundImageStyles[heroBackgroundImageLight.name] = `url(${backgroundSrcLight})`;
59+
customStyles[heroBackgroundImageLight.name] = `url(${backgroundSrcLight})`;
5260
}
5361
if (backgroundSrcDark) {
54-
backgroundImageStyles[heroBackgroundImageDark.name] = `url(${backgroundSrcDark})`;
62+
customStyles[heroBackgroundImageDark.name] = `url(${backgroundSrcDark})`;
5563
}
5664

5765
if (gradientLight?.stop1) {
58-
backgroundImageStyles[heroGradientStop1Light.name] = gradientLight.stop1;
66+
customStyles[heroGradientStop1Light.name] = gradientLight.stop1;
5967
}
6068
if (gradientLight?.stop2) {
61-
backgroundImageStyles[heroGradientStop2Light.name] = gradientLight.stop2;
69+
customStyles[heroGradientStop2Light.name] = gradientLight.stop2;
6270
}
6371
if (gradientLight?.stop3) {
64-
backgroundImageStyles[heroGradientStop3Light.name] = gradientLight.stop3;
72+
customStyles[heroGradientStop3Light.name] = gradientLight.stop3;
6573
}
6674
if (gradientDark?.stop1) {
67-
backgroundImageStyles[heroGradientStop1Dark.name] = gradientDark.stop1;
75+
customStyles[heroGradientStop1Dark.name] = gradientDark.stop1;
6876
}
6977
if (gradientDark?.stop2) {
70-
backgroundImageStyles[heroGradientStop2Dark.name] = gradientDark.stop2;
78+
customStyles[heroGradientStop2Dark.name] = gradientDark.stop2;
7179
}
7280
if (gradientDark?.stop3) {
73-
backgroundImageStyles[heroGradientStop3Dark.name] = gradientDark.stop3;
81+
customStyles[heroGradientStop3Dark.name] = gradientDark.stop3;
82+
}
83+
84+
if (bodyWidth) {
85+
customStyles[heroBodyWidth.name] = bodyWidth;
86+
}
87+
if (bodyMaxWidth) {
88+
customStyles[heroBodyMaxWidth.name] = bodyMaxWidth;
7489
}
7590

7691
return (
7792
<div
7893
className={css(styles.hero, hasNoGlass && styles.modifiers.noGlass, className)}
79-
style={{ ...props.style, ...backgroundImageStyles }}
94+
style={{ ...props.style, ...customStyles }}
8095
{...props}
8196
>
82-
{children}
97+
<div className={css(styles.heroBody)}>{children}</div>
8398
</div>
8499
);
85100
};

packages/react-core/src/components/Hero/HeroBody.tsx

Lines changed: 0 additions & 19 deletions
This file was deleted.

packages/react-core/src/components/Hero/__tests__/Hero.test.tsx

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

19-
test(`Renders with ${styles.hero} class by defaulty`, () => {
19+
test(`Renders with ${styles.hero} class on wrapper by defaulty`, () => {
2020
render(<Hero>Test</Hero>);
2121

22-
expect(screen.getByText('Test')).toHaveClass(`${styles.hero}`, { exact: true });
22+
expect(screen.getByText('Test').parentElement).toHaveClass(`${styles.hero}`, { exact: true });
2323
});
2424

25-
test('Renders with custom class name when className prop is provided', () => {
25+
test('Renders with custom class name on wrapper when className prop is provided', () => {
2626
render(<Hero className="custom-class">Test</Hero>);
27-
expect(screen.getByText('Test')).toHaveClass('custom-class');
27+
expect(screen.getByText('Test').parentElement).toHaveClass('custom-class');
2828
});
2929

30-
test('Renders with additional props spread to the component', () => {
30+
test(`Renders with class ${styles.heroBody} on content element`, () => {
31+
render(<Hero>Test</Hero>);
32+
33+
expect(screen.getByText('Test')).toHaveClass(`${styles.heroBody}`, { exact: true });
34+
});
35+
36+
test('Renders with additional props spread to the wrapper component', () => {
3137
render(<Hero id="custom-id">Test</Hero>);
32-
expect(screen.getByText('Test')).toHaveAttribute('id', 'custom-id');
38+
expect(screen.getByText('Test').parentElement).toHaveAttribute('id', 'custom-id');
3339
});
3440

3541
test('Renders with light background image style when backgroundSrcLight is provided', () => {
3642
const backgroundSrc = 'light-bg.jpg';
3743
render(<Hero backgroundSrcLight={backgroundSrc}>Test</Hero>);
38-
expect(screen.getByText('Test')).toHaveStyle(`--pf-v6-c-hero--BackgroundImage--light: url(${backgroundSrc})`);
44+
expect(screen.getByText('Test').parentElement).toHaveStyle(
45+
`--pf-v6-c-hero--BackgroundImage--light: url(${backgroundSrc})`
46+
);
3947
});
4048

4149
test('Renders with dark background image style when backgroundSrcDark is provided', () => {
4250
const backgroundSrc = 'dark-bg.jpg';
4351
render(<Hero backgroundSrcDark={backgroundSrc}>Test</Hero>);
44-
expect(screen.getByText('Test')).toHaveStyle(`--pf-v6-c-hero--BackgroundImage--dark: url(${backgroundSrc})`);
52+
expect(screen.getByText('Test').parentElement).toHaveStyle(
53+
`--pf-v6-c-hero--BackgroundImage--dark: url(${backgroundSrc})`
54+
);
4555
});
4656

4757
test('Renders with both light and dark background image styles when both are provided', () => {
@@ -52,7 +62,7 @@ test('Renders with both light and dark background image styles when both are pro
5262
Test
5363
</Hero>
5464
);
55-
const heroElement = screen.getByText('Test');
65+
const heroElement = screen.getByText('Test').parentElement;
5666
expect(heroElement).toHaveStyle(`--pf-v6-c-hero--BackgroundImage--light: url(${lightSrc})`);
5767
expect(heroElement).toHaveStyle(`--pf-v6-c-hero--BackgroundImage--dark: url(${darkSrc})`);
5868
});
@@ -64,7 +74,7 @@ test('Renders with light gradient styles when gradientLight is provided', () =>
6474
stop3: '#0000ff'
6575
};
6676
render(<Hero gradientLight={gradient}>Test</Hero>);
67-
const heroElement = screen.getByText('Test');
77+
const heroElement = screen.getByText('Test').parentElement;
6878
expect(heroElement).toHaveStyle(`--pf-v6-c-hero--gradient--stop-1--light: ${gradient.stop1}`);
6979
expect(heroElement).toHaveStyle(`--pf-v6-c-hero--gradient--stop-2--light: ${gradient.stop2}`);
7080
expect(heroElement).toHaveStyle(`--pf-v6-c-hero--gradient--stop-3--light: ${gradient.stop3}`);
@@ -77,7 +87,7 @@ test('Renders with dark gradient styles when gradientDark is provided', () => {
7787
stop3: '#0000ff'
7888
};
7989
render(<Hero gradientDark={gradient}>Test</Hero>);
80-
const heroElement = screen.getByText('Test');
90+
const heroElement = screen.getByText('Test').parentElement;
8191
expect(heroElement).toHaveStyle(`--pf-v6-c-hero--gradient--stop-1--dark: ${gradient.stop1}`);
8292
expect(heroElement).toHaveStyle(`--pf-v6-c-hero--gradient--stop-2--dark: ${gradient.stop2}`);
8393
expect(heroElement).toHaveStyle(`--pf-v6-c-hero--gradient--stop-3--dark: ${gradient.stop3}`);
@@ -99,7 +109,7 @@ test('Renders with both light and dark gradient styles when both are provided',
99109
Test
100110
</Hero>
101111
);
102-
const heroElement = screen.getByText('Test');
112+
const heroElement = screen.getByText('Test').parentElement;
103113
expect(heroElement).toHaveStyle(`--pf-v6-c-hero--gradient--stop-1--light: ${lightGradient.stop1}`);
104114
expect(heroElement).toHaveStyle(`--pf-v6-c-hero--gradient--stop-1--dark: ${darkGradient.stop1}`);
105115
});
@@ -120,13 +130,29 @@ test('Renders with both background images and gradient styles when both are prov
120130
Test
121131
</Hero>
122132
);
123-
const heroElement = screen.getByText('Test');
133+
const heroElement = screen.getByText('Test').parentElement;
124134
expect(heroElement).toHaveStyle(`--pf-v6-c-hero--BackgroundImage--light: url(${lightSrc})`);
125135
expect(heroElement).toHaveStyle(`--pf-v6-c-hero--BackgroundImage--dark: url(${darkSrc})`);
126136
expect(heroElement).toHaveStyle(`--pf-v6-c-hero--gradient--stop-1--light: ${lightGradient.stop1}`);
127137
expect(heroElement).toHaveStyle(`--pf-v6-c-hero--gradient--stop-1--dark: ${darkGradient.stop1}`);
128138
});
129139

140+
test('Renders with inline width style when bodyWidth is passed', () => {
141+
const bodyWidth = '100px';
142+
143+
render(<Hero bodyWidth={bodyWidth}>Test</Hero>);
144+
const heroElement = screen.getByText('Test').parentElement;
145+
expect(heroElement).toHaveStyle(`--pf-v6-c-hero__body--Width: ${bodyWidth}`);
146+
});
147+
148+
test('Renders with inline max-width style when bodyMaxWidth is passed', () => {
149+
const bodyMaxWidth = '100px';
150+
151+
render(<Hero bodyMaxWidth={bodyMaxWidth}>Test</Hero>);
152+
const heroElement = screen.getByText('Test').parentElement;
153+
expect(heroElement).toHaveStyle(`--pf-v6-c-hero__body--MaxWidth: ${bodyMaxWidth}`);
154+
});
155+
130156
test('Matches the snapshot without backgroundSrc and gradient props', () => {
131157
const { asFragment } = render(<Hero>Hero content</Hero>);
132158

packages/react-core/src/components/Hero/__tests__/HeroBody.test.tsx

Lines changed: 0 additions & 39 deletions
This file was deleted.

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

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,11 @@ exports[`Matches the snapshot with backgroundSrc and gradient props 1`] = `
66
class="pf-v6-c-hero"
77
style="--pf-v6-c-hero--BackgroundImage--light: url(light.jpg); --pf-v6-c-hero--BackgroundImage--dark: url(dark.jpg); --pf-v6-c-hero--gradient--stop-1--light: #ff0000; --pf-v6-c-hero--gradient--stop-2--light: #00ff00; --pf-v6-c-hero--gradient--stop-3--light: #0000ff; --pf-v6-c-hero--gradient--stop-1--dark: #000000; --pf-v6-c-hero--gradient--stop-2--dark: #ffffff; --pf-v6-c-hero--gradient--stop-3--dark: #808080;"
88
>
9-
Hero content
9+
<div
10+
class="pf-v6-c-hero__body"
11+
>
12+
Hero content
13+
</div>
1014
</div>
1115
</DocumentFragment>
1216
`;
@@ -16,7 +20,11 @@ exports[`Matches the snapshot without backgroundSrc and gradient props 1`] = `
1620
<div
1721
class="pf-v6-c-hero"
1822
>
19-
Hero content
23+
<div
24+
class="pf-v6-c-hero__body"
25+
>
26+
Hero content
27+
</div>
2028
</div>
2129
</DocumentFragment>
2230
`;

packages/react-core/src/components/Hero/__tests__/__snapshots__/HeroBody.test.tsx.snap

Lines changed: 0 additions & 11 deletions
This file was deleted.

packages/react-core/src/components/Hero/examples/Hero.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,16 @@ id: Hero
33
section: components
44
cssPrefix: pf-v6-c-hero
55
beta: true
6-
propComponents: ['Hero', 'HeroBody']
6+
propComponents: ['Hero']
77
---
88

99
## Examples
1010

1111
### Basic
1212

13-
To ensure readability and prevent text from overlapping with the background image, use the `<HeroBody>` component. The `<HeroBody>` is optional and can be omitted if there's no background image or if you'd like finer control over text placement.
13+
The `bodyWidth` and `bodyMaxWidth` properties can be used for finer control over the placement of text content within the `<Hero>`, such as if you omit a background image. Be mindful of adjusting these properties when a background image is still present, as you may need to ensure the contrast of text is sufficient should it overlap the image.
1414

15-
When using `gradientLight` or `gradientDark`, regardless of the presence of a `<HeroBody>`, check the color contrast to ensure proper accessibility.
15+
When using `gradientLight` or `gradientDark`, check the color contrast to ensure proper accessibility.
1616

1717
```ts file="HeroBasic.tsx"
1818

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,3 @@
1-
import { Hero, HeroBody } from '@patternfly/react-core';
1+
import { Hero } from '@patternfly/react-core';
22

3-
export const HeroBasic: React.FunctionComponent = () => (
4-
<Hero>
5-
<HeroBody>Basic hero content</HeroBody>
6-
</Hero>
7-
);
3+
export const HeroBasic: React.FunctionComponent = () => <Hero>Basic hero content</Hero>;
Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1 @@
11
export * from './Hero';
2-
export * from './HeroBody';

0 commit comments

Comments
 (0)