Now liveThe Skillselion MCP - thousands of ranked skills, loaded into your agent mid-task. No install.Get it →
dpearson2699 avatar

Focus Engine

  • 1.6k installs
  • 944 repo stars
  • Updated July 15, 2026
  • dpearson2699/swift-ios-skills

focus-engine is an agent skill for implement swiftui and uikit keyboard, directional, and scene-level focus behavior.

About

The focus-engine skill is designed for implement SwiftUI and UIKit keyboard, directional, and scene-level focus behavior. Focus Engine Focus behavior for SwiftUI and UIKit apps targeting iOS 26+, iPadOS, macOS, tvOS, and visionOS connected-input paths. Covers keyboard focus, directional focus, scene-focused values, focus restoration, and UIKit focus guides. Invoke when the user manages @FocusState, UIFocusGuide, focus sections, or tvOS/visionOS focus routing.

  • Use this skill for keyboard, remote, game-controller, and scene focus behavior.
  • For visionOS, describe gaze, direct touch, and pointer targeting as hover/input affordances, not focus.
  • SwiftUI FocusState.
  • Default Focus.
  • Focused Values and Scene Values.

Focus Engine by the numbers

  • 1,581 all-time installs (skills.sh)
  • +111 installs in the week ending Jul 29, 2026 (Skillselion tracking)
  • Ranked #154 of 1,039 Mobile Development skills by installs in the Skillselion catalog
  • Security screen: LOW risk (skills.sh audit)
  • Data as of Jul 31, 2026 (Skillselion catalog sync)
At a glance

focus-engine capabilities & compatibility

Capabilities
use this skill for keyboard, remote, game contro · for visionos, describe gaze, direct touch, and p · swiftui focusstate · default focus
Use cases
frontend
From the docs

What focus-engine says it does

Implements keyboard, directional, and scene-level focus behavior across SwiftUI and UIKit. Use when managing @FocusState, defaultFocus, focused values, focusable interactions, focu
SKILL.md
Implements keyboard, directional, and scene-level focus behavior across SwiftUI and UIKit. Use when managing @FocusState, defaultFocus, focused values, focusabl
SKILL.md
npx skills add https://github.com/dpearson2699/swift-ios-skills --skill focus-engine

Add your badge

Show developers this skill is listed on Skillselion. Paste this into your README.

Listed on Skillselion
Installs1.6k
repo stars944
Security audit3 / 3 scanners passed
Last updatedJuly 15, 2026
Repositorydpearson2699/swift-ios-skills

How do I implement swiftui and uikit keyboard, directional, and scene-level focus behavior?

Implement SwiftUI and UIKit keyboard, directional, and scene-level focus behavior.

Who is it for?

iOS developers managing @FocusState, focus guides, tvOS navigation, and focus restoration.

Skip if: Skip for VoiceOver-only accessibility work covered by ios-accessibility skill.

When should I use this skill?

User manages @FocusState, UIFocusGuide, focus sections, or tvOS/visionOS focus routing.

What you get

Completed focus-engine workflow with documented commands, files, and expected deliverables.

  • focus-aware view implementations
  • platform-specific focus handlers

By the numbers

  • Targets iOS 26+ alongside iPadOS, macOS, tvOS, watchOS, and visionOS

Files

SKILL.mdMarkdownGitHub ↗

Focus Engine

Focus behavior for SwiftUI and UIKit apps targeting iOS 26+, iPadOS, macOS, tvOS, and visionOS connected-input paths. Covers keyboard focus, directional focus, scene-focused values, focus restoration, and UIKit focus guides. focusSection() guidance in this skill applies to macOS and tvOS. visionOS gaze-driven hover is an input affordance, not focus. Accessibility-specific focus for VoiceOver and Switch Control lives in the ios-accessibility skill.

When a request mixes focus with accessibility or spatial input, keep the boundary explicit:

  • Use this skill for keyboard, remote, game-controller, and scene focus behavior.
  • For visionOS, describe gaze, direct touch, and pointer targeting as hover/input affordances, not focus.
  • For VoiceOver, Switch Control, Voice Control, or accessibility element ordering, give only a brief handoff to ios-accessibility.

Contents

SwiftUI FocusState

Use @FocusState to read and write focus placement inside a scene. Use Bool for a single target or an optional Hashable enum for multiple targets.

struct LoginView: View {
    enum Field: Hashable { case email, password }

    @State private var email = ""
    @State private var password = ""
    @FocusState private var focusedField: Field?

    var body: some View {
        Form {
            TextField("Email", text: $email)
                .focused($focusedField, equals: .email)

            SecureField("Password", text: $password)
                .focused($focusedField, equals: .password)
        }
        .onAppear { focusedField = .email }
        .onSubmit {
            switch focusedField {
            case .email: focusedField = .password
            case .password, nil: submit()
            }
        }
    }
}

Keep focus state local to the view that owns the focusable controls.

Default Focus

Use .defaultFocus to set the preferred initial focus region or control when a view appears or when focus is reassigned automatically.

struct SidebarView: View {
    enum Target: Hashable { case library, settings }
    @FocusState private var focusedTarget: Target?

    var body: some View {
        VStack {
            Button("Library") { }
                .focused($focusedTarget, equals: .library)

            Button("Settings") { }
                .focused($focusedTarget, equals: .settings)
        }
        .defaultFocus($focusedTarget, .library)
    }
}

Prefer one clear default destination per screen or focus region.

Focused Values and Scene Values

Use focused values to expose state from the currently focused view. Use scene-focused values when commands or scene-wide UI should keep access to the value even after focus moves within that scene.

struct SelectedRecipeKey: FocusedValueKey {
    typealias Value = Binding<Recipe>
}

extension FocusedValues {
    var selectedRecipe: Binding<Recipe>? {
        get { self[SelectedRecipeKey.self] }
        set { self[SelectedRecipeKey.self] = newValue }
    }
}

struct RecipeDetailView: View {
    @Binding var recipe: Recipe

    var body: some View {
        Text(recipe.title)
            .focusedSceneValue(\.selectedRecipe, $recipe)
    }
}

Use this pattern for menus, commands, and toolbars that need to act on the focused scene's current content.

Focusable Interactions

Use .focusable(_:interactions:) on custom SwiftUI views that should participate in keyboard or directional focus.

struct SelectableCard: View {
    let title: String
    let action: () -> Void
    @FocusState private var isFocused: Bool

    var body: some View {
        Button(action: action) {
            RoundedRectangle(cornerRadius: 12)
                .fill(isFocused ? Color.accentColor.opacity(0.15) : .clear)
                .overlay { Text(title) }
        }
        .buttonStyle(.plain)
        .focusable(interactions: .activate)
        .focused($isFocused)
    }
}

Prefer semantic Button, Toggle, TextField, and other system controls before making arbitrary gesture-driven views focusable. Use .focusable(interactions: .activate) for custom button-like controls only when a semantic control cannot express the UI. Reserve broader interactions for views that genuinely need editing or multiple focus-driven behaviors.

Focus Sections

Use focusSection() on macOS 13+ and tvOS 15+ to guide directional movement across groups of focusable descendants in uneven layouts.

struct TVLibraryView: View {
    var body: some View {
        HStack {
            VStack {
                Button("Recent") { }
                Button("Favorites") { }
                Button("Downloaded") { }
            }
            .focusSection()

            VStack {
                Button("Featured") { }
                Button("Top Picks") { }
                Button("Continue Watching") { }
            }
            .focusSection()
        }
    }
}

Use focus sections on macOS and tvOS when default left/right or up/down movement skips the intended group.

Focus Restoration

After dismissing a sheet, popover, or transient overlay, return focus to a stable trigger or logical next target.

struct FiltersView: View {
    @State private var showSheet = false
    @FocusState private var isFilterButtonFocused: Bool

    var body: some View {
        Button("Filters") { showSheet = true }
            .focused($isFilterButtonFocused)
            .sheet(isPresented: $showSheet) {
                FilterEditor()
                    .onDisappear {
                        Task { @MainActor in
                            isFilterButtonFocused = true
                        }
                    }
            }
    }
}

Restore focus intentionally whenever presentation changes would otherwise leave users disoriented.

UIKit Focus Guides

Use UIFocusGuide when UIKit or tvOS layouts need custom routing across empty space or awkward geometry.

final class DashboardViewController: UIViewController {
    private let focusGuide = UIFocusGuide()
    @IBOutlet private weak var leadingButton: UIButton!
    @IBOutlet private weak var trailingButton: UIButton!

    override func viewDidLoad() {
        super.viewDidLoad()

        view.addLayoutGuide(focusGuide)
        focusGuide.preferredFocusEnvironments = [trailingButton]

        NSLayoutConstraint.activate([
            focusGuide.leadingAnchor.constraint(equalTo: leadingButton.trailingAnchor),
            focusGuide.trailingAnchor.constraint(equalTo: trailingButton.leadingAnchor),
            focusGuide.topAnchor.constraint(equalTo: leadingButton.topAnchor),
            focusGuide.bottomAnchor.constraint(equalTo: leadingButton.bottomAnchor)
        ])
    }
}

UIFocusGuide is invisible and not a view. Use it to redirect focus without adding decorative UI.

Common Mistakes

1. Mixing accessibility focus and keyboard or directional focus in the same mental model. 2. Storing @FocusState in shared models instead of the owning view. 3. Setting multiple competing default focus targets on one screen. 4. Using .focusable() on decorative views. 5. Forgetting focus restoration after sheets, popovers, or custom overlays. 6. Reaching for UIFocusGuide before trying focusSection() on macOS or tvOS, or better layout grouping in SwiftUI. 7. Using gesture handlers for primary actions on custom focusable controls instead of a semantic Button when possible. 8. Treating visionOS gaze hover as focus; reserve focus guidance for connected input such as keyboards and game controllers.

Review Checklist

  • [ ] @FocusState is local to the view that owns the controls
  • [ ] Initial focus target is explicit when the screen needs one
  • [ ] Focus movement between fields or groups is deterministic
  • [ ] focusedSceneValue or related focused-value APIs are used when commands need current scene state
  • [ ] Custom controls opt into focus only when they are truly interactive
  • [ ] focusSection() is used for uneven directional layouts on macOS or tvOS before dropping to UIKit
  • [ ] Focus returns to a stable element after temporary presentations dismiss
  • [ ] UIFocusGuide geometry and preferred destinations match the intended route
  • [ ] visionOS guidance distinguishes connected-device focus from gaze-driven hover or RealityKit input targets
  • [ ] Accessibility focus concerns are handled in ios-accessibility, not mixed into keyboard-directional focus logic

References

  • Detailed patterns: references/focus-patterns.md
  • Multi-platform focus (tvOS, watchOS, visionOS, macOS): references/multi-platform-focus.md
  • Focus debugging and anti-patterns: references/focus-debugging.md

Related skills

How it compares

Use focus-engine for Apple-platform focus APIs rather than generic accessibility skills that do not cover tvOS geometric focus or visionOS gaze behavior.

FAQ

What does focus-engine do?

Implement SwiftUI and UIKit keyboard, directional, and scene-level focus behavior.

When should I use focus-engine?

User manages @FocusState, UIFocusGuide, focus sections, or tvOS/visionOS focus routing.

Is focus-engine safe to install?

Review the Security Audits panel on this page before installing in production.

This week in AI coding

Five minutes, every Monday - the tools, releases and tactics for developers.

unsubscribe anytime.