From c3e1422b02d2c3ddd53de9f0e407e8e65baa1867 Mon Sep 17 00:00:00 2001 From: lacvet Date: Sun, 5 Apr 2026 16:20:55 +0900 Subject: [PATCH] =?UTF-8?q?AX=20Agent=20=EC=9E=91=EC=97=85=20=EC=9C=A0?= =?UTF-8?q?=ED=98=95=20=EC=B9=B4=EB=93=9C=20=EC=A0=95=EB=A6=AC=20=EB=B0=8F?= =?UTF-8?q?=20hover=20=EC=84=A4=EB=AA=85=20=EB=9D=BC=EB=B2=A8=20=EC=A0=81?= =?UTF-8?q?=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 작업 유형 카드 하단 상시 설명을 제거하고 모든 카드 크기를 동일 규격으로 통일함 - 카드 hover 시 확대 애니메이션을 제거하고 하단 설명 라벨과 배경/테두리 반응만 남겨 안정적으로 정리함 - 기타/프리셋 추가 카드도 같은 hover 규칙과 설명 노출 방식으로 통일함 - EmptyState 제목/설명 폰트를 키워 현재 화면 전반의 글자 크기를 보정함 - README 및 DEVELOPMENT 문서에 2026-04-05 19:02 (KST) 기준 변경 이력을 반영함 검증: - dotnet build src/AxCopilot/AxCopilot.csproj -c Release -v minimal -p:OutputPath=bin\\verify\\ -p:IntermediateOutputPath=obj\\verify\\ - 경고 0 / 오류 0 --- README.md | 5 + docs/DEVELOPMENT.md | 5 + src/AxCopilot/Views/ChatWindow.xaml | 6 +- src/AxCopilot/Views/ChatWindow.xaml.cs | 283 +++++++++++++++---------- 4 files changed, 180 insertions(+), 119 deletions(-) diff --git a/README.md b/README.md index b6c098e..1618603 100644 --- a/README.md +++ b/README.md @@ -883,6 +883,11 @@ ow + toggle 시각 언어로 통일했습니다. - 같은 파일에서 하단 컴포저의 `토큰 사용 카드`와 `프리셋` 버튼이 같은 컬럼을 같이 써서 겹치던 문제를 수정했습니다. 모델/토큰/프리셋을 각각 독립 컬럼으로 분리했고, 관련 버튼과 레이블의 폰트/패딩도 함께 키워 하단 정보가 눌려 보이지 않게 다시 정리했습니다. - 검증: `dotnet build src/AxCopilot/AxCopilot.csproj -c Release -v minimal -p:OutputPath=bin\\verify\\ -p:IntermediateOutputPath=obj\\verify\\` 경고 0 / 오류 0 - 업데이트: 2026-04-05 18:55 (KST) +- 작업 유형 카드 UX도 다시 다듬었습니다. [ChatWindow.xaml.cs](/E:/AX%20Copilot%20-%20Codex/src/AxCopilot/Views/ChatWindow.xaml.cs) 의 `BuildTopicButtons()` 에서 카드 하단의 상시 설명 텍스트를 제거하고, 모든 카드 크기를 같은 규격으로 통일했습니다. +- 각 카드 설명은 이제 hover 시 카드 하단의 작은 라벨로만 보이게 바꿨고, 기존 확대 애니메이션은 제거해 배경/테두리만 반응하는 안정적인 hover로 정리했습니다. `기타`, `프리셋 추가` 카드도 같은 규칙으로 맞췄습니다. +- [ChatWindow.xaml](/E:/AX%20Copilot%20-%20Codex/src/AxCopilot/Views/ChatWindow.xaml) 에서는 빈 상태 제목/설명 폰트도 함께 키워 이 화면 전반의 글자 크기가 너무 작아 보이지 않게 보정했습니다. +- 검증: `dotnet build src/AxCopilot/AxCopilot.csproj -c Release -v minimal -p:OutputPath=bin\\verify\\ -p:IntermediateOutputPath=obj\\verify\\` 경고 0 / 오류 0 +- 업데이트: 2026-04-05 19:02 (KST) --- diff --git a/docs/DEVELOPMENT.md b/docs/DEVELOPMENT.md index 9de4ab4..d772d7b 100644 --- a/docs/DEVELOPMENT.md +++ b/docs/DEVELOPMENT.md @@ -4643,3 +4643,8 @@ ow + toggle ?쒓컖 ?몄뼱濡??ㅼ떆 ?뺣젹?덈떎. - 같은 파일의 하단 컴포저 상단 줄에서는 `TokenUsageCard`와 `BtnTemplateSelector`가 같은 Grid 컬럼을 공유해 겹치던 구조를 수정했습니다. 컬럼을 4개로 나눠 `모델 선택 / 여백 / 토큰 카드 / 프리셋 버튼`을 각각 독립 배치했고, 카드/버튼의 폰트와 패딩도 다시 키워 하단 레이아웃이 눌려 보이지 않게 정리했습니다. - 검증: `dotnet build src/AxCopilot/AxCopilot.csproj -c Release -v minimal -p:OutputPath=bin\verify\ -p:IntermediateOutputPath=obj\verify\` 경고 0 / 오류 0 - 업데이트: 2026-04-05 18:55 (KST) +- 작업 유형 카드도 사용자 피드백 기준으로 다시 정리했습니다. [ChatWindow.xaml.cs](/E:/AX%20Copilot%20-%20Codex/src/AxCopilot/Views/ChatWindow.xaml.cs)의 `BuildTopicButtons()` 에서 프리셋/기타/프리셋 추가 카드 하단의 상시 설명 텍스트를 제거하고, 모든 카드를 `132 x 110` 규격으로 통일했습니다. +- 카드 설명은 hover 시 카드 하단에 뜨는 작은 라벨과 ToolTip으로만 노출되게 바꿨고, 기존 `ScaleTransform` 확대 애니메이션은 제거해 hover 시 배경과 테두리만 바뀌도록 정리했습니다. 이로써 마우스 오버 시 카드가 들썩이던 UX를 안정적으로 바꿨습니다. +- [ChatWindow.xaml](/E:/AX%20Copilot%20-%20Codex/src/AxCopilot/Views/ChatWindow.xaml) 에서는 `EmptyStateTitle`, `EmptyStateDesc` 폰트를 키워 현재 빈 상태 화면 전반의 글자 크기도 함께 보정했습니다. +- 검증: `dotnet build src/AxCopilot/AxCopilot.csproj -c Release -v minimal -p:OutputPath=bin\verify\ -p:IntermediateOutputPath=obj\verify\` 경고 0 / 오류 0 +- 업데이트: 2026-04-05 19:02 (KST) diff --git a/src/AxCopilot/Views/ChatWindow.xaml b/src/AxCopilot/Views/ChatWindow.xaml index 611fd28..d0e0129 100644 --- a/src/AxCopilot/Views/ChatWindow.xaml +++ b/src/AxCopilot/Views/ChatWindow.xaml @@ -1211,13 +1211,13 @@ HorizontalAlignment="Center" VerticalAlignment="Center"/> - diff --git a/src/AxCopilot/Views/ChatWindow.xaml.cs b/src/AxCopilot/Views/ChatWindow.xaml.cs index f96b71d..43a4792 100644 --- a/src/AxCopilot/Views/ChatWindow.xaml.cs +++ b/src/AxCopilot/Views/ChatWindow.xaml.cs @@ -12094,6 +12094,34 @@ public partial class ChatWindow : Window } var presets = Services.PresetService.GetByTabWithCustom(_activeTab, _settings.Settings.Llm.CustomPresets); + var cardBackground = TryFindResource("ItemBackground") as Brush ?? Brushes.Transparent; + var cardHoverBackground = TryFindResource("ItemHoverBackground") as Brush ?? Brushes.Transparent; + var cardBorder = TryFindResource("BorderColor") as Brush ?? BrushFromHex("#E5E7EB"); + var primaryText = TryFindResource("PrimaryText") as Brush ?? Brushes.White; + var secondaryText = TryFindResource("SecondaryText") as Brush ?? Brushes.Gray; + + void AttachTopicCardHover(Border card, Border hoverLabel, Brush normalBackground, Brush hoverBackground) + { + card.MouseEnter += (s, _) => + { + if (s is Border b) + { + b.Background = hoverBackground; + b.BorderBrush = TryFindResource("AccentColor") as Brush ?? cardBorder; + } + hoverLabel.Visibility = Visibility.Visible; + hoverLabel.Opacity = 1; + }; + card.MouseLeave += (s, _) => + { + if (s is Border b) + { + b.Background = normalBackground; + b.BorderBrush = cardBorder; + } + hoverLabel.Visibility = Visibility.Collapsed; + }; + } foreach (var preset in presets) { @@ -12102,34 +12130,38 @@ public partial class ChatWindow : Window var border = new Border { - Background = TryFindResource("ItemBackground") as Brush ?? Brushes.Transparent, + Background = cardBackground, + BorderBrush = cardBorder, + BorderThickness = new Thickness(1), CornerRadius = new CornerRadius(14), - Padding = new Thickness(14, 14, 14, 14), - Margin = new Thickness(6, 6, 6, 10), + Padding = new Thickness(14, 14, 14, 12), + Margin = new Thickness(6, 6, 6, 8), Cursor = Cursors.Hand, - Width = 124, - Height = 116, + Width = 132, + Height = 110, ClipToBounds = true, - RenderTransformOrigin = new Point(0.5, 0.5), - RenderTransform = new ScaleTransform(1, 1), }; - var stack = new StackPanel { HorizontalAlignment = HorizontalAlignment.Center }; + var contentGrid = new Grid(); + var stack = new StackPanel + { + HorizontalAlignment = HorizontalAlignment.Center, + VerticalAlignment = VerticalAlignment.Center, + }; - // 아이콘 컨테이너 (원형 배경 + 펄스 애니메이션) var iconCircle = new Border { - Width = 40, Height = 40, - CornerRadius = new CornerRadius(20), + Width = 42, Height = 42, + CornerRadius = new CornerRadius(21), Background = new SolidColorBrush(((SolidColorBrush)btnColor).Color) { Opacity = 0.15 }, HorizontalAlignment = HorizontalAlignment.Center, - Margin = new Thickness(0, 0, 0, 12), + Margin = new Thickness(0, 0, 0, 10), }; var iconTb = new TextBlock { Text = preset.Symbol, FontFamily = new FontFamily("Segoe MDL2 Assets"), - FontSize = 18, + FontSize = 18.5, Foreground = btnColor, HorizontalAlignment = HorizontalAlignment.Center, VerticalAlignment = VerticalAlignment.Center, @@ -12137,33 +12169,46 @@ public partial class ChatWindow : Window iconCircle.Child = iconTb; stack.Children.Add(iconCircle); - // 제목 stack.Children.Add(new TextBlock { Text = preset.Label, - FontSize = 13, FontWeight = FontWeights.SemiBold, - Foreground = TryFindResource("PrimaryText") as Brush ?? Brushes.White, + FontSize = 14, + FontWeight = FontWeights.SemiBold, + Foreground = primaryText, HorizontalAlignment = HorizontalAlignment.Center, + TextAlignment = TextAlignment.Center, + TextWrapping = TextWrapping.Wrap, + MaxWidth = 98, }); - // 설명 - stack.Children.Add(new TextBlock + var hoverLabel = new Border { - Text = preset.Description, - FontSize = 9, TextWrapping = TextWrapping.Wrap, - TextTrimming = TextTrimming.CharacterEllipsis, - MaxHeight = 32, - Foreground = TryFindResource("SecondaryText") as Brush ?? Brushes.Gray, - HorizontalAlignment = HorizontalAlignment.Center, - Margin = new Thickness(0, 2, 0, 0), - TextAlignment = TextAlignment.Center, - }); + Background = TryFindResource("LauncherBackground") as Brush ?? Brushes.White, + BorderBrush = cardBorder, + BorderThickness = new Thickness(1), + CornerRadius = new CornerRadius(8), + Padding = new Thickness(8, 4, 8, 4), + Margin = new Thickness(8, 0, 8, 6), + VerticalAlignment = VerticalAlignment.Bottom, + HorizontalAlignment = HorizontalAlignment.Stretch, + Visibility = Visibility.Collapsed, + IsHitTestVisible = false, + Child = new TextBlock + { + Text = preset.Description, + FontSize = 10.5, + TextWrapping = TextWrapping.Wrap, + TextTrimming = TextTrimming.CharacterEllipsis, + MaxHeight = 30, + Foreground = secondaryText, + TextAlignment = TextAlignment.Center, + } + }; // 커스텀 프리셋: 좌측 상단 뱃지 if (capturedPreset.IsCustom) { - var grid = new Grid(); - grid.Children.Add(stack); + contentGrid.Children.Add(stack); var badge = new Border { Width = 16, Height = 16, @@ -12183,33 +12228,17 @@ public partial class ChatWindow : Window HorizontalAlignment = HorizontalAlignment.Center, VerticalAlignment = VerticalAlignment.Center, }; - grid.Children.Add(badge); - border.Child = grid; + contentGrid.Children.Add(badge); } else { - border.Child = stack; + contentGrid.Children.Add(stack); } - // 호버 애니메이션 — 스케일 1.05x + 밝기 변경 - var hoverBg = TryFindResource("ItemHoverBackground") as Brush ?? Brushes.Transparent; - var normalBg = TryFindResource("ItemBackground") as Brush ?? Brushes.Transparent; - border.MouseEnter += (s, _) => - { - if (s is Border b && b.RenderTransform is ScaleTransform st) - { - st.ScaleX = 1.03; st.ScaleY = 1.03; - b.Background = hoverBg; - } - }; - border.MouseLeave += (s, _) => - { - if (s is Border b && b.RenderTransform is ScaleTransform st) - { - st.ScaleX = 1.0; st.ScaleY = 1.0; - b.Background = normalBg; - } - }; + contentGrid.Children.Add(hoverLabel); + border.Child = contentGrid; + border.ToolTip = preset.Description; + AttachTopicCardHover(border, hoverLabel, cardBackground, cardHoverBackground); // 클릭 → 해당 주제로 새 대화 시작 border.MouseLeftButtonDown += (_, _) => SelectTopic(capturedPreset); @@ -12232,33 +12261,38 @@ public partial class ChatWindow : Window var etcColor = BrushFromHex("#6B7280"); // 회색 var etcBorder = new Border { - Background = TryFindResource("ItemBackground") as Brush ?? Brushes.Transparent, + Background = cardBackground, + BorderBrush = cardBorder, + BorderThickness = new Thickness(1), CornerRadius = new CornerRadius(14), - Padding = new Thickness(14, 14, 14, 14), - Margin = new Thickness(6, 6, 6, 10), + Padding = new Thickness(14, 14, 14, 12), + Margin = new Thickness(6, 6, 6, 8), Cursor = Cursors.Hand, - Width = 124, - Height = 116, + Width = 132, + Height = 110, ClipToBounds = true, - RenderTransformOrigin = new Point(0.5, 0.5), - RenderTransform = new ScaleTransform(1, 1), }; - var etcStack = new StackPanel { HorizontalAlignment = HorizontalAlignment.Center }; + var etcGrid = new Grid(); + var etcStack = new StackPanel + { + HorizontalAlignment = HorizontalAlignment.Center, + VerticalAlignment = VerticalAlignment.Center, + }; var etcIconCircle = new Border { - Width = 40, Height = 40, - CornerRadius = new CornerRadius(20), + Width = 42, Height = 42, + CornerRadius = new CornerRadius(21), Background = new SolidColorBrush(((SolidColorBrush)etcColor).Color) { Opacity = 0.15 }, HorizontalAlignment = HorizontalAlignment.Center, - Margin = new Thickness(0, 0, 0, 12), + Margin = new Thickness(0, 0, 0, 10), }; etcIconCircle.Child = new TextBlock { Text = "\uE70F", // Edit 아이콘 FontFamily = new FontFamily("Segoe MDL2 Assets"), - FontSize = 18, + FontSize = 18.5, Foreground = etcColor, HorizontalAlignment = HorizontalAlignment.Center, VerticalAlignment = VerticalAlignment.Center, @@ -12268,37 +12302,42 @@ public partial class ChatWindow : Window etcStack.Children.Add(new TextBlock { Text = "기타", - FontSize = 13, FontWeight = FontWeights.SemiBold, - Foreground = TryFindResource("PrimaryText") as Brush ?? Brushes.White, + FontSize = 14, + FontWeight = FontWeights.SemiBold, + Foreground = primaryText, HorizontalAlignment = HorizontalAlignment.Center, - }); - etcStack.Children.Add(new TextBlock - { - Text = "프리셋 없이 자유롭게 대화합니다", - FontSize = 9, TextWrapping = TextWrapping.Wrap, - TextTrimming = TextTrimming.CharacterEllipsis, - MaxHeight = 32, - Foreground = TryFindResource("SecondaryText") as Brush ?? Brushes.Gray, - HorizontalAlignment = HorizontalAlignment.Center, - Margin = new Thickness(0, 2, 0, 0), TextAlignment = TextAlignment.Center, }); - - etcBorder.Child = etcStack; - - var hoverBg2 = TryFindResource("ItemHoverBackground") as Brush ?? Brushes.Transparent; - var normalBg2 = TryFindResource("ItemBackground") as Brush ?? Brushes.Transparent; - etcBorder.MouseEnter += (s, _) => + var etcHoverLabel = new Border { - if (s is Border b && b.RenderTransform is ScaleTransform st) - { st.ScaleX = 1.03; st.ScaleY = 1.03; b.Background = hoverBg2; } - }; - etcBorder.MouseLeave += (s, _) => - { - if (s is Border b && b.RenderTransform is ScaleTransform st) - { st.ScaleX = 1.0; st.ScaleY = 1.0; b.Background = normalBg2; } + Background = TryFindResource("LauncherBackground") as Brush ?? Brushes.White, + BorderBrush = cardBorder, + BorderThickness = new Thickness(1), + CornerRadius = new CornerRadius(8), + Padding = new Thickness(8, 4, 8, 4), + Margin = new Thickness(8, 0, 8, 6), + VerticalAlignment = VerticalAlignment.Bottom, + HorizontalAlignment = HorizontalAlignment.Stretch, + Visibility = Visibility.Collapsed, + IsHitTestVisible = false, + Child = new TextBlock + { + Text = "프리셋 없이 자유롭게 대화합니다", + FontSize = 10.5, + TextWrapping = TextWrapping.Wrap, + TextTrimming = TextTrimming.CharacterEllipsis, + MaxHeight = 30, + Foreground = secondaryText, + TextAlignment = TextAlignment.Center, + } }; + etcGrid.Children.Add(etcStack); + etcGrid.Children.Add(etcHoverLabel); + etcBorder.Child = etcGrid; + etcBorder.ToolTip = "프리셋 없이 자유롭게 대화합니다"; + AttachTopicCardHover(etcBorder, etcHoverLabel, cardBackground, cardHoverBackground); + etcBorder.MouseLeftButtonDown += (_, _) => { EmptyState.Visibility = Visibility.Collapsed; @@ -12313,23 +12352,18 @@ public partial class ChatWindow : Window var addBorder = new Border { Background = Brushes.Transparent, + BorderBrush = cardBorder, + BorderThickness = new Thickness(1), CornerRadius = new CornerRadius(14), - Padding = new Thickness(14, 14, 14, 14), - Margin = new Thickness(6, 6, 6, 10), + Padding = new Thickness(14, 14, 14, 12), + Margin = new Thickness(6, 6, 6, 8), Cursor = Cursors.Hand, - Width = 124, Height = 116, + Width = 132, + Height = 110, ClipToBounds = true, - BorderBrush = TryFindResource("BorderColor") as Brush ?? Brushes.Gray, - BorderThickness = new Thickness(1.5), - RenderTransformOrigin = new Point(0.5, 0.5), - RenderTransform = new ScaleTransform(1, 1), }; - // 점선 효과를 위한 Dashes - if (addBorder.BorderBrush is SolidColorBrush scb) - { - var dashPen = new Pen(scb, 1.5) { DashStyle = DashStyles.Dash }; - } + var addGrid = new Grid(); var addStack = new StackPanel { HorizontalAlignment = HorizontalAlignment.Center, VerticalAlignment = VerticalAlignment.Center }; // + 아이콘 @@ -12338,33 +12372,50 @@ public partial class ChatWindow : Window Text = "\uE710", FontFamily = new FontFamily("Segoe MDL2 Assets"), FontSize = 24, - Foreground = TryFindResource("SecondaryText") as Brush ?? Brushes.Gray, + Foreground = secondaryText, HorizontalAlignment = HorizontalAlignment.Center, - Margin = new Thickness(0, 8, 0, 8), + Margin = new Thickness(0, 10, 0, 8), }; addStack.Children.Add(plusIcon); addStack.Children.Add(new TextBlock { Text = "프리셋 추가", - FontSize = 12, - Foreground = TryFindResource("SecondaryText") as Brush ?? Brushes.Gray, + FontSize = 13, + FontWeight = FontWeights.SemiBold, + Foreground = secondaryText, HorizontalAlignment = HorizontalAlignment.Center, }); - addBorder.Child = addStack; + var addHoverLabel = new Border + { + Background = TryFindResource("LauncherBackground") as Brush ?? Brushes.White, + BorderBrush = cardBorder, + BorderThickness = new Thickness(1), + CornerRadius = new CornerRadius(8), + Padding = new Thickness(8, 4, 8, 4), + Margin = new Thickness(8, 0, 8, 6), + VerticalAlignment = VerticalAlignment.Bottom, + HorizontalAlignment = HorizontalAlignment.Stretch, + Visibility = Visibility.Collapsed, + IsHitTestVisible = false, + Child = new TextBlock + { + Text = "새 작업 유형 카드를 직접 추가합니다", + FontSize = 10.5, + TextWrapping = TextWrapping.Wrap, + TextTrimming = TextTrimming.CharacterEllipsis, + MaxHeight = 30, + Foreground = secondaryText, + TextAlignment = TextAlignment.Center, + } + }; - var hoverBg3 = TryFindResource("ItemHoverBackground") as Brush ?? Brushes.Transparent; - addBorder.MouseEnter += (s, _) => - { - if (s is Border b && b.RenderTransform is ScaleTransform st) - { st.ScaleX = 1.03; st.ScaleY = 1.03; b.Background = hoverBg3; } - }; - addBorder.MouseLeave += (s, _) => - { - if (s is Border b && b.RenderTransform is ScaleTransform st) - { st.ScaleX = 1.0; st.ScaleY = 1.0; b.Background = Brushes.Transparent; } - }; + addGrid.Children.Add(addStack); + addGrid.Children.Add(addHoverLabel); + addBorder.Child = addGrid; + addBorder.ToolTip = "새 작업 유형 카드를 직접 추가합니다"; + AttachTopicCardHover(addBorder, addHoverLabel, Brushes.Transparent, cardHoverBackground); addBorder.MouseLeftButtonDown += (_, _) => ShowCustomPresetDialog(); TopicButtonPanel.Children.Add(addBorder); }