Skip to content

Commit 1c84ec7

Browse files
committed
feat: handle composed ParallaxBannerLayers as children; add story demonstration #147
1 parent cb5bce9 commit 1c84ec7

File tree

3 files changed

+65
-17
lines changed

3 files changed

+65
-17
lines changed

src/components/ParallaxBanner/components/ParallaxBannerLayer.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ const absoluteStyle: CSSProperties = {
1414
};
1515

1616
export const ParallaxBannerLayer = (
17-
props: BannerLayer & { testId: string }
17+
props: BannerLayer & { testId?: string }
1818
) => {
1919
const { parallaxProps, rest } = getIsolatedParallaxProps(props);
2020
const {

src/components/ParallaxBanner/index.tsx

Lines changed: 43 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import React, {
44
useEffect,
55
useRef,
66
useState,
7+
ReactElement,
78
} from 'react';
89
import { ParallaxBannerLayer } from './components/ParallaxBannerLayer';
910
import { ParallaxBannerProps } from './types';
@@ -17,9 +18,8 @@ const containerStyle: CSSProperties = {
1718
export const ParallaxBanner = (
1819
props: PropsWithChildren<ParallaxBannerProps>
1920
) => {
20-
const [targetElement, setTargetElement] = useState<HTMLDivElement | null>(
21-
null
22-
);
21+
const [targetElement, setTargetElement] =
22+
useState<HTMLDivElement | null>(null);
2323
const containerRef = useRef<HTMLDivElement>(null);
2424
useEffect(() => {
2525
setTargetElement(containerRef.current);
@@ -30,24 +30,52 @@ export const ParallaxBanner = (
3030
layers = [],
3131
...rootRest
3232
} = props;
33+
34+
function renderLayers() {
35+
if (targetElement) {
36+
const shouldUseLayers = layers && layers.length > 0;
37+
if (shouldUseLayers) {
38+
return layers.map((layer, i) => (
39+
<ParallaxBannerLayer
40+
{...layer}
41+
targetElement={targetElement}
42+
key={`layer-${i}`}
43+
testId={`layer-${i}`}
44+
/>
45+
));
46+
}
47+
}
48+
return null;
49+
}
50+
51+
function renderChildren() {
52+
if (targetElement) {
53+
return React.Children.map(props.children, (child) => {
54+
const item = child as ReactElement<
55+
PropsWithChildren<{ targetElement: any }>
56+
>;
57+
// adds the targetElement prop to any ParallaxBannerLayer components
58+
if (item.type === ParallaxBannerLayer) {
59+
const clone = React.cloneElement(item, {
60+
targetElement,
61+
});
62+
return clone;
63+
}
64+
return child;
65+
});
66+
}
67+
return null;
68+
}
3369
return (
3470
<div
3571
ref={containerRef}
3672
style={{ ...containerStyle, ...rootStyle }}
3773
{...rootRest}
3874
>
39-
{layers.map(
40-
(layer, i) =>
41-
targetElement && (
42-
<ParallaxBannerLayer
43-
{...layer}
44-
targetElement={targetElement}
45-
key={`layer-${i}`}
46-
testId={`layer-${i}`}
47-
/>
48-
)
49-
)}
50-
{props.children}
75+
{/* Using the `layers` prop to define children */}
76+
{renderLayers()}
77+
{/* Using children to compose layers */}
78+
{renderChildren()}
5179
</div>
5280
);
5381
};

stories/ParallaxBanner/4_ParallaxBanner.stories.tsx

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import React from 'react';
22
import { ParallaxBanner, ParallaxProvider } from '../../src';
3+
import { ParallaxBannerLayer } from '../../src/components/ParallaxBanner/components/ParallaxBannerLayer';
34
import styles from './ParallaxBanner.module.scss';
45

56
const Log = () => {
@@ -28,7 +29,7 @@ const Log = () => {
2829

2930
const Wrapper = (props) => (
3031
<ParallaxProvider>
31-
<Log />
32+
{/* <Log /> */}
3233
<div style={{ height: '300vh' }} className="vertical">
3334
<div className={styles.bannerContainer}>{props.children}</div>
3435
</div>
@@ -110,6 +111,25 @@ export const WithMultipleBackground = () => (
110111
</Wrapper>
111112
);
112113

114+
export const WithMultipleBackgroundsUsingBannerLayerComponents = () => (
115+
<Wrapper>
116+
<ParallaxBanner
117+
className={styles.bannerBg}
118+
style={{ aspectRatio: '2 / 1' }}
119+
>
120+
<ParallaxBannerLayer
121+
image="https://s3-us-west-2.amazonaws.com/s.cdpn.io/105988/banner-background.jpg"
122+
speed={-20}
123+
/>
124+
<ParallaxBannerLayer
125+
image="https://s3-us-west-2.amazonaws.com/s.cdpn.io/105988/banner-foreground.png"
126+
speed={-10}
127+
/>
128+
<div>nope</div>
129+
</ParallaxBanner>
130+
</Wrapper>
131+
);
132+
113133
export const WithAVideo = () => (
114134
<Wrapper>
115135
<ParallaxBanner

0 commit comments

Comments
 (0)