style(ui): agent strip with worktree panel and diff meter

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
mika kuns
2026-04-20 11:35:33 +02:00
parent b64ff3d908
commit c3f077e3b6
3 changed files with 155 additions and 27 deletions

View File

@@ -664,6 +664,23 @@
<Setter Property="Foreground" Value="{StaticResource TextDimBrush}" />
</Style>
<!-- ============================================================ -->
<!-- DIFF METER -->
<!-- ============================================================ -->
<!-- Outer track (full width, line-bright bg) -->
<Style Selector="Border.diff-meter-track">
<Setter Property="Height" Value="4" />
<Setter Property="CornerRadius" Value="2" />
<Setter Property="Background" Value="{StaticResource LineBrightBrush}" />
<Setter Property="ClipToBounds" Value="True" />
</Style>
<!-- Filled portion (moss; width set via ScaleTransform or Width binding in view) -->
<Style Selector="Rectangle.diff-meter-fill">
<Setter Property="Height" Value="4" />
<Setter Property="Fill" Value="{StaticResource MossBrightBrush}" />
<Setter Property="HorizontalAlignment" Value="Left" />
</Style>
<!-- ============================================================ -->
<!-- SECTION LABELS (OVERDUE / TASKS / COMPLETED) -->
<!-- ============================================================ -->

View File

@@ -37,6 +37,26 @@ public sealed partial class DetailsIslandViewModel : ViewModelBase
[ObservableProperty] private string? _branchLine;
[ObservableProperty] private int _turns;
[ObservableProperty] private int _tokens;
[ObservableProperty] private int _diffAdditions;
[ObservableProperty] private int _diffDeletions;
[ObservableProperty] private int _commitsOnBranch;
public string TokensFormatted => Tokens >= 1000 ? $"{Tokens / 1000.0:F1}k" : Tokens.ToString();
public string ElapsedFormatted => ""; // placeholder — no start-time stored yet
partial void OnTokensChanged(int value) => OnPropertyChanged(nameof(TokensFormatted));
partial void OnDiffAdditionsChanged(int value) => OnPropertyChanged(nameof(DiffMeterRatio));
partial void OnDiffDeletionsChanged(int value) => OnPropertyChanged(nameof(DiffMeterRatio));
// 0.01.0 additions share for the diff meter
public double DiffMeterRatio
{
get
{
var total = DiffAdditions + DiffDeletions;
return total == 0 ? 0.0 : (double)DiffAdditions / total;
}
}
public ObservableCollection<LogLineViewModel> Log { get; } = new();
public ObservableCollection<SubtaskRowViewModel> Subtasks { get; } = new();

View File

@@ -3,38 +3,129 @@
xmlns:vm="using:ClaudeDo.Ui.ViewModels.Islands"
x:Class="ClaudeDo.Ui.Views.Islands.AgentStripView"
x:DataType="vm:DetailsIslandViewModel">
<Border Classes="agent-strip">
<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"
Classes.status-pulse="{Binding IsRunning}"/>
<TextBlock Text="{Binding AgentStatusLabel}" FontSize="12"
Foreground="{DynamicResource TextBrush}" VerticalAlignment="Center"/>
<TextBlock Text="{Binding Model}" FontFamily="{DynamicResource MonoFamily}"
FontSize="11" Foreground="{DynamicResource TextDimBrush}" VerticalAlignment="Center"
<Border Classes="agent-strip"
Classes.running="{Binding IsRunning}"
Margin="18,8,18,0">
<StackPanel Margin="12,10" Spacing="6">
<!-- Row 1: pulsing dot · status label · model · stop button -->
<Grid ColumnDefinitions="Auto,Auto,*,Auto">
<Ellipse Grid.Column="0"
Width="8" Height="8"
Fill="{DynamicResource MossBrush}"
VerticalAlignment="Center"
Classes.status-pulse="{Binding IsRunning}"
Margin="0,0,6,0"/>
<TextBlock Grid.Column="1"
Text="{Binding AgentStatusLabel}"
FontFamily="{DynamicResource MonoFont}"
FontSize="10"
LetterSpacing="1.2"
Foreground="{DynamicResource TextDimBrush}"
VerticalAlignment="Center"
Margin="0,0,8,0"/>
<TextBlock Grid.Column="2"
Text="{Binding Model}"
FontFamily="{DynamicResource MonoFont}"
FontSize="10"
Foreground="{DynamicResource TextFaintBrush}"
VerticalAlignment="Center"
TextTrimming="CharacterEllipsis"
IsVisible="{Binding Model, Converter={x:Static ObjectConverters.IsNotNull}}"/>
<TextBlock Text="{Binding Turns, StringFormat='turns: {0}'}" FontSize="11"
Foreground="{DynamicResource TextMuteBrush}" VerticalAlignment="Center"/>
<TextBlock Text="{Binding Tokens, StringFormat='tok: {0}'}" FontSize="11"
Foreground="{DynamicResource TextMuteBrush}" VerticalAlignment="Center"/>
<!-- Stop button — only when running -->
<Button Grid.Column="3"
Classes="icon-btn"
Command="{Binding StopCommand}"
IsVisible="{Binding IsRunning}"
ToolTip.Tip="Stop agent"
VerticalAlignment="Center">
<PathIcon Data="{StaticResource Icon.X}" Width="12" Height="12"
Foreground="{DynamicResource BloodBrush}"/>
</Button>
</Grid>
<!-- Row 2: WORKTREE label + path + copy button -->
<Grid ColumnDefinitions="Auto,*,Auto"
IsVisible="{Binding WorktreePath, Converter={x:Static ObjectConverters.IsNotNull}}">
<TextBlock Grid.Column="0"
Text="WORKTREE"
FontFamily="{DynamicResource MonoFont}" FontSize="9"
LetterSpacing="1.2"
Foreground="{DynamicResource TextFaintBrush}"
VerticalAlignment="Center"
Margin="0,0,8,0"/>
<TextBlock Grid.Column="1"
Text="{Binding WorktreePath}"
FontFamily="{DynamicResource MonoFont}" FontSize="10"
Foreground="{DynamicResource TextDimBrush}"
TextTrimming="CharacterEllipsis"
VerticalAlignment="Center"/>
<Button Grid.Column="2"
Classes="icon-btn"
ToolTip.Tip="Copy path"
VerticalAlignment="Center">
<PathIcon Data="{StaticResource Icon.Copy}" Width="11" Height="11"/>
</Button>
</Grid>
<!-- Row 3: Branch line — icon + branch ← main + commits chip -->
<StackPanel Orientation="Horizontal" Spacing="6"
IsVisible="{Binding BranchLine, Converter={x:Static ObjectConverters.IsNotNull}}">
<PathIcon Data="{StaticResource Icon.GitBranch}" Width="11" Height="11"
Foreground="{DynamicResource AccentBrush}"
VerticalAlignment="Center"/>
<TextBlock Text="{Binding BranchLine}"
FontFamily="{DynamicResource MonoFont}" FontSize="10"
Foreground="{DynamicResource TextDimBrush}"
VerticalAlignment="Center"/>
<Border Classes="chip"
IsVisible="{Binding CommitsOnBranch}"
Padding="5,1" CornerRadius="4">
<TextBlock Text="{Binding CommitsOnBranch, StringFormat='{}{0}c'}"
FontFamily="{DynamicResource MonoFont}" FontSize="9"
Foreground="{DynamicResource TextFaintBrush}"/>
</Border>
</StackPanel>
<!-- Row 2: worktree path -->
<TextBlock Text="{Binding WorktreePath}" FontFamily="{DynamicResource MonoFamily}"
FontSize="11" Foreground="{DynamicResource TextDimBrush}"
TextTrimming="CharacterEllipsis"
IsVisible="{Binding WorktreePath, Converter={x:Static ObjectConverters.IsNotNull}}"/>
<!-- Row 3: branch line -->
<TextBlock Text="{Binding BranchLine}" FontFamily="{DynamicResource MonoFamily}"
FontSize="11" Foreground="{DynamicResource TextDimBrush}"
IsVisible="{Binding BranchLine, Converter={x:Static ObjectConverters.IsNotNull}}"/>
<!-- Button row -->
<StackPanel Orientation="Horizontal" Spacing="8" Margin="0,6,0,0">
<!-- Row 4: DIFF label + +add del + meter bar -->
<Grid ColumnDefinitions="Auto,Auto,Auto,*">
<TextBlock Grid.Column="0"
Text="DIFF"
FontFamily="{DynamicResource MonoFont}" FontSize="9"
LetterSpacing="1.2"
Foreground="{DynamicResource TextFaintBrush}"
VerticalAlignment="Center"
Margin="0,0,8,0"/>
<TextBlock Grid.Column="1"
Text="{Binding DiffAdditions, StringFormat='+{0}'}"
Classes="diff-add"
VerticalAlignment="Center"
Margin="0,0,4,0"/>
<TextBlock Grid.Column="2"
Text="{Binding DiffDeletions, StringFormat='{0}'}"
Classes="diff-del"
VerticalAlignment="Center"
Margin="0,0,8,0"/>
<!-- Slim 4px meter: track + fill using a Grid overlay -->
<Grid Grid.Column="3" VerticalAlignment="Center">
<Border Classes="diff-meter-track"/>
<Rectangle Classes="diff-meter-fill"
Width="{Binding DiffMeterRatio}"
HorizontalAlignment="Left"
RenderTransformOrigin="0,0.5">
<Rectangle.RenderTransform>
<ScaleTransform ScaleX="{Binding $parent[Grid].Bounds.Width}"/>
</Rectangle.RenderTransform>
</Rectangle>
</Grid>
</Grid>
<!-- Action buttons -->
<StackPanel Orientation="Horizontal" Spacing="6" Margin="0,4,0,0">
<Button Classes="btn" Content="Open diff" Command="{Binding OpenDiffCommand}"/>
<Button Classes="btn" Content="Worktree" Command="{Binding OpenWorktreeCommand}"/>
<Button Classes="btn" Content="Stop" Command="{Binding StopCommand}"/>
<Button Classes="btn" Content="Approve &amp; merge" Command="{Binding ApproveMergeCommand}"/>
</StackPanel>
</StackPanel>
</Border>
</UserControl>