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.
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:
Menucomponent 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!
- Learn about doc:Focus for advanced focus management
- Explore doc:StateManagement for more complex state patterns
- Try building a doc:BuildThemableUI with theme switching
- Check out doc:Appearance for custom styling