Docs/Accessibility
100% Accessible

Accessibility

SwiftDS is built with accessibility as a core principle. Every component includes proper VoiceOver support, keyboard navigation, and follows WCAG 2.1 AA guidelines.

What We Support

๐Ÿ”Š

VoiceOver

Full screen reader support on all platforms with descriptive labels and hints.

๐Ÿ“

Dynamic Type

Text scales with user preferences up to 310% without breaking layouts.

โŒจ๏ธ

Keyboard Navigation

Full keyboard support with logical focus order and visible indicators.

๐ŸŽจ

Color Contrast

WCAG AA compliant (4.5:1 for text, 3:1 for UI components).

๐ŸŽฏ

Focus Management

Logical focus order with visible focus indicators throughout.

๐Ÿท๏ธ

Semantic Traits

Proper accessibility traits (button, header, etc.) on all elements.

Accessibility Patterns

SwiftDS components follow consistent accessibility patterns. Here are the main patterns used throughout the system:

Interactive Components (Buttons, Links)

All interactive components provide clear labels, hints, and state information:

swift
Button(action: action) {
    // Button content
}
.accessibilityLabel(accessibilityLabel ?? title)
.accessibilityHint(isDisabled ? "Disabled" : "Double-tap to activate")
.accessibilityAddTraits(.isButton)

Input Fields

Text inputs provide rich accessibility information with proper labels and error states:

swift
TextField(placeholder, text: $text)
    .accessibilityLabel(label ?? placeholder)
    .accessibilityValue(text.isEmpty ? "Empty" : text)
    .accessibilityHint(error != nil ? "Error: \(error!)" : "Text field")

Display Components (Cards, Labels)

Display components combine multiple text elements into a single announcement:

swift
VStack {
    Text("Title")
    Text("Subtitle")
}
.accessibilityElement(children: .combine)
.accessibilityLabel("Title, Subtitle")

Progress Indicators

Progress components announce current state and percentage:

swift
ProgressView(value: progress)
    .accessibilityLabel("Loading")
    .accessibilityValue("\(Int(progress * 100))%")

Adjustable Components (Sliders, Ratings)

Components with adjustable values support swipe up/down gestures:

swift
Slider(value: $value)
    .accessibilityLabel("Volume")
    .accessibilityValue("\(Int(value))%")
    .accessibilityAdjustableAction { direction in
        switch direction {
        case .increment: value += 10
        case .decrement: value -= 10
        @unknown default: break
        }
    }

Testing with VoiceOver

All SwiftDS components have been tested with VoiceOver on iOS and macOS. Here's how to test your implementation:

Enabling VoiceOver

iOS/iPadOS:

  • Settings โ†’ Accessibility โ†’ VoiceOver โ†’ On
  • Or triple-click side button (if configured)
  • Or ask Siri: "Turn on VoiceOver"

macOS:

  • System Settings โ†’ Accessibility โ†’ VoiceOver โ†’ On
  • Or press Cmd+F5
  • Or ask Siri: "Turn on VoiceOver"

VoiceOver Gestures (iOS)

Swipe rightNext element
Swipe leftPrevious element
Double-tapActivate element
Swipe up/downAdjustable actions
Two-finger swipe upRead from top
Two-finger swipe downRead from current

Testing Checklist

When testing a component with VoiceOver, verify these items:

Navigate to component - Can you reach it by swiping?

Hear label - Is the label descriptive and clear?

Hear hint - Does the hint explain how to interact?

Hear value - Is the current state/value announced?

Activate - Does double-tap trigger the action?

State changes - Are loading/disabled states announced?

Error states - Are errors clearly communicated?

Adjustable actions - Do swipe up/down work for sliders/ratings?

Focus order - Is the focus order logical?

No orphaned elements - Are all visible elements accessible?

Keyboard Navigation

SwiftUI provides automatic keyboard navigation for most components. Here are the supported shortcuts:

TabNext focusable element
Shift+TabPrevious focusable element
SpaceActivate button/toggle
ReturnSubmit form/activate primary button
EscapeDismiss modal/sheet
Arrow keysNavigate lists/grids

Best Practices

โœ… Do: Use Descriptive Labels

โŒ Bad

swift
.accessibilityLabel("Button")

โœ… Good

swift
.accessibilityLabel("Sign in to your account")

โœ… Do: Announce State Changes

โŒ Bad

swift
Button("Submit") { submit() }

โœ… Good

swift
Button("Submit") { submit() }
.accessibilityHint(
    isLoading ? "Loading" : "Double-tap to submit"
)

โœ… Do: Hide Decorative Elements

โŒ Bad

swift
HStack {
    Image(systemName: "star.fill")
    Text("Featured")
}

โœ… Good

swift
HStack {
    Image(systemName: "star.fill")
        .accessibilityHidden(true)
    Text("Featured")
}

โœ… Do: Group Related Content

โŒ Bad

swift
VStack {
    Text("John Doe")
    Text("Software Engineer")
}

โœ… Good

swift
VStack {
    Text("John Doe")
    Text("Software Engineer")
}
.accessibilityElement(children: .combine)
.accessibilityLabel("John Doe, Software Engineer")

Component Checklist

When creating new components, ensure they meet these accessibility requirements:

Required Features

accessibilityLabel - Descriptive label for screen readers

accessibilityHint - Usage hint (how to interact)

accessibilityValue - Current state/value (if applicable)

accessibilityElement - Proper grouping (combine/contain/ignore)

Traits - Correct semantic traits (button, header, etc.)

State changes - Loading/disabled/error states announced

Focus management - Logical focus order

Keyboard support - Tab navigation and shortcuts

Color contrast - WCAG AA compliant (4.5:1 for text)

Dynamic Type - Text scales properly

Resources

Accessibility is Built-In

When building with SwiftDS, accessibility is built-in by default. All 118+ components include proper VoiceOver support, keyboard navigation, and follow Apple's accessibility guidelines. No extra work required!