소스 검색

Remove location field from dashboard search bar

Drop the divider, map pin, and location text field so the bar is
keywords plus Find jobs only; let the keyword field expand to fill width.

Co-authored-by: Cursor <cursoragent@cursor.com>
AhtashamShahzad1 2 달 전
부모
커밋
a3ecd2606f
1개의 변경된 파일75개의 추가작업 그리고 36개의 파일을 삭제
  1. 75 36
      App for Indeed/Views/DashboardView.swift

+ 75 - 36
App for Indeed/Views/DashboardView.swift

@@ -4,6 +4,7 @@
 //
 
 import Cocoa
+import QuartzCore
 
 final class DashboardView: NSView, NSTextFieldDelegate {
     /// Indeed.com-inspired neutrals and brand blue (white surfaces, `#2557a7` accent, `#2d2d2d` / `#767676` text, `#d4d2d0` borders).
@@ -29,6 +30,8 @@ final class DashboardView: NSView, NSTextFieldDelegate {
         static let proAccent = NSColor(srgbRed: 37 / 255, green: 87 / 255, blue: 167 / 255, alpha: 1)
         static let proCTABackground = NSColor(srgbRed: 37 / 255, green: 87 / 255, blue: 167 / 255, alpha: 1)
         static let proCTAText = NSColor(srgbRed: 1, green: 1, blue: 1, alpha: 1)
+        /// Slightly lighter blue for the top of the search-bar “Find jobs” pill (reads less flat than a solid fill).
+        static let findJobsCTAHighlight = NSColor(srgbRed: 54 / 255, green: 110 / 255, blue: 198 / 255, alpha: 1)
     }
 
     private let contentStack = NSStackView()
@@ -43,10 +46,10 @@ final class DashboardView: NSView, NSTextFieldDelegate {
     private let searchCard = NSView()
     private let jobSearchIcon = NSImageView()
     private let jobKeywordsField = NSTextField()
-    private let searchDivider = NSView()
-    private let locationIcon = NSImageView()
-    private let locationField = NSTextField()
     private let findJobsButton = NSButton()
+    private let findJobsCTAHost = NSView()
+    private let findJobsCTAChrome = NSView()
+    private var findJobsCTAGradientLayer: CAGradientLayer?
     private let scrollView = NSScrollView()
 
     private var currentSidebarItems: [SidebarItem] = []
@@ -66,6 +69,8 @@ final class DashboardView: NSView, NSTextFieldDelegate {
         super.layout()
         updateDocumentLayout()
         updateSearchBarShadowPath()
+        findJobsCTAGradientLayer?.frame = findJobsCTAChrome.bounds
+        updateFindJobsCTAShadowPath()
     }
 
     func render(_ data: DashboardData) {
@@ -257,52 +262,81 @@ final class DashboardView: NSView, NSTextFieldDelegate {
 
         configureField(jobKeywordsField, placeholder: "Job title, keywords, or company")
 
-        searchDivider.translatesAutoresizingMaskIntoConstraints = false
-        searchDivider.wantsLayer = true
-        searchDivider.layer?.backgroundColor = Theme.border.cgColor
-
-        locationIcon.translatesAutoresizingMaskIntoConstraints = false
-        locationIcon.symbolConfiguration = NSImage.SymbolConfiguration(pointSize: 15, weight: .medium)
-        locationIcon.image = NSImage(systemSymbolName: "mappin.and.ellipse", accessibilityDescription: "Location")
-        locationIcon.contentTintColor = Theme.primaryText
+        let ctaHeight: CGFloat = 42
+        let ctaCorner = ctaHeight / 2
+
+        findJobsCTAHost.translatesAutoresizingMaskIntoConstraints = false
+        findJobsCTAHost.wantsLayer = true
+        findJobsCTAHost.layer?.masksToBounds = false
+        findJobsCTAHost.layer?.shadowColor = NSColor.black.cgColor
+        findJobsCTAHost.layer?.shadowOpacity = 0.16
+        findJobsCTAHost.layer?.shadowOffset = CGSize(width: 0, height: 2)
+        findJobsCTAHost.layer?.shadowRadius = 6
+
+        findJobsCTAChrome.translatesAutoresizingMaskIntoConstraints = false
+        findJobsCTAChrome.wantsLayer = true
+        findJobsCTAChrome.layer?.masksToBounds = true
+        findJobsCTAChrome.layer?.cornerRadius = ctaCorner
+        if #available(macOS 11.0, *) {
+            findJobsCTAChrome.layer?.cornerCurve = .continuous
+        }
 
-        configureField(locationField, placeholder: "City, state, zip code, or \"remote\"")
+        let gradient = CAGradientLayer()
+        gradient.colors = [Theme.findJobsCTAHighlight.cgColor, Theme.brandBlue.cgColor]
+        gradient.startPoint = CGPoint(x: 0.5, y: 1)
+        gradient.endPoint = CGPoint(x: 0.5, y: 0)
+        findJobsCTAChrome.layer?.addSublayer(gradient)
+        findJobsCTAGradientLayer = gradient
 
         findJobsButton.translatesAutoresizingMaskIntoConstraints = false
-        findJobsButton.title = "Find jobs"
+        findJobsButton.title = ""
+        findJobsButton.attributedTitle = NSAttributedString(
+            string: "Find jobs",
+            attributes: [
+                .font: NSFont.systemFont(ofSize: 14, weight: .semibold),
+                .foregroundColor: Theme.proCTAText,
+                .kern: 0.35
+            ]
+        )
         findJobsButton.isBordered = false
         findJobsButton.bezelStyle = .rounded
-        findJobsButton.font = .systemFont(ofSize: 14, weight: .bold)
-        findJobsButton.contentTintColor = Theme.proCTAText
         findJobsButton.wantsLayer = true
-        findJobsButton.layer?.backgroundColor = Theme.brandBlue.cgColor
-        findJobsButton.layer?.cornerRadius = 10
+        findJobsButton.layer?.backgroundColor = NSColor.clear.cgColor
+        findJobsButton.focusRingType = .none
         findJobsButton.target = self
         findJobsButton.action = #selector(didSubmitSearch)
         findJobsButton.setContentHuggingPriority(.required, for: .horizontal)
         findJobsButton.setContentCompressionResistancePriority(.required, for: .horizontal)
 
+        findJobsCTAHost.addSubview(findJobsCTAChrome)
+        findJobsCTAHost.addSubview(findJobsButton)
+        NSLayoutConstraint.activate([
+            findJobsCTAChrome.leadingAnchor.constraint(equalTo: findJobsCTAHost.leadingAnchor),
+            findJobsCTAChrome.trailingAnchor.constraint(equalTo: findJobsCTAHost.trailingAnchor),
+            findJobsCTAChrome.topAnchor.constraint(equalTo: findJobsCTAHost.topAnchor),
+            findJobsCTAChrome.bottomAnchor.constraint(equalTo: findJobsCTAHost.bottomAnchor),
+
+            findJobsButton.leadingAnchor.constraint(equalTo: findJobsCTAHost.leadingAnchor, constant: 14),
+            findJobsButton.trailingAnchor.constraint(equalTo: findJobsCTAHost.trailingAnchor, constant: -14),
+            findJobsButton.topAnchor.constraint(equalTo: findJobsCTAHost.topAnchor),
+            findJobsButton.bottomAnchor.constraint(equalTo: findJobsCTAHost.bottomAnchor)
+        ])
+
         let keywordsStack = NSStackView(views: [jobSearchIcon, jobKeywordsField])
         keywordsStack.orientation = .horizontal
         keywordsStack.spacing = 10
         keywordsStack.alignment = .centerY
         keywordsStack.translatesAutoresizingMaskIntoConstraints = false
         keywordsStack.edgeInsets = NSEdgeInsets(top: 0, left: 18, bottom: 0, right: 10)
+        keywordsStack.setContentHuggingPriority(.defaultLow, for: .horizontal)
 
-        let locationStack = NSStackView(views: [locationIcon, locationField])
-        locationStack.orientation = .horizontal
-        locationStack.spacing = 10
-        locationStack.alignment = .centerY
-        locationStack.translatesAutoresizingMaskIntoConstraints = false
-        locationStack.edgeInsets = NSEdgeInsets(top: 0, left: 10, bottom: 0, right: 10)
-
-        let row = NSStackView(views: [keywordsStack, searchDivider, locationStack, findJobsButton])
+        let row = NSStackView(views: [keywordsStack, findJobsCTAHost])
         row.orientation = .horizontal
         row.spacing = 0
         row.alignment = .centerY
         row.distribution = .fill
         row.translatesAutoresizingMaskIntoConstraints = false
-        row.edgeInsets = NSEdgeInsets(top: 0, left: 0, bottom: 0, right: 10)
+        row.edgeInsets = NSEdgeInsets(top: 0, left: 0, bottom: 0, right: 7)
 
         searchCard.addSubview(row)
 
@@ -321,19 +355,24 @@ final class DashboardView: NSView, NSTextFieldDelegate {
 
             jobSearchIcon.widthAnchor.constraint(equalToConstant: 18),
             jobSearchIcon.heightAnchor.constraint(equalToConstant: 18),
-            locationIcon.widthAnchor.constraint(equalToConstant: 18),
-            locationIcon.heightAnchor.constraint(equalToConstant: 18),
-
-            searchDivider.widthAnchor.constraint(equalToConstant: 1),
-            searchDivider.heightAnchor.constraint(equalToConstant: 30),
 
-            keywordsStack.widthAnchor.constraint(equalTo: locationStack.widthAnchor),
-
-            findJobsButton.heightAnchor.constraint(equalToConstant: 40),
-            findJobsButton.widthAnchor.constraint(greaterThanOrEqualToConstant: 108)
+            findJobsCTAHost.heightAnchor.constraint(equalToConstant: ctaHeight),
+            findJobsCTAHost.widthAnchor.constraint(greaterThanOrEqualToConstant: 112)
         ])
     }
 
+    private func updateFindJobsCTAShadowPath() {
+        guard findJobsCTAHost.bounds.width > 0, findJobsCTAHost.bounds.height > 0 else { return }
+        let r = findJobsCTAHost.bounds
+        let radius = min(r.height / 2, r.width / 2)
+        findJobsCTAHost.layer?.shadowPath = CGPath(
+            roundedRect: r,
+            cornerWidth: radius,
+            cornerHeight: radius,
+            transform: nil
+        )
+    }
+
     private func updateSearchBarShadowPath() {
         guard searchBarShadowHost.bounds.width > 0, searchBarShadowHost.bounds.height > 0 else { return }
         let r = searchBarShadowHost.bounds
@@ -360,7 +399,7 @@ final class DashboardView: NSView, NSTextFieldDelegate {
 
     private func applySearchFieldInsertionPoint(_ object: Any?) {
         guard let field = object as? NSTextField,
-              field === jobKeywordsField || field === locationField,
+              field === jobKeywordsField,
               let textView = field.window?.fieldEditor(true, for: field) as? NSTextView else { return }
         textView.insertionPointColor = Theme.primaryText
     }