Creates SwiftUI Views with ViewModel integration. Use when creating views, integrating with ViewModels, adding SwiftUI previews, implementing state rendering, or setting up accessibility identifiers and localized strings.
Guide for creating SwiftUI Views that use ViewModels with dependency injection.
This skill owns only Sources/Presentation/{Screen}/Views/ and its snapshot tests.
| Need | Delegate to |
|---|---|
| ViewModel creation | /viewmodel skill |
| Design tokens & components | /design-system skill |
| Snapshot tests setup | /snapshot skill |
| UI tests & robots | /ui-tests skill |
| Navigation wiring | /navigator skill |
| Type | When | Reference |
|---|
| Stateful | ViewModel has @Observable + state property | references/stateful.md |
| Stateless | ViewModel has actions only, no observable state | references/stateless.md |
Before creating the View, verify the required ViewModel exists in Sources/Presentation/{Screen}/ViewModels/.
/viewmodel skill first. Return here after completion.Read the appropriate reference from Step 1 and implement. Each reference includes: View struct, subviews, LocalizedStrings, AccessibilityIdentifier, previews, snapshot test stub, and snapshot test examples.
Sources/Presentation/{Screen}/Views/Tests/Shared/Stubs/Tests/Snapshots/Presentation/{Screen}/<ViewModel: {Screen}ViewModelContract> for testability@State private var viewModel with _viewModel = State(initialValue:) in initlet viewModel (no @State needed)public or private on View structCRITICAL: All views must use the
/design-systemskill for UI construction.
{AppName}DesignSystemDSCardInfoRow, DSAsyncImage, etc.)Pass accessibilityIdentifier: parameter or .dsAccessibilityIdentifier() to DS components. Identifiers propagate to children: .image, .title, .status suffixes.
{AppName}Resources, use .localized()Empty, Error){screenName}.{elementType}row(id:)).accessibilityIdentifier() for SwiftUI elements, .dsAccessibilityIdentifier() / accessibilityIdentifier: for DS components/* */) to exclude from coverageidle#if DEBUG@Observable stub with state injection + PreviewError enumfinal class stub with no-op methods, single previewRootContainerView and similar app-level containers are exceptions: not generic, no LocalizedStrings, no AccessibilityIdentifier, no .onFirstAppear. Located at AppKit/Sources/Presentation/Views/.
Features/{Feature}/
├── Sources/Presentation/{Screen}/
│ ├── Views/
│ │ └── {Screen}View.swift
│ └── ViewModels/
└── Tests/
├── Snapshots/Presentation/{Screen}/
│ ├── {Screen}ViewSnapshotTests.swift
│ └── __Snapshots__/
└── Shared/Stubs/
└── {Screen}ViewModelStub.swift
| Component | Visibility | Location |
|---|---|---|
| View | internal | Sources/Presentation/{Screen}/Views/ |
| LocalizedStrings | private | inside View file |
| AccessibilityIdentifier | private | inside View file |
| Preview stubs | private | inside View file (#if DEBUG) |
| Snapshot stub | internal | Tests/Shared/Stubs/ |
/design-system skill before building the view{AppName}Resources and {AppName}DesignSystemLocalizedStrings enumAccessibilityIdentifier enumidle)@State private var viewModel with State(initialValue:) init.onFirstAppear { await viewModel.didAppear() }@ViewBuilder content with switch viewModel.statelet viewModel (no @State).onFirstAppear { viewModel.didAppear() } (sync, no await)switch on state — layout is fixed