Skip to content

Commit 3a5d042

Browse files
committed
Done
1 parent 18198fb commit 3a5d042

File tree

5 files changed

+152
-37
lines changed

5 files changed

+152
-37
lines changed

apps/builder/app/routes/_ui.playground.tsx

Lines changed: 76 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,86 @@
11
import { Scroll } from "@webstudio-is/sdk-components-animation";
2+
import { parseCssValue } from "@webstudio-is/css-data";
3+
import { Box, styled } from "@webstudio-is/design-system";
4+
5+
const H1 = styled("h1");
6+
7+
const DEBUG = false;
28

39
const Playground = () => {
410
return (
5-
<>
6-
<Scroll debug={process.env.NODE_ENV !== "production"}>
7-
<div
8-
style={{ height: "200px", width: "200px", backgroundColor: "red" }}
9-
></div>
10-
<div
11-
style={{
12-
height: "100px",
13-
width: "100px",
14-
backgroundColor: "yellow",
11+
<Box>
12+
<Scroll
13+
debug={DEBUG}
14+
action={{
15+
type: "scroll",
16+
animations: [
17+
{
18+
timing: {
19+
fill: "backwards",
20+
rangeStart: ["start", { type: "unit", value: 0, unit: "%" }],
21+
rangeEnd: ["start", { type: "unit", value: 200, unit: "px" }],
22+
},
23+
keyframes: [
24+
{
25+
offset: 0,
26+
styles: {
27+
transform: parseCssValue(
28+
"transform",
29+
"translate(0, -120px)"
30+
),
31+
opacity: parseCssValue("opacity", "0.2"),
32+
},
33+
},
34+
],
35+
},
36+
{
37+
timing: {
38+
fill: "forwards",
39+
rangeStart: ["end", { type: "unit", value: 200, unit: "px" }],
40+
rangeEnd: ["end", { type: "unit", value: 0, unit: "%" }],
41+
},
42+
keyframes: [
43+
{
44+
offset: 1,
45+
styles: {
46+
transform: parseCssValue(
47+
"transform",
48+
"translate(0, 120px)"
49+
),
50+
opacity: parseCssValue("opacity", "0.0"),
51+
},
52+
},
53+
],
54+
},
55+
],
56+
}}
57+
>
58+
<H1
59+
css={{
1560
position: "fixed",
16-
left: 0,
17-
top: 0,
61+
width: "100%",
62+
textAlign: "center",
63+
top: "80px",
64+
margin: 0,
65+
padding: 0,
66+
"&:hover": {
67+
color: "red",
68+
},
1869
}}
19-
></div>
70+
>
71+
HELLO WORLD
72+
</H1>
2073
</Scroll>
21-
</>
74+
<Box css={{ height: "200px", backgroundColor: "#eee", p: 4 }}>
75+
Start scrolling, and when the current box scrolls out, the “HELLO WORLD”
76+
header will fly in and become hoverable. (During the animation, it won’t
77+
be hoverable.)
78+
</Box>
79+
<Box css={{ height: "200vh" }}></Box>
80+
<Box css={{ height: "200px", backgroundColor: "#eee", p: 4 }}>
81+
When you see this box, the “HELLO WORLD” header will fly out.
82+
</Box>
83+
</Box>
2284
);
2385
};
2486

packages/sdk-components-animation/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@
6767
"@webstudio-is/template": "workspace:*",
6868
"@webstudio-is/tsconfig": "workspace:*",
6969
"@webstudio-is/css-data": "workspace:*",
70+
"@webstudio-is/design-system": "workspace:*",
7071
"react": "18.3.0-canary-14898b6a9-20240318",
7172
"react-dom": "18.3.0-canary-14898b6a9-20240318",
7273
"type-fest": "^4.32.0"

packages/sdk-components-animation/src/scroll.stories.tsx

Lines changed: 49 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,12 @@
11
import { parseCssValue } from "@webstudio-is/css-data";
2+
import { Box, styled } from "@webstudio-is/design-system";
3+
24
import { Scroll } from "./scroll";
35

46
const DEBUG = false;
57

8+
const H1 = styled("h1");
9+
610
export default {
711
title: "Components/Animate",
812
};
@@ -14,7 +18,7 @@ const Story = {
1418

1519
render() {
1620
return (
17-
<div>
21+
<Box>
1822
<Scroll
1923
debug={DEBUG}
2024
action={{
@@ -32,28 +36,61 @@ const Story = {
3236
styles: {
3337
transform: parseCssValue(
3438
"transform",
35-
"translate(0, 100px)"
39+
"translate(0, -120px)"
40+
),
41+
opacity: parseCssValue("opacity", "0.2"),
42+
},
43+
},
44+
],
45+
},
46+
{
47+
timing: {
48+
fill: "forwards",
49+
rangeStart: ["end", { type: "unit", value: 200, unit: "px" }],
50+
rangeEnd: ["end", { type: "unit", value: 0, unit: "%" }],
51+
},
52+
keyframes: [
53+
{
54+
offset: 1,
55+
styles: {
56+
transform: parseCssValue(
57+
"transform",
58+
"translate(0, 120px)"
3659
),
60+
opacity: parseCssValue("opacity", "0.0"),
3761
},
3862
},
3963
],
4064
},
4165
],
4266
}}
4367
>
44-
<div
45-
style={{
46-
height: "100px",
47-
width: "100px",
48-
backgroundColor: "yellow",
68+
<H1
69+
css={{
4970
position: "fixed",
50-
left: 0,
51-
top: 0,
71+
width: "100%",
72+
textAlign: "center",
73+
top: "80px",
74+
margin: 0,
75+
padding: 0,
76+
"&:hover": {
77+
color: "red",
78+
},
5279
}}
53-
></div>
80+
>
81+
HELLO WORLD
82+
</H1>
5483
</Scroll>
55-
<div style={{ height: "200vh" }}></div>
56-
</div>
84+
<Box css={{ height: "200px", backgroundColor: "#eee", p: 4 }}>
85+
Start scrolling, and when the current box scrolls out, the “HELLO
86+
WORLD” header will fly in and become hoverable. (During the animation,
87+
it won’t be hoverable.)
88+
</Box>
89+
<Box css={{ height: "200vh" }}></Box>
90+
<Box css={{ height: "200px", backgroundColor: "#eee", p: 4 }}>
91+
When you see this box, the “HELLO WORLD” header will fly out.
92+
</Box>
93+
</Box>
5794
);
5895
},
5996
};

packages/sdk-components-animation/src/scroll.tsx

Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -69,17 +69,29 @@ const Animate = ({ id, action }: { id: string; action: AnimationAction }) => {
6969
? getScrollRangeValue(animation.timing.rangeEnd)
7070
: undefined;
7171

72-
const nativeAnimation = element.animate(
73-
[{ offset: 0, transform: "translate(0, 100px)" }],
74-
{
75-
...keyframeEffectOptoins,
76-
// Scroll dependent options
77-
timeline,
78-
// @ts-expect-error missing in types
79-
rangeStart,
80-
rangeEnd,
72+
const keyframes = animation.keyframes.map((animationKeyframe) => {
73+
const keyframe: Keyframe = {
74+
offset: animationKeyframe.offset,
75+
composite: "auto",
76+
// easing: animationKeyframe.easing,
77+
};
78+
79+
for (const [property, value] of Object.entries(
80+
animationKeyframe.styles
81+
)) {
82+
keyframe[property] = toValue(value);
8183
}
82-
);
84+
return keyframe;
85+
});
86+
87+
const nativeAnimation = element.animate(keyframes, {
88+
...keyframeEffectOptoins,
89+
// Scroll dependent options
90+
timeline,
91+
// @ts-expect-error missing in types
92+
rangeStart,
93+
rangeEnd,
94+
});
8395

8496
return () => {
8597
nativeAnimation.cancel();
@@ -91,7 +103,7 @@ const Animate = ({ id, action }: { id: string; action: AnimationAction }) => {
91103
return () => {
92104
disposables.forEach((dispose) => dispose());
93105
};
94-
}, [id]);
106+
}, [action.animations, action.axis, action.source, id]);
95107

96108
return undefined;
97109
};

pnpm-lock.yaml

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)