green-code-initiative/ecoCode-challenge

[Hackathon 2024][Niobium][iOS] Respecting “Reduce Motion” Accessibility Settings in SwiftUI Animations

LaurentBnpp opened this issue · 0 comments

Rule title

Respecting “Reduce Motion” Accessibility Settings in SwiftUI Animations

Language and platform

Swift (5.3+), SwiftUI (iOS 13+, macOS 10.15+, tvOS 13+, watchOS 6+, visionOS 1+)

Rule description

This rule aims to ensure that developers write animations in SwiftUI while taking into account the user’s “Reduce Motion” accessibility settings. The “Reduce Motion” setting is an accessibility feature that minimizes the animations and transitions on the screen for users who are sensitive to motion.

Bad example

struct ContentView: View {
    @State private var scale = 1.0

    var body: some View {
        VStack {
            Spacer()

            Circle()
                .frame(width: 20, height: 20)
                .scaleEffect(scale)
                .animation( .spring(response: 1, dampingFraction: 0.1), value: scale)

            Spacer()

            Button("Increase Scale") {
                scale *= 1.5
            }
        }
    }
}

Good example

struct ContentView: View {
    @Environment(\.accessibilityReduceMotion) var reduceMotion
    @State private var scale = 1.0

    var body: some View {
        VStack {
            Spacer()

            Circle()
                .frame(width: 20, height: 20)
                .scaleEffect(scale)
                .animation(reduceMotion ? nil : .spring(response: 1, dampingFraction: 0.1), value: scale)

            Spacer()

            Button("Increase Scale") {
                scale *= 1.5
            }
        }
    }
}
how-to-detect-the-reduce-motion-accessibility-setting-1.mp4

Rule short description

Ensure SwiftUI animations respect the user’s “Reduce Motion” accessibility setting.

Rule justification

Ignoring the “Reduce Motion” setting can lead to an uncomfortable user experience for those sensitive to motion and in the worst-case scenario, some users might no longer be able to use your application.

(https://accessibilite.numerique.gouv.fr/methode/criteres-et-tests/#13.7)[RGAA Rule 13.7]
(https://accessibilite.numerique.gouv.fr/methode/criteres-et-tests/#13.8)[RGAA Rule 13.8]

Severity / Remediation Cost

Severity: high.
Ignoring this setting can degrade the user experience, but it does not make the application unusable.

Remediation Cost: easy.
It only requires adding a condition to animations to respect the “Reduce Motion” setting.

Implementation principle

During the static analysis of the source code, we will need to detect instances where Animation is used without the @Environment(\.accessibilityReduceMotion) var reduceMotion modifier and animation(reduceMotion ? nil : .spring()).

Source video & code
Paul Hudson @twostraws December 1st 2022
https://www.hackingwithswift.com/quick-start/swiftui/how-to-detect-the-reduce-motion-accessibility-setting