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:
commit
fbc3cdb2bc
@ -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"
|
||||
|
||||
@ -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()
|
||||
|
||||
@ -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() {
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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 }
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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()
|
||||
}
|
||||
|
||||
@ -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) }
|
||||
|
||||
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
Loading…
Reference in New Issue
Block a user