From 18b03ee8c4169bef174479ba1d2a5472b823520f Mon Sep 17 00:00:00 2001 From: Kyle Date: Sun, 4 Jan 2026 02:02:53 +0800 Subject: [PATCH 1/3] Fix Transition animation issue If missing containerInputs call, DynamicTransaction will not work. Then transaction.addAnimationListener will not be added. So the animation will be triggerred right away instead of the normal completion --- Sources/OpenSwiftUICore/Layout/Dynamic/DynamicLayoutView.swift | 1 + 1 file changed, 1 insertion(+) diff --git a/Sources/OpenSwiftUICore/Layout/Dynamic/DynamicLayoutView.swift b/Sources/OpenSwiftUICore/Layout/Dynamic/DynamicLayoutView.swift index fa5cf062f..0f0547a3d 100644 --- a/Sources/OpenSwiftUICore/Layout/Dynamic/DynamicLayoutView.swift +++ b/Sources/OpenSwiftUICore/Layout/Dynamic/DynamicLayoutView.swift @@ -226,6 +226,7 @@ struct DynamicLayoutViewAdaptor: DynamicContainerAdaptor { var containerID = DynamicContainerID(uniqueId: uniqueId, viewIndex: 0) let outputs = item.elements.makeAllElements(inputs: inputs) { elementInputs, body in var elementInputs = elementInputs + containerInputs(&elementInputs) if elementInputs.needsGeometry { let childGeometry = Attribute( DynamicLayoutViewChildGeometry( From e41e051baf59556baeb13900d118a7229e5aa994 Mon Sep 17 00:00:00 2001 From: Kyle Date: Sun, 4 Jan 2026 02:03:36 +0800 Subject: [PATCH 2/3] [NFC] Optimize MoveTransition --- .../OpenSwiftUICore/Animation/Transition/MoveTransition.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Sources/OpenSwiftUICore/Animation/Transition/MoveTransition.swift b/Sources/OpenSwiftUICore/Animation/Transition/MoveTransition.swift index 1f0f60aff..26c54702b 100644 --- a/Sources/OpenSwiftUICore/Animation/Transition/MoveTransition.swift +++ b/Sources/OpenSwiftUICore/Animation/Transition/MoveTransition.swift @@ -53,11 +53,11 @@ public struct MoveTransition: Transition { } public func _makeContentTransition(transition: inout _Transition_ContentTransition) { - guard case let .effects(style, size) = transition.operation else { + guard case let .effects(_, size) = transition.operation else { transition.result = .bool(true) return } - let effectiveSize = edge.translationOffset(for: size) + let effectiveSize = edge.translationOffset(for: size) let effect = ContentTransition.Effect(.translation(effectiveSize)) transition.result = .effects([effect]) } From 141e526c12e68d23fb7c77bfef0532f9c7f85b81 Mon Sep 17 00:00:00 2001 From: Kyle Date: Sun, 4 Jan 2026 02:06:37 +0800 Subject: [PATCH 3/3] Add test case for transition fix --- .../DynamicViewContent/ForEachUITests.swift | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/Example/OpenSwiftUIUITests/View/DynamicViewContent/ForEachUITests.swift b/Example/OpenSwiftUIUITests/View/DynamicViewContent/ForEachUITests.swift index 993f27bf7..d814dd2db 100644 --- a/Example/OpenSwiftUIUITests/View/DynamicViewContent/ForEachUITests.swift +++ b/Example/OpenSwiftUIUITests/View/DynamicViewContent/ForEachUITests.swift @@ -137,4 +137,34 @@ struct ForEachUITests { } openSwiftUIAssertSnapshot(of: ContentView()) } + + @Test( + .bug( + "https://github.com/OpenSwiftUIProject/OpenSwiftUI/issues/655", + id: 655 + ) + ) + func transitionAnimation() { + struct ContentView: AnimationTestView { + nonisolated static var model: AnimationTestModel { + AnimationTestModel(duration: 2.0, count: 4) + } + @State private var items = [6] + + var body: some View { + VStack(spacing: 10) { + ForEach(items, id: \.self) { item in + Color.blue.opacity(Double(item) / 6.0) + .frame(height: 50) + .transition(.slide) + } + } + .animation(.easeInOut(duration: Self.model.duration), value: items) + .onAppear { + items.removeAll { $0 == 6 } + } + } + } + openSwiftUIAssertAnimationSnapshot(of: ContentView()) + } }