Skip to content

Commit c88aed2

Browse files
committed
fix: vocalization of checkbox only label (a11y) (#488)
Signed-off-by: Pierre-Yves Lapersonne <[email protected]>
1 parent 00f1d02 commit c88aed2

File tree

4 files changed

+45
-8
lines changed

4 files changed

+45
-8
lines changed

DesignToolbox/DesignToolbox/Pages/Components/Checkbox/Checkbox/CheckboxPage.swift

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,9 @@ private struct CheckboxDemo: View {
7575
var body: some View {
7676
HStack(alignment: .center) {
7777
Spacer()
78-
OUDSCheckbox(state: $model.selectorState, isError: model.isError)
78+
OUDSCheckbox(state: $model.selectorState,
79+
accessibilityLabel: "app_components_checkbox_hint_a11y".localized(),
80+
isError: model.isError)
7981
.disabled(!model.enabled)
8082
Spacer()
8183
}

DesignToolbox/DesignToolbox/Resources/Localizable.xcstrings

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -556,6 +556,24 @@
556556
}
557557
}
558558
},
559+
"app_components_checkbox_hint_a11y" : {
560+
"comment" : "Component - Checkbox",
561+
"extractionState" : "manual",
562+
"localizations" : {
563+
"en" : {
564+
"stringUnit" : {
565+
"state" : "translated",
566+
"value" : "This is a fake label used in the demo app"
567+
}
568+
},
569+
"fr" : {
570+
"stringUnit" : {
571+
"state" : "translated",
572+
"value" : "Ceci est un label bidon pour l’app de démo"
573+
}
574+
}
575+
}
576+
},
559577
"app_components_checkbox_label" : {
560578
"comment" : "Component - Checkbox",
561579
"extractionState" : "manual",

OUDS/Core/Components/Sources/Checkbox/OUDSCheckbox.swift

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,13 @@ import SwiftUI
3333
/// In addition, the ``OUDSCheckbox`` can be in read only mode, i.e. the user cannot interact with the component yet but this component must not be considered
3434
/// as disabled.
3535
///
36-
/// ## Case forbidden by design
36+
/// ## Accessibility considerations
37+
///
38+
/// Note also the component must be instanciated with a string parameter used as accessibility label.
39+
/// It is a good pratice (a least) to define a label for a component without text for accessibility reasons. This label will be vocalized by *Voice Over*.
40+
/// The vocalization tool will also use, after the label, a description of the component (if disabled, if error context), and a fake trait for checkbox.
41+
///
42+
/// ## Cases forbidden by design
3743
///
3844
/// **The design system does not allow to have both an error situation and a disabled component.**
3945
///
@@ -44,14 +50,14 @@ import SwiftUI
4450
/// @Published var state: OUDSCheckboxSelectorState = .undeterminate
4551
///
4652
/// // A simple checkbox, no error, not in read only mode
47-
/// OUDSCheckbox(state: $state)
53+
/// OUDSCheckbox(state: $state, accessibilityLabel: "The cake is a lie")
4854
///
4955
/// // A simple checkbox, but is an error context
50-
/// OUDSCheckbox(state: $state, isError: true)
56+
/// OUDSCheckbox(state: $state, accessibilityLabel: "The cake is a lie"), isError: true)
5157
///
5258
/// // Never disable an error-related checkbox as it will crash
5359
/// // This is forbidden by design!
54-
/// OUDSCheckbox(state: $state, isError: true).disabled(true) // fatal error
60+
/// OUDSCheckbox(state: $state, accessibilityLabel: "The cake is a lie"), isError: true).disabled(true) // fatal error
5561
/// ```
5662
///
5763
/// ## Design documentation
@@ -64,6 +70,7 @@ public struct OUDSCheckbox: View {
6470
// MARK: - Properties
6571

6672
private let isError: Bool
73+
private let a11yLabel: String
6774

6875
@Binding var selectorState: OUDSCheckboxSelectorState
6976
@Environment(\.isEnabled) private var isEnabled
@@ -76,12 +83,18 @@ public struct OUDSCheckbox: View {
7683
///
7784
/// - Parameters:
7885
/// - state: A binding to a property that determines wether the selector is ticked, unticked or preticked.
86+
/// - accessibilityLabel: The accessibility label the component must have
7987
/// - isError: True if the look and feel of the component must reflect an error state, default set to `false`
8088
public init(state: Binding<OUDSCheckboxSelectorState>,
89+
accessibilityLabel: String,
8190
isError: Bool = false) {
82-
self._selectorState = state
83-
self.isError = isError
91+
if accessibilityLabel.isEmpty {
92+
OL.warning("The OUDSCheckbox should not have an empty accessibility label, think about your disabled users!")
8493
}
94+
self._selectorState = state
95+
self.isError = isError
96+
a11yLabel = accessibilityLabel
97+
}
8598

8699
// MARK: Body
87100

@@ -103,7 +116,7 @@ public struct OUDSCheckbox: View {
103116
let errorDescription = isError ? "core_checkbox_error_a11y".localized() : ""
104117
let checkboxA11yTrait = "core_checkbox_trait_a11y".localized() // Fake trait for Voice Over vocalization
105118

106-
let result = "\(stateDescription) \(errorDescription) \(checkboxA11yTrait)"
119+
let result = "\(a11yLabel), \(stateDescription) \(errorDescription) \(checkboxA11yTrait)"
107120
return result
108121
}
109122
}

OUDS/Core/Components/Sources/Checkbox/OUDSCheckboxItem.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,10 @@ import SwiftUI
4040
/// In addition, the ``OUDSCheckboxItem`` can be in read only mode, i.e. the user cannot interact with the component yet but this component must not be considered
4141
/// as disabled.
4242
///
43+
/// ## Accessibility considerations
44+
///
45+
/// *Voice Over* will use several elements to describe the component: if component disabled / read only, if error context, the label and helper texts and a custom checkbox trait.
46+
///
4347
/// ## Forbidden by design
4448
///
4549
/// **The design system does not allow to have both an error situation and a read only component.**

0 commit comments

Comments
 (0)