Files
TUIkit/TUIKit.docc/Tutorials/BuildInteractiveMenu.md
T
phranck 2cf72c2b19 feat: Add comprehensive DocC documentation with tutorials
Add complete Apple-style DocC documentation for TUIKit framework:

## Documentation Structure
- Main landing page (TUIKit.md) with quick-start and topic navigation
- 8 guide articles: GettingStarted, ViewHierarchy, StateManagement, Theming, Appearance, Focus, Modifiers, Architecture
- 3 step-by-step tutorials: BuildYourFirstApp, BuildInteractiveMenu, BuildThemableUI
- Documentation catalog with proper Info.plist configuration

## Code Improvements
- Enhanced Box.swift documentation with clear container comparison
- Added comprehensive examples and usage patterns
- Explained appearance integration and sizing behavior

## Infrastructure
- GitHub Actions workflow (.github/workflows/docc.yml) for automatic DocC building
- Configured for deployment to GitHub Pages on push to main
- Uses xcrun docc build with proper artifact handling

## Documentation Includes
- API reference stubs for all major components
- Comprehensive guide articles with code examples
- Interactive tutorials following Apple's documentation style
- Cross-references using DocC syntax (``Type``)
- Best practices and design patterns explained

The documentation is ready for automated building and deployment to GitHub Pages.
2026-01-29 02:42:29 +01:00

12 KiB

Building an Interactive Menu

Create a navigation menu with keyboard shortcuts and status bar hints.

@Intro(title: "Build an Interactive Menu App") { Learn how to create a functional menu system with keyboard navigation, selection handling, and status bar integration.

You'll build a simple settings menu that demonstrates focus management,
keyboard events, and status bar items.

}

Overview

In this tutorial, you'll create a menu-driven application featuring:

  • Menu component for selection
  • Keyboard shortcut handling
  • Status bar with hints
  • Page navigation patterns

@Section(title: "Create the Menu Component") { @ContentAndMedia { Start with a basic menu that displays options and tracks selection. }

@Steps {
    @Step {
        Create your app with a `Menu`:

        ```swift
        import TUIKit

        @main
        struct MenuApp: App {
            @State private var selectedOption: String = "home"

            var body: some Scene {
                WindowGroup {
                    VStack(spacing: 2) {
                        Text("Main Menu")
                            .bold()
                            .foregroundColor(.theme.accent)

                        Spacer()

                        Menu(
                            items: [
                                MenuItem("📄 View Profile", id: "profile"),
                                MenuItem("⚙️  Settings", id: "settings"),
                                MenuItem("💾 Save Data", id: "save"),
                                MenuItem("❌ Exit", id: "exit")
                            ],
                            selection: $selectedOption
                        )

                        Spacer()

                        Text("Selected: \(selectedOption)")
                            .foregroundColor(.theme.foregroundSecondary)
                    }
                    .padding()
                }
            }
        }
        ```

        - `Menu` creates an interactive selectable list
        - `$selectedOption` creates a two-way binding
        - Use Tab/Arrow keys to navigate
        - Press Enter to confirm selection
    }

    @Step {
        Run the app:

        ```bash
        swift run
        ```

        Test navigating with Tab, arrow keys, and Enter.
        The "Selected" text updates as you navigate.
    }
}

}

@Section(title: "Add Page Navigation") { @ContentAndMedia { Create different pages that show based on menu selection. }

@Steps {
    @Step {
        Add conditional pages:

        ```swift
        @main
        struct MenuApp: App {
            @State private var selectedOption: String = "home"

            var body: some Scene {
                WindowGroup {
                    if selectedOption == "exit" {
                        VStack {
                            Text("Exiting...")
                        }
                    } else {
                        VStack(spacing: 2) {
                            Text("Main Menu")
                                .bold()
                                .foregroundColor(.theme.accent)

                            Spacer()

                            Menu(
                                items: [
                                    MenuItem("📄 View Profile", id: "profile"),
                                    MenuItem("⚙️  Settings", id: "settings"),
                                    MenuItem("💾 Save Data", id: "save"),
                                    MenuItem("❌ Exit", id: "exit")
                                ],
                                selection: $selectedOption
                            )

                            Spacer()

                            currentPageContent
                        }
                        .padding()
                    }
                }
            }

            @ViewBuilder
            var currentPageContent: some View {
                switch selectedOption {
                case "profile":
                    VStack(spacing: 1) {
                        Text("📄 Profile Information").bold()
                        Text("Name: John Doe")
                        Text("Role: Developer")
                    }
                case "settings":
                    VStack(spacing: 1) {
                        Text("⚙️  Application Settings").bold()
                        Text("Theme: Green")
                        Text("Language: English")
                    }
                case "save":
                    Text("✓ Data saved successfully!")
                        .foregroundColor(.theme.success)
                default:
                    Text("Select an option above")
                }
            }
        }
        ```

        The `currentPageContent` computed property shows different content
        based on the selected menu item.
    }

    @Step {
        Run and test navigation:

        ```bash
        swift run
        ```

        Navigate to each menu item and see the page content change.
    }
}

}

@Section(title: "Add Status Bar Hints") { @ContentAndMedia { Add a status bar at the bottom with helpful keyboard hints. }

@Steps {
    @Step {
        Add status bar items:

        ```swift
        @main
        struct MenuApp: App {
            @State private var selectedOption: String = "home"

            var body: some Scene {
                WindowGroup {
                    if selectedOption == "exit" {
                        VStack {
                            Text("Exiting...")
                        }
                    } else {
                        VStack(spacing: 2) {
                            Text("Main Menu")
                                .bold()
                                .foregroundColor(.theme.accent)

                            Spacer()

                            Menu(
                                items: [
                                    MenuItem("📄 View Profile", id: "profile"),
                                    MenuItem("⚙️  Settings", id: "settings"),
                                    MenuItem("💾 Save Data", id: "save"),
                                    MenuItem("❌ Exit", id: "exit")
                                ],
                                selection: $selectedOption
                            )

                            Spacer()

                            currentPageContent
                        }
                        .padding()
                    }
                    .statusBarItems {
                        StatusBarItem(
                            label: "Select",
                            shortcut: Shortcut.enter,
                            action: { }
                        )

                        StatusBarItem(
                            label: "Theme",
                            shortcut: Shortcut.letter("t"),
                            action: { }
                        )

                        StatusBarItem(
                            label: "Help",
                            shortcut: Shortcut.letter("?"),
                            action: { }
                        )

                        StatusBarItem(
                            label: "Quit",
                            shortcut: Shortcut.letter("q"),
                            action: { }
                        )
                    }
                }
            }

            @ViewBuilder
            var currentPageContent: some View {
                switch selectedOption {
                case "profile":
                    VStack(spacing: 1) {
                        Text("📄 Profile Information").bold()
                        Text("Name: John Doe")
                        Text("Role: Developer")
                    }
                case "settings":
                    VStack(spacing: 1) {
                        Text("⚙️  Application Settings").bold()
                        Text("Theme: Green")
                        Text("Language: English")
                    }
                case "save":
                    Text("✓ Data saved successfully!")
                        .foregroundColor(.theme.success)
                default:
                    Text("Select an option above")
                }
            }
        }
        ```

        `statusBarItems` adds a bottom status bar with keyboard shortcuts.
    }

    @Step {
        Run the app:

        ```bash
        swift run
        ```

        The status bar appears at the bottom showing available shortcuts.
    }
}

}

@Section(title: "Add Keyboard Shortcuts") { @ContentAndMedia { Handle custom keyboard shortcuts to navigate directly to menu items. }

@Steps {
    @Step {
        Add keyboard event handling:

        ```swift
        .onKeyPress { event in
            switch event.key {
            case .character("1"):
                selectedOption = "profile"
                return true
            case .character("2"):
                selectedOption = "settings"
                return true
            case .character("3"):
                selectedOption = "save"
                return true
            case .character("e"):
                selectedOption = "exit"
                return true
            default:
                return false
            }
        }
        ```

        Add this modifier to your main `VStack`. Now users can:
        - Press `1` to go to Profile
        - Press `2` to go to Settings
        - Press `3` to Save
        - Press `e` to Exit
    }

    @Step {
        Update the status bar to show these shortcuts:

        ```swift
        .statusBarItems {
            StatusBarItem(
                label: "Profile",
                shortcut: Shortcut.digit("1"),
                action: { }
            )

            StatusBarItem(
                label: "Settings",
                shortcut: Shortcut.digit("2"),
                action: { }
            )

            StatusBarItem(
                label: "Save",
                shortcut: Shortcut.digit("3"),
                action: { }
            )

            StatusBarItem(
                label: "Exit",
                shortcut: Shortcut.letter("e"),
                action: { }
            )
        }
        ```
    }

    @Step {
        Test your shortcuts:

        ```bash
        swift run
        ```

        Press number keys to jump directly to menu items.
    }
}

}

Next Steps

You've created an interactive menu-driven application!