Skip to content

Commit

Permalink
Animation UI - Type Select
Browse files Browse the repository at this point in the history
  • Loading branch information
istarkov committed Feb 10, 2025
1 parent 38625d0 commit 14f757e
Show file tree
Hide file tree
Showing 13 changed files with 320 additions and 158 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import {
Grid,
theme,
Select,
Label,
Separator,
Box,
toast,
} from "@webstudio-is/design-system";
import { useIds } from "~/shared/form-utils";
import type { PropAndMeta } from "../use-props-logic";
import type { AnimationAction } from "@webstudio-is/sdk";
import { toPascalCase } from "~/builder/features/style-panel/shared/keyword-utils";
import { animationActionSchema } from "@webstudio-is/sdk";

const animationTypes = [
"scroll",
"view",
] as const satisfies AnimationAction["type"][];

const animationTypeDescription: Record<AnimationAction["type"], string> = {
scroll:
"Scroll-based animations are triggered and controlled by the user’s scroll position.",
view: "View-based animations occur when an element enters or exits the viewport. They rely on the element’s visibility rather than the scroll position.",
};

const defaultActionValue: AnimationAction = {
type: "scroll",
animations: [],
};

export const AnimateSection = ({
animationAction,
onChange,
}: {
animationAction: PropAndMeta;
onChange: (value: AnimationAction) => void;
}) => {
const fieldIds = useIds(["type"] as const);

const { prop } = animationAction;

const value: AnimationAction =
prop?.type === "animationAction" ? prop.value : defaultActionValue;

return (
<Grid
css={{
paddingBottom: theme.panel.paddingBlock,
}}
>
<Box css={{ height: theme.panel.paddingBlock }} />
<Separator />
<Box css={{ height: theme.panel.paddingBlock }} />
<Grid gap={1} css={{ paddingInline: theme.panel.paddingInline }}>
<Label htmlFor={fieldIds.type}>Animation Type</Label>
<Select
options={animationTypes}
// getValue={(docType: (typeof documentTypes)[number]) => docType}
getLabel={(animationType: AnimationAction["type"]) =>
toPascalCase(animationType)
}
value={value.type}
getDescription={(animationType: AnimationAction["type"]) => (
<Box
css={{
width: theme.spacing[28],
}}
>
{animationTypeDescription[animationType]}
</Box>
)}
onChange={(typeValue) => {
const newValue = { ...value, type: typeValue };
const parsedValue = animationActionSchema.safeParse(newValue);
if (parsedValue.success) {
onChange(parsedValue.data);
return;
}

toast.error("Schemas are incompatible, try fix");
}}
/>
</Grid>
</Grid>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import { renderControl } from "../controls/combined";
import { usePropsLogic, type PropAndMeta } from "./use-props-logic";
import { serverSyncStore } from "~/shared/sync";
import { $selectedInstanceKey } from "~/shared/awareness";
import { AnimateSection } from "@webstudio-is/sdk-components-animation/ui";
import { AnimateSection } from "./animation/animation-section";

type Item = {
name: string;
Expand Down Expand Up @@ -166,16 +166,26 @@ export const PropsSection = (props: PropsSectionProps) => {
const hasItems =
logic.addedProps.length > 0 || addingProp || logic.initialProps.length > 0;

const hasAnimation = logic.initialProps.some(
const animationAction = logic.initialProps.find(
(prop) => prop.meta.type === "animationAction"
);

const hasAnimation = animationAction !== undefined;

const showPropertiesSection =
isDesignMode || (isContentMode && logic.initialProps.length > 0);

return hasAnimation ? (
<>
<AnimateSection />
<AnimateSection
animationAction={animationAction}
onChange={(value) =>
logic.handleChangeByPropName(animationAction.propName, {
type: "animationAction",
value,
})
}
/>
</>
) : (
<>
Expand Down
6 changes: 5 additions & 1 deletion apps/builder/app/builder/features/settings-panel/shared.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,11 @@ export type PropValue =
| { type: "expression"; value: string }
| { type: "asset"; value: Asset["id"] }
| { type: "page"; value: Extract<Prop, { type: "page" }>["value"] }
| { type: "action"; value: Extract<Prop, { type: "action" }>["value"] };
| { type: "action"; value: Extract<Prop, { type: "action" }>["value"] }
| {
type: "animationAction";
value: Extract<Prop, { type: "animationAction" }>["value"];
};

// Weird code is to make type distributive
// https://www.typescriptlang.org/docs/handbook/2/conditional-types.html#distributive-conditional-types
Expand Down
9 changes: 2 additions & 7 deletions packages/sdk-components-animation/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,6 @@
"types": "./lib/types/components.d.ts",
"import": "./lib/components.js"
},
"./ui": {
"webstudio-private": "./private-src/ui/animate-section.tsx",
"webstudio": "./src/ui/animate-section.tsx",
"types": "./lib/types/animate-section.d.ts",
"import": "./lib/animate-section.js"
},
"./metas": {
"webstudio": "./src/metas.ts",
"types": "./lib/types/metas.d.ts",
Expand Down Expand Up @@ -82,6 +76,7 @@
"react": "18.3.0-canary-14898b6a9-20240318",
"react-dom": "18.3.0-canary-14898b6a9-20240318",
"type-fest": "^4.32.0",
"vitest": "^3.0.4"
"vitest": "^3.0.4",
"zod": "^3.22.4"
}
}
2 changes: 1 addition & 1 deletion packages/sdk-components-animation/private-src
2 changes: 1 addition & 1 deletion packages/sdk-components-animation/src/scroll.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { AnimationAction } from "@webstudio-is/sdk";
import { forwardRef, type ElementRef } from "react";
import type { AnimationAction } from "./shared/animation-types";

type ScrollProps = {
debug?: boolean;
Expand Down
140 changes: 0 additions & 140 deletions packages/sdk-components-animation/src/shared/animation-types.tsx

This file was deleted.

3 changes: 0 additions & 3 deletions packages/sdk-components-animation/src/ui/animate-section.tsx

This file was deleted.

7 changes: 6 additions & 1 deletion packages/sdk-components-animation/tsconfig.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
{
"extends": "@webstudio-is/tsconfig/base.json",
"include": ["src", "../../@types/**/scroll-timeline.d.ts", "private-src"],
"include": [
"src",
"../../@types/**/scroll-timeline.d.ts",
"private-src",
"../sdk/src/schema/animation-schema.ts"
],
"compilerOptions": {
"types": ["react/experimental", "react-dom/experimental", "@types/node"]
}
Expand Down
14 changes: 14 additions & 0 deletions packages/sdk/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,17 @@ export * from "./expression";
export * from "./resources-generator";
export * from "./page-meta-generator";
export * from "./url-pattern";

export type {
AnimationAction,
AnimationKeyframe,
KeyframeStyles,
RangeUnit,
RangeUnitValue,
ScrollNamedRange,
ScrollRangeValue,
ViewNamedRange,
ViewRangeValue,
} from "./schema/animation-schema";

export { animationActionSchema } from "./schema/animation-schema";
Loading

0 comments on commit 14f757e

Please sign in to comment.