-
Notifications
You must be signed in to change notification settings - Fork 2.8k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
refactor(motion): simplify variant creation, starting with Collapse (#…
…32939) Co-authored-by: Oleksandr Fediashov <[email protected]>
- Loading branch information
1 parent
348f676
commit 82c0e84
Showing
11 changed files
with
126 additions
and
67 deletions.
There are no files selected for viewing
7 changes: 7 additions & 0 deletions
7
change/@fluentui-react-motion-b1633b2c-174b-4a91-936d-4d761d14218d.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
{ | ||
"type": "minor", | ||
"comment": "feat: export MotionParam type", | ||
"packageName": "@fluentui/react-motion", | ||
"email": "[email protected]", | ||
"dependentChangeType": "patch" | ||
} |
7 changes: 7 additions & 0 deletions
7
change/@fluentui-react-motion-components-preview-b135985c-054b-4ade-a67f-fb34089647ab.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
{ | ||
"type": "minor", | ||
"comment": "refactor: simplify motion component variant creation", | ||
"packageName": "@fluentui/react-motion-components-preview", | ||
"email": "[email protected]", | ||
"dependentChangeType": "patch" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
102 changes: 60 additions & 42 deletions
102
...ct-components/react-motion-components-preview/library/src/components/Collapse/Collapse.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,49 +1,67 @@ | ||
import { | ||
motionTokens, | ||
type PresenceMotionFn, | ||
createPresenceComponent, | ||
createPresenceComponentVariant, | ||
} from '@fluentui/react-motion'; | ||
import { motionTokens, createPresenceComponent } from '@fluentui/react-motion'; | ||
import type { PresenceMotionFnCreator } from '../../types'; | ||
|
||
type CollapseVariantParams = { | ||
/** Time (ms) for the enter transition (expand). Defaults to the `durationNormal` value (200 ms). */ | ||
enterDuration?: number; | ||
|
||
/** Easing curve for the enter transition (expand). Defaults to the `easeEaseMax` value. */ | ||
enterEasing?: string; | ||
|
||
/** Time (ms) for the exit transition (collapse). Defaults to the `enterDuration` param for symmetry. */ | ||
exitDuration?: number; | ||
|
||
/** Easing curve for the exit transition (collapse). Defaults to the `enterEasing` param for symmetry. */ | ||
exitEasing?: string; | ||
}; | ||
|
||
type CollapseRuntimeParams = { | ||
/** Whether to animate the opacity. Defaults to `true`. */ | ||
animateOpacity?: boolean; | ||
}; | ||
|
||
/** Define a presence motion for collapse/expand */ | ||
const collapseMotion: PresenceMotionFn<{ animateOpacity?: boolean }> = ({ element, animateOpacity = true }) => { | ||
const fromOpacity = animateOpacity ? 0 : 1; | ||
const toOpacity = 1; | ||
const fromHeight = '0'; // Could be a custom param in the future: start partially expanded | ||
const toHeight = `${element.scrollHeight}px`; | ||
const overflow = 'hidden'; | ||
|
||
const duration = motionTokens.durationNormal; | ||
const easing = motionTokens.curveEasyEaseMax; | ||
|
||
const enterKeyframes = [ | ||
{ opacity: fromOpacity, maxHeight: fromHeight, overflow }, | ||
// Transition to the height of the content, at 99.99% of the duration. | ||
{ opacity: toOpacity, maxHeight: toHeight, offset: 0.9999, overflow }, | ||
// On completion, remove the maxHeight because the content might need to expand later. | ||
// This extra keyframe is simpler than firing a callback on completion. | ||
{ opacity: toOpacity, maxHeight: 'unset', overflow }, | ||
]; | ||
|
||
const exitKeyframes = [ | ||
{ opacity: toOpacity, maxHeight: toHeight, overflow }, | ||
{ opacity: fromOpacity, maxHeight: fromHeight, overflow }, | ||
]; | ||
|
||
return { | ||
enter: { duration, easing, keyframes: enterKeyframes }, | ||
exit: { duration, easing, keyframes: exitKeyframes }, | ||
export const createCollapsePresence: PresenceMotionFnCreator<CollapseVariantParams, CollapseRuntimeParams> = | ||
({ | ||
enterDuration = motionTokens.durationNormal, | ||
enterEasing = motionTokens.curveEasyEaseMax, | ||
exitDuration = enterDuration, | ||
exitEasing = enterEasing, | ||
} = {}) => | ||
({ element, animateOpacity = true }) => { | ||
const fromOpacity = animateOpacity ? 0 : 1; | ||
const toOpacity = 1; | ||
const fromHeight = '0'; // Could be a custom param in the future to start partially expanded | ||
const toHeight = `${element.scrollHeight}px`; | ||
const overflow = 'hidden'; | ||
|
||
const enterKeyframes = [ | ||
{ opacity: fromOpacity, maxHeight: fromHeight, overflow }, | ||
// Transition to the height of the content, at 99.99% of the duration. | ||
{ opacity: toOpacity, maxHeight: toHeight, offset: 0.9999, overflow }, | ||
// On completion, remove the maxHeight because the content might need to expand later. | ||
// This extra keyframe is simpler than firing a callback on completion. | ||
{ opacity: toOpacity, maxHeight: 'unset', overflow }, | ||
]; | ||
|
||
const exitKeyframes = [ | ||
{ opacity: toOpacity, maxHeight: toHeight, overflow }, | ||
{ opacity: fromOpacity, maxHeight: fromHeight, overflow }, | ||
]; | ||
|
||
return { | ||
enter: { duration: enterDuration, easing: enterEasing, keyframes: enterKeyframes }, | ||
exit: { duration: exitDuration, easing: exitEasing, keyframes: exitKeyframes }, | ||
}; | ||
}; | ||
}; | ||
|
||
/** A React component that applies collapse/expand transitions to its children. */ | ||
export const Collapse = createPresenceComponent(collapseMotion); | ||
export const Collapse = createPresenceComponent(createCollapsePresence()); | ||
|
||
export const CollapseSnappy = createPresenceComponentVariant(Collapse, { | ||
all: { duration: motionTokens.durationUltraFast }, | ||
}); | ||
export const CollapseSnappy = createPresenceComponent( | ||
createCollapsePresence({ enterDuration: motionTokens.durationFast }), | ||
); | ||
|
||
export const CollapseExaggerated = createPresenceComponentVariant(Collapse, { | ||
enter: { duration: motionTokens.durationSlow, easing: motionTokens.curveEasyEaseMax }, | ||
exit: { duration: motionTokens.durationNormal, easing: motionTokens.curveEasyEaseMax }, | ||
}); | ||
export const CollapseExaggerated = createPresenceComponent( | ||
createCollapsePresence({ enterDuration: motionTokens.durationSlower }), | ||
); |
2 changes: 1 addition & 1 deletion
2
packages/react-components/react-motion-components-preview/library/src/index.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,3 @@ | ||
export { Collapse, CollapseSnappy, CollapseExaggerated } from './components/Collapse'; | ||
export { Collapse, CollapseSnappy, CollapseExaggerated, createCollapsePresence } from './components/Collapse'; | ||
export { Fade, FadeSnappy, FadeExaggerated } from './components/Fade'; | ||
export { Scale, ScaleSnappy, ScaleExaggerated } from './components/Scale'; |
17 changes: 17 additions & 0 deletions
17
packages/react-components/react-motion-components-preview/library/src/types.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
import type { MotionParam, PresenceMotionFn } from '@fluentui/react-motion'; | ||
|
||
/** | ||
* This is a factory function that generates a motion function, which has variant params bound into it. | ||
* The generated motion function accepts other runtime params that aren't locked into the variant, but supplied at runtime. | ||
* This separation allows the variant to be defined once and reused with different runtime params which may be orthogonal to the variant params. | ||
* For example, a variant may define the duration and easing of a transition, which are fixed for all instances of the variant, | ||
* while the runtime params may give access to the target element, which is different for each instance. | ||
* | ||
* The generated motion function is also framework-independent, i.e. non-React. | ||
* It can be turned into a React component using `createPresenceComponent`. | ||
*/ | ||
// TODO: move to @fluentui/react-motion when stable | ||
export type PresenceMotionFnCreator< | ||
MotionVariantParams extends Record<string, MotionParam> = {}, | ||
MotionRuntimeParams extends Record<string, MotionParam> = {}, | ||
> = (variantParams?: MotionVariantParams) => PresenceMotionFn<MotionRuntimeParams>; |
19 changes: 12 additions & 7 deletions
19
...motion-components-preview/stories/src/Collapse/CollapseCustomization.stories.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters