Skip to content

experimental: Stagger Animation #5066

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 15 commits into from
Mar 30, 2025
20 changes: 20 additions & 0 deletions packages/icons/icons/stagger-animation.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
24 changes: 24 additions & 0 deletions packages/icons/src/__generated__/components.tsx

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions packages/icons/src/__generated__/svg.ts

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion packages/sdk-components-animation/private-src

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

15 changes: 15 additions & 0 deletions packages/sdk-components-animation/src/animate-text.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,24 @@ const split = {
};

type AnimateChildrenProps = {
/**
* Size of the sliding window for the animation:
* - 0: Typewriter effect (no animation).
* - (0..1]: Animates one part of the text at a time.
* - (1..n]: Animates multiple parts of the text within the sliding window.
*/
slidingWindow?: number;
/**
* Easing function applied within the sliding window.
*/
easing?: keyof typeof easings;
/**
* Text content to animate.
*/
children: React.ReactNode;
/**
* Defines how the text is split for animation (e.g., by character, space, or symbol).
*/
splitBy?: keyof typeof split;
};

Expand Down
1 change: 1 addition & 0 deletions packages/sdk-components-animation/src/components.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
export { AnimateChildren } from "./animate-children";
export { AnimateText } from "./animate-text";
export { StaggerAnimation } from "./stagger-animation";
1 change: 1 addition & 0 deletions packages/sdk-components-animation/src/metas.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
export { meta as AnimateChildren } from "./animate-children.ws";
export { meta as AnimateText } from "./animate-text.ws";
export { meta as StaggerAnimation } from "./stagger-animation.ws";
1 change: 1 addition & 0 deletions packages/sdk-components-animation/src/props.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
export { propsMeta as AnimateChildren } from "./animate-children.ws";
export { propsMeta as AnimateText } from "./animate-text.ws";
export { propsMeta as StaggerAnimation } from "./stagger-animation.ws";
43 changes: 43 additions & 0 deletions packages/sdk-components-animation/src/stagger-animation.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { forwardRef, type ElementRef } from "react";

const easings = {
linear: true,
easeIn: true,
easeInCubic: true,
easeInQuart: true,
easeOut: true,
easeOutCubic: true,
easeOutQuart: true,
ease: true,
easeInOutCubic: true,
easeInOutQuart: true,
};

type StaggerAnimationProps = {
/**
* Size of the sliding window for the animation:
* - 0: Typewriter effect (no animation).
* - (0..1]: Animates one child at a time.
* - (1..n]: Animates multiple children within the sliding window.
*/
slidingWindow?: number;
/**
* Easing function applied within the sliding window.
*/
easing?: keyof typeof easings;
/**
* Text content to animate.
*/
children: React.ReactNode;
};

export const StaggerAnimation = forwardRef<
ElementRef<"div">,
StaggerAnimationProps
>(({ slidingWindow = 1, easing = "linear", ...props }, ref) => {
// Implementation is located in private-src
return <div ref={ref} {...props} />;
});

const displayName = "StaggerAnimation";
StaggerAnimation.displayName = displayName;
25 changes: 25 additions & 0 deletions packages/sdk-components-animation/src/stagger-animation.ws.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { StaggerAnimationIcon } from "@webstudio-is/icons/svg";
import type { WsComponentMeta, WsComponentPropsMeta } from "@webstudio-is/sdk";
import { props } from "./__generated__/stagger-animation.props";

export const meta: WsComponentMeta = {
category: "animations",
type: "container",
description:
"Stagger animation allows you to animate children elements with a sliding window.",
icon: StaggerAnimationIcon,
order: 6,
label: "Stagger Animation",
constraints: [
{ relation: "parent", component: { $eq: "AnimateChildren" } },
{
relation: "child",
text: false,
},
],
};

export const propsMeta: WsComponentPropsMeta = {
props,
initialProps: ["slidingWindow", "easing"],
};