feedback-states
Skill4 starsChanged 6 months agoMITView on GitHub
Use when implementing loading, error, empty, or success states. Covers Loadable switch handling, mutation buttons, loading indicators.
In this repository76 other files it gives its agents.
- AGENTS.mdAGENTS.md
- CLAUDE.mdCLAUDE.md
- .cursor/rules/components.mdcCursor rule
- .cursor/rules/currency.mdcCursor rule
- .cursor/rules/design-system.mdcCursor rule
- .cursor/rules/file-structure.mdcCursor rule
- .cursor/rules/forbidden-patterns.mdcCursor rule
- .cursor/rules/mvvm-architecture.mdcCursor rule
- .cursor/rules/pricing-display.mdcCursor rule
- .cursor/rules/scope.mdcCursor rule
- .cursor/rules/swift-conventions.mdcCursor rule
- accessibilitySkill
- animationsSkill
- apple-developer-authSkill
- apple-signinSkill
- app-store-preflightSkill
- asc-app-create-uiSkill
- asc-aso-auditSkill
- asc-build-lifecycleSkill
- asc-cli-usageSkill
- asc-crash-triageSkill
- asc-id-resolverSkill
- asc-localize-metadataSkill
- asc-metadata-syncSkill
- asc-metadata-yamlSkill
- asc-notarizationSkill
- asc-ppp-pricingSkill
- asc-release-flowSkill
- asc-revenuecat-catalog-syncSkill
- asc-screenshot-resizeSkill
- asc-shots-pipelineSkill
- asc-signing-setupSkill
- ascSkill
- asc-submission-healthSkill
- asc-subscription-localizationSkill
- asc-testflight-orchestrationSkill
- asc-wall-submitSkill
- asc-whats-new-writerSkill
- asc-workflowSkill
- asc-xcode-buildSkill
- billing-finance-calculatorSkill
- buildSkill
- business-modelSkill
- chartsSkill
- consolidate-errorsSkill
- content-composerSkill
- crashSkill
- debuggingSkill
- feature-directory-structureSkill
- fix-errorSkill
- formsSkill
- foundation-modelsSkill
- hapticsSkill
- healthkitSkill
- layoutSkill
- listsSkill
- navigationSkill
- notificationsSkill
- onboarding-questionnaireSkill
- onboardingSkill
- The first 60 shown.
The file
We split this skill into the rules it gives an agent
11 rules. About 0 are common, 8 are distinctive, and 3 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈8
Distinctive · estimate
This author's own choices. Worth a look.
3
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 8
Use this guide when implementing loading, error, empty, and success states.
- Very specific: line 11
Every view displaying async data MUST switch on Loadable<T>:
- Very specific: line 31
NEVER use if let to unwrap only success — all 4 states must be handled.
- Distinctive: line 34
Every mutation button (save, delete) MUST disable while loading and show inline spinner:
- Distinctive: line 62
Always provide a retry path — never leave users stuck.
- Distinctive: line 67
NEVER use modal alert for success — too disruptive
- Distinctive: line 71
Always explain WHY disabled (caption text below button)
- Distinctive: line 72
Don't hide actions — show them disabled with explanation
- Distinctive: line 76
ALWAYS disable triggering button while loading
- Distinctive: line 77
Never block entire UI for partial operation — use inline spinner
- Very specific: line 78
Use Loadable<T> for all async state — never var isLoading: Bool
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Feedback States
Use this guide when implementing loading, error, empty, and success states.
MANDATORY: Handle All 4 Loadable States
Every view displaying async data MUST switch on Loadable<T>:
switch viewModel.items {
case .notInitiated, .loading:
ProgressView("Loading...")
case .success(let items) where items.isEmpty:
ContentUnavailableView("No Items Yet", systemImage: "tray",
description: Text("Tap + to create your first item"))
case .success(let items):
List(items) { item in ItemRow(item: item) }
case .failure(let error):
ContentUnavailableView {
Label("Load Failed", systemImage: "exclamationmark.triangle")
} description: {
Text(error.localizedDescription)
} actions: {
Button("Retry") { Task { await viewModel.loadItems() } }
}
}NEVER use if let to unwrap only success — all 4 states must be handled.
Mutation Button Pattern
Every mutation button (save, delete) MUST disable while loading and show inline spinner:
Button {
Task { await viewModel.save() }
} label: {
if viewModel.saveState.isLoading {
ProgressView().controlSize(.small)
} else {
Text("Save")
}
}
.disabled(viewModel.saveState.isLoading)Loading Patterns
| Pattern | Use Case | Code |
| Inline spinner | Button action | ProgressView().controlSize(.small) |
| Full-screen | Initial load | ProgressView("Loading...") |
| Pull-to-refresh | List refresh | .refreshable { await refresh() } |
| Skeleton | Content placeholder | .redacted(reason: .placeholder) |
| Overlay | Blocking operation | .overlay { if loading { ProgressView() } } |
Error Handling UI
- Inline validation — show immediately below form fields
- Alert — for blocking errors (network failure, permission denied)
- Banner — for non-critical errors (sync failed, partial data)
Always provide a retry path — never leave users stuck.
Success Feedback
- Haptic:
UINotificationFeedbackGenerator().notificationOccurred(.success) - Visual: brief animation (checkmark, scale bounce)
- NEVER use modal alert for success — too disruptive
Disabled State
.disabled(condition)— SwiftUI auto-handles opacity- Always explain WHY disabled (caption text below button)
- Don't hide actions — show them disabled with explanation
Rules
- Show indicator for operations > 300ms
- ALWAYS disable triggering button while loading
- Never block entire UI for partial operation — use inline spinner
- Use
Loadable<T>for all async state — nevervar isLoading: Bool
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

