swiftui-input-api
SKILL.md
User Input API Reference
Lifecycle Position
Phase 3 API Reference — load during implementation when building forms, text fields, or interactive controls. Dispatched from autonomous-ui-workflow Phase 2 research table.
Text Input
TextField("Username", text: $username)
TextField(text: $username, prompt: Text("Required")) { Text("Username") }
SecureField("Password", text: $password)
TextEditor(text: $notes)
TextEditor(text: $attributedText, selection: $selection) // rich text
Text Modifiers
| Modifier | Purpose |
|---|---|
.autocorrectionDisabled() |
Disable autocorrect |
.keyboardType(_:) |
Keyboard type (iOS) |
.scrollDismissesKeyboard(_:) |
Dismiss on scroll |
.textInputAutocapitalization(_:) |
Auto-caps |
.textInputSuggestions { } |
Custom suggestions |
.textContentType(_:) |
Content type hints |
.textSelection(_:) |
Enable/disable selection |
Controls
Picker("Choice", selection: $choice) { Text("A").tag(0) }.pickerStyle(.menu)
Slider(value: $volume, in: 0...100)
Stepper("Qty: \(count)", value: $count, in: 1...10)
Toggle("Feature", isOn: $isEnabled).toggleStyle(.switch)
Keyboard Shortcuts
Button("Save") { save() }.keyboardShortcut("s", modifiers: .command)
Button("OK") { confirm() }.keyboardShortcut(.defaultAction)
Key Press Handling
.onKeyPress(.return) { submit(); return .handled }
.onKeyPress(phases: .down) { keyPress in return .handled }
.onKeyPress(characters: .alphanumerics, phases: .down) { _ in .handled }
.onModifierKeysChanged(mask: .shift) { old, new in }
When to Use Which
| Need | Use |
|---|---|
| Single-line text entry | TextField("Placeholder", text: $value) |
| Password/secret entry | SecureField("Password", text: $password) |
| Multi-line text editing | TextEditor(text: $body) or TextField with .lineLimit(3...6) (iOS 16+) |
| Email/URL/phone input | TextField with .textContentType(.emailAddress) and .keyboardType(.emailAddress) |
| Date/time selection | DatePicker("Date", selection: $date) |
| Color selection | ColorPicker("Color", selection: $color) |
| Numeric stepper | Stepper("Count: \(count)", value: $count, in: 0...100) |
| Form field navigation | @FocusState with .focused($focus, equals: .field) |
| Search filtering | .searchable(text: $search) on NavigationStack |
Focus Management (Critical for forms)
enum Field: Hashable { case name, email, password }
@FocusState private var focus: Field?
TextField("Name", text: $name)
.focused($focus, equals: .name)
.onSubmit { focus = .email }
.submitLabel(.next)
TextField("Email", text: $email)
.focused($focus, equals: .email)
.textContentType(.emailAddress)
.onSubmit { focus = .password }
.submitLabel(.next)
SecureField("Password", text: $password)
.focused($focus, equals: .password)
.onSubmit { submit() }
.submitLabel(.done)
macOS Form Conventions
- Use
ForminSettingsscene for preference windows - Use
LabeledContent("Label") { control }for aligned form rows - Use
Toggle,Pickerwith.pickerStyle(.menu)for macOS-native feel - Keyboard shortcuts:
.keyboardShortcut("s", modifiers: .command)on save buttons
Common Mistakes
- No
@FocusStatein forms — user can't Tab between fields on macOS or use Next on iOS keyboard - TextField without
.textContentType()— misses AutoFill for emails, passwords, addresses - Using
onTapGestureto dismiss keyboard instead of.scrollDismissesKeyboard(.interactively) - Missing
.submitLabel()— iOS keyboard shows generic "return" instead of "Next"/"Done"/"Search" DatePickerwithout.datePickerStyle()on macOS — defaults may not fit the layout
Before (incorrect):
// Form with no focus management:
TextField("Email", text: $email)
TextField("Password", text: $password)
// User must tap each field manually; Tab does nothing on macOS
After (correct):
enum Field: Hashable { case email, password }
@FocusState private var focus: Field?
TextField("Email", text: $email)
.focused($focus, equals: .email)
.textContentType(.emailAddress)
.submitLabel(.next)
.onSubmit { focus = .password }
SecureField("Password", text: $password)
.focused($focus, equals: .password)
.textContentType(.password)
.submitLabel(.done)
.onSubmit { login() }
Before (incorrect):
// Dismiss keyboard on tap — brittle, misses scroll gesture:
.onTapGesture { UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder), ...) }
After (correct):
ScrollView {
// form content
}
.scrollDismissesKeyboard(.interactively)
Checklist
- All form fields have
@FocusStatefor keyboard/Tab navigation - Text fields have
.textContentType()for AutoFill -
.submitLabel()set on all text fields in forms -
.onSubmitchains focus to next field (or submits on last field) - macOS forms use
LabeledContentfor alignment -
.searchable()used instead of custom search TextField in navigation contexts
Cross-References
swiftui-presentation-api— sheets and alerts that contain formsswiftui-typography-api— text styles for form labelsswiftui-ui-patterns— state management for form data (@Observableview model pattern)swiftui-26-api— iOS 26 rich text:AttributedTextSelection,AttributedTextFormattingDefinition,FindContext
Weekly Installs
2
Repository
kmshdev/claude-…-toolkitFirst Seen
1 day ago
Security Audits
Installed on
mcpjam2
claude-code2
replit2
junie2
windsurf2
zencoder2