@@ -5,146 +5,101 @@ import {
55 createPresenceComponentVariant ,
66 AtomMotion ,
77} from '@fluentui/react-motion' ;
8- import type { CollapseDelayedParams , CollapseParams } from './collapse-types' ;
8+ import type { CollapseParams } from './collapse-types' ;
99import { sizeEnterAtom , sizeExitAtom , whitespaceAtom } from './collapse-atoms' ;
1010import { fadeAtom } from '../../atoms/fade-atom' ;
1111
12- /** Internal helper to create collapse atoms with shared logic */
13- function createCollapseAtoms ( {
12+ /**
13+ * Define a presence motion for collapse/expand
14+ *
15+ * @param element - The element to apply the collapse motion to
16+ * @param duration - Time (ms) for the enter transition (expand). Defaults to the `durationNormal` value (200 ms)
17+ * @param easing - Easing curve for the enter transition. Defaults to the `curveEasyEaseMax` value
18+ * @param delay - Time (ms) to delay the entire enter transition. Defaults to 0
19+ * @param exitDuration - Time (ms) for the exit transition (collapse). Defaults to the `duration` param for symmetry
20+ * @param exitEasing - Easing curve for the exit transition. Defaults to the `easing` param for symmetry
21+ * @param exitDelay - Time (ms) to delay the entire exit transition. Defaults to the `delay` param for symmetry
22+ * @param staggerDelay - Time (ms) offset between the size and opacity animations. Defaults to 0
23+ * @param exitStaggerDelay - Time (ms) offset between the size and opacity animations on exit. Defaults to the `staggerDelay` param for symmetry
24+ * @param sizeDuration - Time (ms) for the size animation during enter. Defaults to `duration` for unified timing
25+ * @param opacityDuration - Time (ms) for the opacity animation during enter. Defaults to `sizeDuration` for synchronized timing
26+ * @param exitSizeDuration - Time (ms) for the size animation during exit. Defaults to `exitDuration` for unified timing
27+ * @param exitOpacityDuration - Time (ms) for the opacity animation during exit. Defaults to `exitSizeDuration` for synchronized timing
28+ * @param animateOpacity - Whether to animate the opacity. Defaults to `true`
29+ * @param orientation - The orientation of the size animation. Defaults to `'vertical'` to expand/collapse the height
30+ * @param fromSize - The starting size for the expand animation. Defaults to `'0px'`
31+ */
32+ const collapsePresenceFn : PresenceMotionFn < CollapseParams > = ( {
1433 element,
15- orientation,
16- animateOpacity,
34+ // Primary duration controls (simple API)
35+ duration = motionTokens . durationNormal ,
36+ exitDuration = duration ,
1737
18- // Enter params
19- sizeDuration,
38+ // Granular duration controls with smart defaults (advanced API)
39+ sizeDuration = duration ,
2040 opacityDuration = sizeDuration ,
21- easing,
22- delay,
23-
24- // Exit params
25- exitSizeDuration,
41+ exitSizeDuration = exitDuration ,
2642 exitOpacityDuration = exitSizeDuration ,
27- exitEasing,
28- exitDelay,
29- } : {
30- element : HTMLElement ;
31- } & Required < CollapseDelayedParams > ) {
43+
44+ // Other timing controls
45+ easing = motionTokens . curveEasyEaseMax ,
46+ delay = 0 ,
47+ exitEasing = easing ,
48+ exitDelay = delay ,
49+ staggerDelay = 0 ,
50+ exitStaggerDelay = staggerDelay ,
51+
52+ // Animation controls
53+ animateOpacity = true ,
54+ orientation = 'vertical' ,
55+ fromSize = '0px' ,
56+ } ) => {
3257 // ----- ENTER -----
3358 // The enter transition is an array of up to 3 motion atoms: size, whitespace and opacity.
59+ // For enter: size expands first, then opacity fades in after staggerDelay
3460 const enterAtoms : AtomMotion [ ] = [
35- sizeEnterAtom ( { orientation, duration : sizeDuration , easing, element } ) ,
36- whitespaceAtom ( { direction : 'enter' , orientation, duration : sizeDuration , easing } ) ,
61+ // Apply global delay to size atom - size expansion starts first
62+ sizeEnterAtom ( { orientation, duration : sizeDuration , easing, element, fromSize, delay } ) ,
63+ whitespaceAtom ( { direction : 'enter' , orientation, duration : sizeDuration , easing, delay } ) ,
3764 ] ;
3865 // Fade in only if animateOpacity is true. Otherwise, leave opacity unaffected.
3966 if ( animateOpacity ) {
40- enterAtoms . push ( {
41- ...fadeAtom ( { direction : 'enter' , duration : opacityDuration , easing } ) ,
42- delay,
43- fill : 'both' ,
44- } ) ;
67+ enterAtoms . push ( fadeAtom ( { direction : 'enter' , duration : opacityDuration , easing, delay : delay + staggerDelay } ) ) ;
4568 }
4669
4770 // ----- EXIT -----
4871 // The exit transition is an array of up to 3 motion atoms: opacity, size and whitespace.
72+ // For exit: opacity fades out first, then size collapses after exitStaggerDelay
4973 const exitAtoms : AtomMotion [ ] = [ ] ;
5074 // Fade out only if animateOpacity is true. Otherwise, leave opacity unaffected.
5175 if ( animateOpacity ) {
52- exitAtoms . push ( fadeAtom ( { direction : 'exit' , duration : exitOpacityDuration , easing : exitEasing } ) ) ;
76+ exitAtoms . push (
77+ fadeAtom ( { direction : 'exit' , duration : exitOpacityDuration , easing : exitEasing , delay : exitDelay } ) ,
78+ ) ;
5379 }
5480
5581 exitAtoms . push (
56- sizeExitAtom ( { orientation, duration : exitSizeDuration , easing : exitEasing , element, delay : exitDelay } ) ,
82+ sizeExitAtom ( {
83+ orientation,
84+ duration : exitSizeDuration ,
85+ easing : exitEasing ,
86+ element,
87+ delay : exitDelay + exitStaggerDelay ,
88+ fromSize,
89+ } ) ,
5790 whitespaceAtom ( {
5891 direction : 'exit' ,
5992 orientation,
6093 duration : exitSizeDuration ,
6194 easing : exitEasing ,
62- delay : exitDelay ,
95+ delay : exitDelay + exitStaggerDelay , // Size/whitespace collapse after opacity finishes fading out
6396 } ) ,
6497 ) ;
6598
6699 return {
67100 enter : enterAtoms ,
68101 exit : exitAtoms ,
69102 } ;
70- }
71-
72- /**
73- * Define a presence motion for collapse/expand
74- *
75- * @param element - The element to apply the collapse motion to
76- * @param duration - Time (ms) for the enter transition (expand). Defaults to the `durationNormal` value (200 ms)
77- * @param easing - Easing curve for the enter transition. Defaults to the `curveEasyEaseMax` value
78- * @param exitDuration - Time (ms) for the exit transition (collapse). Defaults to the `duration` param for symmetry
79- * @param exitEasing - Easing curve for the exit transition. Defaults to the `easing` param for symmetry
80- * @param animateOpacity - Whether to animate the opacity. Defaults to `true`
81- * @param orientation - The orientation of the size animation. Defaults to `'vertical'` to expand/collapse the height
82- */
83- const collapsePresenceFn : PresenceMotionFn < CollapseParams > = ( {
84- element,
85- duration = motionTokens . durationNormal ,
86- easing = motionTokens . curveEasyEaseMax ,
87- exitDuration = duration ,
88- exitEasing = easing ,
89- animateOpacity = true ,
90- orientation = 'vertical' ,
91- } ) => {
92- return createCollapseAtoms ( {
93- element,
94- orientation,
95- animateOpacity,
96- sizeDuration : duration ,
97- opacityDuration : duration ,
98- easing,
99- exitSizeDuration : exitDuration ,
100- exitOpacityDuration : exitDuration ,
101- exitEasing,
102- delay : 0 ,
103- exitDelay : 0 ,
104- } ) ;
105- } ;
106-
107- /**
108- * Define a presence motion for collapse/expand that can stagger the size and opacity motions by a given delay
109- *
110- * @param element - The element to apply the collapse motion to
111- * @param sizeDuration - Time (ms) for the size expand. Defaults to the `durationNormal` value (200 ms)
112- * @param opacityDuration - Time (ms) for the fade-in. Defaults to the `durationSlower` value (400 ms)
113- * @param easing - Easing curve for the enter transition. Defaults to the `curveEasyEase` value
114- * @param delay - Time (ms) between the size expand start and the fade-in start. Defaults to the `durationNormal` value (200 ms)
115- * @param exitSizeDuration - Time (ms) for the size collapse. Defaults to the `sizeDuration` param for temporal symmetry
116- * @param exitOpacityDuration - Time (ms) for the fade-out. Defaults to the `opacityDuration` param for temporal symmetry
117- * @param exitEasing - Easing curve for the exit transition. Defaults to the `easing` param for symmetry
118- * @param exitDelay - Time (ms) between the fade-out start and the size collapse start. Defaults to the `durationSlower` value (400 ms)
119- * @param animateOpacity - Whether to animate the opacity. Defaults to `true`
120- * @param orientation - The orientation of the size animation. Defaults to `'vertical'` to expand/collapse the height
121- */
122- const collapseDelayedPresenceFn : PresenceMotionFn < CollapseDelayedParams > = ( {
123- element,
124- sizeDuration = motionTokens . durationNormal ,
125- opacityDuration = motionTokens . durationSlower ,
126- easing = motionTokens . curveEasyEase ,
127- delay = motionTokens . durationNormal ,
128- exitSizeDuration = sizeDuration ,
129- exitOpacityDuration = opacityDuration ,
130- exitEasing = easing ,
131- exitDelay = motionTokens . durationSlower ,
132- animateOpacity = true ,
133- orientation = 'vertical' ,
134- } ) => {
135- return createCollapseAtoms ( {
136- element,
137- orientation,
138- animateOpacity,
139- sizeDuration,
140- opacityDuration,
141- easing,
142- delay,
143- exitSizeDuration,
144- exitOpacityDuration,
145- exitEasing,
146- exitDelay,
147- } ) ;
148103} ;
149104
150105/** A React component that applies collapse/expand transitions to its children. */
@@ -159,4 +114,18 @@ export const CollapseRelaxed = createPresenceComponentVariant(Collapse, {
159114} ) ;
160115
161116/** A React component that applies collapse/expand transitions with delayed fade to its children. */
162- export const CollapseDelayed = createPresenceComponent ( collapseDelayedPresenceFn ) ;
117+ export const CollapseDelayed = createPresenceComponentVariant ( Collapse , {
118+ // Enter timing per motion design spec
119+ sizeDuration : motionTokens . durationNormal , // 200ms
120+ opacityDuration : motionTokens . durationSlower , // 400ms
121+ staggerDelay : motionTokens . durationNormal , // 200ms
122+
123+ // Exit timing per motion design spec
124+ exitSizeDuration : motionTokens . durationNormal , // 200ms
125+ exitOpacityDuration : motionTokens . durationSlower , // 400ms
126+ exitStaggerDelay : motionTokens . durationSlower , // 400ms
127+
128+ // Easing per motion design spec
129+ easing : motionTokens . curveEasyEase ,
130+ exitEasing : motionTokens . curveEasyEase ,
131+ } ) ;
0 commit comments