iOSforms-feedbackIntermediate

Designing Accessible Forms and Error Handling

Forms often require multiple inputs—such as name, email, address, or payment details—and any mistakes or omissions must be communicated clearly. If the error feedback isn’t sufficiently descriptive or can’t be detected by screen readers, users may become stuck and unable to complete essential tasks.

🎯 Why It Matters

Filling out forms can be a cumbersome process for many users, especially those who rely on screen readers or have motor impairments. Forms often require multiple inputs—such as name, email, address, or payment details—and any mistakes or omissions must be communicated clearly. If the error feedback isn't sufficiently descriptive or can't be detected by screen readers, users may become stuck and unable to complete essential tasks.

Key accessibility barriers this solution addresses:

  • Focus Management: Users need to know exactly which field has an error
  • Descriptive Error Messages: Feedback must be concise but meaningful—e.g., "Enter a valid email address" rather than "Invalid input"
  • Visual & Verbal Indicators: Use color, icons, or text for visual cues, while also ensuring screen readers can announce the issue

💻 Implementation

Correct Code Example: Creating an Accessible Form with Error Handling in SwiftUI

Demo Description

This is a simplified form that requests an email address and password. It includes real-time validation feedback and displays an error message when necessary. The same approach can be extended to complex forms with multiple fields.

// SwiftUI
 
TextField("Email Address", text: $email)
    .focused($focusedField, equals: .email)
    .accessibilityLabel("Email Address")
    .onChange(of: email) { _ in validateEmail() }
 
if let error = emailError {
    Text(error)
        .foregroundColor(.red)
        .accessibilityLabel(error)
}
 
SecureField("Password", text: $password)
    .focused($focusedField, equals: .password)
    .accessibilityLabel("Password")
    .onChange(of: password) { _ in validatePassword() }

Code Explanation

This implementation improves accessibility by ensuring that each TextField and SecureField is explicitly labelled with clear, descriptive text such as “Email Address” and “Password,” making the form easy to understand for screen reader users. It provides immediate validation feedback by displaying text-based error messages as input changes, allowing assistive technologies like VoiceOver to announce issues as soon as they occur. The error messages themselves are concise yet meaningful—for example, “Please enter a valid email address”—so users understand exactly what needs to be corrected without being overwhelmed. In addition, the use of the @FocusState property enables optional focus management, making it possible to direct users back to the field that failed validation, while also demonstrating how focus can be tracked within the form.

Correct Code Example: Accessible Toggle (Terms and Conditions)

Demo Description

For toggles, use a full phrase in the accessibility value so VoiceOver announces both label and state on focus and when the value changes (e.g. "Accept terms and conditions on" rather than only on after the first read).

// SwiftUI – accessible toggle with full phrase announcement
    Toggle(isOn: $termsAccepted) {
        Text("I accept the Terms and Conditions")
    }
    .accessibilityLabel("")
    .accessibilityValue(termsAccepted
        ? "Accept terms and conditions on"
        : "Accept terms and conditions off")
    .onChange(of: termsAccepted) { _, _ in validateTerms(moveFocus: true) }

    if let error = termsError {
        Text(error)
            .foregroundColor(.red)
            .accessibilityLabel(error)
    }

Code Explanation

Full phrase in value: accessibilityValue is the full “Accept terms and conditions on/off” so VoiceOver says the full phrase on focus and every time the toggle changes, not just “on”/“off”.

✅ Best Practices

Do's

  • Provide clear, explicit labels for all form fields
  • Display error messages immediately adjacent to the relevant field
  • Use both visual indicators (color, icons) and text for error states
  • Ensure error messages are announced by screen readers
  • Implement real-time validation with accessible feedback
  • Use focus management to guide users to fields with errors
  • Make error messages concise and actionable

Don'ts

  • Rely only on color to indicate errors
  • Use vague error messages like "Invalid input" or "Error"
  • Display all errors at the top of the form without field-specific feedback
  • Remove error messages before the user has corrected the issue
  • Use placeholder text as the only label for form fields
  • Fail to announce dynamic error messages to screen readers

🔍 Common Pitfalls

Missing Error Associations

Error messages not properly associated with their corresponding form fields, making it unclear which field has the problem

Color-Only Indicators

Using only red borders or text color to indicate errors without accompanying text or icons

Generic Error Messages

Vague messages like "Invalid" that don't explain what's wrong or how to fix it

Silent Errors

Error messages that appear visually but aren't announced by screen readers

Poor Focus Management

Not directing user attention to fields with errors, especially on form submission

Placeholder Confusion

Using placeholder text as labels, which disappears when users start typing

VoiceOver/TalkBack

Screen readers will announce field labels, current values, and error messages. When an error appears, VoiceOver should announce the error text immediately. Users navigating to a field with an error should hear both the field label and the associated error message

Switch Control

Users navigating with switch control need clear visual indicators of which field has focus and which fields contain errors. Error messages should be focusable elements in the navigation order

Dynamic Type

All form labels, input text, and error messages should scale appropriately with the user's text size preferences. Ensure layouts don't break when text size increases

Voice Control

Field labels should be clear and unique to enable voice-based form filling

🧪 Testing Steps

  1. 1Enable VoiceOver: Settings → Accessibility → VoiceOver
  2. 2Navigate through form fields: Swipe right to move between form elements
  3. 3Verify field labels: Ensure all fields are announced with proper labels
  4. 4Trigger validation errors: Enter invalid data and check error announcements
  5. 5Test error recovery: Correct errors and verify error messages disappear
  6. 6Check focus management: Ensure focus moves logically through the form
  7. 7Test with Dynamic Type: Increase text size and verify form remains usable

Become a member to read this solution, and all of Ma11y.

This resource is part of our member knowledge base. Log in or create an account to unlock:

  • Complete accessibility guidance and implementation examples
  • Curated compliance frameworks and checklists
  • Early access to new tools and features