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

Restyle home feature shortcut cards to match reference design

Update Role, Company, and Skill tiles with outline SF Symbols, corporate
blue and slate secondary colors, pastel icon wells, light border, softer
shadow, and subtitle row with trailing arrow. Increase padding and card
spacing.

Co-authored-by: Cursor <cursoragent@cursor.com>
AhtashamShahzad1 недель назад: 3
Родитель
Сommit
ac4b4c47c0
1 измененных файлов с 54 добавлено и 35 удалено
  1. 54 35
      App for Indeed/Views/DashboardView.swift

+ 54 - 35
App for Indeed/Views/DashboardView.swift

@@ -312,14 +312,14 @@ final class DashboardView: NSView, NSTextFieldDelegate {
312 312
 
313 313
     private func configureFeatureShortcutCards() {
314 314
         featureCardsRow.orientation = .horizontal
315
-        featureCardsRow.spacing = 12
315
+        featureCardsRow.spacing = 16
316 316
         featureCardsRow.distribution = .fillEqually
317 317
         featureCardsRow.alignment = .top
318 318
         featureCardsRow.translatesAutoresizingMaskIntoConstraints = false
319 319
 
320 320
         let specs: [(symbol: String, title: String, subtitle: String, action: Selector)] = [
321
-            ("briefcase.fill", "Role", "Explore similar or better job roles", #selector(didTapFeatureRole)),
322
-            ("building.2.fill", "Company", "Find opportunities at other companies", #selector(didTapFeatureCompany)),
321
+            ("briefcase", "Role", "Explore similar or better job roles", #selector(didTapFeatureRole)),
322
+            ("building.2", "Company", "Find opportunities at other companies", #selector(didTapFeatureCompany)),
323 323
             ("chevron.left.forwardslash.chevron.right", "Skill", "Match jobs that fit your skills", #selector(didTapFeatureSkill))
324 324
         ]
325 325
         for spec in specs {
@@ -2540,8 +2540,9 @@ private struct OpenAIAPIErrorResponse: Codable {
2540 2540
     }
2541 2541
 }
2542 2542
 
2543
-/// Home welcome row: three tappable shortcuts that seed the main search field (matches the reference dashboard tiles).
2543
+/// Home welcome row: three tappable shortcuts that seed the main search field (reference: white cards, pastel icon well, arrow at bottom trailing).
2544 2544
 private final class FeatureShortcutCardView: NSView {
2545
+    private static let cardCornerRadius: CGFloat = 14
2545 2546
     private weak var actionTarget: AnyObject?
2546 2547
     private var actionSelector: Selector
2547 2548
 
@@ -2551,37 +2552,44 @@ private final class FeatureShortcutCardView: NSView {
2551 2552
         super.init(frame: .zero)
2552 2553
         translatesAutoresizingMaskIntoConstraints = false
2553 2554
         wantsLayer = true
2554
-        layer?.cornerRadius = 14
2555
+        layer?.cornerRadius = Self.cardCornerRadius
2555 2556
         if #available(macOS 11.0, *) {
2556 2557
             layer?.cornerCurve = .continuous
2557 2558
         }
2558 2559
         layer?.backgroundColor = NSColor.white.cgColor
2559 2560
         layer?.masksToBounds = false
2560
-        layer?.shadowColor = NSColor.black.withAlphaComponent(0.12).cgColor
2561
+        layer?.borderWidth = 1
2562
+        // `#EDF2F7` — light card stroke.
2563
+        layer?.borderColor = NSColor(srgbRed: 237 / 255, green: 242 / 255, blue: 247 / 255, alpha: 1).cgColor
2564
+        layer?.shadowColor = NSColor.black.withAlphaComponent(0.06).cgColor
2561 2565
         layer?.shadowOffset = CGSize(width: 0, height: 2)
2562
-        layer?.shadowRadius = 10
2566
+        layer?.shadowRadius = 12
2563 2567
         layer?.shadowOpacity = 1
2564 2568
 
2565
-        let brandBlue = NSColor(srgbRed: 37 / 255, green: 87 / 255, blue: 167 / 255, alpha: 1)
2566
-        let iconWellColor = NSColor(srgbRed: 220 / 255, green: 235 / 255, blue: 252 / 255, alpha: 1)
2567
-        let secondary = NSColor(srgbRed: 118 / 255, green: 118 / 255, blue: 118 / 255, alpha: 1)
2569
+        // `#0047AB` — primary title / icons / arrow.
2570
+        let primaryBlue = NSColor(srgbRed: 0 / 255, green: 71 / 255, blue: 171 / 255, alpha: 1)
2571
+        // `#EBF2FF` — circular icon well.
2572
+        let iconWellColor = NSColor(srgbRed: 235 / 255, green: 242 / 255, blue: 255 / 255, alpha: 1)
2573
+        // `#5D6D7E` — muted description.
2574
+        let secondary = NSColor(srgbRed: 93 / 255, green: 109 / 255, blue: 126 / 255, alpha: 1)
2568 2575
 
2576
+        let iconSize: CGFloat = 48
2569 2577
         let iconHost = NSView()
2570 2578
         iconHost.translatesAutoresizingMaskIntoConstraints = false
2571 2579
         iconHost.wantsLayer = true
2572 2580
         iconHost.layer?.backgroundColor = iconWellColor.cgColor
2573
-        iconHost.layer?.cornerRadius = 22
2581
+        iconHost.layer?.cornerRadius = iconSize / 2
2574 2582
 
2575 2583
         let icon = NSImageView()
2576 2584
         icon.translatesAutoresizingMaskIntoConstraints = false
2577
-        icon.symbolConfiguration = NSImage.SymbolConfiguration(pointSize: 16, weight: .semibold)
2585
+        icon.symbolConfiguration = NSImage.SymbolConfiguration(pointSize: 18, weight: .regular)
2578 2586
         icon.image = NSImage(systemSymbolName: symbolName, accessibilityDescription: nil)
2579
-        icon.contentTintColor = brandBlue
2587
+        icon.contentTintColor = primaryBlue
2580 2588
         iconHost.addSubview(icon)
2581 2589
 
2582 2590
         let titleField = NSTextField(wrappingLabelWithString: title)
2583 2591
         titleField.font = .systemFont(ofSize: 15, weight: .bold)
2584
-        titleField.textColor = brandBlue
2592
+        titleField.textColor = primaryBlue
2585 2593
         titleField.maximumNumberOfLines = 1
2586 2594
         titleField.isEditable = false
2587 2595
         titleField.isBordered = false
@@ -2589,50 +2597,60 @@ private final class FeatureShortcutCardView: NSView {
2589 2597
         titleField.alignment = .left
2590 2598
 
2591 2599
         let subtitleField = NSTextField(wrappingLabelWithString: subtitle)
2592
-        subtitleField.font = .systemFont(ofSize: 11, weight: .regular)
2600
+        subtitleField.font = .systemFont(ofSize: 12, weight: .regular)
2593 2601
         subtitleField.textColor = secondary
2594 2602
         subtitleField.maximumNumberOfLines = 2
2595 2603
         subtitleField.isEditable = false
2596 2604
         subtitleField.isBordered = false
2597 2605
         subtitleField.drawsBackground = false
2598 2606
         subtitleField.alignment = .left
2599
-        subtitleField.preferredMaxLayoutWidth = 160
2600
-
2601
-        let textColumn = NSStackView(views: [titleField, subtitleField])
2602
-        textColumn.orientation = .vertical
2603
-        textColumn.spacing = 4
2604
-        textColumn.alignment = .leading
2605
-        textColumn.translatesAutoresizingMaskIntoConstraints = false
2606
-        textColumn.setContentHuggingPriority(.defaultLow, for: .horizontal)
2607
-        textColumn.setContentCompressionResistancePriority(.defaultLow, for: .horizontal)
2607
+        subtitleField.lineBreakMode = .byWordWrapping
2608
+        subtitleField.setContentHuggingPriority(.defaultLow, for: .horizontal)
2609
+        subtitleField.setContentCompressionResistancePriority(.defaultLow, for: .horizontal)
2608 2610
 
2609 2611
         let chevron = NSImageView()
2610 2612
         chevron.translatesAutoresizingMaskIntoConstraints = false
2611
-        chevron.symbolConfiguration = NSImage.SymbolConfiguration(pointSize: 13, weight: .semibold)
2613
+        chevron.symbolConfiguration = NSImage.SymbolConfiguration(pointSize: 12, weight: .semibold)
2612 2614
         chevron.image = NSImage(systemSymbolName: "arrow.right", accessibilityDescription: nil)
2613
-        chevron.contentTintColor = brandBlue
2615
+        chevron.contentTintColor = primaryBlue
2614 2616
         chevron.setContentHuggingPriority(.required, for: .horizontal)
2615 2617
         chevron.setContentCompressionResistancePriority(.required, for: .horizontal)
2616 2618
 
2619
+        let subtitleRow = NSStackView(views: [subtitleField, chevron])
2620
+        subtitleRow.orientation = .horizontal
2621
+        subtitleRow.spacing = 10
2622
+        subtitleRow.alignment = .bottom
2623
+        subtitleRow.distribution = .fill
2624
+        subtitleRow.translatesAutoresizingMaskIntoConstraints = false
2625
+
2626
+        let textColumn = NSStackView(views: [titleField, subtitleRow])
2627
+        textColumn.orientation = .vertical
2628
+        textColumn.spacing = 6
2629
+        textColumn.alignment = .leading
2630
+        textColumn.translatesAutoresizingMaskIntoConstraints = false
2631
+        textColumn.setContentHuggingPriority(.defaultLow, for: .horizontal)
2632
+        textColumn.setContentCompressionResistancePriority(.defaultLow, for: .horizontal)
2633
+
2617 2634
         iconHost.setContentHuggingPriority(.required, for: .horizontal)
2618 2635
         iconHost.setContentCompressionResistancePriority(.required, for: .horizontal)
2619 2636
 
2620
-        let row = NSStackView(views: [iconHost, textColumn, chevron])
2637
+        let row = NSStackView(views: [iconHost, textColumn])
2621 2638
         row.orientation = .horizontal
2622
-        row.spacing = 12
2639
+        row.spacing = 16
2623 2640
         row.alignment = .centerY
2624 2641
         row.distribution = .fill
2625 2642
         row.translatesAutoresizingMaskIntoConstraints = false
2626 2643
         addSubview(row)
2627 2644
 
2645
+        let inset: CGFloat = 22
2628 2646
         NSLayoutConstraint.activate([
2629
-            row.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 14),
2630
-            row.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -14),
2631
-            row.topAnchor.constraint(equalTo: topAnchor, constant: 16),
2632
-            row.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -16),
2647
+            row.leadingAnchor.constraint(equalTo: leadingAnchor, constant: inset),
2648
+            row.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -inset),
2649
+            row.topAnchor.constraint(equalTo: topAnchor, constant: inset),
2650
+            row.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -inset),
2633 2651
 
2634
-            iconHost.widthAnchor.constraint(equalToConstant: 44),
2635
-            iconHost.heightAnchor.constraint(equalToConstant: 44),
2652
+            iconHost.widthAnchor.constraint(equalToConstant: iconSize),
2653
+            iconHost.heightAnchor.constraint(equalToConstant: iconSize),
2636 2654
             icon.centerXAnchor.constraint(equalTo: iconHost.centerXAnchor),
2637 2655
             icon.centerYAnchor.constraint(equalTo: iconHost.centerYAnchor)
2638 2656
         ])
@@ -2651,7 +2669,8 @@ private final class FeatureShortcutCardView: NSView {
2651 2669
         super.layout()
2652 2670
         guard let layer = layer, bounds.width > 0, bounds.height > 0 else { return }
2653 2671
         let r = bounds
2654
-        layer.shadowPath = CGPath(roundedRect: r, cornerWidth: 14, cornerHeight: 14, transform: nil)
2672
+        let cr = Self.cardCornerRadius
2673
+        layer.shadowPath = CGPath(roundedRect: r, cornerWidth: cr, cornerHeight: cr, transform: nil)
2655 2674
     }
2656 2675
 
2657 2676
     override func mouseDown(with event: NSEvent) {