feat(ui): pulse, hover, modal, and row-add animations

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
mika kuns
2026-04-20 10:33:39 +02:00
parent abd7733c90
commit 47e8e1ff94
6 changed files with 98 additions and 1 deletions

View File

@@ -7,7 +7,8 @@
<StackPanel Margin="14,12" Spacing="6">
<!-- Row 1: status dot · status label · model · turns · tokens -->
<StackPanel Orientation="Horizontal" Spacing="10">
<Ellipse Width="8" Height="8" Fill="{DynamicResource MossBrush}" VerticalAlignment="Center"/>
<Ellipse Width="8" Height="8" Fill="{DynamicResource MossBrush}" VerticalAlignment="Center"
Classes.status-pulse="{Binding IsRunning}"/>
<TextBlock Text="{Binding AgentStatusLabel}" FontSize="12"
Foreground="{DynamicResource TextBrush}" VerticalAlignment="Center"/>
<TextBlock Text="{Binding Model}" FontFamily="{DynamicResource MonoFamily}"

View File

@@ -1,8 +1,33 @@
using Avalonia;
using Avalonia.Animation;
using Avalonia.Animation.Easings;
using Avalonia.Controls;
using Avalonia.Media;
using Avalonia.Styling;
namespace ClaudeDo.Ui.Views.Islands;
public partial class TaskRowView : UserControl
{
public TaskRowView() { InitializeComponent(); }
protected override async void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e)
{
base.OnAttachedToVisualTree(e);
RenderTransform = new TranslateTransform(0, 8);
Opacity = 0;
var anim = new Avalonia.Animation.Animation
{
Duration = TimeSpan.FromMilliseconds(300),
Easing = new CubicEaseOut(),
Children =
{
new KeyFrame { Cue = new Cue(0), Setters = { new Setter(OpacityProperty, 0d) } },
new KeyFrame { Cue = new Cue(1), Setters = { new Setter(OpacityProperty, 1d) } },
}
};
await anim.RunAsync(this);
Opacity = 1;
RenderTransform = null;
}
}

View File

@@ -1,5 +1,10 @@
using Avalonia;
using Avalonia.Animation;
using Avalonia.Animation.Easings;
using Avalonia.Controls;
using Avalonia.Input;
using Avalonia.Media;
using Avalonia.Styling;
using ClaudeDo.Ui.ViewModels.Modals;
namespace ClaudeDo.Ui.Views.Modals;
@@ -18,6 +23,27 @@ public partial class DiffModalView : Window
vm.CloseAction = Close;
}
protected override async void OnOpened(EventArgs e)
{
base.OnOpened(e);
Opacity = 0;
RenderTransform = new ScaleTransform(0.98, 0.98);
var anim = new Avalonia.Animation.Animation
{
Duration = TimeSpan.FromMilliseconds(180),
Easing = new CubicEaseOut(),
FillMode = FillMode.Forward,
Children =
{
new KeyFrame { Cue = new Cue(0), Setters = { new Setter(OpacityProperty, 0d) } },
new KeyFrame { Cue = new Cue(1), Setters = { new Setter(OpacityProperty, 1d) } },
}
};
await anim.RunAsync(this);
Opacity = 1;
RenderTransform = new ScaleTransform(1.0, 1.0);
}
private void TitleBar_PointerPressed(object? sender, PointerPressedEventArgs e)
{
if (e.GetCurrentPoint(this).Properties.IsLeftButtonPressed)

View File

@@ -1,5 +1,10 @@
using Avalonia;
using Avalonia.Animation;
using Avalonia.Animation.Easings;
using Avalonia.Controls;
using Avalonia.Input;
using Avalonia.Media;
using Avalonia.Styling;
using ClaudeDo.Ui.ViewModels.Modals;
namespace ClaudeDo.Ui.Views.Modals;
@@ -18,6 +23,27 @@ public partial class WorktreeModalView : Window
vm.CloseAction = Close;
}
protected override async void OnOpened(EventArgs e)
{
base.OnOpened(e);
Opacity = 0;
RenderTransform = new ScaleTransform(0.98, 0.98);
var anim = new Avalonia.Animation.Animation
{
Duration = TimeSpan.FromMilliseconds(180),
Easing = new CubicEaseOut(),
FillMode = FillMode.Forward,
Children =
{
new KeyFrame { Cue = new Cue(0), Setters = { new Setter(OpacityProperty, 0d) } },
new KeyFrame { Cue = new Cue(1), Setters = { new Setter(OpacityProperty, 1d) } },
}
};
await anim.RunAsync(this);
Opacity = 1;
RenderTransform = new ScaleTransform(1.0, 1.0);
}
private void OnTitleBarPressed(object? sender, PointerPressedEventArgs e)
{
if (e.GetCurrentPoint(this).Properties.IsLeftButtonPressed)