Files
2025-03-07 19:22:02 +01:00

86 lines
3.9 KiB
JavaScript

import { motionTokens, createPresenceComponent } from '@fluentui/react-motion';
import { sizeEnterAtom, sizeExitAtom, whitespaceAtom } from './collapse-atoms';
import { fadeAtom } from '../../atoms/fade-atom';
/** Define a presence motion for collapse/expand that can stagger the size and opacity motions by a given delay. */ export const createCollapseDelayedPresence = ({ // enter
enterSizeDuration = motionTokens.durationNormal, enterOpacityDuration = enterSizeDuration, enterEasing = motionTokens.curveEasyEaseMax, enterDelay = 0, // exit: durations and easing default to enter values for symmetry
exitSizeDuration = enterSizeDuration, exitOpacityDuration = enterOpacityDuration, exitEasing = enterEasing, exitDelay = 0 } = {})=>({ element, animateOpacity = true, orientation = 'vertical' })=>{
// ----- ENTER -----
// The enter transition is an array of up to 3 motion atoms: size, whitespace and opacity.
const enterAtoms = [
sizeEnterAtom({
orientation,
duration: enterSizeDuration,
easing: enterEasing,
element
}),
whitespaceAtom({
direction: 'enter',
orientation,
duration: enterSizeDuration,
easing: enterEasing
})
];
// Fade in only if animateOpacity is true. Otherwise, leave opacity unaffected.
if (animateOpacity) {
enterAtoms.push({
...fadeAtom({
direction: 'enter',
duration: enterOpacityDuration,
easing: enterEasing
}),
delay: enterDelay,
fill: 'both'
});
}
// ----- EXIT -----
// The exit transition is an array of up to 3 motion atoms: opacity, size and whitespace.
const exitAtoms = [];
// Fade out only if animateOpacity is true. Otherwise, leave opacity unaffected.
if (animateOpacity) {
exitAtoms.push(fadeAtom({
direction: 'exit',
duration: exitOpacityDuration,
easing: exitEasing
}));
}
exitAtoms.push(sizeExitAtom({
orientation,
duration: exitSizeDuration,
easing: exitEasing,
element,
delay: exitDelay
}), whitespaceAtom({
direction: 'exit',
orientation,
duration: exitSizeDuration,
easing: exitEasing,
delay: exitDelay
}));
return {
enter: enterAtoms,
exit: exitAtoms
};
};
/** Defines a presence motion for collapse/expand. */ export const createCollapsePresence = ({ enterDuration = motionTokens.durationNormal, enterEasing = motionTokens.curveEasyEaseMax, exitDuration = enterDuration, exitEasing = enterEasing } = {})=>// Implement a regular collapse as a special case of the delayed collapse,
// where the delays are zero, and the size and opacity durations are equal.
createCollapseDelayedPresence({
enterSizeDuration: enterDuration,
enterEasing,
exitSizeDuration: exitDuration,
exitEasing
});
/** A React component that applies collapse/expand transitions to its children. */ export const Collapse = createPresenceComponent(createCollapsePresence());
export const CollapseSnappy = createPresenceComponent(createCollapsePresence({
enterDuration: motionTokens.durationFast
}));
export const CollapseRelaxed = createPresenceComponent(createCollapsePresence({
enterDuration: motionTokens.durationSlower
}));
export const CollapseDelayed = createPresenceComponent(createCollapseDelayedPresence({
enterSizeDuration: motionTokens.durationNormal,
enterOpacityDuration: motionTokens.durationSlower,
enterDelay: motionTokens.durationNormal,
exitDelay: motionTokens.durationSlower,
enterEasing: motionTokens.curveEasyEase
}));