This commit is contained in:
Thomas Ricouard 2026-03-15 11:12:21 +01:00
parent b638136486
commit fe34551d78
3 changed files with 43 additions and 41 deletions

View file

@ -88,46 +88,6 @@ Use `references/components-index.md` as the entry point. Each component referenc
- Pitfalls and performance notes.
- Paths to existing examples in the current repo.
For detail surfaces that progressively reveal actions, metadata, or contextual panels, use `references/scroll-reveal.md`.
## Sheet patterns
### Item-driven sheet (preferred)
```swift
@State private var selectedItem: Item?
.sheet(item: $selectedItem) { item in
EditItemSheet(item: item)
}
```
### Sheet owns its actions
```swift
struct EditItemSheet: View {
@Environment(\.dismiss) private var dismiss
@Environment(Store.self) private var store
let item: Item
@State private var isSaving = false
var body: some View {
VStack {
Button(isSaving ? "Saving…" : "Save") {
Task { await save() }
}
}
}
private func save() async {
isSaving = true
await store.save(item)
dismiss()
}
}
```
## Adding a new component reference
- Create `references/<component>.md`.

View file

@ -6,7 +6,7 @@ Use this file to find component and cross-cutting guidance. Each entry lists whe
- TabView: `references/tabview.md` — Use when building a tab-based app or any tabbed feature set.
- NavigationStack: `references/navigationstack.md` — Use when you need push navigation and programmatic routing, especially per-tab history.
- Sheets and modal routing: `references/sheets.md` — Use when you want centralized, enum-driven sheet presentation.
- Sheets and presentation: `references/sheets.md` — Use for local item-driven sheets, centralized modal routing, and sheet-specific action patterns.
- Form and Settings: `references/form.md` — Use for settings, grouped inputs, and structured data entry.
- macOS Settings: `references/macos-settings.md` — Use when building a macOS Settings window with SwiftUI's Settings scene.
- Split views and columns: `references/split-views.md` — Use for iPad/macOS multi-column layouts or custom secondary columns.

View file

@ -11,6 +11,18 @@ Use a centralized sheet routing pattern so any view can present modals without p
- Create a view modifier like `withSheetDestinations(...)` that maps the enum to concrete sheet views.
- Inject the router into the environment so child views can set `presentedSheet` directly.
## Example: item-driven local sheet
Use this when sheet state is local to one screen and does not need centralized routing.
```swift
@State private var selectedItem: Item?
.sheet(item: $selectedItem) { item in
EditItemSheet(item: item)
}
```
## Example: SheetDestination enum
```swift
@ -99,15 +111,45 @@ struct NavigationSheet<Content: View>: View {
}
```
## Example: sheet owns its actions
Keep dismissal and confirmation logic inside the sheet when the actions belong to the modal itself.
```swift
struct EditItemSheet: View {
@Environment(\.dismiss) private var dismiss
@Environment(Store.self) private var store
let item: Item
@State private var isSaving = false
var body: some View {
VStack {
Button(isSaving ? "Saving..." : "Save") {
Task { await save() }
}
}
}
private func save() async {
isSaving = true
await store.save(item)
dismiss()
}
}
```
## Design choices to keep
- Centralize sheet routing so features can present modals without wiring bindings through many layers.
- Use `sheet(item:)` to guarantee a single sheet is active and to drive presentation from the enum.
- Group related sheets under the same `id` when they are mutually exclusive (e.g., editor flows).
- Keep sheet views lightweight and composed from smaller views; avoid large monoliths.
- Let sheets own their actions and call `dismiss()` internally instead of forwarding `onCancel` or `onConfirm` closures through many layers.
## Pitfalls
- Avoid mixing `sheet(isPresented:)` and `sheet(item:)` for the same concern; prefer a single enum.
- Avoid `if let` inside a sheet body when the presentation state already carries the selected model; prefer `sheet(item:)`.
- Do not store heavy state inside `SheetDestination`; pass lightweight identifiers or models.
- If multiple sheets can appear from the same screen, give them distinct `id` values.