Skip to content

Add smooth tab reorder animation during drag#19598

Closed
Z-a-r-a-k-i wants to merge 1 commit intomicrosoft:mainfrom
Z-a-r-a-k-i:feature/tab-reorder-animation
Closed

Add smooth tab reorder animation during drag#19598
Z-a-r-a-k-i wants to merge 1 commit intomicrosoft:mainfrom
Z-a-r-a-k-i:feature/tab-reorder-animation

Conversation

@Z-a-r-a-k-i
Copy link

Summary of the Pull Request

Adds smooth tab reorder animation during same-window tab dragging. When a tab is dragged, other tabs animate to show where the tab will be inserted, similar to Chrome/Edge behavior.

References and Relevant Issues

Detailed Description of the Pull Request / Additional comments

  • Implements TabReorderAnimator class that uses TranslateTransform to animate tabs
  • Same-window drags: tabs shift left/right to create visual gap at insertion point
  • Cross-window drags: also animates to show insertion point
  • On drop: transforms snap back immediately to avoid conflicting with TabView's reorder animation
  • Respects DisableAnimations global setting (checked at init and on settings reload)
  • Disables TabView's built-in ItemContainerTransitions during drag to prevent conflicts

Validation Steps Performed

  • Same-window tab reordering animates smoothly
  • Cross-window tab drops animate correctly
  • Animation respects DisableAnimations setting
  • Drag leave resets animations properly
  • Rapid pointer movement doesn't leave tabs stuck (storyboard conflicts resolved)
  • Settings reload updates animation preference

PR Checklist

@github-actions

This comment has been minimized.

@Z-a-r-a-k-i Z-a-r-a-k-i force-pushed the feature/tab-reorder-animation branch from 2bcb73a to b0e75de Compare November 30, 2025 18:25
@Z-a-r-a-k-i
Copy link
Author

@microsoft-github-policy-service agree

@DHowett
Copy link
Member

DHowett commented Dec 1, 2025

WHOA. Do you have a video of this? It sounds great!

@DHowett
Copy link
Member

DHowett commented Dec 1, 2025

/azp run

@azure-pipelines
Copy link

Azure Pipelines successfully started running 1 pipeline(s).

@Z-a-r-a-k-i
Copy link
Author

WHOA. Do you have a video of this? It sounds great!

Demo

Copy link
Member

@carlos-zamora carlos-zamora left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the contribution! Looks great! There's a few changes I've suggested that would simplify it a bit (i.e. remove possible extra vars or code).

Aside from that, I'm excited to see this merge soon. 😊

Comment on lines +5554 to 5562
void TerminalPage::_onTabStripDragLeave(const winrt::Windows::Foundation::IInspectable& /*sender*/,
const winrt::Windows::UI::Xaml::DragEventArgs& /*e*/)
{
// When the drag leaves the tab strip, reset the gap animation
if (_tabReorderAnimator)
{
_tabReorderAnimator->OnDragLeave();
}
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: perhaps this makes more sense in TabManagement.cpp

Comment on lines +143 to +160
for (uint32_t i = 0; i < tabCount; i++)
{
if (static_cast<int>(i) != _draggedTabIndex)
{
if (const auto item = _tabView.ContainerFromIndex(i).try_as<MUX::TabViewItem>())
{
return item.ActualWidth();
}
}
}

if (_draggedTabIndex >= 0 && _draggedTabIndex < static_cast<int>(tabCount))
{
if (const auto item = _tabView.ContainerFromIndex(_draggedTabIndex).try_as<MUX::TabViewItem>())
{
return item.ActualWidth();
}
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need both? Why not just the second block?

_StopAllAnimations();
_transforms.clear();

const auto tabCount = _tabView.TabItems().Size();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
const auto tabCount = _tabView.TabItems().Size();
const auto tabCount = _tabView.TabItems().Size();
_transforms.reserve(tabCount);

nit: set the size of _transforms to tabCount since it'll always be that.

Comment on lines +232 to +233
const auto duration = DurationHelper::FromTimeSpan(
TimeSpan{ std::chrono::milliseconds(AnimationDurationMs) });
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
const auto duration = DurationHelper::FromTimeSpan(
TimeSpan{ std::chrono::milliseconds(AnimationDurationMs) });
const auto duration = DurationHelper::FromTimeSpan( TimeSpan{ std::chrono::milliseconds(AnimationDurationMs) });

nit: no need to split into 2 lines

Comment on lines +39 to +40
Windows::UI::Xaml::Media::Animation::TransitionCollection _savedTransitions{ nullptr };
bool _transitionsSaved{ false };
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need _transitionsSaved? Can't we just check if _savedTransitions is null?

@microsoft-github-policy-service microsoft-github-policy-service bot added the Needs-Author-Feedback The original author of the issue/PR needs to come back and respond to something label Jan 16, 2026
@Z-a-r-a-k-i
Copy link
Author

Closing this PR - after further investigation, I discovered that the WinUI TabView control already provides smooth tab reorder animation natively via ReorderThemeTransition (defined in App.xaml). The gap preview during drag is built-in behavior when CanReorderTabs is enabled.

This means the TabReorderAnimator implementation is redundant and was essentially duplicating (and potentially conflicting with) existing functionality.

Thanks @carlos-zamora and @DHowett for the review feedback!

@microsoft-github-policy-service microsoft-github-policy-service bot added Needs-Attention The core contributors need to come back around and look at this ASAP. and removed Needs-Author-Feedback The original author of the issue/PR needs to come back and respond to something labels Jan 20, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Needs-Attention The core contributors need to come back around and look at this ASAP.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants