Library

macOS · SwiftUI

Use Sitka's design tokens in a macOS SwiftUI app. The same typed Swift constants that power iOS — with macOS-native color APIs, window-chrome conventions, and HIG-correct component patterns.

1

Download the Swift token file

Go to the Token Export page and download SitkaTokens.swift. It contains the same brand colors and spacing scale used across web and iOS.

bash
npx style-dictionary build --config style-dictionary.config.js
# outputs dist/SitkaTokens.swift
2

Add to your Xcode project

  1. Drag SitkaTokens.swift into your Xcode project navigator.
  2. In the Add Files dialog, ensure Copy items if needed is checked and your macOS target is selected.
  3. For shared iOS+macOS targets, the same token file works on both platforms — only the semantic color bridges differ.
3

macOS semantic color bridges

macOS uses NSColor instead of UIColor for system colors. The mapping is consistent across all Sitka component pages.

iOS (UIColor)macOS (NSColor)Semantic role
UIColor.systemBackgroundNSColor.windowBackgroundColorWindow / screen background
UIColor.secondarySystemBackgroundNSColor.controlBackgroundColorCard / panel surface
UIColor.tertiarySystemBackgroundNSColor.quaternaryLabelColor.opacity(0.06)Subtle fill
UIColor.labelNSColor.labelColor / .labelColorPrimary text
UIColor.secondaryLabelNSColor.secondaryLabelColorSecondary text
UIColor.tertiaryLabelNSColor.tertiaryLabelColorTertiary text
UIColor.separatorNSColor.separatorColorBorders & dividers
SitkaTokens+macOS.swift
swift
import SwiftUI
import AppKit

// Drop this file into a macOS-only target alongside SitkaTokens.swift
// to get NSColor-backed semantic tokens.

extension SitkaTokens.Color {
    // Adaptive surfaces — follow the system light/dark mode automatically
    public static var windowBackground: Color { Color(NSColor.windowBackgroundColor) }
    public static var controlBackground: Color { Color(NSColor.controlBackgroundColor) }
    public static var separator:         Color { Color(NSColor.separatorColor) }

    // Adaptive text
    public static var label:          Color { Color(.labelColor) }
    public static var secondaryLabel: Color { Color(.secondaryLabelColor) }
    public static var tertiaryLabel:  Color { Color(.tertiaryLabelColor) }
}

Usage examples

Card surface

swift
VStack(alignment: .leading, spacing: SitkaTokens.Spacing.s3) {
    Text("Card title")
        .font(.system(size: SitkaTokens.Typography.sizeSM, weight: .semibold))
        .foregroundStyle(SitkaTokens.Color.label)

    Text("Subtitle text")
        .font(.system(size: SitkaTokens.Typography.sizeXS))
        .foregroundStyle(SitkaTokens.Color.secondaryLabel)
}
.padding(SitkaTokens.Spacing.s5)
.background(SitkaTokens.Color.controlBackground)
.clipShape(RoundedRectangle(cornerRadius: SitkaTokens.Radius.md, style: .continuous))
.overlay(
    RoundedRectangle(cornerRadius: SitkaTokens.Radius.md, style: .continuous)
        .stroke(SitkaTokens.Color.separator, lineWidth: 1)
)

Settings form

swift
struct AppSettingsView: View {
    @State private var notifications = true
    @State private var theme = "system"

    var body: some View {
        Form {
            Section("General") {
                Toggle("Enable notifications", isOn: $notifications)
                    .toggleStyle(.checkbox)

                Picker("Appearance", selection: $theme) {
                    Text("System").tag("system")
                    Text("Light").tag("light")
                    Text("Dark").tag("dark")
                }
                .pickerStyle(.radioGroup)
            }
        }
        .formStyle(.grouped)
        .frame(width: 380)
        .padding()
    }
}

Keyboard shortcut

swift
Button("New Document") { createDocument() }
    .keyboardShortcut("n", modifiers: .command)

Button("Find") { openFind() }
    .keyboardShortcut("f", modifiers: .command)

Button("Close") { closeWindow() }
    .keyboardShortcut("w", modifiers: .command)

Native toolbar

swift
struct ContentView: View {
    var body: some View {
        NavigationSplitView {
            List(items) { item in
                NavigationLink(item.title, value: item)
            }
            .listStyle(.sidebar)
        } detail: {
            DetailView()
        }
        .toolbar {
            ToolbarItem(placement: .primaryAction) {
                Button(action: addItem) {
                    Label("Add", systemImage: "plus")
                }
            }
        }
        .navigationTitle("Library")
    }
}

macOS-specific patterns

PatterniOS approachmacOS approach
Modal / sheetZStack overlay fullscreen.sheet(isPresented:) on window
TooltipsCustom overlay on long press.help() modifier (native hover)
Form layoutSection {} in Form.formStyle(.grouped)
TogglesToggle with .tint.toggleStyle(.checkbox)
Radio buttonsCustom button groupPicker with .pickerStyle(.radioGroup)
Sidebar navTabView / NavigationStackNavigationSplitView + .listStyle(.sidebar)
TableCustom VStack/HStack rowsSwiftUI Table view (sortable, multi-select)
ShortcutsN/A (touch-first).keyboardShortcut() on any Button

Environment propagation for sheets

On macOS, sheets presented from a WindowGroup do not inherit the parent view's environment. Every .sheet() modifier must explicitly re-inject all required environment objects — including ThemeManager — or theming will silently break inside sheets.

swift
// Correct — ThemeManager re-injected into the sheet
.sheet(isPresented: $showSettings) {
    SettingsView()
        .environmentObject(themeManager)
        .environmentObject(appSettings)
}

See the complete wiring guide for ThemeManager, adaptive tokens, and effectiveAccent: Wire Sitka's ThemeManager in SwiftUI →

Requirements

Swift

5.9+

macOS

13+

Xcode

15+

Back to all libraries.