Przeglądaj źródła

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 1 tydzień temu
rodzic
commit
f22acc287b
1 zmienionych plików z 70 dodań i 7 usunięć
  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
     private func makeScheduleFilterDropdown() -> NSPopUpButton {
2522
     private func makeScheduleFilterDropdown() -> NSPopUpButton {
2523
-        let button = NSPopUpButton(frame: .zero, pullsDown: false)
2523
+        let button = HoverPopUpButton(frame: .zero, pullsDown: false)
2524
         button.translatesAutoresizingMaskIntoConstraints = false
2524
         button.translatesAutoresizingMaskIntoConstraints = false
2525
         button.autoenablesItems = false
2525
         button.autoenablesItems = false
2526
+        button.isBordered = false
2527
+        button.bezelStyle = .regularSquare
2526
         button.wantsLayer = true
2528
         button.wantsLayer = true
2527
         button.layer?.cornerRadius = 8
2529
         button.layer?.cornerRadius = 8
2530
+        button.layer?.masksToBounds = true
2528
         button.layer?.backgroundColor = palette.inputBackground.cgColor
2531
         button.layer?.backgroundColor = palette.inputBackground.cgColor
2529
         button.layer?.borderColor = palette.inputBorder.cgColor
2532
         button.layer?.borderColor = palette.inputBorder.cgColor
2530
         button.layer?.borderWidth = 1
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
         scheduleFilterDropdown = button
2562
         scheduleFilterDropdown = button
2549
         return button
2563
         return button
2550
     }
2564
     }
@@ -2573,7 +2587,7 @@ private extension ViewController {
2573
         button.isBordered = false
2587
         button.isBordered = false
2574
         button.bezelStyle = .regularSquare
2588
         button.bezelStyle = .regularSquare
2575
         button.wantsLayer = true
2589
         button.wantsLayer = true
2576
-        button.layer?.cornerRadius = 21
2590
+        button.layer?.cornerRadius = 16
2577
         button.layer?.borderWidth = 1
2591
         button.layer?.borderWidth = 1
2578
         button.font = NSFont.systemFont(ofSize: 14, weight: .semibold)
2592
         button.font = NSFont.systemFont(ofSize: 14, weight: .semibold)
2579
         button.imagePosition = .imageLeading
2593
         button.imagePosition = .imageLeading
@@ -2599,24 +2613,36 @@ private extension ViewController {
2599
     }
2613
     }
2600
 
2614
 
2601
     private func makeScheduleRefreshButton() -> NSButton {
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
         button.translatesAutoresizingMaskIntoConstraints = false
2618
         button.translatesAutoresizingMaskIntoConstraints = false
2604
         button.isBordered = false
2619
         button.isBordered = false
2605
         button.bezelStyle = .regularSquare
2620
         button.bezelStyle = .regularSquare
2606
         button.wantsLayer = true
2621
         button.wantsLayer = true
2607
-        button.layer?.cornerRadius = 21
2622
+        button.layer?.cornerRadius = diameter / 2
2623
+        button.layer?.masksToBounds = true
2608
         button.layer?.backgroundColor = palette.inputBackground.cgColor
2624
         button.layer?.backgroundColor = palette.inputBackground.cgColor
2609
         button.layer?.borderColor = palette.inputBorder.cgColor
2625
         button.layer?.borderColor = palette.inputBorder.cgColor
2610
         button.layer?.borderWidth = 1
2626
         button.layer?.borderWidth = 1
2611
         button.setButtonType(.momentaryChange)
2627
         button.setButtonType(.momentaryChange)
2612
         button.contentTintColor = palette.textSecondary
2628
         button.contentTintColor = palette.textSecondary
2613
         button.image = NSImage(systemSymbolName: "arrow.clockwise", accessibilityDescription: "Refresh meetings")
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
         button.imagePosition = .imageOnly
2631
         button.imagePosition = .imageOnly
2616
         button.imageScaling = .scaleProportionallyDown
2632
         button.imageScaling = .scaleProportionallyDown
2617
         button.focusRingType = .none
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
         return button
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
 private func circularNSImage(_ image: NSImage, diameter: CGFloat) -> NSImage {
3177
 private func circularNSImage(_ image: NSImage, diameter: CGFloat) -> NSImage {
3115
     let size = NSSize(width: diameter, height: diameter)
3178
     let size = NSSize(width: diameter, height: diameter)
3116
     let result = NSImage(size: size)
3179
     let result = NSImage(size: size)