All skills
rshankras avatar

/ui-review-tahoe

@32566aa

Comprehensive UI/UX review for macOS Tahoe apps. Covers Liquid Glass design, HIG compliance, SwiftUI patterns, and accessibility. Use when reviewing macOS UI or checking HIG compliance.

Use this Skill: https://skilld.dev/gh/rshankras/claude-code-apple-skills/ui-review-tahoe

This session only. Nothing lands on disk.

macos-tahoe-hig.md

≈3k tokens on demand. Your agent reads this file only when SKILL.md points to it.

macOS Tahoe Human Interface Guidelines

Platform-specific design guidelines for macOS 26 (Tahoe).

Window Management

Window Chrome

// ✅ GOOD: Modern window with unified toolbar
@main
struct MyApp: App {
    var body: some Scene {
        WindowGroup {
            ContentView()
        }
        .windowStyle(.hiddenTitleBar)
        .windowToolbarStyle(.unified)
    }
}

// ✅ GOOD: Toolbar with standard controls
struct ContentView: View {
    var body: some View {
        NavigationSplitView {
            SidebarView()
        } detail: {
            DetailView()
        }
        .toolbar {
            ToolbarItem(placement: .navigation) {
                Button(action: toggleSidebar) {
                    Label("Toggle Sidebar", systemImage: "sidebar.left")
                }
            }

            ToolbarItem(placement: .primaryAction) {
                Button("New") {
                    // Action
                }
            }
        }
    }
}

// ❌ BAD: Custom window chrome (avoid unless necessary)

Window Sizing and Constraints

// ✅ GOOD: Appropriate size constraints
WindowGroup {
    ContentView()
}
.defaultSize(width: 800, height: 600)
.windowResizability(.contentSize)  // or .automatic

// Document windows
DocumentGroup(newDocument: { MyDocument() }) { file in
    DocumentView(document: file.$document)
}
.defaultSize(width: 1024, height: 768)

Multiple Windows

// ✅ GOOD: Supporting multiple windows
@main
struct MyApp: App {
    var body: some Scene {
        // Main window
        WindowGroup {
            ContentView()
        }
        .commands {
            CommandGroup(replacing: .newItem) {
                Button("New Window") {
                    // Create new window
                }
                .keyboardShortcut("n", modifiers: .command)
            }
        }

        // Settings window
        Settings {
            SettingsView()
        }
    }
}

Toolbar Design

Standard Toolbar Items

// ✅ GOOD: Well-organized toolbar
.toolbar(id: "main") {
    // Leading items
    ToolbarItem(id: "sidebar", placement: .navigation) {
        Button(action: toggleSidebar) {
            Label("Sidebar", systemImage: "sidebar.left")
        }
    }

    // Flexible space
    ToolbarItem(placement: .automatic) {
        Spacer()
    }

    // Center items (search, filters)
    ToolbarItem(id: "search", placement: .automatic) {
        TextField("Search", text: $searchText)
            .textFieldStyle(.roundedBorder)
            .frame(width: 200)
    }

    // Trailing items
    ToolbarItem(id: "share", placement: .primaryAction) {
        ShareLink(item: currentItem)
    }

    ToolbarItem(id: "add", placement: .primaryAction) {
        Button(action: addNew) {
            Label("Add", systemImage: "plus")
        }
    }
}
.toolbarRole(.editor)

Customizable Toolbars

// ✅ GOOD: Allow toolbar customization
.toolbar(id: "customizable-toolbar") {
    ToolbarItem(id: "action1", placement: .automatic, showsByDefault: true) {
        Button("Action 1") { }
    }

    ToolbarItem(id: "action2", placement: .automatic, showsByDefault: false) {
        Button("Action 2") { }
    }
}
.toolbarRole(.editor)

Menu Bar Organization

Standard Menu Structure

@main
struct MyApp: App {
    var body: some Scene {
        WindowGroup {
            ContentView()
        }
        .commands {
            // Replace standard commands
            CommandGroup(replacing: .newItem) {
                Button("New Document") {
                    // Action
                }
                .keyboardShortcut("n")
            }

            // Add after File menu
            CommandGroup(after: .newItem) {
                Button("Import...") {
                    // Action
                }
                .keyboardShortcut("i")
            }

            // Custom menu
            CommandMenu("Tools") {
                Button("Refresh") {
                    // Action
                }
                .keyboardShortcut("r")

                Divider()

                Button("Export...") {
                    // Action
                }
                .keyboardShortcut("e", modifiers: [.command, .shift])
            }
        }
    }
}

Keyboard Shortcuts

// ✅ GOOD: Standard keyboard shortcuts
.keyboardShortcut("n", modifiers: .command)           // ⌘N
.keyboardShortcut("s", modifiers: .command)           // ⌘S
.keyboardShortcut("w", modifiers: .command)           // ⌘W
.keyboardShortcut("z", modifiers: .command)           // ⌘Z
.keyboardShortcut("z", modifiers: [.command, .shift]) // ⇧⌘Z

// ⚠️ Don't override system shortcuts (⌘Q, ⌘H, ⌘M, ⌘Tab, etc.)

// ✅ GOOD: Function key shortcuts
.keyboardShortcut(.return, modifiers: .command)       // ⌘↩
.keyboardShortcut(.delete, modifiers: .command)       // ⌘⌫
.keyboardShortcut(.escape)                            // ⎋

Navigation Patterns

Sidebar Navigation

// ✅ GOOD: Three-column layout
struct ContentView: View {
    @State private var selectedCategory: Category?
    @State private var selectedItem: Item?

    var body: some View {
        NavigationSplitView {
            // Primary sidebar
            List(categories, selection: $selectedCategory) { category in
                Label(category.name, systemImage: category.icon)
            }
            .navigationSplitViewColumnWidth(min: 180, ideal: 200)
        } content: {
            // Secondary sidebar
            if let category = selectedCategory {
                List(category.items, selection: $selectedItem) { item in
                    Text(item.name)
                }
            }
            .navigationSplitViewColumnWidth(min: 200, ideal: 250)
        } detail: {
            // Detail view
            if let item = selectedItem {
                ItemDetailView(item: item)
            } else {
                Text("Select an item")
                    .foregroundStyle(.secondary)
            }
        }
    }
}

// ✅ GOOD: Two-column layout
NavigationSplitView {
    List(items, selection: $selectedItem) { item in
        NavigationLink(value: item) {
            Label(item.name, systemImage: item.icon)
        }
    }
} detail: {
    if let item = selectedItem {
        DetailView(item: item)
    }
}

Tab Navigation

// ✅ GOOD: TabView for distinct sections
TabView {
    DashboardView()
        .tabItem {
            Label("Dashboard", systemImage: "chart.bar")
        }

    ProjectsView()
        .tabItem {
            Label("Projects", systemImage: "folder")
        }

    SettingsView()
        .tabItem {
            Label("Settings", systemImage: "gear")
        }
}
.frame(minWidth: 600, minHeight: 400)

Control Patterns

Buttons

// ✅ GOOD: Appropriate button styles
Button("Primary Action") {
    // Action
}
.buttonStyle(.borderedProminent)  // Primary CTA

Button("Secondary Action") {
    // Action
}
.buttonStyle(.bordered)  // Secondary action

Button("Cancel") {
    // Action
}
.buttonStyle(.borderless)  // Tertiary action

// ✅ GOOD: Destructive actions
Button("Delete", role: .destructive) {
    // Action
}
.buttonStyle(.bordered)

Forms and Fields

// ✅ GOOD: Form layout
Form {
    Section("General") {
        TextField("Name", text: $name)
        TextField("Email", text: $email)
            .textContentType(.emailAddress)

        Picker("Role", selection: $role) {
            ForEach(roles) { role in
                Text(role.name).tag(role)
            }
        }
    }

    Section("Preferences") {
        Toggle("Enable notifications", isOn: $notificationsEnabled)
        Toggle("Dark mode", isOn: $darkModeEnabled)

        Picker("Theme", selection: $theme) {
            Text("Light").tag(Theme.light)
            Text("Dark").tag(Theme.dark)
            Text("Auto").tag(Theme.auto)
        }
        .pickerStyle(.segmented)
    }

    Section {
        HStack {
            Spacer()
            Button("Cancel") {
                dismiss()
            }
            .buttonStyle(.bordered)

            Button("Save") {
                save()
            }
            .buttonStyle(.borderedProminent)
        }
    }
}
.formStyle(.grouped)
.frame(minWidth: 400, minHeight: 300)

Lists and Tables

// ✅ GOOD: List with context menu
List(items, selection: $selection) { item in
    ItemRow(item: item)
        .contextMenu {
            Button("Open") { openItem(item) }
            Button("Duplicate") { duplicateItem(item) }
            Divider()
            Button("Delete", role: .destructive) {
                deleteItem(item)
            }
        }
}
.listStyle(.sidebar)

// ✅ GOOD: Table view
Table(items, selection: $selection) {
    TableColumn("Name") { item in
        Text(item.name)
    }
    TableColumn("Date") { item in
        Text(item.date, style: .date)
    }
    TableColumn("Size") { item in
        Text(item.size, format: .byteCount(style: .file))
    }
}

Alerts and Sheets

Alerts

// ✅ GOOD: Simple alert
.alert("Delete Item?", isPresented: $showingAlert) {
    Button("Cancel", role: .cancel) { }
    Button("Delete", role: .destructive) {
        deleteItem()
    }
} message: {
    Text("This action cannot be undone.")
}

// ✅ GOOD: Confirmation dialog
.confirmationDialog("Export Options", isPresented: $showingExport) {
    Button("PDF") { exportPDF() }
    Button("HTML") { exportHTML() }
    Button("Markdown") { exportMarkdown() }
    Button("Cancel", role: .cancel) { }
}

Sheets and Popovers

// ✅ GOOD: Sheet presentation
.sheet(isPresented: $showingSheet) {
    SettingsView()
        .frame(minWidth: 500, minHeight: 400)
}

// ✅ GOOD: Popover
.popover(isPresented: $showingPopover) {
    FilterOptionsView()
        .frame(width: 300)
}

Touch Bar (Legacy)

Touch Bar is removed on newer Macs — don't rely on it for essential functionality; provide alternative toolbar/menu access.

macOS Tahoe-Specific Features

Spotlight Integration

// ✅ GOOD: Make content searchable
// Implement NSUserActivity for Spotlight indexing
func makeUserActivity() -> NSUserActivity {
    let activity = NSUserActivity(activityType: "com.app.viewArticle")
    activity.title = "View Article"
    activity.userInfo = ["articleID": article.id.uuidString]
    activity.isEligibleForSearch = true

    let attributes = CSSearchableItemAttributeSet(itemContentType: kUTTypeContent as String)
    attributes.title = article.title
    attributes.contentDescription = article.excerpt
    activity.contentAttributeSet = attributes

    return activity
}

Phone App on Mac

// ✅ GOOD: Support phone links for Phone app integration
Link("Call Support", destination: URL(string: "tel:1-800-555-0123")!)

// Continuity features automatically handled by system

Platform Conventions Checklist

  • Use standard window chrome (unified toolbar)
  • Appropriate window size constraints
  • Support multiple windows (if applicable)
  • Well-organized toolbar with standard items
  • Standard menu structure with shortcuts
  • Keyboard shortcut consistency
  • Appropriate navigation pattern (sidebar, tabs)
  • Platform-standard controls and buttons
  • Proper alert and dialog usage
  • Context menus for list items
  • Spotlight integration (if applicable)
  • No reliance on Touch Bar

Resources

Source: SKILL.md on GitHub

No alerts2mo3 checks · Risk SAFE
  • Gen Agent Trust Hub2mo

    The skill is a set of instructional documents and guidance for performing UI/UX reviews of macOS applications. It contains no malicious code, obfuscation, or data exfiltration patterns, and is focused entirely on providing design feedback based on Apple's guidelines.

  • Socket2mo

    No alerts

  • Snyk2mo

    Risk: LOW · No issues

Signed by skilld at 32566aa. This ties the file your Agent reads to that commit on GitHub. It does not review the instructions.

Last checked against GitHub 2 months ago.

Steadyupdated 3 months ago
What it can do
Reads files Network
last_verified
2026-07-16
review_by
2027-06-22
os_version
iOS 27 / macOS 27
All 4 allowed tools
ReadGlobGrepWebFetch

README badge

README badge for rshankras/claude-code-apple-skills/ui-review-tahoe