Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Designing APIs: How to ensure accessibility in ...

Designing APIs: How to ensure accessibility in design system components

Presentation for Pragma Conference, October 2024 in Bologna, Italy.

Explore design systems with a focus on accessibility, understand abstraction levels, and learn best practices for API design. Bonus: a live demo will be included at the end.

Today, most apps use some form of a design system with shared UI components, allowing you to quickly create new features that fit your app’s style. Imagine if these components were accessible out of the box, freeing you from last-minute concerns when developing new features under time pressure. But what’s the right level of abstraction to build accessibility into your UI components? The more generic the component is, the more flexibly it can be used in the app, making it difficult to provide excellent accessibility support by default. How should the API be build to ensure the best possible developer and user experience? Discover the answers and see a live demo of assistive technology in action. Elevate your development skills and create apps that are effortlessly inclusive from the ground up.

Feli Bernutz

November 04, 2024
Tweet

More Decks by Feli Bernutz

Other Decks in Programming

Transcript

  1. by Feli Bernutz, Pragma Conference 2024 How to ensure accessibility

    in design system components Designing APIs
  2. My name is Feli Bernutz (she/her) • iOS engineer at

    @Spotify • Nuremberg, Germany " • Sketchnoting • Sports # $% • Pineapple on pizza & Heyy '
  3. () It’s the process of architecting and structuring software to

    meet specific functional and technical requirements, like • scalability • security • performance System Design
  4. *+ It’s a collection of • reusable UI components •

    style guidelines • design principles to ensure consistency across a product’s user interface. Design System
  5. 1. 114: “Accessibility on Apple’s platforms”, with … 2. Swift

    by Sundell 3. Sommer Panage returns to the show to … 4. Mar 21, 2022, 1 hr, 12 min 5. Remove from Your Library 6. Download 7. Share 8. More options 9. Play 10. Paul Van Workum - App Accessibility Expert 11. The Digital Accessibility Podcast 12. In this episode, Joe James is joined by … 13. Apr 25, 2023, 34 min 14. Remove from Episodes 15. Download 16. Share 17. More options 18. Play
  6. 1. 114: “Accessibility on Apple’s platforms”, with special guest Sommer

    Panage. Swift by Sundell, Published on 21. March 2022, Episode length is 1 hr, 12 min, Added to Your Library, Button, View episode details 2. Paul Van Workum - App Accessibility Expert. The Digital Accessibility Podcast, Published on 25. April 2023, Episode length is 34 min, Added to Your Library, Button, View episode details 3. Special: Daniel Devesa Derksen-Staats. AppForce1: news and info for iOS app developers, Published on 14. January 2021, Episode length is 41 min, Added to Your Library, Button, View episode details
  7. Source: Jason Fried – The Obvious, the Easy, and the

    Possible (2011) & Jake Wharton – Slope-intercept library design (2022) Possible 4 % Easy 16 % Obvious 80 % Different levels of abstractions
  8. 4 // Default accessibility props are set internally var listRow

    = Encore.ListRow(content: .init( )) Out of the box solution The Game Plan – Step 1
  9. 4 // Default accessibility props are set internally var listRow

    = Encore.ListRow(content: .init( media: .image(UIImage), )) Out of the box solution The Game Plan – Step 1
  10. 4 Most Shared Podcast in Sweden // Default accessibility props

    are set internally var listRow = Encore.ListRow(content: .init( media: .image(UIImage), pretitle: .text("Most Shared Podcast in Sweden"), )) Out of the box solution The Game Plan – Step 1
  11. 4 Most Shared Podcast in Sweden, Damn Fine Coffee //

    Default accessibility props are set internally var listRow = Encore.ListRow(content: .init( media: .image(UIImage), pretitle: .text("Most Shared Podcast in Sweden"), title: .text("Damn Fine Coffee"), )) Out of the box solution The Game Plan – Step 1
  12. 4 Most Shared Podcast in Sweden, Damn Fine Coffee, Actions

    available // Default accessibility props are set internally var listRow = Encore.ListRow(content: .init( media: .image(UIImage), pretitle: .text("Most Shared Podcast in Sweden"), title: .text("Damn Fine Coffee"), trailing: .button(Encore.Button), )) Out of the box solution The Game Plan – Step 1
  13. 4 Most Shared Podcast in Sweden, Damn Fine Coffee, Actions

    available // Default accessibility props are set internally var listRow = Encore.ListRow(content: .init( media: .image(UIImage), pretitle: .text("Most Shared Podcast in Sweden"), title: .text("Damn Fine Coffee"), trailing: .button(Encore.Button), )) Out of the box solution The Game Plan – Step 1
  14. // Simplified internal logic func setup(content: Encore.Content) { accessibilityIdentifier =

    "Encore.ListRow" } Internal implementation The Game Plan – Step 1
  15. // Simplified internal logic func setup(content: Encore.Content) { accessibilityIdentifier =

    "Encore.ListRow" isAccessibilityElement = true } Internal implementation The Game Plan – Step 1
  16. // Simplified internal logic func setup(content: Encore.Content) { accessibilityIdentifier =

    "Encore.ListRow" isAccessibilityElement = true // Compute accessibility information by using the available content accessibilityLabel = content.accessibilityLabel } Internal implementation The Game Plan – Step 1
  17. // Simplified internal logic func setup(content: Encore.Content) { accessibilityIdentifier =

    "Encore.ListRow" isAccessibilityElement = true // Compute accessibility information by using the available content accessibilityLabel = content.accessibilityLabel } Internal implementation The Game Plan – Step 1 extension Encore.Content { var accessibilityLabel: String { [ pretitle?.accessibilityLabel, title.accessibilityLabel, subtitle?.accessibilityLabel, media?.accessibilityLabel, leading?.accessibilityLabel, trailing?.accessibilityLabel, footer?.accessibilityLabel, ] .compactMap { $0 } .filter { !$0.isEmpty } .joined(separator: ", ") .replacingOccurrences(of: " • ", with: ", ") } }
  18. // Simplified internal logic func setup(content: Encore.Content) { accessibilityIdentifier =

    "Encore.ListRow" isAccessibilityElement = true // Compute accessibility information by using the available content accessibilityLabel = content.accessibilityLabel accessibilityCustomActions = content.buttons.compactMap { $0.accessibilityCustomAction } } Internal implementation The Game Plan – Step 1
  19. // Simplified internal logic func setup(content: Encore.Content) { accessibilityIdentifier =

    "Encore.ListRow" isAccessibilityElement = true // Compute accessibility information by using the available content accessibilityLabel = content.accessibilityLabel accessibilityCustomActions = content.buttons.compactMap { $0.accessibilityCustomAction } accessibilityCustomContent = content.accessibilityCustomContent } Internal implementation The Game Plan – Step 1
  20. // Simplified internal logic func setup(content: Encore.Content) { accessibilityIdentifier =

    "Encore.ListRow" isAccessibilityElement = true // Compute accessibility information by using the available content accessibilityLabel = content.accessibilityLabel accessibilityCustomActions = content.buttons.compactMap { $0.accessibilityCustomAction } accessibilityCustomContent = content.accessibilityCustomContent accessibilityUserInputLabels = content.accessibilityUserInputLabels } Internal implementation The Game Plan – Step 1
  21. // Simplified internal logic public var body: some View {

    makeBody(with: content) .accessibilityIdentifier("Encore.ListRow") .accessibilityElement(children: .combine) } SwiftUI internal implementation The Game Plan – Step 1
  22. ✨ DONE ✨ 1. Add out-of-the-box solution is it good

    enough? yes no 2. Add explicit API for accessibility info is it good enough? no yes The Game Plan
  23. 4 var box = Encore.Box( contentView: ContentView(), ) Explicit API

    for accessibility info The Game Plan – Step 2
  24. 4 Soft Pop Hits, Playlist, by Spotify var box =

    Encore.Box( contentView: ContentView(), accessibilityLabel: "Soft Pop Hits, Playlist, by Spotify", ) Explicit API for accessibility info The Game Plan – Step 2
  25. 4 Soft Pop Hits, Playlist, by Spotify, Currently playing var

    box = Encore.Box( contentView: ContentView(), accessibilityLabel: "Soft Pop Hits, Playlist, by Spotify", accessibilityValue: "Currently playing", ) Explicit API for accessibility info The Game Plan – Step 2
  26. 4 Soft Pop Hits, Playlist, by Spotify, Currently playing var

    box = Encore.Box( contentView: ContentView(), accessibilityLabel: "Soft Pop Hits, Playlist, by Spotify", accessibilityValue: "Currently playing", accessibilityHint: nil, ) Explicit API for accessibility info The Game Plan – Step 2
  27. 4 Soft Pop Hits, Playlist, by Spotify, Currently playing, Button

    var box = Encore.Box( contentView: ContentView(), accessibilityLabel: "Soft Pop Hits, Playlist, by Spotify", accessibilityValue: "Currently playing", accessibilityHint: nil, accessibilityTraits: .button, ) Explicit API for accessibility info The Game Plan – Step 2
  28. 4 Soft Pop Hits, Playlist, by Spotify, Currently playing, Button,

    Actions available var box = Encore.Box( contentView: ContentView(), accessibilityLabel: "Soft Pop Hits, Playlist, by Spotify", accessibilityValue: "Currently playing", accessibilityHint: nil, accessibilityTraits: .button, accessibilityCustomActions: [ playButton.accessibilityCustomAction, ] ) Explicit API for accessibility info The Game Plan – Step 2
  29. 4 Soft Pop Hits, Playlist, by Spotify, Currently playing, Button,

    Actions available var box = Encore.Box( contentView: ContentView(), accessibilityLabel: "Soft Pop Hits, Playlist, by Spotify", accessibilityValue: "Currently playing", accessibilityHint: nil, accessibilityTraits: .button, accessibilityCustomActions: [ playButton.accessibilityCustomAction, ] ) Explicit API for accessibility info The Game Plan – Step 2
  30. ✨ DONE ✨ 1. Add out-of-the-box solution is it good

    enough? yes no 2. Add explicit API for accessibility info is it good enough? no yes 3. Create Guidelines is it good enough? yes The Game Plan