Skip to content

Commit

Permalink
fix(#588): a11y - first item of components vocalized
Browse files Browse the repository at this point in the history
Signed-off-by: Pierre-Yves Lapersonne <[email protected]>
  • Loading branch information
pylapp committed Jan 29, 2024
1 parent bcb1ab7 commit 0ede444
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,37 @@ struct RequestAccessibleFocusModifier: ViewModifier {

func body(content: Content) -> some View {
content.onAppear {
// Voice Over gives focus to some random item in the middle of the screen in the list, need to move focus
DispatchQueue.main.asyncAfter(deadline: deadline) {
requestFocus = true
}
}
}
}

// ===============================
// MARK: - Accessibility Focusable
// ===============================

public enum AccessibilityFocusable: Hashable {
case none
case some(id: String)
}

// ====================================================
// MARK: - Restricted Request Accessible Focus Modifier
// ====================================================

struct RestrictedRequestAccessibleFocusModifier: ViewModifier {

@AccessibilityFocusState var requestFocus: AccessibilityFocusable?
let target: AccessibilityFocusable
let deadline: DispatchTime

func body(content: Content) -> some View {
content.onAppear {
DispatchQueue.main.asyncAfter(deadline: deadline) {
requestFocus = target
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -48,4 +48,15 @@ extension View {
self.modifier(RequestAccessibleFocusModifier(requestFocus: requestFocus,
deadline: .now() + AccessibilityDelay.accessibleFocusRequestDelay))
}

/// Adds a modifier to the current `View` so as to defer a focus request after the view is displayed for the given elment
/// - Parameters:
/// - requestFocus: The boolean binding (e.g. the `AccessibilityFocusState`)
/// - target: The item which will get the focus
/// - Returns View: The view with a new modifier
public func odsRequestAccessibleFocus(_ requestFocus: AccessibilityFocusState<AccessibilityFocusable?>, for target: AccessibilityFocusable) -> some View {
self.modifier(RestrictedRequestAccessibleFocusModifier(requestFocus: requestFocus,
target: target,
deadline: .now() + AccessibilityDelay.accessibleFocusRequestDelay))
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ struct ComponentsList: View {

@Environment(\.sizeCategory) private var sizeCategory
@EnvironmentObject private var themeProvider: ThemeProvider
@AccessibilityFocusState private var requestFocus: AccessibilityFocusable?

// =======================
// MARK: Stored Properties
Expand Down Expand Up @@ -67,10 +68,14 @@ struct ComponentsList: View {
.padding(.all, ODSSpacing.s)
}
}
.navigationbarMenuForThemeSelection()
.odsNavigationTitle("main_view.tabs.components".🌐)

ComponentPage(component: components[0])
.navigationbarMenuForThemeSelection()
// .odsRequestAccessibleFocus(_requestFocus, for: .some(id: components[0].id)) // <--- Not called at first display but called for next ones
.onAppear { // <--- Called at first display and for next ones
DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) {
requestFocus = .some(id: components[0].id)
}
}
}
.navigationViewStyle(.stack)
}
Expand All @@ -92,10 +97,15 @@ struct ComponentsList: View {
ODSCardSmall(
title: Text(component.name),
imageSource: .image(themeProvider.imageFromResources(component.imageName)))
.accessibilityFocused($requestFocus, equals: .some(id: component.id))
}
}
}

// ===============
// MARK: - Preview
// ===============

#if DEBUG
import OrangeTheme

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ private struct ColorList: View {
.foregroundColor(theme.componentColors.navigationBarForeground)
}
}
.navigationTitle("screens.guidelines.colors.palette.title")
.odsNavigationTitle("screens.guidelines.colors.palette.title".🌐)
}

// ============================
Expand Down

0 comments on commit 0ede444

Please sign in to comment.