Bladeren bron

Add custom sparkle icon to Quick Start section titles.

Refactor section title icons behind an enum and use bold typography for section headers.

Co-authored-by: Cursor <cursoragent@cursor.com>
AhtashamShahzad1 1 maand geleden
bovenliggende
commit
c88f4b8ea4
2 gewijzigde bestanden met toevoegingen van 95 en 20 verwijderingen
  1. 57 0
      smart_printer/UIComponents.swift
  2. 38 20
      smart_printer/ViewController.swift

+ 57 - 0
smart_printer/UIComponents.swift

@@ -204,6 +204,63 @@ final class PillButton: NSButton {
     }
 }
 
+// MARK: - Sparkle Icon
+
+final class SparkleIconView: NSView {
+    var color: NSColor = AppTheme.blue
+
+    override var isFlipped: Bool { true }
+    override var isOpaque: Bool { false }
+
+    override func draw(_ dirtyRect: NSRect) {
+        super.draw(dirtyRect)
+        guard let context = NSGraphicsContext.current?.cgContext else { return }
+
+        let s = min(bounds.width, bounds.height)
+        let cx = bounds.midX
+        let cy = bounds.midY
+
+        let tipR = s * 0.34
+        let valleyR = s * 0.09
+
+        let tips = [
+            CGPoint(x: cx, y: cy - tipR),
+            CGPoint(x: cx + tipR, y: cy),
+            CGPoint(x: cx, y: cy + tipR),
+            CGPoint(x: cx - tipR, y: cy),
+        ]
+        let valleys = [
+            CGPoint(x: cx + valleyR, y: cy - valleyR),
+            CGPoint(x: cx + valleyR, y: cy + valleyR),
+            CGPoint(x: cx - valleyR, y: cy + valleyR),
+            CGPoint(x: cx - valleyR, y: cy - valleyR),
+        ]
+
+        let starPath = CGMutablePath()
+        starPath.move(to: tips[0])
+        for i in 0..<4 {
+            starPath.addQuadCurve(to: tips[(i + 1) % 4], control: valleys[i])
+        }
+        starPath.closeSubpath()
+
+        context.setFillColor(color.cgColor)
+        context.addPath(starPath)
+        context.fillPath()
+
+        let dotR = s * 0.052
+        let dotOffset = s * 0.30
+        let dotPositions = [
+            CGPoint(x: cx + dotOffset, y: cy - dotOffset),
+            CGPoint(x: cx + dotOffset, y: cy + dotOffset),
+            CGPoint(x: cx - dotOffset, y: cy + dotOffset),
+            CGPoint(x: cx - dotOffset, y: cy - dotOffset),
+        ]
+        for pos in dotPositions {
+            context.fillEllipse(in: CGRect(x: pos.x - dotR, y: pos.y - dotR, width: dotR * 2, height: dotR * 2))
+        }
+    }
+}
+
 // MARK: - Quick Start Card
 
 struct QuickStartCardData {

+ 38 - 20
smart_printer/ViewController.swift

@@ -162,7 +162,7 @@ class ViewController: NSViewController {
         let documentView = FlippedDocumentView()
         documentView.translatesAutoresizingMaskIntoConstraints = false
 
-        let sectionTitle = makeSectionTitle(title, showGridIcon: true)
+        let sectionTitle = makeSectionTitle(title, icon: .grid)
         let grid = makeFeatureRow(features: features)
 
         documentView.addSubview(sectionTitle)
@@ -271,40 +271,58 @@ class ViewController: NSViewController {
         return scrollView
     }
 
-    private func makeSectionTitle(_ text: String, showGridIcon: Bool = false) -> NSView {
+    private enum SectionTitleIcon {
+        case none
+        case sparkle
+        case grid
+    }
+
+    private func makeSectionTitle(_ text: String, icon: SectionTitleIcon = .none) -> NSView {
         let container = NSView()
         container.translatesAutoresizingMaskIntoConstraints = false
 
         var leadingAnchor = container.leadingAnchor
-
-        if showGridIcon {
-            let gridIcon = NSImageView()
-            gridIcon.translatesAutoresizingMaskIntoConstraints = false
-            if let image = NSImage(systemSymbolName: "square.grid.2x2", accessibilityDescription: nil) {
-                let config = NSImage.SymbolConfiguration(pointSize: 16, weight: .medium)
-                gridIcon.image = image.withSymbolConfiguration(config)
+        var iconSpacing: CGFloat = 0
+
+        if icon != .none {
+            let titleIcon: NSView
+            switch icon {
+            case .sparkle:
+                titleIcon = SparkleIconView()
+            case .grid:
+                let gridIcon = NSImageView()
+                if let image = NSImage(systemSymbolName: "square.grid.2x2", accessibilityDescription: nil) {
+                    let config = NSImage.SymbolConfiguration(pointSize: 16, weight: .medium)
+                    gridIcon.image = image.withSymbolConfiguration(config)
+                }
+                gridIcon.contentTintColor = AppTheme.textPrimary
+                titleIcon = gridIcon
+            case .none:
+                titleIcon = NSView()
             }
-            gridIcon.contentTintColor = AppTheme.textPrimary
-            container.addSubview(gridIcon)
+
+            titleIcon.translatesAutoresizingMaskIntoConstraints = false
+            container.addSubview(titleIcon)
 
             NSLayoutConstraint.activate([
-                gridIcon.leadingAnchor.constraint(equalTo: container.leadingAnchor),
-                gridIcon.centerYAnchor.constraint(equalTo: container.centerYAnchor),
-                gridIcon.widthAnchor.constraint(equalToConstant: 20),
-                gridIcon.heightAnchor.constraint(equalToConstant: 20),
+                titleIcon.leadingAnchor.constraint(equalTo: container.leadingAnchor),
+                titleIcon.centerYAnchor.constraint(equalTo: container.centerYAnchor),
+                titleIcon.widthAnchor.constraint(equalToConstant: 24),
+                titleIcon.heightAnchor.constraint(equalToConstant: 24),
             ])
-            leadingAnchor = gridIcon.trailingAnchor
+            leadingAnchor = titleIcon.trailingAnchor
+            iconSpacing = 8
         }
 
         let label = NSTextField(labelWithString: text)
-        label.font = AppTheme.semiboldFont(size: 20)
+        label.font = .systemFont(ofSize: 20, weight: .bold)
         label.textColor = AppTheme.textPrimary
         label.translatesAutoresizingMaskIntoConstraints = false
         container.addSubview(label)
 
         NSLayoutConstraint.activate([
             container.heightAnchor.constraint(equalToConstant: 28),
-            label.leadingAnchor.constraint(equalTo: leadingAnchor, constant: showGridIcon ? 8 : 0),
+            label.leadingAnchor.constraint(equalTo: leadingAnchor, constant: iconSpacing),
             label.centerYAnchor.constraint(equalTo: container.centerYAnchor),
             label.trailingAnchor.constraint(equalTo: container.trailingAnchor),
         ])
@@ -316,7 +334,7 @@ class ViewController: NSViewController {
         let section = NSView()
         section.translatesAutoresizingMaskIntoConstraints = false
 
-        let title = makeSectionTitle("Quick Start")
+        let title = makeSectionTitle("Quick Start", icon: .sparkle)
         section.addSubview(title)
 
         let cardsStack = NSStackView()
@@ -375,7 +393,7 @@ class ViewController: NSViewController {
         let section = NSView()
         section.translatesAutoresizingMaskIntoConstraints = false
 
-        let title = makeSectionTitle("Create & Print", showGridIcon: true)
+        let title = makeSectionTitle("Create & Print", icon: .grid)
         section.addSubview(title)
 
         let features: [FeatureCardData] = [