Explorar o código

Build Zoom-style macOS sign-in UI with sidebar and tuned proportions.

Align colors with classroom_app dark-mode palette for a true dark appearance while keeping Zoom-like blue accents.

Made-with: Cursor
huzaifahayat12 hai 1 semana
pai
achega
135a5b6480
Modificáronse 1 ficheiros con 296 adicións e 4 borrados
  1. 296 4
      zoom_app/ViewController.swift

+ 296 - 4
zoom_app/ViewController.swift

@@ -8,19 +8,311 @@
8 8
 import Cocoa
9 9
 
10 10
 class ViewController: NSViewController {
11
+    private let sidebarWidth: CGFloat = 78
12
+    // Dark-mode values copied from classroom_app Palette(isDarkMode: true).
13
+    private let appBackground = NSColor(calibratedRed: 10 / 255, green: 11 / 255, blue: 12 / 255, alpha: 1)
14
+    private let sidebarBackground = NSColor(calibratedRed: 16 / 255, green: 17 / 255, blue: 19 / 255, alpha: 1)
15
+    private let sidebarActiveBackground = NSColor(calibratedRed: 22 / 255, green: 23 / 255, blue: 26 / 255, alpha: 1)
16
+    private let cardBackground = NSColor(calibratedRed: 20 / 255, green: 21 / 255, blue: 24 / 255, alpha: 1)
17
+    private let separatorColor = NSColor(calibratedRed: 26 / 255, green: 27 / 255, blue: 30 / 255, alpha: 1)
18
+    private let accentBlue = NSColor(calibratedRed: 56 / 255, green: 132 / 255, blue: 255 / 255, alpha: 1)
19
+    private let primaryText = NSColor(calibratedWhite: 0.98, alpha: 1)
20
+    private let secondaryText = NSColor(calibratedWhite: 0.78, alpha: 1)
21
+    private let mutedText = NSColor(calibratedWhite: 0.66, alpha: 1)
11 22
 
12 23
     override func viewDidLoad() {
13 24
         super.viewDidLoad()
25
+        setupUI()
26
+    }
27
+
28
+    override func viewDidAppear() {
29
+        super.viewDidAppear()
30
+
31
+        // Keep a practical default size for this desktop mock.
32
+        view.window?.setContentSize(NSSize(width: 960, height: 700))
33
+        view.window?.title = "zoom Workplace"
34
+    }
35
+
36
+    private func setupUI() {
37
+        view.wantsLayer = true
38
+        view.layer?.backgroundColor = appBackground.cgColor
39
+
40
+        let sidebar = makeSidebar()
41
+        let content = makeContent()
42
+
43
+        view.addSubview(sidebar)
44
+        view.addSubview(content)
45
+
46
+        sidebar.translatesAutoresizingMaskIntoConstraints = false
47
+        content.translatesAutoresizingMaskIntoConstraints = false
48
+
49
+        NSLayoutConstraint.activate([
50
+            sidebar.leadingAnchor.constraint(equalTo: view.leadingAnchor),
51
+            sidebar.topAnchor.constraint(equalTo: view.topAnchor),
52
+            sidebar.bottomAnchor.constraint(equalTo: view.bottomAnchor),
53
+            sidebar.widthAnchor.constraint(equalToConstant: sidebarWidth),
54
+
55
+            content.leadingAnchor.constraint(equalTo: sidebar.trailingAnchor),
56
+            content.trailingAnchor.constraint(equalTo: view.trailingAnchor),
57
+            content.topAnchor.constraint(equalTo: view.topAnchor),
58
+            content.bottomAnchor.constraint(equalTo: view.bottomAnchor)
59
+        ])
60
+    }
61
+
62
+    private func makeSidebar() -> NSView {
63
+        let sidebar = NSView()
64
+        sidebar.wantsLayer = true
65
+        sidebar.layer?.backgroundColor = sidebarBackground.cgColor
66
+
67
+        let title = NSTextField(labelWithString: "Home")
68
+        title.font = .systemFont(ofSize: 11, weight: .medium)
69
+        title.textColor = primaryText
70
+        title.alignment = .center
71
+
72
+        let homeBox = NSBox()
73
+        homeBox.boxType = .custom
74
+        homeBox.borderType = .noBorder
75
+        homeBox.cornerRadius = 12
76
+        homeBox.fillColor = sidebarActiveBackground
77
+
78
+        let homeIcon = NSTextField(labelWithString: "⌂")
79
+        homeIcon.font = .systemFont(ofSize: 20, weight: .medium)
80
+        homeIcon.textColor = .white
81
+        homeIcon.alignment = .center
14 82
 
15
-        // Do any additional setup after loading the view.
83
+        homeBox.contentView?.addSubview(homeIcon)
84
+        homeIcon.translatesAutoresizingMaskIntoConstraints = false
85
+        NSLayoutConstraint.activate([
86
+            homeIcon.centerXAnchor.constraint(equalTo: homeBox.contentView!.centerXAnchor),
87
+            homeIcon.centerYAnchor.constraint(equalTo: homeBox.contentView!.centerYAnchor)
88
+        ])
89
+
90
+        let sidebarItems = ["Chat", "Phone", "Docs", "Whiteboards", "Clips", "More"]
91
+        var itemViews: [NSView] = []
92
+
93
+        for item in sidebarItems {
94
+            let container = NSView()
95
+            let icon = NSTextField(labelWithString: "◻︎")
96
+            icon.font = .systemFont(ofSize: 15, weight: .regular)
97
+            icon.textColor = secondaryText
98
+            icon.alignment = .center
99
+
100
+            let label = NSTextField(labelWithString: item)
101
+            label.font = .systemFont(ofSize: 12, weight: .regular)
102
+            label.textColor = secondaryText
103
+            label.alignment = .center
104
+
105
+            container.addSubview(icon)
106
+            container.addSubview(label)
107
+            icon.translatesAutoresizingMaskIntoConstraints = false
108
+            label.translatesAutoresizingMaskIntoConstraints = false
109
+
110
+            NSLayoutConstraint.activate([
111
+                icon.topAnchor.constraint(equalTo: container.topAnchor),
112
+                icon.centerXAnchor.constraint(equalTo: container.centerXAnchor),
113
+                label.topAnchor.constraint(equalTo: icon.bottomAnchor, constant: 5),
114
+                label.centerXAnchor.constraint(equalTo: container.centerXAnchor),
115
+                label.bottomAnchor.constraint(equalTo: container.bottomAnchor)
116
+            ])
117
+            itemViews.append(container)
118
+        }
119
+
120
+        let stack = NSStackView(views: itemViews)
121
+        stack.orientation = .vertical
122
+        stack.spacing = 16
123
+        stack.alignment = .centerX
124
+        stack.distribution = .gravityAreas
125
+
126
+        sidebar.addSubview(homeBox)
127
+        sidebar.addSubview(title)
128
+        sidebar.addSubview(stack)
129
+
130
+        homeBox.translatesAutoresizingMaskIntoConstraints = false
131
+        title.translatesAutoresizingMaskIntoConstraints = false
132
+        stack.translatesAutoresizingMaskIntoConstraints = false
133
+
134
+        NSLayoutConstraint.activate([
135
+            homeBox.topAnchor.constraint(equalTo: sidebar.topAnchor, constant: 42),
136
+            homeBox.centerXAnchor.constraint(equalTo: sidebar.centerXAnchor),
137
+            homeBox.widthAnchor.constraint(equalToConstant: 56),
138
+            homeBox.heightAnchor.constraint(equalToConstant: 56),
139
+
140
+            title.topAnchor.constraint(equalTo: homeBox.bottomAnchor, constant: 8),
141
+            title.centerXAnchor.constraint(equalTo: sidebar.centerXAnchor),
142
+
143
+            stack.topAnchor.constraint(equalTo: title.bottomAnchor, constant: 30),
144
+            stack.leadingAnchor.constraint(equalTo: sidebar.leadingAnchor),
145
+            stack.trailingAnchor.constraint(equalTo: sidebar.trailingAnchor)
146
+        ])
147
+
148
+        return sidebar
16 149
     }
17 150
 
18
-    override var representedObject: Any? {
19
-        didSet {
20
-        // Update the view, if already loaded.
151
+    private func makeContent() -> NSView {
152
+        let content = NSView()
153
+
154
+        let back = NSTextField(labelWithString: "‹  Back")
155
+        back.font = .systemFont(ofSize: 34, weight: .regular)
156
+        back.textColor = accentBlue
157
+
158
+        let logo = NSTextField(labelWithString: "zoom\nWorkplace")
159
+        logo.font = .systemFont(ofSize: 24, weight: .bold)
160
+        logo.textColor = primaryText
161
+        logo.alignment = .center
162
+        logo.maximumNumberOfLines = 2
163
+
164
+        let domain = NSTextField(labelWithString: "us05web.zoom.us")
165
+        domain.font = .systemFont(ofSize: 16, weight: .semibold)
166
+        domain.textColor = primaryText
167
+        domain.alignment = .center
168
+
169
+        let emailField = NSTextField()
170
+        emailField.placeholderString = "Email or phone number"
171
+        emailField.font = .systemFont(ofSize: 20, weight: .regular)
172
+        emailField.textColor = .white
173
+        emailField.focusRingType = .none
174
+        emailField.wantsLayer = true
175
+        emailField.layer?.cornerRadius = 10
176
+        emailField.layer?.borderWidth = 1.5
177
+        emailField.layer?.borderColor = accentBlue.cgColor
178
+        emailField.layer?.backgroundColor = cardBackground.cgColor
179
+
180
+        let nextButton = NSButton(title: "Next", target: nil, action: nil)
181
+        nextButton.font = .systemFont(ofSize: 20, weight: .semibold)
182
+        nextButton.bezelStyle = .regularSquare
183
+        nextButton.isBordered = false
184
+        nextButton.wantsLayer = true
185
+        nextButton.layer?.cornerRadius = 10
186
+        nextButton.layer?.backgroundColor = cardBackground.cgColor
187
+        nextButton.contentTintColor = mutedText
188
+
189
+        let divider = NSBox()
190
+        divider.boxType = .separator
191
+        divider.borderColor = separatorColor
192
+
193
+        let signInText = NSTextField(labelWithString: "or sign in with")
194
+        signInText.font = .systemFont(ofSize: 14, weight: .regular)
195
+        signInText.textColor = secondaryText
196
+        signInText.alignment = .center
197
+
198
+        let ssoButton = makeSocialButton(icon: "🔑", text: "SSO")
199
+        let googleButton = makeSocialButton(icon: "G", text: "Google")
200
+        let appleButton = makeSocialButton(icon: "", text: "Apple")
201
+        let facebookButton = makeSocialButton(icon: "f", text: "Facebook")
202
+        let microsoftButton = makeSocialButton(icon: "■", text: "Microsoft")
203
+
204
+        let socialStack = NSStackView(views: [ssoButton, googleButton, appleButton, facebookButton, microsoftButton])
205
+        socialStack.orientation = .horizontal
206
+        socialStack.spacing = 14
207
+        socialStack.distribution = .fillEqually
208
+
209
+        let signup = NSTextField(labelWithString: "Don't have an account? Sign up")
210
+        signup.font = .systemFont(ofSize: 15, weight: .regular)
211
+        signup.textColor = primaryText
212
+        signup.alignment = .center
213
+
214
+        let footer = NSTextField(labelWithString: "Help    Terms    Privacy")
215
+        footer.font = .systemFont(ofSize: 14, weight: .regular)
216
+        footer.textColor = NSColor(calibratedRed: 72 / 255, green: 129 / 255, blue: 218 / 255, alpha: 1)
217
+        footer.alignment = .center
218
+
219
+        content.addSubview(back)
220
+        content.addSubview(logo)
221
+        content.addSubview(domain)
222
+        content.addSubview(emailField)
223
+        content.addSubview(nextButton)
224
+        content.addSubview(divider)
225
+        content.addSubview(signInText)
226
+        content.addSubview(socialStack)
227
+        content.addSubview(signup)
228
+        content.addSubview(footer)
229
+
230
+        [back, logo, domain, emailField, nextButton, divider, signInText, socialStack, signup, footer].forEach {
231
+            $0.translatesAutoresizingMaskIntoConstraints = false
21 232
         }
233
+
234
+        NSLayoutConstraint.activate([
235
+            back.topAnchor.constraint(equalTo: content.topAnchor, constant: 26),
236
+            back.leadingAnchor.constraint(equalTo: content.leadingAnchor, constant: 34),
237
+
238
+            logo.topAnchor.constraint(equalTo: content.topAnchor, constant: 118),
239
+            logo.centerXAnchor.constraint(equalTo: content.centerXAnchor),
240
+
241
+            domain.topAnchor.constraint(equalTo: logo.bottomAnchor, constant: 12),
242
+            domain.centerXAnchor.constraint(equalTo: content.centerXAnchor),
243
+
244
+            emailField.topAnchor.constraint(equalTo: domain.bottomAnchor, constant: 30),
245
+            emailField.centerXAnchor.constraint(equalTo: content.centerXAnchor),
246
+            emailField.widthAnchor.constraint(equalToConstant: 520),
247
+            emailField.heightAnchor.constraint(equalToConstant: 52),
248
+
249
+            nextButton.topAnchor.constraint(equalTo: emailField.bottomAnchor, constant: 20),
250
+            nextButton.centerXAnchor.constraint(equalTo: content.centerXAnchor),
251
+            nextButton.widthAnchor.constraint(equalTo: emailField.widthAnchor),
252
+            nextButton.heightAnchor.constraint(equalToConstant: 52),
253
+
254
+            divider.topAnchor.constraint(equalTo: nextButton.bottomAnchor, constant: 28),
255
+            divider.centerXAnchor.constraint(equalTo: content.centerXAnchor),
256
+            divider.widthAnchor.constraint(equalTo: emailField.widthAnchor),
257
+
258
+            signInText.centerXAnchor.constraint(equalTo: content.centerXAnchor),
259
+            signInText.centerYAnchor.constraint(equalTo: divider.centerYAnchor),
260
+
261
+            socialStack.topAnchor.constraint(equalTo: divider.bottomAnchor, constant: 18),
262
+            socialStack.centerXAnchor.constraint(equalTo: content.centerXAnchor),
263
+            socialStack.widthAnchor.constraint(equalTo: emailField.widthAnchor),
264
+
265
+            signup.topAnchor.constraint(equalTo: socialStack.bottomAnchor, constant: 14),
266
+            signup.centerXAnchor.constraint(equalTo: content.centerXAnchor),
267
+
268
+            footer.bottomAnchor.constraint(equalTo: content.bottomAnchor, constant: -16),
269
+            footer.centerXAnchor.constraint(equalTo: content.centerXAnchor)
270
+        ])
271
+
272
+        return content
22 273
     }
23 274
 
275
+    private func makeSocialButton(icon: String, text: String) -> NSView {
276
+        let wrapper = NSView()
277
+        let iconLabel = NSTextField(labelWithString: icon)
278
+        iconLabel.font = .systemFont(ofSize: 22, weight: .medium)
279
+        iconLabel.alignment = .center
280
+        iconLabel.textColor = primaryText
281
+
282
+        let iconBox = NSBox()
283
+        iconBox.boxType = .custom
284
+        iconBox.cornerRadius = 12
285
+        iconBox.borderType = .noBorder
286
+        iconBox.fillColor = cardBackground
24 287
 
288
+        let textLabel = NSTextField(labelWithString: text)
289
+        textLabel.font = .systemFont(ofSize: 12, weight: .regular)
290
+        textLabel.textColor = secondaryText
291
+        textLabel.alignment = .center
292
+
293
+        wrapper.addSubview(iconBox)
294
+        wrapper.addSubview(textLabel)
295
+        iconBox.contentView?.addSubview(iconLabel)
296
+
297
+        iconBox.translatesAutoresizingMaskIntoConstraints = false
298
+        iconLabel.translatesAutoresizingMaskIntoConstraints = false
299
+        textLabel.translatesAutoresizingMaskIntoConstraints = false
300
+
301
+        NSLayoutConstraint.activate([
302
+            iconBox.topAnchor.constraint(equalTo: wrapper.topAnchor),
303
+            iconBox.centerXAnchor.constraint(equalTo: wrapper.centerXAnchor),
304
+            iconBox.widthAnchor.constraint(equalToConstant: 52),
305
+            iconBox.heightAnchor.constraint(equalToConstant: 52),
306
+
307
+            iconLabel.centerXAnchor.constraint(equalTo: iconBox.contentView!.centerXAnchor),
308
+            iconLabel.centerYAnchor.constraint(equalTo: iconBox.contentView!.centerYAnchor),
309
+
310
+            textLabel.topAnchor.constraint(equalTo: iconBox.bottomAnchor, constant: 6),
311
+            textLabel.centerXAnchor.constraint(equalTo: wrapper.centerXAnchor),
312
+            textLabel.bottomAnchor.constraint(equalTo: wrapper.bottomAnchor)
313
+        ])
314
+
315
+        return wrapper
316
+    }
25 317
 }
26 318