Просмотр исходного кода

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 недель назад: 3
Родитель
Сommit
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 @@
4 4
 //
5 5
 
6 6
 import Cocoa
7
+import QuartzCore
7 8
 
8 9
 final class DashboardView: NSView, NSTextFieldDelegate {
9 10
     /// 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 {
29 30
         static let proAccent = NSColor(srgbRed: 37 / 255, green: 87 / 255, blue: 167 / 255, alpha: 1)
30 31
         static let proCTABackground = NSColor(srgbRed: 37 / 255, green: 87 / 255, blue: 167 / 255, alpha: 1)
31 32
         static let proCTAText = NSColor(srgbRed: 1, green: 1, blue: 1, alpha: 1)
33
+        /// Slightly lighter blue for the top of the search-bar “Find jobs” pill (reads less flat than a solid fill).
34
+        static let findJobsCTAHighlight = NSColor(srgbRed: 54 / 255, green: 110 / 255, blue: 198 / 255, alpha: 1)
32 35
     }
33 36
 
34 37
     private let contentStack = NSStackView()
@@ -43,10 +46,10 @@ final class DashboardView: NSView, NSTextFieldDelegate {
43 46
     private let searchCard = NSView()
44 47
     private let jobSearchIcon = NSImageView()
45 48
     private let jobKeywordsField = NSTextField()
46
-    private let searchDivider = NSView()
47
-    private let locationIcon = NSImageView()
48
-    private let locationField = NSTextField()
49 49
     private let findJobsButton = NSButton()
50
+    private let findJobsCTAHost = NSView()
51
+    private let findJobsCTAChrome = NSView()
52
+    private var findJobsCTAGradientLayer: CAGradientLayer?
50 53
     private let scrollView = NSScrollView()
51 54
 
52 55
     private var currentSidebarItems: [SidebarItem] = []
@@ -66,6 +69,8 @@ final class DashboardView: NSView, NSTextFieldDelegate {
66 69
         super.layout()
67 70
         updateDocumentLayout()
68 71
         updateSearchBarShadowPath()
72
+        findJobsCTAGradientLayer?.frame = findJobsCTAChrome.bounds
73
+        updateFindJobsCTAShadowPath()
69 74
     }
70 75
 
71 76
     func render(_ data: DashboardData) {
@@ -257,52 +262,81 @@ final class DashboardView: NSView, NSTextFieldDelegate {
257 262
 
258 263
         configureField(jobKeywordsField, placeholder: "Job title, keywords, or company")
259 264
 
260
-        searchDivider.translatesAutoresizingMaskIntoConstraints = false
261
-        searchDivider.wantsLayer = true
262
-        searchDivider.layer?.backgroundColor = Theme.border.cgColor
263
-
264
-        locationIcon.translatesAutoresizingMaskIntoConstraints = false
265
-        locationIcon.symbolConfiguration = NSImage.SymbolConfiguration(pointSize: 15, weight: .medium)
266
-        locationIcon.image = NSImage(systemSymbolName: "mappin.and.ellipse", accessibilityDescription: "Location")
267
-        locationIcon.contentTintColor = Theme.primaryText
265
+        let ctaHeight: CGFloat = 42
266
+        let ctaCorner = ctaHeight / 2
267
+
268
+        findJobsCTAHost.translatesAutoresizingMaskIntoConstraints = false
269
+        findJobsCTAHost.wantsLayer = true
270
+        findJobsCTAHost.layer?.masksToBounds = false
271
+        findJobsCTAHost.layer?.shadowColor = NSColor.black.cgColor
272
+        findJobsCTAHost.layer?.shadowOpacity = 0.16
273
+        findJobsCTAHost.layer?.shadowOffset = CGSize(width: 0, height: 2)
274
+        findJobsCTAHost.layer?.shadowRadius = 6
275
+
276
+        findJobsCTAChrome.translatesAutoresizingMaskIntoConstraints = false
277
+        findJobsCTAChrome.wantsLayer = true
278
+        findJobsCTAChrome.layer?.masksToBounds = true
279
+        findJobsCTAChrome.layer?.cornerRadius = ctaCorner
280
+        if #available(macOS 11.0, *) {
281
+            findJobsCTAChrome.layer?.cornerCurve = .continuous
282
+        }
268 283
 
269
-        configureField(locationField, placeholder: "City, state, zip code, or \"remote\"")
284
+        let gradient = CAGradientLayer()
285
+        gradient.colors = [Theme.findJobsCTAHighlight.cgColor, Theme.brandBlue.cgColor]
286
+        gradient.startPoint = CGPoint(x: 0.5, y: 1)
287
+        gradient.endPoint = CGPoint(x: 0.5, y: 0)
288
+        findJobsCTAChrome.layer?.addSublayer(gradient)
289
+        findJobsCTAGradientLayer = gradient
270 290
 
271 291
         findJobsButton.translatesAutoresizingMaskIntoConstraints = false
272
-        findJobsButton.title = "Find jobs"
292
+        findJobsButton.title = ""
293
+        findJobsButton.attributedTitle = NSAttributedString(
294
+            string: "Find jobs",
295
+            attributes: [
296
+                .font: NSFont.systemFont(ofSize: 14, weight: .semibold),
297
+                .foregroundColor: Theme.proCTAText,
298
+                .kern: 0.35
299
+            ]
300
+        )
273 301
         findJobsButton.isBordered = false
274 302
         findJobsButton.bezelStyle = .rounded
275
-        findJobsButton.font = .systemFont(ofSize: 14, weight: .bold)
276
-        findJobsButton.contentTintColor = Theme.proCTAText
277 303
         findJobsButton.wantsLayer = true
278
-        findJobsButton.layer?.backgroundColor = Theme.brandBlue.cgColor
279
-        findJobsButton.layer?.cornerRadius = 10
304
+        findJobsButton.layer?.backgroundColor = NSColor.clear.cgColor
305
+        findJobsButton.focusRingType = .none
280 306
         findJobsButton.target = self
281 307
         findJobsButton.action = #selector(didSubmitSearch)
282 308
         findJobsButton.setContentHuggingPriority(.required, for: .horizontal)
283 309
         findJobsButton.setContentCompressionResistancePriority(.required, for: .horizontal)
284 310
 
311
+        findJobsCTAHost.addSubview(findJobsCTAChrome)
312
+        findJobsCTAHost.addSubview(findJobsButton)
313
+        NSLayoutConstraint.activate([
314
+            findJobsCTAChrome.leadingAnchor.constraint(equalTo: findJobsCTAHost.leadingAnchor),
315
+            findJobsCTAChrome.trailingAnchor.constraint(equalTo: findJobsCTAHost.trailingAnchor),
316
+            findJobsCTAChrome.topAnchor.constraint(equalTo: findJobsCTAHost.topAnchor),
317
+            findJobsCTAChrome.bottomAnchor.constraint(equalTo: findJobsCTAHost.bottomAnchor),
318
+
319
+            findJobsButton.leadingAnchor.constraint(equalTo: findJobsCTAHost.leadingAnchor, constant: 14),
320
+            findJobsButton.trailingAnchor.constraint(equalTo: findJobsCTAHost.trailingAnchor, constant: -14),
321
+            findJobsButton.topAnchor.constraint(equalTo: findJobsCTAHost.topAnchor),
322
+            findJobsButton.bottomAnchor.constraint(equalTo: findJobsCTAHost.bottomAnchor)
323
+        ])
324
+
285 325
         let keywordsStack = NSStackView(views: [jobSearchIcon, jobKeywordsField])
286 326
         keywordsStack.orientation = .horizontal
287 327
         keywordsStack.spacing = 10
288 328
         keywordsStack.alignment = .centerY
289 329
         keywordsStack.translatesAutoresizingMaskIntoConstraints = false
290 330
         keywordsStack.edgeInsets = NSEdgeInsets(top: 0, left: 18, bottom: 0, right: 10)
331
+        keywordsStack.setContentHuggingPriority(.defaultLow, for: .horizontal)
291 332
 
292
-        let locationStack = NSStackView(views: [locationIcon, locationField])
293
-        locationStack.orientation = .horizontal
294
-        locationStack.spacing = 10
295
-        locationStack.alignment = .centerY
296
-        locationStack.translatesAutoresizingMaskIntoConstraints = false
297
-        locationStack.edgeInsets = NSEdgeInsets(top: 0, left: 10, bottom: 0, right: 10)
298
-
299
-        let row = NSStackView(views: [keywordsStack, searchDivider, locationStack, findJobsButton])
333
+        let row = NSStackView(views: [keywordsStack, findJobsCTAHost])
300 334
         row.orientation = .horizontal
301 335
         row.spacing = 0
302 336
         row.alignment = .centerY
303 337
         row.distribution = .fill
304 338
         row.translatesAutoresizingMaskIntoConstraints = false
305
-        row.edgeInsets = NSEdgeInsets(top: 0, left: 0, bottom: 0, right: 10)
339
+        row.edgeInsets = NSEdgeInsets(top: 0, left: 0, bottom: 0, right: 7)
306 340
 
307 341
         searchCard.addSubview(row)
308 342
 
@@ -321,19 +355,24 @@ final class DashboardView: NSView, NSTextFieldDelegate {
321 355
 
322 356
             jobSearchIcon.widthAnchor.constraint(equalToConstant: 18),
323 357
             jobSearchIcon.heightAnchor.constraint(equalToConstant: 18),
324
-            locationIcon.widthAnchor.constraint(equalToConstant: 18),
325
-            locationIcon.heightAnchor.constraint(equalToConstant: 18),
326
-
327
-            searchDivider.widthAnchor.constraint(equalToConstant: 1),
328
-            searchDivider.heightAnchor.constraint(equalToConstant: 30),
329 358
 
330
-            keywordsStack.widthAnchor.constraint(equalTo: locationStack.widthAnchor),
331
-
332
-            findJobsButton.heightAnchor.constraint(equalToConstant: 40),
333
-            findJobsButton.widthAnchor.constraint(greaterThanOrEqualToConstant: 108)
359
+            findJobsCTAHost.heightAnchor.constraint(equalToConstant: ctaHeight),
360
+            findJobsCTAHost.widthAnchor.constraint(greaterThanOrEqualToConstant: 112)
334 361
         ])
335 362
     }
336 363
 
364
+    private func updateFindJobsCTAShadowPath() {
365
+        guard findJobsCTAHost.bounds.width > 0, findJobsCTAHost.bounds.height > 0 else { return }
366
+        let r = findJobsCTAHost.bounds
367
+        let radius = min(r.height / 2, r.width / 2)
368
+        findJobsCTAHost.layer?.shadowPath = CGPath(
369
+            roundedRect: r,
370
+            cornerWidth: radius,
371
+            cornerHeight: radius,
372
+            transform: nil
373
+        )
374
+    }
375
+
337 376
     private func updateSearchBarShadowPath() {
338 377
         guard searchBarShadowHost.bounds.width > 0, searchBarShadowHost.bounds.height > 0 else { return }
339 378
         let r = searchBarShadowHost.bounds
@@ -360,7 +399,7 @@ final class DashboardView: NSView, NSTextFieldDelegate {
360 399
 
361 400
     private func applySearchFieldInsertionPoint(_ object: Any?) {
362 401
         guard let field = object as? NSTextField,
363
-              field === jobKeywordsField || field === locationField,
402
+              field === jobKeywordsField,
364 403
               let textView = field.window?.fieldEditor(true, for: field) as? NSTextView else { return }
365 404
         textView.insertionPointColor = Theme.primaryText
366 405
     }