diff --git a/clients/macos/vellum-assistant/Features/Chat/AssistantProgressView.swift b/clients/macos/vellum-assistant/Features/Chat/AssistantProgressView.swift index 21025128f80..5740fa34632 100644 --- a/clients/macos/vellum-assistant/Features/Chat/AssistantProgressView.swift +++ b/clients/macos/vellum-assistant/Features/Chat/AssistantProgressView.swift @@ -901,13 +901,11 @@ private struct StepDetailRow: View { } // Title (reason-first, then skillLabel for skill_execute, then fallback) - VStack(alignment: .leading, spacing: VSpacing.xxs) { - Text(stepTitle) - .font(VFont.labelDefault) - .foregroundStyle(stepTitleColor) - .lineLimit(1) - .truncationMode(.tail) - } + Text(stepTitle) + .font(VFont.labelDefault) + .foregroundStyle(stepTitleColor) + .lineLimit(1) + .truncationMode(.tail) Spacer() @@ -970,23 +968,21 @@ private struct StepDetailRow: View { .foregroundStyle(VColor.contentTertiary) .textCase(.uppercase) - VStack(alignment: .leading, spacing: VSpacing.xs) { - if let reason = toolCall.reasonDescription, !reason.isEmpty { - Text(toolCall.actionDescription) - .font(VFont.labelDefault) - .foregroundStyle(VColor.contentSecondary) - } - Text(toolCall.friendlyName) + if let reason = toolCall.reasonDescription, !reason.isEmpty { + Text(toolCall.actionDescription) .font(VFont.labelDefault) .foregroundStyle(VColor.contentSecondary) - if !resolvedInputFull.isEmpty { - outputBlock( - text: resolvedInputFull, - attributedText: nil, - copyText: resolvedInputFull, - copyLabel: "Copy input" - ) - } + } + Text(toolCall.friendlyName) + .font(VFont.labelDefault) + .foregroundStyle(VColor.contentSecondary) + if !resolvedInputFull.isEmpty { + outputBlock( + text: resolvedInputFull, + attributedText: nil, + copyText: resolvedInputFull, + copyLabel: "Copy input" + ) } } .padding(.horizontal, VSpacing.lg) @@ -1054,7 +1050,10 @@ private struct StepDetailRow: View { outputTextView(text: text, attributedText: attributedText, isError: isError) .padding(EdgeInsets(top: VSpacing.sm, leading: VSpacing.sm, bottom: VSpacing.sm, trailing: VSpacing.sm + VSpacing.xl)) .frame(maxWidth: .infinity, alignment: .leading) - .background(VColor.surfaceOverlay.opacity(0.6)) + .background( + RoundedRectangle(cornerRadius: VRadius.sm) + .fill(VColor.surfaceOverlay.opacity(0.6)) + ) .clipShape(RoundedRectangle(cornerRadius: VRadius.sm)) .overlay( RoundedRectangle(cornerRadius: VRadius.sm) @@ -1168,20 +1167,18 @@ private struct CompactPermissionChip: View { var body: some View { HStack(spacing: VSpacing.xxs) { - Group { - switch state { - case .approved: - VIconView(.circleCheck, size: 10) - .foregroundStyle(chipColor) - case .denied: - VIconView(.circleAlert, size: 10) - .foregroundStyle(chipColor) - case .timedOut: - VIconView(.clock, size: 10) - .foregroundStyle(chipColor) - default: - EmptyView() - } + switch state { + case .approved: + VIconView(.circleCheck, size: 10) + .foregroundStyle(chipColor) + case .denied: + VIconView(.circleAlert, size: 10) + .foregroundStyle(chipColor) + case .timedOut: + VIconView(.clock, size: 10) + .foregroundStyle(chipColor) + default: + EmptyView() } Text(state == .approved || state == .denied ? label : "Timed Out") diff --git a/clients/macos/vellum-assistant/Features/Chat/ChatBubbleToolStatusView.swift b/clients/macos/vellum-assistant/Features/Chat/ChatBubbleToolStatusView.swift index 6fdb66d4ed5..1d2a3cfc6fb 100644 --- a/clients/macos/vellum-assistant/Features/Chat/ChatBubbleToolStatusView.swift +++ b/clients/macos/vellum-assistant/Features/Chat/ChatBubbleToolStatusView.swift @@ -59,14 +59,12 @@ extension ChatBubble { inlineToolCallImages(from: message.toolCalls) } else if !effectiveConfirmations.isEmpty, !inlineToolProgressRenderedInContent { // No tool display needed — only show permission chips. - VStack(alignment: .leading, spacing: 0) { - HStack(alignment: .center, spacing: VSpacing.sm) { - ForEach(Array(effectiveConfirmations.enumerated()), id: \.offset) { _, confirmation in - compactPermissionChip(confirmation) - } - Spacer() + HStack(alignment: .center, spacing: VSpacing.sm) { + ForEach(Array(effectiveConfirmations.enumerated()), id: \.offset) { _, confirmation in + compactPermissionChip(confirmation) } } + .frame(maxWidth: .infinity, alignment: .leading) .padding(.top, VSpacing.xxs) } } @@ -86,20 +84,18 @@ extension ChatBubble { let chipColor: Color = isApproved ? VColor.primaryBase : isDenied ? VColor.systemNegativeStrong : VColor.contentTertiary return HStack(spacing: VSpacing.xs) { - Group { - switch confirmation.state { - case .approved: - VIconView(.circleCheck, size: 12) - .foregroundStyle(chipColor) - case .denied: - VIconView(.circleAlert, size: 12) - .foregroundStyle(chipColor) - case .timedOut: - VIconView(.clock, size: 12) - .foregroundStyle(chipColor) - default: - EmptyView() - } + switch confirmation.state { + case .approved: + VIconView(.circleCheck, size: 12) + .foregroundStyle(chipColor) + case .denied: + VIconView(.circleAlert, size: 12) + .foregroundStyle(chipColor) + case .timedOut: + VIconView(.clock, size: 12) + .foregroundStyle(chipColor) + default: + EmptyView() } Text(isApproved || isDenied ? "\(confirmation.toolCategory)" : diff --git a/clients/macos/vellum-assistant/Features/Chat/MarkdownSegmentView.swift b/clients/macos/vellum-assistant/Features/Chat/MarkdownSegmentView.swift index 69b36c0dc58..98c62bb9dcf 100644 --- a/clients/macos/vellum-assistant/Features/Chat/MarkdownSegmentView.swift +++ b/clients/macos/vellum-assistant/Features/Chat/MarkdownSegmentView.swift @@ -826,10 +826,11 @@ private struct CodeBlockView: View, Equatable { Spacer() VCopyButton(text: code, size: .compact) .opacity(isHovered ? 1 : 0) + .allowsHitTesting(isHovered) + .accessibilityHidden(!isHovered) .animation(VAnimation.fast, value: isHovered) } - .padding(.horizontal, VSpacing.sm) - .padding(.top, VSpacing.xs) + .padding(EdgeInsets(top: VSpacing.xs, leading: VSpacing.sm, bottom: 0, trailing: VSpacing.sm)) } let codeLineCount = code.utf8.reduce(1) { $0 + ($1 == 0x0A ? 1 : 0) } @@ -869,6 +870,8 @@ private struct CodeBlockView: View, Equatable { if language == nil || language?.isEmpty == true { VCopyButton(text: code, size: .compact) .opacity(isHovered ? 1 : 0) + .allowsHitTesting(isHovered) + .accessibilityHidden(!isHovered) .animation(VAnimation.fast, value: isHovered) .padding(VSpacing.xs) }