Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Compose iOS accessibility support #75

Merged
merged 13 commits into from
Feb 28, 2024
5 changes: 4 additions & 1 deletion mpd.tree
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,10 @@
<toc-element id="compose-images-resources.md"/>
<toc-element id="compose-navigation-routing.md"/>
<toc-element id="compose-test.md"/>
<toc-element id="compose-ios-ui-integration.md" toc-title="Integration with other UI frameworks"/>
<toc-element toc-title="iOS specific features">
zamulla marked this conversation as resolved.
Show resolved Hide resolved
<toc-element id="compose-ios-ui-integration.md" toc-title="Integration with UIKit and SwiftUI"/>
<toc-element id="compose-ios-accessibility.md" toc-title="iOS accessibility support"/>
</toc-element>
<toc-element id="compose-android-only-components.md"/>
<toc-element toc-title="Compose Multiplatform for web" href="https://kotlinlang.org/docs/wasm-get-started.html"/>
<toc-element id="compose-compatibility-and-versioning.md"/>
Expand Down
101 changes: 101 additions & 0 deletions topics/compose/compose-ios-accessibility.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
[//]: # (title: Support for iOS accessibility features)

Compose Multiplatform accessibility support allows people with disabilities to interact with the Compose Multiplatform UI
as comfortably as with the native iOS UI:
* Screen readers and VoiceOver can access the content of the Compose Multiplatform UI.
* The Compose Multiplatform UI supports the same gestures as the native iOS UI for navigation and interaction.

This is possible because semantics data produced by Compose APIs is now mapped to native objects and properties
that are consumed by iOS Accessibility Services. For most interfaces built with Material widgets, this should happen
automatically.

You can also use this semantic data in testing and other automation: properties such as `testTag` will correctly map
to native accessibility properties such as `accessibilityIdentifier`. This makes semantic data from Compose Multiplatform available
to Accessibility Services and XCTest framework.

The Compose accessibility API doesn't currently support:
* Live regions (announcements about content changes in a specific area).
* [UIKit elements inside Compose Multiplatform UI](compose-ios-ui-integration.md#use-uikit-inside-compose-multiplatform).

iOS accessibility support is in the early stages of development. If you have trouble with this feature,
we would appreciate your feedback in the [#compose-ios](https://kotlinlang.slack.com/archives/C0346LWVBJ4/p1678888063176359)
Slack channel or as an issue in the [Compose Multiplatform GitHub repo](https://github.com/JetBrains/compose-multiplatform/issues).

## Customize synchronization of the accessibility tree

With default settings:
* The iOS accessibility tree is synchronized with the UI only when Accessibility Services are running.
* Synchronization events are not logged.

You can customize these settings with the new Compose Multiplatform API.

### Choose the tree synchronization option

To debug and test events and interactions, you can change the synchronization mode:
zamulla marked this conversation as resolved.
Show resolved Hide resolved
* to never sync the tree with UI (for example, to temporarily disable accessibility mapping),
zamulla marked this conversation as resolved.
Show resolved Hide resolved
* to always sync the tree, so that it is rewritten every time the UI updates (to thoroughly test the accessibility integration).
zamulla marked this conversation as resolved.
Show resolved Hide resolved

> Remember that synchronizing the tree after each UI event can be quite useful for debugging and testing but can degrade
> the performance of your app.
>
{type="note"}

An example of enabling the option to always synchronize the accessibility tree:

```kotlin
ComposeUIViewController(configure = {
accessibilitySyncOptions = AccessibilitySyncOptions.Always(debugLogger = null)
}) {
// your @Composable content
}
```

The `AccessibilitySyncOptions` class contains all available options:

```kotlin
// package androidx.compose.ui.platform

@ExperimentalComposeApi
sealed class AccessibilitySyncOptions {

// Option to never synchronize the accessibility tree
object Never: AccessibilitySyncOptions

// Option to synchronize the tree only when Accessibility Services are running
//
// You can include an AccessibilityDebugLogger to log interactions and tree syncing events
class WhenRequiredByAccessibilityServices(debugLogger: AccessibilityDebugLogger?)

// Option to always synchronize the accessibility tree
//
// You can include an AccessibilityDebugLogger to log interactions and tree syncing events
class Always(debugLogger: AccessibilityDebugLogger?)
}
```

### Implement the logging interface

You can implement the `AccessibilityDebugLogger` interface to write custom messages to an output of your choosing:

```kotlin
ComposeUIViewController(configure = {
accessibilitySyncOptions = AccessibilitySyncOptions.WhenRequiredByAccessibilityServices(object: AccessibilityDebugLogger {
override fun log(message: Any?) {
if (message == null) {
println()
} else {
println("[a11y]: $message")
}
}
})
}) {
// your @Composable content
}
```

## What's next?

Now that you're up to speed with iOS accessibility support in Compose Multiplatform:
* Try out the project generated by [the Kotlin Multiplatform wizard](https://kmp.jetbrains.com/) in your usual iOS accessibility workflow.
* Learn about [resource qualifiers](compose-images-resources.md) that will be helpful when adapting
a Compose Multiplatform UI to a particular situation.