Merge branch 'mbruce/bugfix' into 'develop'

CXTDT-546824 - Notification - Accessibility - Redundant text is provided for the notification icon.

See merge request BPHV_MIPS/vds_ios!222
This commit is contained in:
Bruce, Matt R 2024-05-07 16:55:53 +00:00
commit fbc3cdb2bc
14 changed files with 160 additions and 21 deletions

View File

@ -210,6 +210,7 @@ open class BadgeIndicator: View {
/// The Container's height.
open var height: CGFloat? { didSet { setNeedsUpdate() } }
open var accessibilityText: String? { didSet { setNeedsUpdate() } }
//--------------------------------------------------
// MARK: - Private Properties
//--------------------------------------------------
@ -348,7 +349,9 @@ open class BadgeIndicator: View {
open override func updateAccessibility() {
super.updateAccessibility()
if kind == .numbered {
if let accessibilityText {
accessibilityLabel = accessibilityText
} else if kind == .numbered {
accessibilityLabel = label.text
} else {
accessibilityLabel = "Simple"

View File

@ -103,8 +103,6 @@ open class DropdownSelect: EntryFieldBase {
open override func setup() {
super.setup()
accessibilityLabel = "Dropdown Select"
// stackview for controls in EntryFieldBase.controlContainerView
let controlStackView = UIStackView().with {
$0.translatesAutoresizingMaskIntoConstraints = false
@ -118,6 +116,10 @@ open class DropdownSelect: EntryFieldBase {
controlStackView.addArrangedSubview(inlineDisplayLabel)
controlStackView.addArrangedSubview(selectedOptionLabel)
containerStackView.isAccessibilityElement = true
containerStackView.accessibilityLabel = "Dropdown Select"
inlineDisplayLabel.isAccessibilityElement = true
controlStackView.setCustomSpacing(0, after: dropdownField)
controlStackView.setCustomSpacing(VDSLayout.space1X, after: inlineDisplayLabel)
controlStackView.setCustomSpacing(VDSLayout.space3X, after: selectedOptionLabel)
@ -245,9 +247,41 @@ open class DropdownSelect: EntryFieldBase {
statusIcon.color = iconColorConfiguration.getColor(self)
}
open override func updateAccessibility() {
super.updateAccessibility()
var selectedOption = selectedOptionLabel.text ?? ""
containerStackView.accessibilityLabel = "Dropdown Select, \(selectedOption) \(isReadOnly ? ", read only" : "")"
containerStackView.accessibilityHint = isReadOnly || !isEnabled ? "" : "Double tap to open."
}
open override var accessibilityElements: [Any]? {
get {
var elements = [Any]()
elements.append(contentsOf: [titleLabel, containerStackView])
if showError {
elements.append(statusIcon)
if let errorText, !errorText.isEmpty {
elements.append(errorLabel)
}
}
if let helperText, !helperText.isEmpty {
elements.append(helperLabel)
}
return elements
}
set { super.accessibilityElements = newValue }
}
@objc open func pickerDoneClicked() {
optionsPicker.isHidden = true
dropdownField.resignFirstResponder()
setNeedsUpdate()
UIAccessibility.post(notification: .layoutChanged, argument: containerStackView)
}
}
@ -258,6 +292,7 @@ extension DropdownSelect: UIPickerViewDelegate, UIPickerViewDataSource {
internal func launchPicker() {
if optionsPicker.isHidden {
UIAccessibility.post(notification: .layoutChanged, argument: optionsPicker)
dropdownField.becomeFirstResponder()
} else {
dropdownField.resignFirstResponder()

View File

@ -544,6 +544,7 @@ open class ButtonIcon: Control, Changeable {
badgeIndicator.horizontalPadding = badgeIndicatorModel.horizontalPadding
badgeIndicator.hideDot = badgeIndicatorModel.hideDot
badgeIndicator.hideBorder = badgeIndicatorModel.hideBorder
badgeIndicator.accessibilityText = badgeIndicatorModel.accessibilityText
}
private func updateExpandDirectionalConstraints() {

View File

@ -46,6 +46,9 @@ extension ButtonIcon {
/// Trailing Text height that will be used for the badge indicator.
public var trailingText: String?
/// Accessibliity Text
public var accessibilityText: String?
/// Dot Size that will be used for the badge indicator.
public var dotSize: CGFloat?
@ -61,7 +64,7 @@ extension ButtonIcon {
/// Hide Border that will be used for the badge indicator.
public var hideBorder: Bool = false
public init(kind: BadgeIndicator.Kind = .simple, fillColor: BadgeIndicator.FillColor = .red, expandDirection: ExpandDirection = .right, size: BadgeIndicator.Size = .xxlarge, maximumDigits: BadgeIndicator.MaximumDigits = .two, width: CGFloat? = nil, height: CGFloat? = nil, number: Int? = nil, leadingCharacter: String? = "", trailingText: String? = "", dotSize: CGFloat? = nil, verticalPadding: CGFloat? = nil, horizontalPadding: CGFloat? = nil, hideDot: Bool = false, hideBorder: Bool = false) {
public init(kind: BadgeIndicator.Kind = .simple, fillColor: BadgeIndicator.FillColor = .red, expandDirection: ExpandDirection = .right, size: BadgeIndicator.Size = .xxlarge, maximumDigits: BadgeIndicator.MaximumDigits = .two, width: CGFloat? = nil, height: CGFloat? = nil, number: Int? = nil, leadingCharacter: String? = "", trailingText: String? = "", accessibilityText: String? = nil, dotSize: CGFloat? = nil, verticalPadding: CGFloat? = nil, horizontalPadding: CGFloat? = nil, hideDot: Bool = false, hideBorder: Bool = false) {
self.kind = kind
self.fillColor = fillColor
self.expandDirection = expandDirection
@ -70,6 +73,7 @@ extension ButtonIcon {
self.width = width
self.height = height
self.number = number
self.accessibilityText = accessibilityText
self.leadingCharacter = leadingCharacter
self.trailingText = trailingText
self.dotSize = dotSize

View File

@ -77,7 +77,7 @@ public class TooltipLabelAttribute: ActionLabelAttributeModel, TooltipLaunchable
self.subscriber = subscriber
self.surface = surface
self.model = model
self.accessibleText = accessibleText
self.accessibleText = accessibleText ?? model.accessibleText
self.presenter = presenter
//create the tooltip click event

View File

@ -104,6 +104,7 @@ open class Notification: View {
open var typeIcon = Icon().with {
$0.name = .infoBold
$0.size = UIDevice.isIPad ? .medium : .small
$0.accessibilityTraits.remove(.image)
}
/// Icon used for the close.

View File

@ -207,7 +207,7 @@ open class EntryFieldBase: Control, Changeable, FormFieldInternalValidatable {
open override func setup() {
super.setup()
isAccessibilityElement = true
isAccessibilityElement = false
addSubview(stackView)
//create the wrapping view

View File

@ -148,7 +148,6 @@ open class InputField: EntryFieldBase {
/// Called once when a view is initialized and is used to Setup additional UI or other constants and configurations.
open override func setup() {
super.setup()
isAccessibilityElement = false
minWidthConstraint = containerView.widthAnchor.constraint(greaterThanOrEqualToConstant: 0)
minWidthConstraint?.isActive = true
@ -373,11 +372,29 @@ open class InputField: EntryFieldBase {
open override func updateAccessibility() {
super.updateAccessibility()
textField.accessibilityLabel = showError ? "error" : nil
if showError {
accessibilityElements = [titleLabel, textField, statusIcon, errorLabel, helperLabel]
} else {
accessibilityElements = [titleLabel, textField, helperLabel]
}
open override var accessibilityElements: [Any]? {
get {
var elements = [Any]()
elements.append(contentsOf: [titleLabel, textField])
if showError {
elements.append(statusIcon)
if let errorText, !errorText.isEmpty {
elements.append(errorLabel)
}
} else if showSuccess, let successText, !successText.isEmpty {
elements.append(successLabel)
}
if let helperText, !helperText.isEmpty {
elements.append(helperLabel)
}
return elements
}
set { super.accessibilityElements = newValue }
}
open override var canBecomeFirstResponder: Bool { true }

View File

@ -10,6 +10,25 @@ import UIKit
@objc(VDSTextField)
open class TextField: UITextField {
//--------------------------------------------------
// MARK: - Initializers
//--------------------------------------------------
required public init() {
super.init(frame: .zero)
initialSetup()
}
public override init(frame: CGRect) {
super.init(frame: .zero)
initialSetup()
}
public required init?(coder: NSCoder) {
super.init(coder: coder)
initialSetup()
}
var horizontalPadding: CGFloat = 0
open override func textRect(forBounds bounds: CGRect) -> CGRect {
@ -35,6 +54,25 @@ open class TextField: UITextField {
}
}
open func initialSetup() {
let doneToolbar: UIToolbar = UIToolbar()
doneToolbar.translatesAutoresizingMaskIntoConstraints = false
doneToolbar.barStyle = .default
let flexSpace = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil)
let done: UIBarButtonItem = UIBarButtonItem(title: "Done", style: .done, target: self, action: #selector(self.doneButtonAction))
done.accessibilityHint = "Double tap to finish editing."
doneToolbar.items = [flexSpace, done]
doneToolbar.sizeToFit()
inputAccessoryView = doneToolbar
}
@objc func doneButtonAction() {
// Resigns the first responder status when 'Done' is tapped
resignFirstResponder()
}
open override func becomeFirstResponder() -> Bool {
let success = super.becomeFirstResponder()
if isSecureTextEntry, let text {

View File

@ -161,7 +161,6 @@ open class TextArea: EntryFieldBase {
/// Called once when a view is initialized and is used to Setup additional UI or other constants and configurations.
open override func setup() {
super.setup()
isAccessibilityElement = false
containerStackView.pinToSuperView(.uniform(VDSFormControls.spaceInset))
minWidthConstraint = containerView.widthAnchor.constraint(greaterThanOrEqualToConstant: containerSize.width)
minWidthConstraint?.isActive = true
@ -264,13 +263,31 @@ open class TextArea: EntryFieldBase {
open override func updateAccessibility() {
super.updateAccessibility()
textView.accessibilityLabel = showError ? "error" : nil
}
open override var accessibilityElements: [Any]? {
get {
var elements = [Any]()
elements.append(contentsOf: [titleLabel, textView])
if showError {
accessibilityElements = [titleLabel, textView, statusIcon, errorLabel, helperLabel]
} else {
accessibilityElements = [titleLabel, textView, helperLabel]
elements.append(statusIcon)
if let errorText, !errorText.isEmpty {
elements.append(errorLabel)
}
}
if let helperText, !helperText.isEmpty {
elements.append(helperLabel)
}
return elements
}
set { super.accessibilityElements = newValue }
}
open override var canBecomeFirstResponder: Bool { true }
open override func resignFirstResponder() -> Bool {

View File

@ -97,7 +97,6 @@ open class TextView: UITextView, ViewProtocol {
initialSetupPerformed = true
backgroundColor = .clear
translatesAutoresizingMaskIntoConstraints = false
accessibilityCustomActions = []
setup()
setNeedsUpdate()
}
@ -106,6 +105,23 @@ open class TextView: UITextView, ViewProtocol {
open func setup() {
translatesAutoresizingMaskIntoConstraints = false
let doneToolbar: UIToolbar = UIToolbar()
doneToolbar.translatesAutoresizingMaskIntoConstraints = false
doneToolbar.barStyle = .default
let flexSpace = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil)
let done: UIBarButtonItem = UIBarButtonItem(title: "Done", style: .done, target: self, action: #selector(self.doneButtonAction))
done.accessibilityHint = "Double tap to finish editing."
doneToolbar.items = [flexSpace, done]
doneToolbar.sizeToFit()
inputAccessoryView = doneToolbar
}
@objc func doneButtonAction() {
// Resigns the first responder status when 'Done' is tapped
resignFirstResponder()
}
open func updateView() {
@ -118,7 +134,6 @@ open class TextView: UITextView, ViewProtocol {
shouldUpdateView = false
surface = .light
text = nil
accessibilityCustomActions = []
shouldUpdateView = true
setNeedsUpdate()
}

View File

@ -48,7 +48,6 @@ open class TooltipDialog: View, UIScrollViewDelegate {
lazy var primaryAccessibilityElement = UIAccessibilityElement(accessibilityContainer: self).with {
$0.accessibilityLabel = "Modal"
$0.accessibilityFrameInContainerSpace = .init(origin: .zero, size: .init(width: fullWidth, height: VDSLayout.space1X))
}
//--------------------------------------------------
@ -222,6 +221,7 @@ open class TooltipDialog: View, UIScrollViewDelegate {
super.updateAccessibility()
primaryAccessibilityElement.accessibilityHint = "Double tap on the \(tooltipModel.closeButtonText) button to close."
primaryAccessibilityElement.accessibilityFrameInContainerSpace = .init(origin: .zero, size: frame.size)
var elements: [Any] = [primaryAccessibilityElement]
contentStackView.arrangedSubviews.forEach{ elements.append($0) }

View File

@ -17,16 +17,19 @@ extension Tooltip {
public var title: String?
public var content: String?
public var contentView: UIView?
public var accessibleText: String?
public var contentViewAlignment: UIStackView.Alignment?
public init(closeButtonText: String = "Close",
title: String? = nil,
content: String? = nil,
contentView: UIView? = nil,
accessibleText: String? = "Tooltip",
contentViewAlignment: UIStackView.Alignment = .leading) {
self.closeButtonText = closeButtonText
self.title = title
self.content = content
self.contentView = contentView
self.accessibleText = accessibleText
self.contentViewAlignment = contentViewAlignment
}
}

View File

@ -1,3 +1,8 @@
1.0.62
----------------
- CXTDT-546824 - Notification - Accessibility - Redundant text is provided for the notification icon.
- CXTDT-553663 - DropdownSelect - Accessibility - 5 issues
1.0.61
----------------
- CXTDT-552068 - Text Area - Text padding