Skip to content

Commit

Permalink
feat(motion): Refactor scale, migrate to new variant structure (#33341)
Browse files Browse the repository at this point in the history
  • Loading branch information
pixel-perfectionist authored Dec 6, 2024
1 parent a9535f5 commit 899b968
Show file tree
Hide file tree
Showing 7 changed files with 97 additions and 51 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"type": "patch",
"comment": "feat(motion): Refactor scale, migrate to new variant structure",
"packageName": "@fluentui/react-motion-components-preview",
"email": "olkatruk@microsoft.com",
"dependentChangeType": "patch"
}
Original file line number Diff line number Diff line change
@@ -1,46 +1,57 @@
import {
motionTokens,
PresenceMotionFn,
createPresenceComponent,
createPresenceComponentVariant,
} from '@fluentui/react-motion';
import { motionTokens, createPresenceComponent } from '@fluentui/react-motion';
import { PresenceMotionFnCreator } from '../../types';
import { ScaleRuntimeParams_unstable, ScaleVariantParams_unstable } from './Scale.types';

/** Define a presence motion for scale in/out */
const scaleMotion: PresenceMotionFn<{ animateOpacity?: boolean }> = ({ animateOpacity = true }) => {
const fromOpacity = animateOpacity ? 0 : 1;
const toOpacity = 1;
const fromScale = 0.9; // Could be a custom param in the future
const toScale = 1;
export const createScalePresence: PresenceMotionFnCreator<ScaleVariantParams_unstable, ScaleRuntimeParams_unstable> =
({
enterDuration = motionTokens.durationGentle,
enterEasing = motionTokens.curveDecelerateMax,
exitDuration = motionTokens.durationNormal,
exitEasing = motionTokens.curveAccelerateMax,
} = {}) =>
({ animateOpacity = true }) => {
const fromOpacity = animateOpacity ? 0 : 1;
const toOpacity = 1;
const fromScale = 0.9; // Could be a custom param in the future
const toScale = 1;

const enterKeyframes = [
{ opacity: fromOpacity, transform: `scale3d(${fromScale}, ${fromScale}, 1)`, visibility: 'visible' },
{ opacity: toOpacity, transform: `scale3d(${toScale}, ${toScale}, 1)` },
];
const enterKeyframes = [
{ opacity: fromOpacity, transform: `scale3d(${fromScale}, ${fromScale}, 1)`, visibility: 'visible' },
{ opacity: toOpacity, transform: `scale3d(${toScale}, ${toScale}, 1)` },
];

const exitKeyframes = [
{ opacity: toOpacity, transform: `scale3d(${toScale}, ${toScale}, 1)` },
{ opacity: fromOpacity, transform: `scale3d(${fromScale}, ${fromScale}, 1)`, visibility: 'hidden' },
];

return {
enter: {
duration: motionTokens.durationGentle,
easing: motionTokens.curveDecelerateMax,
keyframes: enterKeyframes,
},
exit: { duration: motionTokens.durationNormal, easing: motionTokens.curveAccelerateMax, keyframes: exitKeyframes },
const exitKeyframes = [
{ opacity: toOpacity, transform: `scale3d(${toScale}, ${toScale}, 1)` },
{ opacity: fromOpacity, transform: `scale3d(${fromScale}, ${fromScale}, 1)`, visibility: 'hidden' },
];
return {
enter: {
duration: enterDuration,
easing: enterEasing,
keyframes: enterKeyframes,
},
exit: { duration: exitDuration, easing: exitEasing, keyframes: exitKeyframes },
};
};
};

/** A React component that applies scale in/out transitions to its children. */
export const Scale = createPresenceComponent(scaleMotion);
export const Scale = createPresenceComponent(createScalePresence());

export const ScaleSnappy = createPresenceComponentVariant(Scale, {
enter: { duration: motionTokens.durationNormal, easing: motionTokens.curveDecelerateMax },
exit: { duration: motionTokens.durationFast, easing: motionTokens.curveAccelerateMax },
});
export const ScaleSnappy = createPresenceComponent(
createScalePresence({
enterDuration: motionTokens.durationNormal,
enterEasing: motionTokens.curveDecelerateMax,
exitDuration: motionTokens.durationFast,
exitEasing: motionTokens.curveAccelerateMax,
}),
);

export const ScaleRelaxed = createPresenceComponentVariant(Scale, {
enter: { duration: motionTokens.durationSlow, easing: motionTokens.curveDecelerateMax },
exit: { duration: motionTokens.durationGentle, easing: motionTokens.curveAccelerateMax },
});
export const ScaleRelaxed = createPresenceComponent(
createScalePresence({
enterDuration: motionTokens.durationSlow,
enterEasing: motionTokens.curveDecelerateMax,
exitDuration: motionTokens.durationGentle,
exitEasing: motionTokens.curveAccelerateMax,
}),
);
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// eslint-disable-next-line @typescript-eslint/naming-convention
export type ScaleVariantParams_unstable = {
/** Time (ms) for the enter transition. Defaults to the `durationNormal` value (200 ms). */
enterDuration?: number;

/** Easing curve for the enter transition. Defaults to the `easeEaseMax` value. */
enterEasing?: string;

/** Time (ms) for the exit transition. Defaults to the `enterDuration` param for symmetry. */
exitDuration?: number;

/** Easing curve for the exit transition. Defaults to the `enterEasing` param for symmetry. */
exitEasing?: string;
};

// eslint-disable-next-line @typescript-eslint/naming-convention
export type ScaleRuntimeParams_unstable = {
/** Whether to animate the opacity. Defaults to `true`. */
animateOpacity?: boolean;
};
Original file line number Diff line number Diff line change
@@ -1 +1 @@
export { Scale, ScaleRelaxed, ScaleSnappy } from './Scale';
export { Scale, ScaleRelaxed, ScaleSnappy, createScalePresence } from './Scale';
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,4 @@ export {
} from './components/Collapse';
export type { CollapseRuntimeParams } from './components/Collapse';
export { Fade, FadeSnappy, FadeRelaxed, createFadePresence } from './components/Fade';
export { Scale, ScaleSnappy, ScaleRelaxed } from './components/Scale';
export { Scale, ScaleSnappy, ScaleRelaxed, createScalePresence } from './components/Scale';
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
- `duration` and `easing` can be customized for each transition separately using `createPresenceComponentVariant()`.
- The predefined fade transition can be disabled by setting `animateOpacity` to `false`.
- A scale variant can be created with the factory function `createScalePresence()`, then converting the result to a React component using `createPresenceComponent()`:

```tsx
import { motionTokens, createPresenceComponentVariant } from '@fluentui/react-components';
import { Scale } from '@fluentui/react-motion-components-preview';
import { createScalePresence } from '@fluentui/react-motion-components-preview';

const CustomScaleVariant = createPresenceComponentVariant(Scale, {
enter: { duration: motionTokens.durationSlow, easing: motionTokens.curveEasyEaseMax },
exit: { duration: motionTokens.durationNormal, easing: motionTokens.curveEasyEaseMax },
});
const CustomScaleVariant = createPresenceComponent(
createScalePresence({
enterDuration: motionTokens.durationSlow,
enterEasing: motionTokens.curveEasyEaseMax,
exitDuration: motionTokens.durationNormal,
exitEasing: motionTokens.curveEasyEaseMax,
}),
);

const CustomScale = ({ visible }) => (
<CustomScaleVariant animateOpacity={false} unmountOnExit visible={visible}>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import * as React from 'react';
import {
createPresenceComponentVariant,
createPresenceComponent,
Field,
makeStyles,
mergeClasses,
Expand All @@ -10,7 +10,7 @@ import {
Switch,
tokens,
} from '@fluentui/react-components';
import { Scale } from '@fluentui/react-motion-components-preview';
import { createScalePresence } from '@fluentui/react-motion-components-preview';

import description from './ScaleCustomization.stories.md';

Expand Down Expand Up @@ -54,10 +54,14 @@ const useClasses = makeStyles({
},
});

const CustomScaleVariant = createPresenceComponentVariant(Scale, {
enter: { duration: motionTokens.durationSlow, easing: motionTokens.curveEasyEaseMax },
exit: { duration: motionTokens.durationNormal, easing: motionTokens.curveEasyEaseMax },
});
const CustomScaleVariant = createPresenceComponent(
createScalePresence({
enterDuration: motionTokens.durationSlow,
enterEasing: motionTokens.curveEasyEaseMax,
exitDuration: motionTokens.durationNormal,
exitEasing: motionTokens.curveEasyEaseMax,
}),
);

const LoremIpsum = () => (
<>
Expand Down

0 comments on commit 899b968

Please sign in to comment.