Skip to content

Commit a914015

Browse files
committed
test: add staggerChildren test for dynamic items in Motion component
1 parent 2076fae commit a914015

File tree

2 files changed

+61
-2
lines changed

2 files changed

+61
-2
lines changed

packages/motion/src/components/__tests__/variant.test.tsx

Lines changed: 60 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { describe, expect, it } from 'vitest'
22
import { mount } from '@vue/test-utils'
33
import { Motion } from '@/components'
44
import { motionValue, stagger } from 'framer-motion/dom'
5-
import { defineComponent, h, onMounted } from 'vue'
5+
import { defineComponent, h, nextTick, onMounted } from 'vue'
66

77
describe('animate prop as variant', () => {
88
it('when: beforeChildren works correctly', async () => {
@@ -419,4 +419,63 @@ describe('animate prop as variant', () => {
419419
// First stagger should start from first element
420420
expect(firstOrder).toEqual([1, 2, 3, 4])
421421
})
422+
it('staggerChildren is calculated correctly for new children', async () => {
423+
const Component = defineComponent({
424+
props: {
425+
items: {
426+
type: Array as () => string[],
427+
required: true,
428+
},
429+
},
430+
setup(props) {
431+
return () => (
432+
<Motion
433+
animate="enter"
434+
variants={{
435+
enter: { transition: { delayChildren: stagger(0.1) } },
436+
}}
437+
>
438+
{props.items.map(item => (
439+
<Motion
440+
key={item}
441+
id={item}
442+
class="item"
443+
variants={{ enter: { opacity: 1 } }}
444+
initial={{ opacity: 0 }}
445+
/>
446+
))}
447+
</Motion>
448+
)
449+
},
450+
})
451+
452+
const wrapper = mount(Component, {
453+
props: {
454+
items: ['1', '2'],
455+
},
456+
})
457+
458+
await nextTick()
459+
await nextTick()
460+
await nextTick()
461+
await nextTick()
462+
463+
await wrapper.setProps({
464+
items: ['1', '2', '3', '4', '5'],
465+
})
466+
467+
// Wait for animations to complete
468+
await new Promise(resolve => setTimeout(resolve, 1000))
469+
470+
const elements = document.querySelectorAll('.item')
471+
472+
// Check that none of the opacities are the same
473+
const opacities = Array.from(elements).map(el =>
474+
parseFloat(window.getComputedStyle(el).opacity),
475+
)
476+
477+
// All opacities should be unique
478+
const uniqueOpacities = new Set(opacities)
479+
expect(uniqueOpacities.size).toBe(opacities.length)
480+
})
422481
})

packages/motion/src/features/animation/animation.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -272,7 +272,7 @@ export class AnimationFeature extends Feature {
272272
* animate it by delayChildren
273273
*/
274274
if (this.state.parent?.isMounted() && !visualElement.isControllingVariants && parentVisualElement?.enteringChildren?.has(visualElement)) {
275-
const { delayChildren } = this.state.parent.finalTransition;
275+
const { delayChildren } = this.state.parent.finalTransition || {};
276276
(this.animateUpdates({
277277
controlActiveState: this.state.parent.activeStates,
278278
controlDelay: calcChildStagger(parentVisualElement.enteringChildren, visualElement, delayChildren),

0 commit comments

Comments
 (0)