home / skills / willsigmon / sigstack / modal-sheet-debugger

modal-sheet-debugger skill

/plugins/ios-dev/skills/modal-sheet-debugger

This skill helps you fix SwiftUI sheet presentation issues in Leavn by resolving competing sheets, consolidating patterns, and ensuring proper dismissal and

npx playbooks add skill willsigmon/sigstack --skill modal-sheet-debugger

Review the files below or copy the command above to add this skill to your agents.

Files (1)
SKILL.md
790 B
---
name: Modal Sheet Debugger
description: Fix SwiftUI sheet presentation issues in Leavn - competing sheets, dismissal patterns, binding synchronization, enum-based consolidation
allowed-tools: Read, Edit, Grep
---

# Modal Sheet Debugger

Fix sheet presentation issues:

1. **Find competing sheets**: Multiple `.sheet()` modifiers on same view
2. **Consolidate pattern**:
   ```swift
   enum SheetType: Identifiable {
       case optionA, optionB
       var id: String { ... }
   }
   @State var activeSheet: SheetType?
   .sheet(item: $activeSheet) { type in
       switch type { ... }
   }
   ```

3. **Fix dismissal**: Update binding before dismiss()
4. **Check bindings**: Ensure parent and environment in sync

Use when: Multiple sheets conflict, dismissal bugs, sheet state issues

Overview

This skill helps diagnose and fix SwiftUI sheet presentation problems in Leavn. It locates conflicting sheet modifiers, consolidates multiple sheets into a single enum-driven sheet, and recommends fixes for dismissal and binding synchronization. The goal is reliable, predictable modal behavior across view hierarchies.

How this skill works

It inspects view hierarchies and sheet usage patterns to find multiple .sheet() modifiers attached to the same view or overlapping view scopes. It suggests consolidating into a single Identifiable-driven sheet using an enum, ensures you update state bindings before calling dismiss(), and checks that parent state and environment bindings remain synchronized. It also points out common binding race conditions and state propagation issues.

When to use it

  • Multiple sheets are declared on the same view or nested views causing unpredictable presentations
  • Tap actions or programmatic flows dismiss one sheet and immediately present another, causing flicker or no-op behavior
  • Dismissal callbacks appear to fire out of order or UI state lags behind dismiss() calls
  • State for sheet visibility is kept in multiple places (parent and child) and gets out of sync
  • You want to centralize modal types for easier routing and testing

Best practices

  • Use a single .sheet(item:) backed by an Identifiable enum for all modal variants
  • Update the backing binding (activeSheet = nil or new value) before calling dismiss() to avoid race conditions
  • Avoid attaching multiple .sheet modifiers to the same view; move presentation control to a single coordinator view or parent
  • Make bindings the single source of truth—pass the binding down or use environment objects consistently
  • Prefer enum-based consolidation to keep switch logic and view construction in one place

Example use cases

  • Convert two .sheet() modifiers into one by creating SheetType: Identifiable and storing @State var activeSheet
  • Fix a dismissal bug where dismiss() returns to the wrong screen by clearing the activeSheet binding first
  • Resolve presentation conflicts in nested NavigationViews by presenting sheets from a top-level coordinator view
  • Debug a flow where tapping a button should replace one sheet with another, but both compete to present
  • Ensure parent view state and sheet child environment bindings reflect the same value to avoid stale UI

FAQ

Why do multiple .sheet modifiers cause issues?

SwiftUI can only reliably manage one active sheet per view scope; multiple modifiers can compete and produce unpredictable presentation behavior.

How does an Identifiable enum help?

An enum as Identifiable centralizes modal types so a single .sheet(item:) can switch on the enum to present different content without modifier conflicts.