浏览代码

Build dark themed meetings dashboard UI.

Implement the first-page layout with refined navigation, meeting tabs, schedule cards, and a tuned color/typography system to match the requested design updates.

Made-with: Cursor
huzaifahayat12 3 月之前
父节点
当前提交
c02309f5c2
共有 2 个文件被更改,包括 469 次插入5 次删除
  1. 2 1
      meetings_app/AppDelegate.swift
  2. 467 4
      meetings_app/ViewController.swift

+ 2 - 1
meetings_app/AppDelegate.swift

@@ -14,7 +14,8 @@ class AppDelegate: NSObject, NSApplicationDelegate {
 
 
     func applicationDidFinishLaunching(_ aNotification: Notification) {
-        // Insert code here to initialize your application
+        // Force app-wide dark appearance for consistent dark UI.
+        NSApp.appearance = NSAppearance(named: .darkAqua)
     }
 
     func applicationWillTerminate(_ aNotification: Notification) {

+ 467 - 4
meetings_app/ViewController.swift

@@ -7,20 +7,483 @@
 
 import Cocoa
 
-class ViewController: NSViewController {
+final class ViewController: NSViewController {
+    private let palette = Palette()
+    private let typography = Typography()
 
     override func viewDidLoad() {
         super.viewDidLoad()
+        setupRootView()
+        buildMainLayout()
+    }
 
-        // Do any additional setup after loading the view.
+    override func viewDidAppear() {
+        super.viewDidAppear()
+        view.window?.setContentSize(NSSize(width: 1120, height: 690))
+        view.window?.minSize = NSSize(width: 940, height: 600)
+        view.window?.title = "App for Google Meet"
     }
 
     override var representedObject: Any? {
-        didSet {
-        // Update the view, if already loaded.
+        didSet {}
+    }
+}
+
+private extension ViewController {
+    func setupRootView() {
+        view.appearance = NSAppearance(named: .darkAqua)
+        view.wantsLayer = true
+        view.layer?.backgroundColor = palette.pageBackground.cgColor
+    }
+
+    func buildMainLayout() {
+        let splitContainer = NSStackView()
+        splitContainer.translatesAutoresizingMaskIntoConstraints = false
+        splitContainer.orientation = .horizontal
+        splitContainer.spacing = 0
+        splitContainer.alignment = .top
+        view.addSubview(splitContainer)
+
+        NSLayoutConstraint.activate([
+            splitContainer.leadingAnchor.constraint(equalTo: view.leadingAnchor),
+            splitContainer.trailingAnchor.constraint(equalTo: view.trailingAnchor),
+            splitContainer.topAnchor.constraint(equalTo: view.topAnchor),
+            splitContainer.bottomAnchor.constraint(equalTo: view.bottomAnchor)
+        ])
+
+        let sidebar = makeSidebar()
+        let mainPanel = makeMainPanel()
+        splitContainer.addArrangedSubview(sidebar)
+        splitContainer.addArrangedSubview(mainPanel)
+    }
+
+    func makeSidebar() -> NSView {
+        let sidebar = NSView()
+        sidebar.translatesAutoresizingMaskIntoConstraints = false
+        sidebar.wantsLayer = true
+        sidebar.layer?.backgroundColor = palette.sidebarBackground.cgColor
+        sidebar.layer?.borderColor = palette.separator.cgColor
+        sidebar.layer?.borderWidth = 1
+        sidebar.layer?.shadowColor = NSColor.black.cgColor
+        sidebar.layer?.shadowOpacity = 0.25
+        sidebar.layer?.shadowOffset = CGSize(width: 2, height: 0)
+        sidebar.layer?.shadowRadius = 10
+        sidebar.widthAnchor.constraint(equalToConstant: 210).isActive = true
+
+        let titleRow = NSStackView(views: [
+            iconLabel("📅", size: 24),
+            textLabel("Meetings", font: typography.sidebarBrand, color: palette.textPrimary)
+        ])
+        titleRow.translatesAutoresizingMaskIntoConstraints = false
+        titleRow.orientation = .horizontal
+        titleRow.alignment = .centerY
+        titleRow.spacing = 8
+
+        let menuStack = NSStackView()
+        menuStack.translatesAutoresizingMaskIntoConstraints = false
+        menuStack.orientation = .vertical
+        menuStack.spacing = 10
+
+        menuStack.addArrangedSubview(sidebarSectionTitle("Meetings"))
+        menuStack.addArrangedSubview(sidebarItem("Join Meetings", icon: "􀉣", selected: true))
+        menuStack.addArrangedSubview(sidebarSectionTitle("Backgrounds"))
+        menuStack.addArrangedSubview(sidebarItem("Photo", icon: "􀏂", selected: false))
+        menuStack.addArrangedSubview(sidebarItem("Video", icon: "􀎚", selected: false))
+        menuStack.addArrangedSubview(sidebarSectionTitle("Additional"))
+        menuStack.addArrangedSubview(sidebarItem("Tutorials", icon: "􀛩", selected: false))
+        menuStack.addArrangedSubview(sidebarItem("Settings", icon: "􀍟", selected: false))
+
+        sidebar.addSubview(titleRow)
+        sidebar.addSubview(menuStack)
+
+        NSLayoutConstraint.activate([
+            titleRow.leadingAnchor.constraint(equalTo: sidebar.leadingAnchor, constant: 16),
+            titleRow.topAnchor.constraint(equalTo: sidebar.topAnchor, constant: 24),
+            titleRow.trailingAnchor.constraint(lessThanOrEqualTo: sidebar.trailingAnchor, constant: -16),
+
+            menuStack.leadingAnchor.constraint(equalTo: sidebar.leadingAnchor, constant: 12),
+            menuStack.trailingAnchor.constraint(equalTo: sidebar.trailingAnchor, constant: -12),
+            menuStack.topAnchor.constraint(equalTo: titleRow.bottomAnchor, constant: 20)
+        ])
+
+        return sidebar
+    }
+
+    func makeMainPanel() -> NSView {
+        let panel = NSView()
+        panel.translatesAutoresizingMaskIntoConstraints = false
+        panel.wantsLayer = true
+        panel.layer?.backgroundColor = palette.pageBackground.cgColor
+
+        let contentStack = NSStackView()
+        contentStack.translatesAutoresizingMaskIntoConstraints = false
+        contentStack.orientation = .vertical
+        contentStack.spacing = 14
+        contentStack.alignment = .leading
+
+        contentStack.addArrangedSubview(textLabel("Join Meetings", font: typography.pageTitle, color: palette.textPrimary))
+        contentStack.addArrangedSubview(meetingTypeTabs())
+        contentStack.addArrangedSubview(textLabel("Join with URL", font: typography.sectionTitle, color: palette.textPrimary))
+        contentStack.addArrangedSubview(meetingUrlSection())
+        contentStack.addArrangedSubview(scheduleHeader())
+        contentStack.addArrangedSubview(textLabel("Tuesday, 14 Apr", font: typography.dateHeading, color: palette.textSecondary))
+        contentStack.addArrangedSubview(scheduleCardsRow())
+
+        panel.addSubview(contentStack)
+
+        NSLayoutConstraint.activate([
+            contentStack.leadingAnchor.constraint(equalTo: panel.leadingAnchor, constant: 28),
+            contentStack.trailingAnchor.constraint(equalTo: panel.trailingAnchor, constant: -28),
+            contentStack.topAnchor.constraint(equalTo: panel.topAnchor, constant: 26)
+        ])
+
+        return panel
+    }
+
+    func meetingTypeTabs() -> NSView {
+        let shell = roundedContainer(cornerRadius: 20, color: palette.tabBarBackground)
+        shell.translatesAutoresizingMaskIntoConstraints = false
+        shell.heightAnchor.constraint(equalToConstant: 56).isActive = true
+
+        let stack = NSStackView()
+        stack.translatesAutoresizingMaskIntoConstraints = false
+        stack.orientation = .horizontal
+        stack.distribution = .fillEqually
+        stack.spacing = 10
+
+        stack.addArrangedSubview(topTab("Meet", icon: "􀤆", selected: true))
+        stack.addArrangedSubview(topTab("Zoom", icon: "􀤉", selected: false))
+        stack.addArrangedSubview(topTab("Teams", icon: "􀉨", selected: false))
+        stack.addArrangedSubview(topTab("Zoho", icon: "􀯶", selected: false))
+
+        shell.addSubview(stack)
+        NSLayoutConstraint.activate([
+            shell.widthAnchor.constraint(greaterThanOrEqualToConstant: 700),
+            stack.leadingAnchor.constraint(equalTo: shell.leadingAnchor, constant: 10),
+            stack.trailingAnchor.constraint(equalTo: shell.trailingAnchor, constant: -10),
+            stack.topAnchor.constraint(equalTo: shell.topAnchor, constant: 8),
+            stack.bottomAnchor.constraint(equalTo: shell.bottomAnchor, constant: -8)
+        ])
+
+        return shell
+    }
+
+    func meetingUrlSection() -> NSView {
+        let wrapper = NSView()
+        wrapper.translatesAutoresizingMaskIntoConstraints = false
+
+        let title = textLabel("Meeting URL", font: typography.fieldLabel, color: palette.textSecondary)
+        let textFieldContainer = roundedContainer(cornerRadius: 10, color: palette.inputBackground)
+        textFieldContainer.translatesAutoresizingMaskIntoConstraints = false
+        textFieldContainer.heightAnchor.constraint(equalToConstant: 40).isActive = true
+        styleSurface(textFieldContainer, borderColor: palette.inputBorder, borderWidth: 1, shadow: false)
+
+        let placeholder = textLabel("Enter meeting URL...", font: typography.inputPlaceholder, color: palette.textMuted)
+        placeholder.translatesAutoresizingMaskIntoConstraints = false
+        textFieldContainer.addSubview(placeholder)
+
+        let actions = NSStackView()
+        actions.orientation = .horizontal
+        actions.spacing = 10
+        actions.translatesAutoresizingMaskIntoConstraints = false
+        actions.alignment = .centerY
+        actions.addArrangedSubview(actionButton(title: "Cancel", color: palette.cancelButton, textColor: palette.textSecondary, width: 110))
+        actions.addArrangedSubview(actionButton(title: "Join", color: palette.primaryBlue, textColor: .white, width: 116))
+
+        wrapper.addSubview(title)
+        wrapper.addSubview(textFieldContainer)
+        wrapper.addSubview(actions)
+
+        NSLayoutConstraint.activate([
+            wrapper.widthAnchor.constraint(greaterThanOrEqualToConstant: 780),
+
+            title.leadingAnchor.constraint(equalTo: wrapper.leadingAnchor),
+            title.topAnchor.constraint(equalTo: wrapper.topAnchor),
+
+            textFieldContainer.leadingAnchor.constraint(equalTo: wrapper.leadingAnchor),
+            textFieldContainer.trailingAnchor.constraint(equalTo: wrapper.trailingAnchor),
+            textFieldContainer.topAnchor.constraint(equalTo: title.bottomAnchor, constant: 10),
+
+            placeholder.leadingAnchor.constraint(equalTo: textFieldContainer.leadingAnchor, constant: 12),
+            placeholder.centerYAnchor.constraint(equalTo: textFieldContainer.centerYAnchor),
+
+            actions.trailingAnchor.constraint(equalTo: wrapper.trailingAnchor),
+            actions.topAnchor.constraint(equalTo: textFieldContainer.bottomAnchor, constant: 14),
+            actions.bottomAnchor.constraint(equalTo: wrapper.bottomAnchor)
+        ])
+
+        return wrapper
+    }
+
+    func scheduleHeader() -> NSView {
+        let row = NSStackView()
+        row.translatesAutoresizingMaskIntoConstraints = false
+        row.orientation = .horizontal
+        row.alignment = .centerY
+        row.distribution = .fill
+        row.spacing = 12
+
+        row.addArrangedSubview(textLabel("Schedule", font: typography.sectionTitleBold, color: palette.textPrimary))
+
+        let spacer = NSView()
+        spacer.translatesAutoresizingMaskIntoConstraints = false
+        row.addArrangedSubview(spacer)
+        spacer.setContentHuggingPriority(.defaultLow, for: .horizontal)
+
+        row.addArrangedSubview(iconRoundButton("?", size: 34))
+        row.addArrangedSubview(iconRoundButton("⟳", size: 34))
+
+        let filter = roundedContainer(cornerRadius: 8, color: palette.inputBackground)
+        filter.translatesAutoresizingMaskIntoConstraints = false
+        filter.widthAnchor.constraint(equalToConstant: 156).isActive = true
+        filter.heightAnchor.constraint(equalToConstant: 34).isActive = true
+        styleSurface(filter, borderColor: palette.inputBorder, borderWidth: 1, shadow: false)
+        let filterText = textLabel("All", font: typography.filterText, color: palette.textSecondary)
+        let arrow = textLabel("▾", font: typography.filterArrow, color: palette.textMuted)
+        filterText.translatesAutoresizingMaskIntoConstraints = false
+        arrow.translatesAutoresizingMaskIntoConstraints = false
+        filter.addSubview(filterText)
+        filter.addSubview(arrow)
+
+        NSLayoutConstraint.activate([
+            filterText.leadingAnchor.constraint(equalTo: filter.leadingAnchor, constant: 12),
+            filterText.centerYAnchor.constraint(equalTo: filter.centerYAnchor),
+            arrow.trailingAnchor.constraint(equalTo: filter.trailingAnchor, constant: -10),
+            arrow.centerYAnchor.constraint(equalTo: filter.centerYAnchor)
+        ])
+
+        row.addArrangedSubview(filter)
+        row.widthAnchor.constraint(greaterThanOrEqualToConstant: 780).isActive = true
+        return row
+    }
+
+    func scheduleCardsRow() -> NSView {
+        let row = NSStackView()
+        row.translatesAutoresizingMaskIntoConstraints = false
+        row.orientation = .horizontal
+        row.spacing = 14
+        row.alignment = .top
+        row.distribution = .fillEqually
+        row.widthAnchor.constraint(greaterThanOrEqualToConstant: 780).isActive = true
+        row.heightAnchor.constraint(equalToConstant: 168).isActive = true
+
+        row.addArrangedSubview(scheduleCard())
+        row.addArrangedSubview(scheduleCard())
+        return row
+    }
+
+    func scheduleCard() -> NSView {
+        let card = roundedContainer(cornerRadius: 12, color: palette.sectionCard)
+        styleSurface(card, borderColor: palette.inputBorder, borderWidth: 1, shadow: true)
+        card.translatesAutoresizingMaskIntoConstraints = false
+        card.heightAnchor.constraint(equalToConstant: 168).isActive = true
+
+        let icon = roundedContainer(cornerRadius: 7, color: palette.meetingBadge)
+        icon.translatesAutoresizingMaskIntoConstraints = false
+        icon.widthAnchor.constraint(equalToConstant: 30).isActive = true
+        icon.heightAnchor.constraint(equalToConstant: 30).isActive = true
+        let iconText = textLabel("••", font: typography.cardIcon, color: .white)
+        iconText.translatesAutoresizingMaskIntoConstraints = false
+        icon.addSubview(iconText)
+        NSLayoutConstraint.activate([
+            iconText.centerXAnchor.constraint(equalTo: icon.centerXAnchor),
+            iconText.centerYAnchor.constraint(equalTo: icon.centerYAnchor)
+        ])
+
+        let title = textLabel("General Meeting", font: typography.cardTitle, color: palette.textPrimary)
+        let subtitle = textLabel("Baisakhi", font: typography.cardSubtitle, color: palette.textSecondary)
+        let time = textLabel("12:00 AM - 11:59 PM", font: typography.cardTime, color: palette.textTertiary)
+
+        card.addSubview(icon)
+        card.addSubview(title)
+        card.addSubview(subtitle)
+        card.addSubview(time)
+
+        NSLayoutConstraint.activate([
+            icon.leadingAnchor.constraint(equalTo: card.leadingAnchor, constant: 14),
+            icon.topAnchor.constraint(equalTo: card.topAnchor, constant: 14),
+
+            title.leadingAnchor.constraint(equalTo: icon.trailingAnchor, constant: 8),
+            title.centerYAnchor.constraint(equalTo: icon.centerYAnchor),
+            title.trailingAnchor.constraint(lessThanOrEqualTo: card.trailingAnchor, constant: -12),
+
+            subtitle.leadingAnchor.constraint(equalTo: card.leadingAnchor, constant: 14),
+            subtitle.topAnchor.constraint(equalTo: icon.bottomAnchor, constant: 12),
+
+            time.leadingAnchor.constraint(equalTo: card.leadingAnchor, constant: 14),
+            time.topAnchor.constraint(equalTo: subtitle.bottomAnchor, constant: 8)
+        ])
+
+        return card
+    }
+}
+
+private extension ViewController {
+    func roundedContainer(cornerRadius: CGFloat, color: NSColor) -> NSView {
+        let view = NSView()
+        view.wantsLayer = true
+        view.layer?.backgroundColor = color.cgColor
+        view.layer?.cornerRadius = cornerRadius
+        return view
+    }
+
+    func styleSurface(_ view: NSView, borderColor: NSColor, borderWidth: CGFloat, shadow: Bool) {
+        view.layer?.borderColor = borderColor.cgColor
+        view.layer?.borderWidth = borderWidth
+        if shadow {
+            view.layer?.shadowColor = NSColor.black.cgColor
+            view.layer?.shadowOpacity = 0.28
+            view.layer?.shadowOffset = CGSize(width: 0, height: -2)
+            view.layer?.shadowRadius = 8
         }
     }
 
+    func textLabel(_ text: String, font: NSFont, color: NSColor) -> NSTextField {
+        let label = NSTextField(labelWithString: text)
+        label.translatesAutoresizingMaskIntoConstraints = false
+        label.textColor = color
+        label.font = font
+        return label
+    }
+
+    func iconLabel(_ text: String, size: CGFloat) -> NSTextField {
+        let label = NSTextField(labelWithString: text)
+        label.translatesAutoresizingMaskIntoConstraints = false
+        label.font = NSFont.systemFont(ofSize: size)
+        return label
+    }
+
+    func sidebarSectionTitle(_ text: String) -> NSTextField {
+        textLabel(text, font: typography.sidebarSection, color: palette.textMuted)
+    }
+
+    func sidebarItem(_ text: String, icon: String, selected: Bool) -> NSView {
+        let item = roundedContainer(cornerRadius: 9, color: selected ? palette.sidebarItemSelectedBackground : .clear)
+        item.translatesAutoresizingMaskIntoConstraints = false
+        item.heightAnchor.constraint(equalToConstant: 36).isActive = true
+        if selected {
+            styleSurface(item, borderColor: palette.sidebarItemSelectedBorder, borderWidth: 1, shadow: false)
+        }
+
+        let iconLabelView = textLabel(icon, font: typography.sidebarIcon, color: selected ? palette.textPrimary : palette.textSecondary)
+        let titleLabel = textLabel(text, font: typography.sidebarItem, color: selected ? palette.textPrimary : palette.textSecondary)
+
+        item.addSubview(iconLabelView)
+        item.addSubview(titleLabel)
+
+        NSLayoutConstraint.activate([
+            iconLabelView.leadingAnchor.constraint(equalTo: item.leadingAnchor, constant: 12),
+            iconLabelView.centerYAnchor.constraint(equalTo: item.centerYAnchor),
+            titleLabel.leadingAnchor.constraint(equalTo: iconLabelView.trailingAnchor, constant: 8),
+            titleLabel.centerYAnchor.constraint(equalTo: item.centerYAnchor)
+        ])
+
+        return item
+    }
+
+    func topTab(_ title: String, icon: String, selected: Bool) -> NSView {
+        let tab = roundedContainer(cornerRadius: 18, color: selected ? palette.primaryBlue : .clear)
+        tab.translatesAutoresizingMaskIntoConstraints = false
+
+        let iconLabelView = textLabel(icon, font: typography.tabIcon, color: palette.textPrimary)
+        let titleLabel = textLabel(title, font: typography.tabTitle, color: palette.textPrimary)
+
+        tab.addSubview(iconLabelView)
+        tab.addSubview(titleLabel)
+
+        NSLayoutConstraint.activate([
+            iconLabelView.leadingAnchor.constraint(equalTo: tab.leadingAnchor, constant: 16),
+            iconLabelView.centerYAnchor.constraint(equalTo: tab.centerYAnchor),
+            titleLabel.leadingAnchor.constraint(equalTo: iconLabelView.trailingAnchor, constant: 6),
+            titleLabel.centerYAnchor.constraint(equalTo: tab.centerYAnchor)
+        ])
+
+        return tab
+    }
+
+    func actionButton(title: String, color: NSColor, textColor: NSColor, width: CGFloat) -> NSView {
+        let button = roundedContainer(cornerRadius: 9, color: color)
+        button.translatesAutoresizingMaskIntoConstraints = false
+        button.widthAnchor.constraint(equalToConstant: width).isActive = true
+        button.heightAnchor.constraint(equalToConstant: 36).isActive = true
+        styleSurface(button, borderColor: title == "Cancel" ? palette.inputBorder : palette.primaryBlueBorder, borderWidth: 1, shadow: false)
+        if title == "Cancel" {
+            button.layer?.backgroundColor = palette.cancelButton.cgColor
+        }
+
+        let label = textLabel(title, font: typography.buttonText, color: textColor)
+        button.addSubview(label)
+        NSLayoutConstraint.activate([
+            label.centerXAnchor.constraint(equalTo: button.centerXAnchor),
+            label.centerYAnchor.constraint(equalTo: button.centerYAnchor)
+        ])
+
+        return button
+    }
+
+    func iconRoundButton(_ symbol: String, size: CGFloat) -> NSView {
+        let button = roundedContainer(cornerRadius: size / 2, color: palette.inputBackground)
+        button.translatesAutoresizingMaskIntoConstraints = false
+        button.widthAnchor.constraint(equalToConstant: size).isActive = true
+        button.heightAnchor.constraint(equalToConstant: size).isActive = true
+        styleSurface(button, borderColor: palette.inputBorder, borderWidth: 1, shadow: false)
+
+        let label = textLabel(symbol, font: typography.iconButton, color: palette.textSecondary)
+        button.addSubview(label)
+        NSLayoutConstraint.activate([
+            label.centerXAnchor.constraint(equalTo: button.centerXAnchor),
+            label.centerYAnchor.constraint(equalTo: button.centerYAnchor)
+        ])
+
+        return button
+    }
+}
+
+private struct Palette {
+    let pageBackground = NSColor(calibratedRed: 23.0 / 255.0, green: 24.0 / 255.0, blue: 24.0 / 255.0, alpha: 1)
+    let sidebarBackground = NSColor(calibratedRed: 32.0 / 255.0, green: 33.0 / 255.0, blue: 35.0 / 255.0, alpha: 1)
+    let sectionCard = NSColor(calibratedRed: 32.0 / 255.0, green: 33.0 / 255.0, blue: 35.0 / 255.0, alpha: 1)
+    let tabBarBackground = NSColor(calibratedRed: 32.0 / 255.0, green: 33.0 / 255.0, blue: 35.0 / 255.0, alpha: 1)
+    let tabIdleBackground = NSColor(calibratedRed: 32.0 / 255.0, green: 33.0 / 255.0, blue: 35.0 / 255.0, alpha: 1)
+    let inputBackground = NSColor(calibratedRed: 32.0 / 255.0, green: 33.0 / 255.0, blue: 35.0 / 255.0, alpha: 1)
+    let inputBorder = NSColor(calibratedRed: 0.14, green: 0.16, blue: 0.21, alpha: 1)
+    let primaryBlue = NSColor(calibratedRed: 27.0 / 255.0, green: 115.0 / 255.0, blue: 232.0 / 255.0, alpha: 1)
+    let primaryBlueBorder = NSColor(calibratedRed: 58.0 / 255.0, green: 139.0 / 255.0, blue: 246.0 / 255.0, alpha: 1)
+    let sidebarItemSelectedBackground = NSColor(calibratedRed: 27.0 / 255.0, green: 115.0 / 255.0, blue: 232.0 / 255.0, alpha: 0.28)
+    let sidebarItemSelectedBorder = NSColor(calibratedRed: 81.0 / 255.0, green: 152.0 / 255.0, blue: 249.0 / 255.0, alpha: 0.7)
+    let cancelButton = NSColor(calibratedRed: 32.0 / 255.0, green: 33.0 / 255.0, blue: 35.0 / 255.0, alpha: 1)
+    let meetingBadge = NSColor(calibratedRed: 0.94, green: 0.73, blue: 0.19, alpha: 1)
+    let separator = NSColor(calibratedWhite: 0.10, alpha: 1)
+    let textPrimary = NSColor(calibratedWhite: 0.96, alpha: 1)
+    let textSecondary = NSColor(calibratedWhite: 0.82, alpha: 1)
+    let textTertiary = NSColor(calibratedWhite: 0.74, alpha: 1)
+    let textMuted = NSColor(calibratedWhite: 0.50, alpha: 1)
+}
+
+private struct Typography {
+    let sidebarBrand = NSFont.systemFont(ofSize: 26, weight: .bold)
+    let sidebarSection = NSFont.systemFont(ofSize: 11, weight: .medium)
+    let sidebarIcon = NSFont.systemFont(ofSize: 12, weight: .medium)
+    let sidebarItem = NSFont.systemFont(ofSize: 16, weight: .medium)
+
+    let pageTitle = NSFont.systemFont(ofSize: 31, weight: .semibold)
+    let sectionTitle = NSFont.systemFont(ofSize: 23, weight: .semibold)
+    let sectionTitleBold = NSFont.systemFont(ofSize: 29, weight: .bold)
+    let dateHeading = NSFont.systemFont(ofSize: 21, weight: .medium)
+
+    let tabIcon = NSFont.systemFont(ofSize: 13, weight: .regular)
+    let tabTitle = NSFont.systemFont(ofSize: 31 / 2, weight: .semibold)
+
+    let fieldLabel = NSFont.systemFont(ofSize: 15, weight: .medium)
+    let inputPlaceholder = NSFont.systemFont(ofSize: 14, weight: .regular)
+    let buttonText = NSFont.systemFont(ofSize: 16, weight: .medium)
+    let filterText = NSFont.systemFont(ofSize: 15, weight: .regular)
+    let filterArrow = NSFont.systemFont(ofSize: 12, weight: .regular)
+    let iconButton = NSFont.systemFont(ofSize: 14, weight: .medium)
 
+    let cardIcon = NSFont.systemFont(ofSize: 10, weight: .bold)
+    let cardTitle = NSFont.systemFont(ofSize: 23, weight: .semibold)
+    let cardSubtitle = NSFont.systemFont(ofSize: 18, weight: .bold)
+    let cardTime = NSFont.systemFont(ofSize: 14, weight: .regular)
 }