Adding accessibility improvements to the emoji picker.
In part one I described how I started building my own SwiftUI emoji picker. This is a quick post about how I made some improvements to it regarding accessibility. Standard disclosure that I’m not saying this is the best way to do things. This is just what I came up with as a hobbyist trying to learn!
Those aren’t buttons!
With the way I built it the emojis displayed aren’t buttons. They’re just strings being displayed. When the user taps an emoji the picker is dismissed and the selection is remembered.
Text(oneEmoji.char)
.font(.largeTitle)
.onTapGesture(count: 1, perform: {
emojiSelected = oneEmoji.char
dismiss()
})
I wasn’t sure how to handle this with VoiceOver and I had a feeling that what I was doing was way too “chatty”.
a11y question: These aren't buttons. With VoiceOver when you touch a fruit the "label" makes the name be pronounced and the "hint" says "Touching this will select this emoji". Is that overkill for each emoji? Should I have that hint tied to the category name you can expand? pic.twitter.com/GodBSRimdt
— Chris Wu (@MuseumShuffle) October 10, 2021
The iOS community is so helpful, and this time was no exception. I got some great feedback from Amro Mousa and Sommer Panage, two great engineers you should be following if you’re not already doing so!
Amro pointed out that even thought the emojis displayed are not buttons you can add accessibility traits that indicate that they act like buttons. According to Sommer that trait along with the selected trait removes the need for such a verbose hint.
Here’s what it looks like in code:
Text(oneEmoji.char)
.font(.largeTitle)
.onTapGesture(count: 1, perform: {
emojiSelected = oneEmoji.char
dismiss()
})
.accessibilityAddTraits([.isButton, .isSelected])
.accessibilityLabel(Text("\(oneEmoji.name)"))
.accessibilityHint(Text("Choose emoji."))
Now when you touch a lemon, for example, VoiceOver reads “Selected, lemon, button, choose emoji.” Much more concise and to the point!
Testing with with VoiceOver
It’s important to test drive all parts of your app when you’re trying to add support for VoiceOver. I quickly realized that I had a problem. When I touched any emoji on the bottom row the emoji was not selected. Instead I heard VoiceOver say “horizontal scroll bar” along with a description of how much content (pages of emojis) you could scroll through.
I got around this by adding some padding to the content the ScrollView is displaying.
.padding(.vertical, 20) // voiceover wouldn't let you select an emoji in the bottom row
For users that aren’t using VoiceOver this change is barely noticeable. But that little bit of padding means that now an emoji on the bottom row can be selected without issue. I’m curious if this was the “correct” way to fix this problem. Always open to feedback!
PRO TIP
There’s a fast way to turn off VoiceOver when you’re done testing with it. Just ask Siri to turn it off!
Conclusion
Adding accessibility features to your app is incredibly important. Hopefully this can help you with that in the future.
If this post was helpful to you I’d love to hear about it! Find me on Twitter.