Build a Great VoiceOver Experience in UIKit Lab
When UIKit Lab v1.0 came out, thanks to UIKit's built-in accessibility features, it was already able to address the need of users facing certain disabilities pretty well. However, v1.0 was a bit lacking in one crucial aspect of accessibility feature—VoiceOver. To make sure UIKit Lab can deliver a great VoiceOver experience, after the release of v1.0, I started working on enhancing the VoiceOver experience in UIKit Lab by redesigning/refactoring certain custom UI components and following industry-recommended principles. After countless late nights, UIKit Lab started "properly" supporting VoiceOver since v1.1.
The problem
Since v1.0, UIKit Lab has been using native iOS UI components provided by UIKit throughout most parts of the app. Thanks to UIKit's built-in accessibility features such as Dynamic Type, Button Shapes, and Reduce Transparency, v1.0 was already able to address the need of users facing certain disabilities pretty well. However, VoiceOver support in v1.0 was not as great. For example, some custom UI components were lack of proper accessibility labeling or grouping logic, making them not as accessible as native iOS UI components.
A closer look at issues
To test UIKit Lab's support for VoiceOver thoroughly, I tapped almost everywhere tappable in UIKit Lab with VoiceOver enabled to understand how VoiceOver identified and read out onscreen UI elements, then record the issues I found. To summarize, there are X types of issues:
- 1Custom UI components and certain symbols didn't have proper accessibility labels.This symbol button is to toggle light/dark mode, but its accessibility label reads "do not disturb/brightness higher".This custom widget is supposed to work as a button, but VoiceOver reads it as plain text label rather than a button.
- 2Helpful accessibility hints were missing in some places of the app, failing to provide necessary context to users.In this example, user can tap the first table cell to change the glyph used for the button, but when VoiceOver focuses on the first table cell, it only reads "star, missing necessary context about what action to take.
- 3Custom UI components didn't have proper grouping logic, making navigation lengthy and relevant information separate and harder to understand.This slider table cell contains three separate elements: minimum value, slider, and maximum value. However, VoiceOver also reads them one by one, requiring more navigation and mental effort for users to understand what this cell does.
Build a great VoiceOver experience
To build a great VoiceOver experience, there are many aspects of
Contextual labeling of UI elements
There are many system-provided and custom SF Symbols used in UIKit Lab. However, they were identified by VoiceOver with their default accessibility labels. This caused issues like the one when a "moon" symbol was supposed to toggle light/dark mode of the UI, but VoiceOver read it as "do not disturb", which is its default accessibility label.
To fix such issues, I carefully audited accessibility labels of all out-of-the-box and custom SF Symbols in UIKit Lab to make sure they convey accurate and concise description of their action.
In addition to SF Symbols, some custom UI components had similar issues of having unclear accessibility labels. For example, some custom buttons were read by VoiceOver as plain text label rather than a button so users might have trouble figuring out what they actually are. In comparison, a standard button will be read as "XXX (button's label), button".
To fix such issues, I added proper suffixes to the accessibility labels of all interactive custom UI components and made sure they accurately describe what these custom components are and how they work.
Proper semantic hints of UI elements
Accessibility hints can be flexible. The accessibility hint for a component in a certain UI might be totally different when it is used in another UI. Regardless of where a component is placed, the point of accessibility hint is to provide proper and helpful semantic information of a component.
Therefore, for all UI components, system-provided or not, their accessibility hints need to provide context relevant to the specific UI. This is exactly what I did to enhance accessibility hints in UIKit Lab.
Efficient grouping of accessibility elements
Previously, some custom UI components didn't have proper grouping logic among their child elements. As a result, user would have to swipe multiple times to get through each label and control that should have been treated as a whole entity. This made navigation lengthy and harder for users with vision impairment to understand the connection between child elements.
To fix such issues, I audited all custom UI components and tried to group relevant child elements into one large group. On top of that, I gave such group meaningful accessibility label so that user can easily understand what it does as a whole.
What I learned
Developing an iOS app (in fact, any product) is not easy, but that should not be an excuse of missing/average accessibility experience because any individual can potentially benefit from a great accessibility experience. When it comes to actual development, it is better to consider the accessibility experience as an integral part of the app since the very beginning. That way, a more consistent accessibility experience can be available from the first version of the app, even though sometimes it means more development time, it is still better than releasing a version that provided an average accessibility experience then enhancing it afterward. I learned my lesson and I will always try my best to follow this principle. 😝😝