ux: float close button outside bubble, stronger shadow

This commit is contained in:
Peter Steinberger
2025-12-08 22:11:38 +01:00
parent c5b073702c
commit 33b54f3d0c

View File

@@ -91,6 +91,8 @@ final class VoiceWakeOverlayController: ObservableObject {
func sendNow(sendChime: VoiceWakeChime = .none) { func sendNow(sendChime: VoiceWakeChime = .none) {
self.autoSendTask?.cancel() self.autoSendTask?.cancel()
self.autoSendTask = nil
if self.model.isSending { return }
self.model.isEditing = false self.model.isEditing = false
guard let forwardConfig, forwardConfig.enabled else { guard let forwardConfig, forwardConfig.enabled else {
self.dismiss(reason: .explicit) self.dismiss(reason: .explicit)
@@ -268,6 +270,7 @@ final class VoiceWakeOverlayController: ObservableObject {
await MainActor.run { await MainActor.run {
guard let self else { return } guard let self else { return }
self.sendNow(sendChime: sendChime) self.sendNow(sendChime: sendChime)
self.autoSendTask = nil
} }
} }
} }
@@ -376,12 +379,9 @@ private struct VoiceWakeOverlayView: View {
in: RoundedRectangle(cornerRadius: 12, style: .continuous)) in: RoundedRectangle(cornerRadius: 12, style: .continuous))
.onHover { self.isHovering = $0 } .onHover { self.isHovering = $0 }
if self.controller.model.isEditing || self.isHovering { // Close button rendered above and outside the clipped bubble
CloseHoverButton(onClose: { CloseButtonOverlay(isVisible: self.controller.model.isEditing || self.isHovering) {
self.controller.cancelEditingAndDismiss() self.controller.cancelEditingAndDismiss()
})
.offset(x: -8, y: -8)
.transition(.opacity)
} }
} }
.onAppear { self.textFocused = false } .onAppear { self.textFocused = false }
@@ -535,6 +535,8 @@ private struct VibrantLabelView: NSViewRepresentable {
label.attributedStringValue = self.attributed.strippingForegroundColor() label.attributedStringValue = self.attributed.strippingForegroundColor()
} }
}
private final class ClickCatcher: NSView { private final class ClickCatcher: NSView {
let onTap: () -> Void let onTap: () -> Void
init(onTap: @escaping () -> Void) { init(onTap: @escaping () -> Void) {
@@ -570,6 +572,22 @@ private struct CloseHoverButton: View {
.padding(6) .padding(6)
} }
} }
private struct CloseButtonOverlay: View {
var isVisible: Bool
var onClose: () -> Void
var body: some View {
Group {
if isVisible {
CloseHoverButton(onClose: onClose)
.offset(x: -12, y: -12)
.transition(.opacity)
}
}
.allowsHitTesting(isVisible)
}
}
} }
private extension NSAttributedString { private extension NSAttributedString {