fayazara/macos-app-skills

macos-settings-ui

Build a proper macOS settings/preferences window with liquid glass support for macOS 26 (Tahoe).

Quelltext ansehen

Verwendung

  1. Installationsbefehl kopieren und das Quellpaket vor der Installation in der eigenen Agentenumgebung prüfen.
  2. Benötigte Werkzeuge, Zugangsdaten und Hosts im Original prüfen.
  3. Eingabe und gewünschtes Ergebnis beschreiben und die Ausgabe mit den Quellen abgleichen.
npx skills add https://github.com/fayazara/macos-app-skills --skill macos-settings-ui

Vor dem Start

  • Die Installation umfasst weder Modellabo noch API-Kontingent oder Dateizugriffsrechte.
  • Sterne und Installationen zeigen Aktivität, keine unabhängige Qualitäts- oder Sicherheitsprüfung.
Originales Skill-Dokument

Aus dem Quell-Repository gerendert; Überschriften, Beispiele, Code, Tabellen, Links und Bilder bleiben erhalten.

macOS Settings UI with Liquid Glass

This skill produces a native macOS settings window that follows Apple's macOS 26 design guidelines. The result is a sidebar + detail NavigationSplitView with liquid glass window chrome, back/forward toolbar navigation, grouped Form sections with transparent backgrounds, and proper scroll edge effects.

Architecture Overview

The settings UI is composed of 3 layers:

  1. Window Controller (SettingsWindowController.swift) — An NSWindowController that creates the NSWindow programmatically with .fullSizeContentView. This is what gives the window rounded liquid glass corners. You cannot get this effect from a SwiftUI Window scene.
  1. Root View (SettingsView.swift) — A NavigationSplitView with a sidebar list and detail pane. Includes back/forward navigation history in the toolbar, which also forces the creation of an NSToolbar (required for the liquid glass title bar treatment).
  1. Detail Panes (one file per tab) — Each pane uses Form { Section(...) { ... } }.formStyle(.grouped).scrollContentBackground(.hidden).

Why NSWindowController Instead of SwiftUI Window Scene

SwiftUI's declarative Window scene does not expose the NSWindow style mask. The .fullSizeContentView flag must be set at window creation time for macOS 26 to render the liquid glass chrome (rounded corners, translucent sidebar, blurred title bar). Trying to inject it later via NSViewRepresentable is unreliable because SwiftUI resets the window's configuration.

The NSWindowController approach also lets you control the toolbar style, frame autosave, minimum size, and delegate lifecycle directly.

Critical Modifiers

Every detail pane MUST have these three modifiers on its Form:

swift
.formStyle(.grouped)
.scrollContentBackground(.hidden)
.contentMargins(.top, 8, for: .scrollContent)
  • .formStyle(.grouped) — gives the native inset rounded-rect section appearance
  • .scrollContentBackground(.hidden) — makes the form background transparent so the liquid glass window chrome shows through. Without this, you get an opaque white/dark background that breaks the glass effect.
  • .contentMargins(.top, 8) — adds breathing room between the toolbar and the first section

The sidebar List MUST have:

swift
.listStyle(.sidebar)
.scrollEdgeEffectStyleSoftIfAvailable()  // macOS 26 progressive blur at scroll edges
.navigationTitle("Settings")

The NavigationSplitView MUST have:

swift
NavigationSplitView(columnVisibility: .constant(.all))  // sidebar always visible
// ...
.navigationTitle("Settings")
.navigationSplitViewStyle(.balanced)

Reference Implementation

Read the reference files for complete, working code:

  • references/SettingsWindowController.swift — The window controller (copy as-is, adapt the activation policy calls to your app)
  • references/SettingsView.swift — The root view with sidebar, detail routing, and navigation history
  • references/ExampleDetailPane.swift — A template detail pane showing common control patterns (Toggle, Picker, Slider, LabeledContent)

Step-by-Step: Adding Settings to a New App

1. Create the Tab Enum

Define your settings categories. Each case needs a title and SF Symbol icon:

swift
enum SettingsTab: String, CaseIterable, Identifiable {
    case general
    case appearance
    case about

    var id: Self { self }

    var title: String {
        switch self {
        case .general: "General"
        case .appearance: "Appearance"
        case .about: "About"
        }
    }

    var systemImage: String {
        switch self {
        case .general: "gearshape"
        case .appearance: "paintbrush"
        case .about: "info.circle"
        }
    }
}

2. Create the Window Controller

Copy references/SettingsWindowController.swift into your project. Adapt:

  • The initial contentRect size (default 700x540 is good for most apps)
  • The minSize (default 620x460)
  • The activation policy calls (AppActivationPolicy.enter()/leave()) — if your app isn't a menu-bar-only app, remove these

3. Create the Root Settings View

Copy references/SettingsView.swift. Adapt:

  • The SettingsTab enum cases to match your categories
  • The SettingsDetailView switch to return your panes

4. Create Detail Panes

For each tab, create a pane file. Use this template:

swift
import SwiftUI

struct GeneralSettingsPane: View {
    @AppStorage("someKey") private var someValue = false

    var body: some View {
        Form {
            Section("Section Name") {
                Toggle("Toggle label", isOn: $someValue)
            }
        }
        .formStyle(.grouped)
        .scrollContentBackground(.hidden)
        .contentMargins(.top, 8, for: .scrollContent)
    }
}

5. Open Settings from Your App

From a menu bar, button, or anywhere:

swift
SettingsWindowController.show(tab: .general)

Do NOT use a SwiftUI Window scene. Do NOT use openWindow(id:). The window controller handles everything.

6. Remove Any SwiftUI Window Scene

If you previously had a Window("Settings", id: "SETTINGS") scene in your App struct, remove it entirely. The SettingsWindowController replaces it.

Common Control Patterns Inside Form Sections

Toggle with description:

swift
Toggle(isOn: $value) {
    VStack(alignment: .leading, spacing: 2) {
        Text("Primary label")
        Text("Description text explaining what this does.")
            .font(.caption)
            .foregroundStyle(.secondary)
    }
}
.toggleStyle(.switch)

Picker (dropdown):

swift
Picker("Label", selection: $value) {
    Text("Option A").tag(OptionEnum.a)
    Text("Option B").tag(OptionEnum.b)
}
.pickerStyle(.menu)

Picker (segmented):

swift
Picker("Label", selection: $value) {
    ForEach(SomeEnum.allCases) { item in
        Text(item.title).tag(item)
    }
}
.pickerStyle(.segmented)

Slider with value label:

swift
LabeledContent("Size") {
    HStack(spacing: 12) {
        Slider(value: $size, in: 24...96, step: 2)
            .frame(width: 180)
        Text("\(Int(size)) pt")
            .monospacedDigit()
            .foregroundStyle(.secondary)
            .frame(width: 46, alignment: .trailing)
    }
}

Button row:

swift
HStack(spacing: 8) {
    Button("Action") { doSomething() }
        .controlSize(.small)
    Button("Reset") { reset() }
        .controlSize(.small)
        .disabled(isDefault)
}

Menu-Bar-Only Apps

If your app uses NSApp.setActivationPolicy(.accessory) (no Dock icon), you need activation policy management so the settings window brings the app to the foreground. The reference SettingsWindowController calls AppActivationPolicy.enter() on show and .leave() on close. Implement this as a simple reference-counting wrapper:

swift
@MainActor
enum AppActivationPolicy {
    private static var count = 0

    static func enter() {
        count += 1
        NSApp.setActivationPolicy(.regular)
        NSApp.activate(ignoringOtherApps: true)
    }

    static func leave() {
        count = max(0, count - 1)
        guard count == 0 else { return }
        Task { @MainActor in
            NSApp.setActivationPolicy(.accessory)
        }
    }
}

If your app always shows in the Dock, remove the AppActivationPolicy calls from the window controller and just use NSApp.activate(ignoringOtherApps: true) in showWindow.

macOS Version Compatibility

The scrollEdgeEffectStyle(.soft) API is macOS 26+ only. Always wrap it in an availability check:

swift
private extension View {
    @ViewBuilder
    func scrollEdgeEffectStyleSoftIfAvailable() -> some View {
        if #available(macOS 26.0, *) {
            scrollEdgeEffectStyle(.soft, for: .all)
        } else {
            self
        }
    }
}

The rest of the pattern (NSWindowController with .fullSizeContentView, grouped Form, NavigationSplitView) works on macOS 14+.

Verwandte Aufgaben

aus demselben Repository

Weitere Skills

Alle Skills
fayazara
Community

macos-auto-update

Add Sparkle auto-update support to a native macOS app. Use this skill whenever the user wants to add auto-updates, implement Sparkle, set up an appcast feed, add "Check for Updates" to their app, or integrate automatic update checking. Also trigger when the user mentions Sparkle, appcast, SUFeedURL, EdDSA signing, or update notifications. This covers the full setup: adding the Sparkle SPM dependency, creating the UpdaterManager singleton, wiring it into the app delegate and UI, configuring Info.

Installationen
2
GitHub Stars
681
Aktualisiert
27. Mai
fayazara
Community

macos-build

Build a native macOS app using xcodebuild from the command line. Use this skill whenever the user asks to build, compile, or check if their macOS project compiles successfully. Also use it when the user asks to fix build errors, verify changes compile, or run a debug build. Trigger on phrases like "build the app", "does it compile", "run xcodebuild", "fix build errors", or even just "build".

Installationen
2
GitHub Stars
681
Aktualisiert
27. Mai
fayazara
Community

macos-notch-ui

Add a Dynamic Island-style notch UI to a macOS app. Use this skill whenever the user wants to create a notch overlay, notch extender, Dynamic Island for Mac, notch indicator, or any UI that extends from the MacBook notch area. Also trigger when the user mentions "notch shape", "notch window", "notch cutout", "notch panel", "recording indicator near the notch", "Dynamic Island style", or wants to show status/content that appears to emerge from the hardware notch. This covers the NSPanel setup, th

Installationen
2
GitHub Stars
681
Aktualisiert
27. Mai
fayazara
Community

macos-patterns

Essential native macOS development patterns that web developers don't know about. Use this skill whenever the user is building a macOS app and needs guidance on native patterns, or when they ask about menu bar apps, floating panels, window levels, keyboard shortcuts, file pickers, clipboard, drag and drop, screen capture, activation policy, Quick Look, launch at login, or any macOS-specific API. Also trigger when the user seems to be applying web development patterns to macOS (e.g., using z-inde

Installationen
2
GitHub Stars
681
Aktualisiert
27. Mai