Repository: MudBlazor/MudBlazor (2026-03-30T23:59:43Z)

Issue:
OnAnimationEnd is triggered by animations inside the MudCollapse's  container
### Before reporting

- [x] I searched existing issues
- [x] I tried in private/incognito browser

### What went wrong?

I have a `MudTable` inside `MudCollapse`. I have a `OnAnimationEnd` handler that does something.
It gets called correctly on the expansion/collapse of the panel. 
The issue is that it also gets called on any animation (loading bar, button hovers, etc.) that is happening inside the `MudCollapse`.

Is that an expected behavior and if yes what can I do do isolate it to Collapse/Expand actions only?

Thanks!

### Reproduction link

https://try.mudblazor.com/snippet/GkwJEZcIYnwnaRSC

### Reproduction steps

1. Click on "OPEN"
2. Hover in and out over  the "ANIMATE" button
3. Observe `AnimationEnd` function appending the string with every button animation cycle


### Version (bug)

8.12.0

### Version (working)

_No response_

### Environment

Chrome

### Blazor rendering mode

WASM


Discussion:
While minds better than mine are maybe hopefully figuring a proper solution here is a work around

https://try.mudblazor.com/snippet/QkcJuZGSWEcbcLAy

Basically the idea here is to add a `OnAnimationEnd` callback when `Expanded` changes and then remove the callback INSIDE the callback function itself.
Observe that in the fiddle in this comment "animate" string is only appended on the Expand/Collapse of the `MudCollapse` and not on the hover on the button inside like in the OP



Patch:
diff --git a/src/MudBlazor/Components/Collapse/MudCollapse.razor.cs b/src/MudBlazor/Components/Collapse/MudCollapse.razor.cs
index 612a68875461..8550a336889b 100644
--- a/src/MudBlazor/Components/Collapse/MudCollapse.razor.cs
+++ b/src/MudBlazor/Components/Collapse/MudCollapse.razor.cs
@@ -101,14 +101,17 @@ private Task AnimationEndAsync()
             {
                 _state = CollapseState.Entered;
                 StateHasChanged();
+                return OnAnimationEnd.InvokeAsync(_expandedState.Value);
             }
-            else if (_state == CollapseState.Exiting)
+
+            if (_state == CollapseState.Exiting)
             {
                 _state = CollapseState.Exited;
                 StateHasChanged();
+                return OnAnimationEnd.InvokeAsync(_expandedState.Value);
             }
 
-            return OnAnimationEnd.InvokeAsync(_expandedState.Value);
+            return Task.CompletedTask;
         }
     }
 }


Test patch:
diff --git a/src/MudBlazor.UnitTests.Viewer/TestComponents/Collapse/CollapseAnimationEndChildTransitionTest.razor b/src/MudBlazor.UnitTests.Viewer/TestComponents/Collapse/CollapseAnimationEndChildTransitionTest.razor
new file mode 100644
index 000000000000..0f8bb299c397
--- /dev/null
+++ b/src/MudBlazor.UnitTests.Viewer/TestComponents/Collapse/CollapseAnimationEndChildTransitionTest.razor
@@ -0,0 +1,14 @@
+﻿<MudCollapse Expanded="true" OnAnimationEnd="OnAnimationEnd">
+    <div id="inner">content</div>
+</MudCollapse>
+
+<div id="animation_end_count">@_animationEndCount</div>
+
+@code {
+    private int _animationEndCount;
+
+    private void OnAnimationEnd()
+    {
+        _animationEndCount++;
+    }
+}
diff --git a/src/MudBlazor.UnitTests/Components/CollapseTests.cs b/src/MudBlazor.UnitTests/Components/CollapseTests.cs
index e590d81efdd6..15ebfd7396a9 100644
--- a/src/MudBlazor.UnitTests/Components/CollapseTests.cs
+++ b/src/MudBlazor.UnitTests/Components/CollapseTests.cs
@@ -43,5 +43,16 @@ public async Task Collapse_TwoWayBinding_Test1()
             await MudSwitch().Find("input").ChangeAsync(true);
             MudSwitch().Find("input").HasAttribute("checked").Should().BeTrue();
         }
+
+        [Test]
+        public async Task Collapse_OnAnimationEnd_ShouldIgnoreChildTransitionEnd()
+        {
+            var comp = Context.Render<CollapseAnimationEndChildTransitionTest>();
+            comp.Find("#animation_end_count").TextContent.Should().Be("0");
+
+            await comp.Find("#inner").TriggerEventAsync("ontransitionend", EventArgs.Empty);
+
+            comp.Find("#animation_end_count").TextContent.Should().Be("0");
+        }
     }
 }