Quellcode durchsuchen

Polish schedule header controls by reducing the refresh button footprint and keeping it perfectly circular.

Add consistent full-surface hover styling for both the refresh button and filter dropdown so interactive states feel unified.

Made-with: Cursor
huzaifahayat12 vor 1 Woche
Ursprung
Commit
f22acc287b
1 geänderte Dateien mit 70 neuen und 7 gelöschten Zeilen
  1. 70 7
      meetings_app/ViewController.swift

+ 70 - 7
meetings_app/ViewController.swift

@@ -2520,11 +2520,14 @@ private extension ViewController {
2520 2520
     }
2521 2521
 
2522 2522
     private func makeScheduleFilterDropdown() -> NSPopUpButton {
2523
-        let button = NSPopUpButton(frame: .zero, pullsDown: false)
2523
+        let button = HoverPopUpButton(frame: .zero, pullsDown: false)
2524 2524
         button.translatesAutoresizingMaskIntoConstraints = false
2525 2525
         button.autoenablesItems = false
2526
+        button.isBordered = false
2527
+        button.bezelStyle = .regularSquare
2526 2528
         button.wantsLayer = true
2527 2529
         button.layer?.cornerRadius = 8
2530
+        button.layer?.masksToBounds = true
2528 2531
         button.layer?.backgroundColor = palette.inputBackground.cgColor
2529 2532
         button.layer?.borderColor = palette.inputBorder.cgColor
2530 2533
         button.layer?.borderWidth = 1
@@ -2545,6 +2548,17 @@ private extension ViewController {
2545 2548
             }
2546 2549
         }
2547 2550
 
2551
+        let baseColor = palette.inputBackground
2552
+        let baseBorder = palette.inputBorder
2553
+        let hoverBlend = darkModeEnabled ? NSColor.white : NSColor.black
2554
+        let hoverColor = baseColor.blended(withFraction: 0.10, of: hoverBlend) ?? baseColor
2555
+        let hoverBorder = baseBorder.blended(withFraction: 0.16, of: hoverBlend) ?? baseBorder
2556
+        button.onHoverChanged = { [weak button] hovering in
2557
+            button?.layer?.backgroundColor = (hovering ? hoverColor : baseColor).cgColor
2558
+            button?.layer?.borderColor = (hovering ? hoverBorder : baseBorder).cgColor
2559
+        }
2560
+        button.onHoverChanged?(false)
2561
+
2548 2562
         scheduleFilterDropdown = button
2549 2563
         return button
2550 2564
     }
@@ -2573,7 +2587,7 @@ private extension ViewController {
2573 2587
         button.isBordered = false
2574 2588
         button.bezelStyle = .regularSquare
2575 2589
         button.wantsLayer = true
2576
-        button.layer?.cornerRadius = 21
2590
+        button.layer?.cornerRadius = 16
2577 2591
         button.layer?.borderWidth = 1
2578 2592
         button.font = NSFont.systemFont(ofSize: 14, weight: .semibold)
2579 2593
         button.imagePosition = .imageLeading
@@ -2599,24 +2613,36 @@ private extension ViewController {
2599 2613
     }
2600 2614
 
2601 2615
     private func makeScheduleRefreshButton() -> NSButton {
2602
-        let button = NSButton(title: "", target: self, action: #selector(scheduleReloadButtonPressed(_:)))
2616
+        let diameter: CGFloat = 30
2617
+        let button = HoverButton(title: "", target: self, action: #selector(scheduleReloadButtonPressed(_:)))
2603 2618
         button.translatesAutoresizingMaskIntoConstraints = false
2604 2619
         button.isBordered = false
2605 2620
         button.bezelStyle = .regularSquare
2606 2621
         button.wantsLayer = true
2607
-        button.layer?.cornerRadius = 21
2622
+        button.layer?.cornerRadius = diameter / 2
2623
+        button.layer?.masksToBounds = true
2608 2624
         button.layer?.backgroundColor = palette.inputBackground.cgColor
2609 2625
         button.layer?.borderColor = palette.inputBorder.cgColor
2610 2626
         button.layer?.borderWidth = 1
2611 2627
         button.setButtonType(.momentaryChange)
2612 2628
         button.contentTintColor = palette.textSecondary
2613 2629
         button.image = NSImage(systemSymbolName: "arrow.clockwise", accessibilityDescription: "Refresh meetings")
2614
-        button.symbolConfiguration = NSImage.SymbolConfiguration(pointSize: 18, weight: .semibold)
2630
+        button.symbolConfiguration = NSImage.SymbolConfiguration(pointSize: 14, weight: .semibold)
2615 2631
         button.imagePosition = .imageOnly
2616 2632
         button.imageScaling = .scaleProportionallyDown
2617 2633
         button.focusRingType = .none
2618
-        button.heightAnchor.constraint(equalToConstant: 42).isActive = true
2619
-        button.widthAnchor.constraint(equalToConstant: 42).isActive = true
2634
+        button.heightAnchor.constraint(equalToConstant: diameter).isActive = true
2635
+        button.widthAnchor.constraint(equalToConstant: diameter).isActive = true
2636
+        let baseColor = palette.inputBackground
2637
+        let baseBorder = palette.inputBorder
2638
+        let hoverBlend = darkModeEnabled ? NSColor.white : NSColor.black
2639
+        let hoverColor = baseColor.blended(withFraction: 0.10, of: hoverBlend) ?? baseColor
2640
+        let hoverBorder = baseBorder.blended(withFraction: 0.16, of: hoverBlend) ?? baseBorder
2641
+        button.onHoverChanged = { [weak button] hovering in
2642
+            button?.layer?.backgroundColor = (hovering ? hoverColor : baseColor).cgColor
2643
+            button?.layer?.borderColor = (hovering ? hoverBorder : baseBorder).cgColor
2644
+        }
2645
+        button.onHoverChanged?(false)
2620 2646
         return button
2621 2647
     }
2622 2648
 
@@ -3111,6 +3137,43 @@ private final class HoverButton: NSButton {
3111 3137
     }
3112 3138
 }
3113 3139
 
3140
+private final class HoverPopUpButton: NSPopUpButton {
3141
+    var onHoverChanged: ((Bool) -> Void)?
3142
+
3143
+    private var trackingAreaRef: NSTrackingArea?
3144
+    private var isHovering = false {
3145
+        didSet {
3146
+            guard isHovering != oldValue else { return }
3147
+            onHoverChanged?(isHovering)
3148
+        }
3149
+    }
3150
+
3151
+    override func updateTrackingAreas() {
3152
+        super.updateTrackingAreas()
3153
+        if let trackingAreaRef {
3154
+            removeTrackingArea(trackingAreaRef)
3155
+        }
3156
+        let options: NSTrackingArea.Options = [
3157
+            .activeInKeyWindow,
3158
+            .inVisibleRect,
3159
+            .mouseEnteredAndExited
3160
+        ]
3161
+        let tracking = NSTrackingArea(rect: bounds, options: options, owner: self, userInfo: nil)
3162
+        addTrackingArea(tracking)
3163
+        trackingAreaRef = tracking
3164
+    }
3165
+
3166
+    override func mouseEntered(with event: NSEvent) {
3167
+        super.mouseEntered(with: event)
3168
+        isHovering = true
3169
+    }
3170
+
3171
+    override func mouseExited(with event: NSEvent) {
3172
+        super.mouseExited(with: event)
3173
+        isHovering = false
3174
+    }
3175
+}
3176
+
3114 3177
 private func circularNSImage(_ image: NSImage, diameter: CGFloat) -> NSImage {
3115 3178
     let size = NSSize(width: diameter, height: diameter)
3116 3179
     let result = NSImage(size: size)