From 6acd22f556ac1cad77f2f612f40170ea9ede1242 Mon Sep 17 00:00:00 2001 From: Pierre-Yves Lapersonne Date: Fri, 26 Jan 2024 17:19:15 +0100 Subject: [PATCH] fix(#563): a11y - title vocalization on screen changed Signed-off-by: Pierre-Yves Lapersonne --- CHANGELOG.md | 2 +- .../Modules/About/ODSAboutModule.swift | 9 ++++- .../project.pbxproj | 12 ++++--- ...mponentList.swift => ComponentsList.swift} | 2 +- .../Screens/Guidelines/GuidelinesList.swift | 12 ++++--- .../Screens/Modules/ModulesList.swift | 2 +- .../UI/AccssibleNavigationTitleModifier.swift | 34 +++++++++++++++++++ 7 files changed, 60 insertions(+), 13 deletions(-) rename OrangeDesignSystemDemo/OrangeDesignSystemDemo/Screens/Components/{ComponentList.swift => ComponentsList.swift} (97%) create mode 100644 OrangeDesignSystemDemo/OrangeDesignSystemDemo/Utils/UI/AccssibleNavigationTitleModifier.swift diff --git a/CHANGELOG.md b/CHANGELOG.md index 6b9a50ab..99b01049 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,7 @@ This project adheres to [Semantic Versioning](http://semver.org/). ## [Unreleased](https://github.com/Orange-OpenSource/ods-ios/compare/0.16.0...qualif) -- [DemoApp] Components page accessibility issues (Bug [#563](https://github.com/Orange-OpenSource/ods-ios/issues/563)) +- [DemoApp/SDK] Components page accessibility issues (Bug [#563](https://github.com/Orange-OpenSource/ods-ios/issues/563)) - [SDK] Update Banners to align buttons when text is too long ([#642](https://github.com/Orange-OpenSource/ods-ios/issues/642)) - [SDK] Update Cards to align buttons when text is too long ([#630](https://github.com/Orange-OpenSource/ods-ios/issues/630)) - [Tooling] Upgrate to xcode 15 ([#638](https://github.com/Orange-OpenSource/ods-ios/issues/638)) diff --git a/OrangeDesignSystem/Sources/OrangeDesignSystem/Modules/About/ODSAboutModule.swift b/OrangeDesignSystem/Sources/OrangeDesignSystem/Modules/About/ODSAboutModule.swift index 2890483c..ea1d3b7b 100644 --- a/OrangeDesignSystem/Sources/OrangeDesignSystem/Modules/About/ODSAboutModule.swift +++ b/OrangeDesignSystem/Sources/OrangeDesignSystem/Modules/About/ODSAboutModule.swift @@ -29,6 +29,7 @@ public struct ODSAboutModule: View where TermsOfService: View { private let headerIllustration: Image private let applicationInformation: ODSAboutApplicationInformation private let listItemConfigurations: [ODSAboutListItemConfig] + private let title: String // ================== // MARK: Initializers @@ -68,6 +69,7 @@ public struct ODSAboutModule: View where TermsOfService: View { ] self.listItemConfigurations = (listItemConfigurations + internalItemsConfig).sorted() + title = °°"modules.about.title" } // ========== @@ -92,7 +94,12 @@ public struct ODSAboutModule: View where TermsOfService: View { .padding(.bottom, ODSSpacing.s) } .listStyle(.plain) - .navigationTitle(°°"modules.about.title") + .navigationTitle(title) + .onAppear { + DispatchQueue.main.asyncAfter(deadline: .now() + 0.25) { + UIAccessibility.post(notification: .screenChanged, argument: title) + } + } .navigationBarTitleDisplayMode(.large) .background(ODSInternalColor.primaryBackground.color) } diff --git a/OrangeDesignSystemDemo/OrangeDesignSystemDemo.xcodeproj/project.pbxproj b/OrangeDesignSystemDemo/OrangeDesignSystemDemo.xcodeproj/project.pbxproj index 5dbd270c..617b7833 100644 --- a/OrangeDesignSystemDemo/OrangeDesignSystemDemo.xcodeproj/project.pbxproj +++ b/OrangeDesignSystemDemo/OrangeDesignSystemDemo.xcodeproj/project.pbxproj @@ -34,7 +34,7 @@ 077C384A2A9DDC79003D6B51 /* CustomizableVariant.swift in Sources */ = {isa = PBXBuildFile; fileRef = 077C37EF2A9DDC78003D6B51 /* CustomizableVariant.swift */; }; 077C384B2A9DDC79003D6B51 /* ComponentPage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 077C37F02A9DDC78003D6B51 /* ComponentPage.swift */; }; 077C384C2A9DDC79003D6B51 /* Component.swift in Sources */ = {isa = PBXBuildFile; fileRef = 077C37F12A9DDC78003D6B51 /* Component.swift */; }; - 077C384D2A9DDC79003D6B51 /* ComponentList.swift in Sources */ = {isa = PBXBuildFile; fileRef = 077C37F22A9DDC78003D6B51 /* ComponentList.swift */; }; + 077C384D2A9DDC79003D6B51 /* ComponentsList.swift in Sources */ = {isa = PBXBuildFile; fileRef = 077C37F22A9DDC78003D6B51 /* ComponentsList.swift */; }; 077C384E2A9DDC79003D6B51 /* ButtonsComponent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 077C37F52A9DDC78003D6B51 /* ButtonsComponent.swift */; }; 077C384F2A9DDC79003D6B51 /* IconVariant.swift in Sources */ = {isa = PBXBuildFile; fileRef = 077C37F62A9DDC78003D6B51 /* IconVariant.swift */; }; 077C38502A9DDC79003D6B51 /* EmphasisAndFunctionnalVariant.swift in Sources */ = {isa = PBXBuildFile; fileRef = 077C37F72A9DDC79003D6B51 /* EmphasisAndFunctionnalVariant.swift */; }; @@ -116,6 +116,7 @@ 5107F55E2AE11BDD00D4D01F /* AppNews.json in Resources */ = {isa = PBXBuildFile; fileRef = 5107F5602AE11BDD00D4D01F /* AppNews.json */; }; 5107F5622AE1209A00D4D01F /* PrivacyNotice.html in Resources */ = {isa = PBXBuildFile; fileRef = 5107F5642AE1209A00D4D01F /* PrivacyNotice.html */; }; 5107F56A2AE1220900D4D01F /* CGU.html in Resources */ = {isa = PBXBuildFile; fileRef = 5107F56C2AE1220900D4D01F /* CGU.html */; }; + 512BF8F32B6411CF00F9FF67 /* AccssibleNavigationTitleModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 512BF8F22B6411CF00F9FF67 /* AccssibleNavigationTitleModifier.swift */; }; 5138768B2ADD449100AE53DF /* InnovationCupTheme in Frameworks */ = {isa = PBXBuildFile; productRef = 076C0E0C2AC1BCF800AAE074 /* InnovationCupTheme */; }; 5138768C2ADD449100AE53DF /* OrangeDesignSystem in Frameworks */ = {isa = PBXBuildFile; productRef = 076C0E0E2AC1BCF800AAE074 /* OrangeDesignSystem */; }; 5138768D2ADD449100AE53DF /* OrangeTheme in Frameworks */ = {isa = PBXBuildFile; productRef = 076C0E102AC1BCF800AAE074 /* OrangeTheme */; }; @@ -188,7 +189,7 @@ 077C37EF2A9DDC78003D6B51 /* CustomizableVariant.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CustomizableVariant.swift; sourceTree = ""; }; 077C37F02A9DDC78003D6B51 /* ComponentPage.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ComponentPage.swift; sourceTree = ""; }; 077C37F12A9DDC78003D6B51 /* Component.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Component.swift; sourceTree = ""; }; - 077C37F22A9DDC78003D6B51 /* ComponentList.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ComponentList.swift; sourceTree = ""; }; + 077C37F22A9DDC78003D6B51 /* ComponentsList.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ComponentsList.swift; sourceTree = ""; }; 077C37F52A9DDC78003D6B51 /* ButtonsComponent.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ButtonsComponent.swift; sourceTree = ""; }; 077C37F62A9DDC78003D6B51 /* IconVariant.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = IconVariant.swift; sourceTree = ""; }; 077C37F72A9DDC79003D6B51 /* EmphasisAndFunctionnalVariant.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EmphasisAndFunctionnalVariant.swift; sourceTree = ""; }; @@ -268,6 +269,7 @@ 07E4C85B2AE7BC2D00FB4DAC /* ListModule.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListModule.swift; sourceTree = ""; }; 07E4C8662AE7BC8E00FB4DAC /* ListModuleOptions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListModuleOptions.swift; sourceTree = ""; }; 2ACFE972C59B1460F410852D /* Pods-OrangeDesignSystemDemo.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-OrangeDesignSystemDemo.debug.xcconfig"; path = "Target Support Files/Pods-OrangeDesignSystemDemo/Pods-OrangeDesignSystemDemo.debug.xcconfig"; sourceTree = ""; }; + 512BF8F22B6411CF00F9FF67 /* AccssibleNavigationTitleModifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccssibleNavigationTitleModifier.swift; sourceTree = ""; }; 513876912ADD62A000AE53DF /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fr; path = OrangeDesignSystemDemo/Resources/fr.lproj/Localizable.strings; sourceTree = ""; }; 513C99F42B5812300043DAAE /* AppsPlus.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; name = AppsPlus.json; path = OrangeDesignSystemDemo/Resources/AppsPlus.json; sourceTree = ""; }; 513C99F62B5937700043DAAE /* LocalAppsPlusRepositoryTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocalAppsPlusRepositoryTest.swift; sourceTree = ""; }; @@ -435,7 +437,7 @@ children = ( 077C37EE2A9DDC78003D6B51 /* Template */, 077C37F32A9DDC78003D6B51 /* Pages */, - 077C37F22A9DDC78003D6B51 /* ComponentList.swift */, + 077C37F22A9DDC78003D6B51 /* ComponentsList.swift */, ); path = Components; sourceTree = ""; @@ -741,6 +743,7 @@ 077C38942A9DEEDC003D6B51 /* Themes */, 077C388F2A9DEEDB003D6B51 /* BackgroundBlurView.swift */, 077C388E2A9DEEDB003D6B51 /* ToastView.swift */, + 512BF8F22B6411CF00F9FF67 /* AccssibleNavigationTitleModifier.swift */, ); path = UI; sourceTree = ""; @@ -1295,7 +1298,7 @@ 077C37E62A9DDC1A003D6B51 /* MainTabView.swift in Sources */, 077C385D2A9DDC79003D6B51 /* ActivityIndicatorVariant.swift in Sources */, 077C38612A9DDC79003D6B51 /* CardExampleData.swift in Sources */, - 077C384D2A9DDC79003D6B51 /* ComponentList.swift in Sources */, + 077C384D2A9DDC79003D6B51 /* ComponentsList.swift in Sources */, 077C38512A9DDC79003D6B51 /* CapitalizedTextInputsVariant.swift in Sources */, 07B1A09C2B1E191F00ABF0A1 /* InputChipsVariant.swift in Sources */, 077C38632A9DDC79003D6B51 /* CardHorizontalVariant.swift in Sources */, @@ -1305,6 +1308,7 @@ 077C38742A9DDC79003D6B51 /* SliderComponent.swift in Sources */, 07C3C7FC2AE7E4E000833957 /* ListModuleDataModel.swift in Sources */, 077C389A2A9DEEDC003D6B51 /* RecipeBookModel.swift in Sources */, + 512BF8F32B6411CF00F9FF67 /* AccssibleNavigationTitleModifier.swift in Sources */, F99FF0732767AE2A006236A0 /* OrangeDesignSystemApp.swift in Sources */, 077C38502A9DDC79003D6B51 /* EmphasisAndFunctionnalVariant.swift in Sources */, ); diff --git a/OrangeDesignSystemDemo/OrangeDesignSystemDemo/Screens/Components/ComponentList.swift b/OrangeDesignSystemDemo/OrangeDesignSystemDemo/Screens/Components/ComponentsList.swift similarity index 97% rename from OrangeDesignSystemDemo/OrangeDesignSystemDemo/Screens/Components/ComponentList.swift rename to OrangeDesignSystemDemo/OrangeDesignSystemDemo/Screens/Components/ComponentsList.swift index 57d48b36..cb2687c4 100644 --- a/OrangeDesignSystemDemo/OrangeDesignSystemDemo/Screens/Components/ComponentList.swift +++ b/OrangeDesignSystemDemo/OrangeDesignSystemDemo/Screens/Components/ComponentsList.swift @@ -67,8 +67,8 @@ struct ComponentsList: View { .padding(.all, ODSSpacing.s) } } - .navigationTitle("main_view.tabs.components") .navigationbarMenuForThemeSelection() + .modifier(AccssibleNavigationTitleModifier(title: "main_view.tabs.components")) ComponentPage(component: components[0]) } diff --git a/OrangeDesignSystemDemo/OrangeDesignSystemDemo/Screens/Guidelines/GuidelinesList.swift b/OrangeDesignSystemDemo/OrangeDesignSystemDemo/Screens/Guidelines/GuidelinesList.swift index 67b29a33..830ea3a5 100644 --- a/OrangeDesignSystemDemo/OrangeDesignSystemDemo/Screens/Guidelines/GuidelinesList.swift +++ b/OrangeDesignSystemDemo/OrangeDesignSystemDemo/Screens/Guidelines/GuidelinesList.swift @@ -16,11 +16,12 @@ import SwiftUI struct GuidelinesList: View { - // ====================== - // MARK: Store properties - // ====================== - @EnvironmentObject private var themeProvider: ThemeProvider + + // ======================= + // MARK: Stored properties + // ======================= + private let guidelines: [Guideline] private let columns = [GridItem(.flexible(), alignment: .topLeading)] @@ -51,8 +52,9 @@ struct GuidelinesList: View { } } .padding(.all, ODSSpacing.m) - .navigationTitle("shared.guidelines") .navigationbarMenuForThemeSelection() + .modifier(AccssibleNavigationTitleModifier(title: "shared.guidelines")) + } GuidelinePage(guideline: guidelines[0]) // Why ? diff --git a/OrangeDesignSystemDemo/OrangeDesignSystemDemo/Screens/Modules/ModulesList.swift b/OrangeDesignSystemDemo/OrangeDesignSystemDemo/Screens/Modules/ModulesList.swift index 8469a4f9..843b90b0 100644 --- a/OrangeDesignSystemDemo/OrangeDesignSystemDemo/Screens/Modules/ModulesList.swift +++ b/OrangeDesignSystemDemo/OrangeDesignSystemDemo/Screens/Modules/ModulesList.swift @@ -63,7 +63,7 @@ struct ModulesList: View { } .padding(.all, ODSSpacing.m) } - .navigationTitle("shared.modules") + .modifier(AccssibleNavigationTitleModifier(title: "shared.modules")) .navigationbarMenuForThemeSelection() } .navigationViewStyle(.stack) diff --git a/OrangeDesignSystemDemo/OrangeDesignSystemDemo/Utils/UI/AccssibleNavigationTitleModifier.swift b/OrangeDesignSystemDemo/OrangeDesignSystemDemo/Utils/UI/AccssibleNavigationTitleModifier.swift new file mode 100644 index 00000000..ad99bf71 --- /dev/null +++ b/OrangeDesignSystemDemo/OrangeDesignSystemDemo/Utils/UI/AccssibleNavigationTitleModifier.swift @@ -0,0 +1,34 @@ +// +// Software Name: Orange Design System +// SPDX-FileCopyrightText: Copyright (c) Orange SA +// SPDX-License-Identifier: MIT +// +// This software is distributed under the MIT licence, +// the text of which is available at https://opensource.org/license/MIT/ +// or see the "LICENSE" file for more details. +// +// Authors: See CONTRIBUTORS.txt +// Software description: A SwiftUI components library with code examples for Orange Design System +// + +import Foundation +import SwiftUI + +struct AccssibleNavigationTitleModifier: ViewModifier { + + let title: String + + init(title: String) { + self.title = title.localized() + } + + func body(content: Content) -> some View { + content + .navigationTitle(title) + .onAppear { + DispatchQueue.main.asyncAfter(deadline: .now() + 0.25) { + UIAccessibility.post(notification: .screenChanged, argument: title) + } + } + } +}