Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 1c84ec7

Browse files
feat: handle composed ParallaxBannerLayers as children; add story demonstration jscottsmith#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)

AltStyle によって変換されたページ (->オリジナル) /