### Install SwiftUI Agent Skill with npx Source: https://github.com/twostraws/swiftui-agent-skill/blob/main/README.md Use this command to install the SwiftUI Pro skill into your AI coding assistant. Ensure Node.js is installed. ```bash npx skills add https://github.com/twostraws/swiftui-agent-skill --skill swiftui-pro ``` -------------------------------- ### Install Node.js using Homebrew Source: https://github.com/twostraws/swiftui-agent-skill/blob/main/README.md If 'npx: command not found' error occurs, install Node.js using Homebrew. This is a prerequisite for using npx. ```bash brew install node ``` -------------------------------- ### Invoke SwiftUI Pro Agent Skill for Full and Partial Reviews Source: https://context7.com/twostraws/swiftui-agent-skill/llms.txt Examples of how to invoke the SwiftUI Pro skill for a full code review or a partial review focusing on specific concerns like deprecated API or accessibility. The invocation command varies slightly between agents (e.g., Claude Code vs. Codex). ```bash # Full review in Claude Code /swiftui-pro # Full review in Codex $swiftui-pro # Partial review — deprecated API only (Claude Code) /swiftui-pro Check for deprecated API # Partial review — accessibility only (Codex) $swiftui-pro Focus on accessibility # Natural language invocation Use the SwiftUI Pro skill to look for performance problems in this project. ``` -------------------------------- ### SwiftUI Modern Preview Macro Source: https://context7.com/twostraws/swiftui-agent-skill/llms.txt Utilizes the `#Preview` macro for defining previews of SwiftUI views. This is the modern approach for creating previews, often including model container setup. ```swift // ✅ Modern preview macro #Preview { ContentView() .modelContainer(for: Item.self, inMemory: true) } ``` -------------------------------- ### Add SwiftUI Agent Skill to Claude Code Source: https://github.com/twostraws/swiftui-agent-skill/blob/main/README.md Claude Code users can add the skill via the marketplace and then install it. This provides direct integration within the Claude environment. ```bash /plugin marketplace add twostraws/SwiftUI-Agent-Skill /plugin install swiftui-pro@swiftui-agent-skill ``` -------------------------------- ### SwiftUI Binding: Prefer @State + onChange Source: https://context7.com/twostraws/swiftui-agent-skill/llms.txt Demonstrates the preferred way to handle text field updates using direct binding (`$model.username`) combined with `.onChange`. Avoid complex `Binding(get:set:)` for simple updates and saving. ```swift // ✅ Clean binding — use @State + onChange instead of Binding(get:set:) // ❌ Avoid TextField("Username", text: Binding( get: { model.username }, set: { model.username = $0; model.save() } )) // ✅ Prefer TextField("Username", text: $model.username) .onChange(of: model.username) { model.save() } ``` -------------------------------- ### Avoid Binding(get:set:) in view body Source: https://github.com/twostraws/swiftui-agent-skill/blob/main/swiftui-pro/skills/swiftui-pro/SKILL.md Replaces manual `Binding(get:set:)` in a view's body with a direct `$state` binding and `.onChange()` modifier for cleaner and more maintainable data flow management. This avoids potential issues with complex binding logic within the view body. ```swift // Before TextField("Username", text: Binding( get: { model.username }, set: { model.username = $0; model.save() } )) // After TextField("Username", text: $model.username) .onChange(of: model.username) { model.save() } ``` -------------------------------- ### Implement SwiftUI Design Principles for Flexibility and Clarity Source: https://context7.com/twostraws/swiftui-agent-skill/llms.txt Use system sizing APIs, flexible frames, and SwiftUI-native components like ContentUnavailableView and Label. Avoid fixed frames and UIKit colors. ```swift // ❌ Design violations let width = UIScreen.main.bounds.width // avoid UIScreen .frame(width: 320) // fixed frame, breaks on large text Color(UIColor.systemBlue) // UIKit color in SwiftUI Text("No results").font(.caption2) // too small // ✅ Flexible, accessible alternatives .containerRelativeFrame(.horizontal) { size, _ in size * 0.9 } .frame(maxWidth: .infinity) // flexible // ✅ ContentUnavailableView for empty states ContentUnavailableView("No Bookmarks", systemImage: "bookmark.slash", description: Text("Save articles to read later.")) // ✅ ContentUnavailableView.search (includes search term automatically) .searchable(text: $query) // In results view: if results.isEmpty { ContentUnavailableView.search } // ✅ Label over HStack for icon+text Label("Favorites", systemImage: "star.fill") // ✅ LabeledContent in Form Form { LabeledContent("Volume") { Slider(value: $volume) } } // ✅ Shared design constants enum AppStyle { static let cornerRadius: CGFloat = 12 static let spacing: CGFloat = 16 static let animation: Animation = .spring(duration: 0.3) } ``` -------------------------------- ### SwiftUI Sheet with Shorthand Initializer Source: https://context7.com/twostraws/swiftui-agent-skill/llms.txt Shows the concise way to present a sheet using `.sheet(item:content:)` with a shorthand initializer for the content view. This is useful when the sheet's data is optional. ```swift // ✅ sheet(item:) with shorthand init for optional data .sheet(item: $selectedBook, content: BookDetailView.init) ``` -------------------------------- ### Documentation Comments for Logic Clarity Source: https://context7.com/twostraws/swiftui-agent-skill/llms.txt Add documentation comments to explain complex logic, parameters, and return values, especially for non-obvious calculations. ```swift /// Calculates the weighted score accounting for streak bonuses. /// - Parameter streak: Number of consecutive correct answers. /// - Returns: Adjusted score capped at `maxScore`. func calculateScore(streak: Int) -> Int { ... } ``` -------------------------------- ### Modern SwiftUI API Replacements Source: https://context7.com/twostraws/swiftui-agent-skill/llms.txt Demonstrates modern SwiftUI API replacements for deprecated patterns, including foreground styling, shape clipping, overlay usage, toolbar items, string concatenation, enumerated ForEach loops, scroll indicator visibility, and the new native WebView. ```swift // ❌ Deprecated patterns Text("Title").foregroundColor(.red) .cornerRadius(12) .overlay(Text("Badge")) .navigationBarItems(trailing: Button("Edit") { }) Text("Hello").foregroundStyle(.red) + Text("World").foregroundStyle(.blue) ForEach(Array(items.enumerated()), id: \.element.id) { index, item in ... } ScrollView { ... }.init(showsIndicators: false) // ✅ Modern replacements Text("Title").foregroundStyle(.red) .clipShape(.rect(cornerRadius: 12)) .overlay { Text("Badge") } .toolbar { ToolbarItem(placement: .topBarTrailing) { Button("Edit") { } } } let red = Text("Hello").foregroundStyle(.red) let blue = Text("World").foregroundStyle(.blue) Text("\(red)\(blue)") ForEach(items.enumerated(), id: \.element.id) { index, item in ... } ScrollView { ... }.scrollIndicators(.hidden) // ✅ @Entry macro replaces manual EnvironmentKey boilerplate extension EnvironmentValues { @Entry var appTheme: AppTheme = .default } // ✅ Native WebView on iOS 26+ import WebKit struct ContentView: View { var body: some View { WebView(url: URL(string: "https://example.com")!) } } // ✅ Tab API replaces tabItem() TabView { Tab("Home", systemImage: "house", value: AppTab.home) { HomeView() } Tab("Settings", systemImage: "gear", value: AppTab.settings) { SettingsView() } } ``` -------------------------------- ### Modern Swift URL and File Management Source: https://context7.com/twostraws/swiftui-agent-skill/llms.txt Utilize the `URL.documentsDirectory` property for direct access to the documents directory instead of manually using `FileManager`. ```swift let docs = URL.documentsDirectory ``` -------------------------------- ### SwiftUI Chained Animation with Completion Closure Source: https://context7.com/twostraws/swiftui-agent-skill/llms.txt Illustrates how to chain animations sequentially using the completion closure of `withAnimation`. Ensure animations are correctly sequenced for desired visual effects. ```swift // ✅ Chained animation via completion closure Button("Animate") { withAnimation(.bouncy) { scale = 2 } completion: { withAnimation(.bouncy) { scale = 1 } } } ``` -------------------------------- ### SwiftUI View Composition: Anti-patterns vs. Correct Patterns Source: https://context7.com/twostraws/swiftui-agent-skill/llms.txt Demonstrates refactoring computed properties for views into separate structs and moving actions from closures to methods. Use extracted subviews for cleaner structure. ```swift // ❌ Anti-patterns struct ContentView: View { var header: some View { // computed property returning View Text("Title").font(.largeTitle) } var body: some View { VStack { header Button(action: { doSomething(); refresh() }) { Image(systemName: "arrow.clockwise") } } } } ``` ```swift // ✅ Correct patterns struct HeaderView: View { // extracted into own file + struct var body: some View { Text("Title").font(.largeTitle) } } struct ContentView: View { var body: some View { VStack { HeaderView() Button("Refresh", systemImage: "arrow.clockwise", action: refresh) } } func refresh() { doSomething() } } ``` -------------------------------- ### Standard Sheet with Item in SwiftUI Source: https://github.com/twostraws/swiftui-agent-skill/blob/main/swiftui-pro/references/navigation.md This is the standard way to present a sheet using an item, where the content closure explicitly receives and uses the item. ```swift .sheet(item: $someItem) { someItem in SomeView(item: someItem) } ``` -------------------------------- ### SwiftUI Confirmation Dialog Attached to Control Source: https://context7.com/twostraws/swiftui-agent-skill/llms.txt Demonstrates how to attach a confirmation dialog to a specific control, such as a button. This provides context for the action prompting the confirmation. ```swift // ✅ confirmationDialog attached to the triggering control Button("Delete") { showConfirm = true } .confirmationDialog("Are you sure?", isPresented: $showConfirm) { Button("Delete", role: .destructive) { deleteItem() } } ``` -------------------------------- ### Swift ISO 8601 Date Parsing Source: https://context7.com/twostraws/swiftui-agent-skill/llms.txt Parse ISO 8601 formatted date strings using the `Date.init(String, strategy:)` initializer. ```swift let date = Date("2025-06-15T12:00:00Z", strategy: .iso8601) ``` -------------------------------- ### Sheet with Item Initializer in SwiftUI Source: https://github.com/twostraws/swiftui-agent-skill/blob/main/swiftui-pro/references/navigation.md When using `sheet(item:)` with a view that accepts the item as its sole initializer parameter, use the `content:` parameter for a more concise syntax. ```swift .sheet(item: $someItem, content: SomeView.init) ``` -------------------------------- ### SwiftUI Numeric TextField with Format Source: https://context7.com/twostraws/swiftui-agent-skill/llms.txt Shows how to use `TextField` with a `value` binding and a `.number` format, combined with `.keyboardType(.numberPad)` for a better user experience when entering numeric data. ```swift // ✅ Numeric TextField with format TextField("Score", value: $score, format: .number) .keyboardType(.numberPad) ``` -------------------------------- ### Import Combine for ObservableObject Source: https://github.com/twostraws/swiftui-agent-skill/blob/main/swiftui-pro/references/api.md When using `ObservableObject`, ensure `import Combine` is explicitly added, as it's no longer implicitly provided by SwiftUI. ```swift import Combine class MyViewModel: ObservableObject { // ... } ``` -------------------------------- ### SwiftUI NavigationStack with navigationDestination Source: https://context7.com/twostraws/swiftui-agent-skill/llms.txt Demonstrates the modern navigation approach using `NavigationStack` and `navigationDestination(for:)`. This replaces the deprecated `NavigationView` and `NavigationLink(destination:)`. ```swift // ❌ Deprecated NavigationView + NavigationLink(destination:) NavigationView { NavigationLink(destination: DetailView(item: item)) { Text(item.title) } } // ✅ NavigationStack + navigationDestination(for:) NavigationStack(path: $path) { List(items) { item in NavigationLink(value: item) { Text(item.title) } } .navigationDestination(for: Item.self) { item in DetailView(item: item) } } ``` -------------------------------- ### Provide Accessibility Labels for Images Source: https://github.com/twostraws/swiftui-agent-skill/blob/main/swiftui-pro/references/accessibility.md Ensure images have clear VoiceOver readings. Use `Image(decorative:)` or `accessibilityHidden()` for purely decorative images, and `accessibilityLabel()` for informative ones. ```swift Image(.newBanner2026) .accessibilityLabel("A banner showing the latest product updates.") ``` ```swift Image(decorative: "decorativeIcon") ``` ```swift Image("logo") .accessibilityHidden(true) ``` -------------------------------- ### Optimize SwiftUI Performance with Stable Identity and Lazy Loading Source: https://context7.com/twostraws/swiftui-agent-skill/llms.txt Avoid view identity churn and expensive computations by using ternary operators for conditional views and pre-computing data. Utilize LazyVStack for large datasets. ```swift // ❌ Performance anti-patterns // Creates _ConditionalContent, destroys/recreates platform view on toggle if isHighlighted { Text(item.title).background(.yellow) } else { Text(item.title).background(.clear) } // Expensive inline transform inside List — runs on every body call List(items) { item in ForEach(items.filter { $0.isActive }.sorted { $0.date > $1.date }) { ... } } // Escaping ViewBuilder closure stored on view struct CardView: View { let content: () -> Content } // ✅ Performant alternatives Text(item.title).background(isHighlighted ? .yellow : .clear) // ternary: stable identity // Pre-compute and cache derived data @State private var activeItems: [Item] = [] // ... invalidated explicitly via onChange or task // LazyVStack for large data sets in ScrollView ScrollView { LazyVStack { ForEach(items) { item in ItemRow(item: item) } } } // Stored view value, not escaping closure struct CardView: View { @ViewBuilder let content: Content var body: some View { VStack { content }.padding().clipShape(.rect(cornerRadius: 8)) } } // ✅ Text formatting inline — no stored DateFormatter needed Text(Date.now, format: .dateTime.day().month().year()) Text(price, format: .currency(code: "USD")) // ✅ Prefer task() over onAppear() for async work (auto-cancelled on disappear) .task { await viewModel.loadData() } ``` -------------------------------- ### Type-Safe String Catalogs in SwiftUI Source: https://context7.com/twostraws/swiftui-agent-skill/llms.txt Utilize Swift's string catalogs for localization and access localized strings using generated, type-safe symbol keys. ```swift // Localizable.xcstrings defines key "welcomeTitle" with extractionState: "manual" Text(.welcomeTitle) // type-safe generated symbol access ``` -------------------------------- ### Modern Swift String and Formatting APIs Source: https://context7.com/twostraws/swiftui-agent-skill/llms.txt Use native string methods like `replacing` and `FormatStyle` for cleaner and more efficient text manipulation. Avoid older methods like `replacingOccurrences` and `String(format:)`. ```swift str.replacing("a", with: "b") Text(value, format: .number.precision(.fractionLength(2))) ``` -------------------------------- ### Chaining Animations with Completion Closures Source: https://github.com/twostraws/swiftui-agent-skill/blob/main/swiftui-pro/references/views.md Use `withAnimation` with a completion closure to chain animations sequentially. This avoids mixing layout and logic by separating animation steps. ```swift Button("Animate Me") { withAnimation { scale = 2 } completion: { withAnimation { scale = 1 } } } ``` -------------------------------- ### Trigger SwiftUI Pro Skill in Codex Source: https://github.com/twostraws/swiftui-agent-skill/blob/main/README.md Invoke the SwiftUI Pro skill in Codex using the specified command. You can add specific instructions for targeted reviews. ```bash $swiftui-pro Focus on accessibility ``` -------------------------------- ### Xcode MCP for Preview Rendering Source: https://context7.com/twostraws/swiftui-agent-skill/llms.txt Use Xcode's MCP (Meta Code Processing) tool to render SwiftUI previews directly within the code editor. ```swift // RenderPreview(target: "ContentView") // DocumentationSearch(query: "NavigationStack") ``` -------------------------------- ### Modern Swift Concurrency and Task Management Source: https://context7.com/twostraws/swiftui-agent-skill/llms.txt Prefer `async/await` with `MainActor.run` or `@MainActor` for main thread operations and use `Task.sleep(for:)` for asynchronous delays. ```swift await MainActor.run { refresh() } // or mark the function @MainActor try await Task.sleep(for: .seconds(1)) ``` -------------------------------- ### Use Dynamic Type for Fonts Source: https://github.com/twostraws/swiftui-agent-skill/blob/main/swiftui-pro/references/accessibility.md Prefer using standard text styles like `.body` and `.headline` to respect the user's Dynamic Type settings. Avoid forcing specific font sizes. ```swift Text("Hello, World!") .font(.body) ``` ```swift Text("Important Title") .font(.headline) ``` -------------------------------- ### Manage Animations with Reduce Motion Source: https://github.com/twostraws/swiftui-agent-skill/blob/main/swiftui-pro/references/accessibility.md When the user has "Reduce Motion" enabled, replace complex animations with simpler alternatives like opacity changes. ```swift struct AnimatedView: View { @Environment("reduceMotion") var reduceMotion var body: some View { if reduceMotion { Color.blue.opacity(0.5) } else { // Complex animation RoundedRectangle(cornerRadius: 10) .fill(Color.blue) .scaleEffect(1.2) .animation(.easeInOut(duration: 1), value: true) } } } ``` -------------------------------- ### Accessible Menus Source: https://github.com/twostraws/swiftui-agent-skill/blob/main/swiftui-pro/references/accessibility.md Provide accessible labels for menus. Using a text and system image combination is preferred over just an icon. Use `.labelStyle(.iconOnly)` if the menu trigger must be visually icon-only. ```swift Menu("Options", systemImage: "ellipsis.circle") { /* menu items */ } Menu { /* menu items */ } label: { Image(systemName: "gear") .labelStyle(.iconOnly) } ``` -------------------------------- ### Unit Testing Core Logic Source: https://context7.com/twostraws/swiftui-agent-skill/llms.txt Write unit tests for the core logic of your application to ensure correctness. UI tests should be reserved for scenarios that cannot be covered by unit tests. ```swift func testScoreCalculation() { #expect(calculateScore(streak: 3) == 150) #expect(calculateScore(streak: 0) == 100) } ``` -------------------------------- ### Swift PersonNameComponents for Name Formatting Source: https://context7.com/twostraws/swiftui-agent-skill/llms.txt Leverage `PersonNameComponents` to manage and format names according to locale-specific conventions. ```swift var nameComponents = PersonNameComponents() nameComponents.givenName = firstName nameComponents.familyName = lastName Text(nameComponents.formatted()) ``` -------------------------------- ### Use accessibilityInputLabels for Voice Control Source: https://github.com/twostraws/swiftui-agent-skill/blob/main/swiftui-pro/references/accessibility.md For buttons with dynamic or complex labels, provide `accessibilityInputLabels` to offer better Voice Control commands. This is useful for live-updating information. ```swift Button("AAPL $271.68") { /* action */ } .accessibilityInputLabels(["Apple stock price"]) ``` -------------------------------- ### Trigger SwiftUI Pro Skill in Claude Code Source: https://github.com/twostraws/swiftui-agent-skill/blob/main/README.md Invoke the SwiftUI Pro skill in Claude Code using the specified command. You can add specific instructions for targeted reviews. ```bash /swiftui-pro Check for deprecated API ``` -------------------------------- ### SwiftUI Data Flow: Legacy vs. Modern Observable Patterns Source: https://context7.com/twostraws/swiftui-agent-skill/llms.txt Compares the legacy `ObservableObject` pattern with the modern `@Observable` macro. `@Observable` classes should be `@MainActor`-isolated for proper data flow on the main thread. ```swift // ❌ Legacy ObservableObject pattern class UserStore: ObservableObject { @Published var name = "" @Published var score = 0 } struct ContentView: View { @StateObject private var store = UserStore() } ``` ```swift // ✅ Modern @Observable pattern @Observable @MainActor class UserStore { var name = "" var score = 0 } struct ContentView: View { @State private var store = UserStore() // owned here var body: some View { ChildView(store: store) // passed as @Bindable or @Environment } } ``` -------------------------------- ### Ensure Accessible UI Elements in SwiftUI Source: https://context7.com/twostraws/swiftui-agent-skill/llms.txt Use accessible equivalents for UI elements to improve VoiceOver compatibility and Dynamic Type support. Ensure buttons have clear labels and minimum tap targets. ```swift // ❌ Accessibility violations Image(.newBanner2026) // unclear VoiceOver label Button(action: addItem) { Image(systemName: "plus") // invisible to VoiceOver } Text("Price").font(.system(size: 12)) // fixed font size someView.onTapGesture { navigate() } // not a button // ✅ Accessible equivalents Image(decorative: .newBanner2026) // purely decorative Button("Add Item", systemImage: "plus", action: addItem) // has text label // If the button must visually show only the icon: Button("Add Item", systemImage: "plus", action: addItem) .labelStyle(.iconOnly) // visual-only, VoiceOver still reads "Add Item" Text("Price").font(.body) // Dynamic Type scales automatically // ✅ Custom font scaling (iOS 26+) Text("Price").font(.body.scaled(by: 0.9)) // ✅ Reduce Motion compliance @Environment(\.accessibilityReduceMotion) var reduceMotion Circle() .scaleEffect(isExpanded ? 2 : 1) .animation(reduceMotion ? .none : .spring, value: isExpanded) // ✅ Voice Control input labels for frequently-changing button labels Button("AAPL $271.68") { showDetail() } .accessibilityInputLabels(["Apple", "Apple stock"]) // ✅ Minimum 44pt tap target Button("Tap me") { } .frame(minWidth: 44, minHeight: 44) ``` -------------------------------- ### Differentiate Without Color Source: https://github.com/twostraws/swiftui-agent-skill/blob/main/swiftui-pro/references/accessibility.md If color is a key differentiator, ensure there are other visual cues like icons or patterns to support users with color blindness, respecting the `.accessibilityDifferentiateWithoutColor` environment setting. ```swift struct ColorCodedView: View { @Environment("accessibilityDifferentiateWithoutColor") var differentiateWithoutColor var body: some View { if differentiateWithoutColor { Image(systemName: "checkmark.circle.fill") } else { Circle().fill(.green) } } } ``` -------------------------------- ### Modern Swift Collection Filtering and Sorting Source: https://context7.com/twostraws/swiftui-agent-skill/llms.txt Employ the `count(where:)` method for more concise collection filtering and ensure custom types conform to `Comparable` for simpler sorting. ```swift let count = items.count(where: \.isActive) // Make Book: Comparable, then just books.sorted() ``` -------------------------------- ### SwiftUI Alert with No Buttons Source: https://context7.com/twostraws/swiftui-agent-skill/llms.txt Illustrates presenting an alert with no explicit buttons, which results in a single dismiss button. This is suitable for simple informational alerts. ```swift // ✅ Alert with no buttons (single dismiss — button can be omitted) .alert("Operation complete", isPresented: $showAlert) { } ``` -------------------------------- ### Swift Expressions for Conditional Logic Source: https://context7.com/twostraws/swiftui-agent-skill/llms.txt Use `if` and `switch` statements as expressions to directly assign values to variables or return them from computed properties. ```swift var tileColor: Color { if isCorrect { .green } else { .red } } ``` -------------------------------- ### Bind TextField to Numeric Value with Formatting Source: https://github.com/twostraws/swiftui-agent-skill/blob/main/swiftui-pro/references/data.md When a user needs to enter a number into a TextField, bind it to a numeric type like Int or Double. Use the `.number` format initializer and apply the appropriate keyboard type modifier. ```swift TextField("Enter your score", value: $score, format: .number) .keyboardType(.numberPad) ``` -------------------------------- ### Sheet with Optional Data in SwiftUI Source: https://github.com/twostraws/swiftui-agent-skill/blob/main/swiftui-pro/references/navigation.md Prefer `sheet(item:)` over `sheet(isPresented:)` when presenting a sheet with optional data to ensure safe unwrapping. ```swift struct ContentView: View { @State private var selectedItem: Item? var body: some View { Button("Show Sheet") { selectedItem = Item() } .sheet(item: $selectedItem) { item in DetailView(item: item) } } } struct Item: Identifiable { var id: UUID = UUID() } struct DetailView: View { let item: Item var body: some View { Text("Detail for item \(item.id)") } } ``` -------------------------------- ### Swift Locale-Aware String Searching Source: https://context7.com/twostraws/swiftui-agent-skill/llms.txt Use `localizedStandardContains` for case-insensitive and accent-insensitive string searching that respects locale. ```swift let results = books.filter { $0.title.localizedStandardContains(query) } ``` -------------------------------- ### Use foregroundStyle() instead of foregroundColor() Source: https://github.com/twostraws/swiftui-agent-skill/blob/main/swiftui-pro/skills/swiftui-pro/SKILL.md Replaces the deprecated `foregroundColor()` modifier with the modern `foregroundStyle()` for better control over text and foreground element styling. ```swift // Before Text("Hello").foregroundColor(.red) // After Text("Hello").foregroundStyle(.red) ``` -------------------------------- ### Use Buttons Instead of onTapGesture Source: https://github.com/twostraws/swiftui-agent-skill/blob/main/swiftui-pro/references/accessibility.md Prefer using `Button` for tappable elements unless tap location or count is specifically needed. If `onTapGesture` must be used, add accessibility traits like `.isButton`. ```swift Rectangle() .fill(Color.red) .frame(width: 100, height: 100) .onTapGesture { // Action } .accessibilityAddTraits(.isButton) ``` -------------------------------- ### Add text label to icon-only button for VoiceOver Source: https://github.com/twostraws/swiftui-agent-skill/blob/main/swiftui-pro/skills/swiftui-pro/SKILL.md Improves accessibility by adding a text label to icon-only buttons, making them understandable for VoiceOver users. Use the `Button` initializer that accepts a title, system image, and action. ```swift // Before Button(action: addUser) { Image(systemName: "plus") } // After Button("Add User", systemImage: "plus", action: addUser) ``` -------------------------------- ### Securely Storing Sensitive Data with Keychain Source: https://context7.com/twostraws/swiftui-agent-skill/llms.txt Avoid storing sensitive information like authentication tokens directly in `@AppStorage`. Use the Keychain for secure storage. ```swift @AppStorage("authToken") var token: String = "" // sensitive — use Keychain // API key hard-coded in source file // ✅ Use Keychain for sensitive data import Security // Store via SecItemAdd / SecItemCopyMatching ``` -------------------------------- ### Prefer Expression Bodies for Simple Returns in Swift Source: https://github.com/twostraws/swiftui-agent-skill/blob/main/swiftui-pro/references/swift.md Use expression bodies for simple computed properties to reduce boilerplate. This applies when the body consists of a single expression that is implicitly returned. ```swift var tileColor: Color { if isCorrect { .green } else { .red } } ``` -------------------------------- ### Dismissible Alert in SwiftUI Source: https://github.com/twostraws/swiftui-agent-skill/blob/main/swiftui-pro/references/navigation.md Use an empty closure for the alert's actions to create a dismissible alert with no explicit buttons. ```swift .alert("Dismiss Me", isPresented: $isShowingAlert) { } ``` -------------------------------- ### Include Text Labels for Image Buttons Source: https://github.com/twostraws/swiftui-agent-skill/blob/main/swiftui-pro/references/accessibility.md Buttons with image labels must always include an accessible text label, even if visually hidden. Use `.labelStyle(.iconOnly)` if the button must remain visually icon-only. ```swift Button("Add Item", systemImage: "plus") { myAction } Button("Settings") { /* action */ } .labelStyle(.iconOnly) ``` -------------------------------- ### Avoid Text Concatenation with + Source: https://github.com/twostraws/swiftui-agent-skill/blob/main/swiftui-pro/references/api.md Do not use `+` for Text concatenation. Instead, use text interpolation for combining attributed strings. ```swift Text("Hello").foregroundStyle(.red) + Text("World").foregroundStyle(.blue) ``` ```swift let red = Text("Hello").foregroundStyle(.red) let blue = Text("World").foregroundStyle(.blue) Text("\(red)\(blue)") ``` -------------------------------- ### SwiftUI Identifiable Structs Source: https://context7.com/twostraws/swiftui-agent-skill/llms.txt Highlights the use of `Identifiable` structs with a default `UUID` for `id`. This simplifies collection views like `ForEach` as explicit `id: \.id` is no longer needed. ```swift // ✅ Identifiable structs instead of id: keypath struct Book: Identifiable { let id = UUID() var title: String } // No need for: ForEach(books, id: \.id) — just ForEach(books) ``` -------------------------------- ### Custom Font Scaling with @ScaledMetric Source: https://github.com/twostraws/swiftui-agent-skill/blob/main/swiftui-pro/references/accessibility.md For custom font sizes on iOS 18 and earlier, use `@ScaledMetric` to ensure fonts scale with user preferences. For iOS 26+, `.font(.body.scaled(by:))` is also available. ```swift @ScaledMetric var customFontSize: CGFloat = 18 Text("Custom Font") .font(.system(size: customFontSize)) ``` -------------------------------- ### Avoid Escaping Closures in View Initializers Source: https://github.com/twostraws/swiftui-agent-skill/blob/main/swiftui-pro/references/performance.md Prefer storing built view values directly instead of escaping `@ViewBuilder` closures. The synthesized initializer handles calling the builder, leading to more efficient view composition. ```swift struct CardView: View { let content: () -> Content var body: some View { VStack(alignment: .leading) { content() } .padding() .background(.ultraThinMaterial) .clipShape(.rect(cornerRadius: 8)) } } ``` ```swift struct CardView: View { @ViewBuilder let content: Content var body: some View { VStack(alignment: .leading) { content } .padding() .background(.ultraThinMaterial) .clipShape(.rect(cornerRadius: 8)) } } ``` -------------------------------- ### SwiftUI Animatable Modifier with @Animatable Macro Source: https://context7.com/twostraws/swiftui-agent-skill/llms.txt Shows how to create animatable view modifiers using the `@Animatable` macro. Note that properties like `Bool` marked with `@AnimatableIgnored` cannot be animated. ```swift // ✅ @Animatable macro @Animatable struct WaveModifier: ViewModifier, Animatable { var amplitude: Double @AnimatableIgnored var isEnabled: Bool // Bool cannot be animated func body(content: Content) -> some View { content.offset(y: isEnabled ? sin(amplitude) * 10 : 0) } } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.