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 }));