Merge branch 'develop' into feature/monarch

This commit is contained in:
Matt Bruce 2024-05-24 12:13:02 -05:00
commit d078b6beed
19 changed files with 195 additions and 58 deletions

View File

@ -102,6 +102,7 @@
EA5F86D02A1F936100BC83E4 /* TabsContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA5F86CF2A1F936100BC83E4 /* TabsContainer.swift */; }; EA5F86D02A1F936100BC83E4 /* TabsContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA5F86CF2A1F936100BC83E4 /* TabsContainer.swift */; };
EA6642952BCEBF9500D81DC4 /* TextLinkModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA6642942BCEBF9500D81DC4 /* TextLinkModel.swift */; }; EA6642952BCEBF9500D81DC4 /* TextLinkModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA6642942BCEBF9500D81DC4 /* TextLinkModel.swift */; };
EA6F330E2B911E9000BACAB9 /* TextView.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA6F330D2B911E9000BACAB9 /* TextView.swift */; }; EA6F330E2B911E9000BACAB9 /* TextView.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA6F330D2B911E9000BACAB9 /* TextView.swift */; };
EA78C7962C00CAC200430AD1 /* Groupable.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA78C7952C00CAC200430AD1 /* Groupable.swift */; };
EA81410B2A0E8E3C004F60D2 /* ButtonIcon.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA81410A2A0E8E3C004F60D2 /* ButtonIcon.swift */; }; EA81410B2A0E8E3C004F60D2 /* ButtonIcon.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA81410A2A0E8E3C004F60D2 /* ButtonIcon.swift */; };
EA8141102A127066004F60D2 /* UIColor+VDSColor.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA81410F2A127066004F60D2 /* UIColor+VDSColor.swift */; }; EA8141102A127066004F60D2 /* UIColor+VDSColor.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA81410F2A127066004F60D2 /* UIColor+VDSColor.swift */; };
EA89200428AECF4B006B9984 /* UITextField+Publisher.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA89200328AECF4B006B9984 /* UITextField+Publisher.swift */; }; EA89200428AECF4B006B9984 /* UITextField+Publisher.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA89200328AECF4B006B9984 /* UITextField+Publisher.swift */; };
@ -318,6 +319,7 @@
EA5F86CF2A1F936100BC83E4 /* TabsContainer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TabsContainer.swift; sourceTree = "<group>"; }; EA5F86CF2A1F936100BC83E4 /* TabsContainer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TabsContainer.swift; sourceTree = "<group>"; };
EA6642942BCEBF9500D81DC4 /* TextLinkModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextLinkModel.swift; sourceTree = "<group>"; }; EA6642942BCEBF9500D81DC4 /* TextLinkModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextLinkModel.swift; sourceTree = "<group>"; };
EA6F330D2B911E9000BACAB9 /* TextView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextView.swift; sourceTree = "<group>"; }; EA6F330D2B911E9000BACAB9 /* TextView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextView.swift; sourceTree = "<group>"; };
EA78C7952C00CAC200430AD1 /* Groupable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Groupable.swift; sourceTree = "<group>"; };
EA81410A2A0E8E3C004F60D2 /* ButtonIcon.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ButtonIcon.swift; sourceTree = "<group>"; }; EA81410A2A0E8E3C004F60D2 /* ButtonIcon.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ButtonIcon.swift; sourceTree = "<group>"; };
EA81410F2A127066004F60D2 /* UIColor+VDSColor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIColor+VDSColor.swift"; sourceTree = "<group>"; }; EA81410F2A127066004F60D2 /* UIColor+VDSColor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIColor+VDSColor.swift"; sourceTree = "<group>"; };
EA89200328AECF4B006B9984 /* UITextField+Publisher.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UITextField+Publisher.swift"; sourceTree = "<group>"; }; EA89200328AECF4B006B9984 /* UITextField+Publisher.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UITextField+Publisher.swift"; sourceTree = "<group>"; };
@ -720,6 +722,7 @@
EA5E305929510F8B0082B959 /* EnumSubset.swift */, EA5E305929510F8B0082B959 /* EnumSubset.swift */,
EAF7F0A1289AFB3900B287F5 /* Errorable.swift */, EAF7F0A1289AFB3900B287F5 /* Errorable.swift */,
EA3361AE288B26310071C351 /* FormFieldable.swift */, EA3361AE288B26310071C351 /* FormFieldable.swift */,
EA78C7952C00CAC200430AD1 /* Groupable.swift */,
EA33624628931B050071C351 /* Initable.swift */, EA33624628931B050071C351 /* Initable.swift */,
EA471F392A95587500CE9E58 /* LayoutConstraintable.swift */, EA471F392A95587500CE9E58 /* LayoutConstraintable.swift */,
EA985C7C297DAED300F2FF2E /* Primitive.swift */, EA985C7C297DAED300F2FF2E /* Primitive.swift */,
@ -1205,6 +1208,7 @@
EA89200428AECF4B006B9984 /* UITextField+Publisher.swift in Sources */, EA89200428AECF4B006B9984 /* UITextField+Publisher.swift in Sources */,
18A65A022B96E848006602CC /* Breadcrumbs.swift in Sources */, 18A65A022B96E848006602CC /* Breadcrumbs.swift in Sources */,
1842B1E12BECE7B70021AFCA /* CalendarHeaderReusableView.swift in Sources */, 1842B1E12BECE7B70021AFCA /* CalendarHeaderReusableView.swift in Sources */,
EA78C7962C00CAC200430AD1 /* Groupable.swift in Sources */,
EA0D1C3F2A6AD5E200E5C127 /* Typography+ContentSizeCategory.swift in Sources */, EA0D1C3F2A6AD5E200E5C127 /* Typography+ContentSizeCategory.swift in Sources */,
EA5F86C82A1BD99100BC83E4 /* TabModel.swift in Sources */, EA5F86C82A1BD99100BC83E4 /* TabModel.swift in Sources */,
EA297A5729FB0A360031ED56 /* AppleGuidelinesTouchable.swift in Sources */, EA297A5729FB0A360031ED56 /* AppleGuidelinesTouchable.swift in Sources */,

View File

@ -39,7 +39,7 @@ extension SelectorGroupSingleSelect {
} }
/// Base Class used for any Grouped Form Control of a Selector Type. /// Base Class used for any Grouped Form Control of a Selector Type.
open class SelectorGroupBase<SelectorItemType: Control>: Control, SelectorGroup, Changeable { open class SelectorGroupBase<SelectorItemType: Groupable>: Control, SelectorGroup, Changeable {
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Private Properties // MARK: - Private Properties

View File

@ -11,7 +11,7 @@ import Combine
import VDSCoreTokens import VDSCoreTokens
/// Base Class used to build out a SelectorControlable control. /// Base Class used to build out a SelectorControlable control.
open class SelectorItemBase<Selector: SelectorControlable>: Control, Errorable, Changeable { open class SelectorItemBase<Selector: SelectorControlable>: Control, Errorable, Changeable, Groupable {
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Initializers // MARK: - Initializers
@ -145,6 +145,8 @@ open class SelectorItemBase<Selector: SelectorControlable>: Control, Errorable,
open var hiddenValue: AnyHashable? { didSet { setNeedsUpdate() } } open var hiddenValue: AnyHashable? { didSet { setNeedsUpdate() } }
open var accessibilityValueText: String?
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Overrides // MARK: - Overrides
//-------------------------------------------------- //--------------------------------------------------
@ -193,6 +195,7 @@ open class SelectorItemBase<Selector: SelectorControlable>: Control, Errorable,
open override func updateAccessibility() { open override func updateAccessibility() {
super.updateAccessibility() super.updateAccessibility()
setAccessibilityLabel(for: [selectorView, label, childLabel, errorLabel]) setAccessibilityLabel(for: [selectorView, label, childLabel, errorLabel])
accessibilityValue = accessibilityValueText
} }
/// Resets to default settings. /// Resets to default settings.

View File

@ -48,7 +48,7 @@ open class CheckboxGroup: SelectorGroupBase<CheckboxItem>, SelectorGroupMultiSel
$0.inputId = model.inputId $0.inputId = model.inputId
$0.hiddenValue = model.value $0.hiddenValue = model.value
$0.accessibilityLabel = model.accessibileText $0.accessibilityLabel = model.accessibileText
$0.accessibilityValue = "item \(index+1) of \(selectorModels.count)" $0.accessibilityValueText = "item \(index+1) of \(selectorModels.count)"
$0.labelText = model.labelText $0.labelText = model.labelText
$0.labelTextAttributes = model.labelTextAttributes $0.labelTextAttributes = model.labelTextAttributes
$0.childText = model.childText $0.childText = model.childText

View File

@ -101,7 +101,9 @@ open class DatePicker: EntryFieldBase, DatePickerViewControllerDelegate, UIPopov
open override func setup() { open override func setup() {
super.setup() super.setup()
accessibilityLabel = "Dropdown Select" fieldStackView.isAccessibilityElement = true
fieldStackView.accessibilityLabel = "Date Picker"
fieldStackView.accessibilityHint = "Double Tap to open"
// setting color config // setting color config
selectedDateLabel.textColorConfiguration = primaryColorConfiguration.eraseToAnyColorable() selectedDateLabel.textColorConfiguration = primaryColorConfiguration.eraseToAnyColorable()
@ -143,6 +145,18 @@ open class DatePicker: EntryFieldBase, DatePickerViewControllerDelegate, UIPopov
calendarIcon.color = iconColorConfiguration.getColor(self) calendarIcon.color = iconColorConfiguration.getColor(self)
} }
open override func updateAccessibility() {
super.updateAccessibility()
let label = "Date Picker, \(isReadOnly ? ", read only" : "")"
if let errorText, showError {
fieldStackView.accessibilityLabel = "\(label) ,error, \(errorText)"
} else {
fieldStackView.accessibilityLabel = label
}
fieldStackView.accessibilityHint = isReadOnly || !isEnabled ? "" : "Double tap to open."
fieldStackView.accessibilityValue = value
}
/// Resets to default settings. /// Resets to default settings.
open override func reset() { open override func reset() {
super.reset() super.reset()

View File

@ -132,7 +132,6 @@ open class DropdownSelect: EntryFieldBase {
super.setup() super.setup()
fieldStackView.isAccessibilityElement = true fieldStackView.isAccessibilityElement = true
fieldStackView.accessibilityLabel = "Dropdown Select"
inlineDisplayLabel.isAccessibilityElement = true inlineDisplayLabel.isAccessibilityElement = true
dropdownField.width(0) dropdownField.width(0)
@ -278,9 +277,14 @@ open class DropdownSelect: EntryFieldBase {
open override func updateAccessibility() { open override func updateAccessibility() {
super.updateAccessibility() super.updateAccessibility()
let selectedOption = selectedOptionLabel.text ?? "" let label = "Dropdown Select, \(isReadOnly ? ", read only" : "")"
fieldStackView.accessibilityLabel = "Dropdown Select, \(selectedOption) \(isReadOnly ? ", read only" : "")" if let errorText, showError {
fieldStackView.accessibilityLabel = "\(label) ,error, \(errorText)"
} else {
fieldStackView.accessibilityLabel = label
}
fieldStackView.accessibilityHint = isReadOnly || !isEnabled ? "" : "Double tap to open." fieldStackView.accessibilityHint = isReadOnly || !isEnabled ? "" : "Double tap to open."
fieldStackView.accessibilityValue = value
} }
open override var accessibilityElements: [Any]? { open override var accessibilityElements: [Any]? {

View File

@ -56,6 +56,7 @@ open class RadioBoxGroup: SelectorGroupBase<RadioBoxItem>, SelectorGroupSingleSe
$0.isSelected = model.selected $0.isSelected = model.selected
$0.strikethrough = model.strikethrough $0.strikethrough = model.strikethrough
$0.strikethroughAccessibilityText = model.strikethroughAccessibileText $0.strikethroughAccessibilityText = model.strikethroughAccessibileText
$0.accessibilityValueText = "item \(index+1) of \(selectorModels.count)"
} }
} }
} }

View File

@ -13,7 +13,7 @@ import VDSCoreTokens
/// Radio boxes are single-select components through which a customer indicates a choice /// Radio boxes are single-select components through which a customer indicates a choice
/// that are used within a ``RadioBoxGroup``. /// that are used within a ``RadioBoxGroup``.
@objc(VDSRadioBoxItem) @objc(VDSRadioBoxItem)
open class RadioBoxItem: Control, Changeable, FormFieldable { open class RadioBoxItem: Control, Changeable, FormFieldable, Groupable {
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Initializers // MARK: - Initializers
@ -131,6 +131,8 @@ open class RadioBoxItem: Control, Changeable, FormFieldable {
open var hiddenValue: AnyHashable? { didSet { setNeedsUpdate() } } open var hiddenValue: AnyHashable? { didSet { setNeedsUpdate() } }
open var accessibilityValueText: String?
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Configuration Properties // MARK: - Configuration Properties
//-------------------------------------------------- //--------------------------------------------------
@ -241,7 +243,15 @@ open class RadioBoxItem: Control, Changeable, FormFieldable {
open override func updateAccessibility() { open override func updateAccessibility() {
super.updateAccessibility() super.updateAccessibility()
setAccessibilityLabel(for: [textLabel, subTextLabel, subTextRightLabel]) setAccessibilityLabel(for: [textLabel, subTextLabel, subTextRightLabel])
accessibilityValue = strikethrough ? strikethroughAccessibilityText : nil if let accessibilityValueText {
accessibilityValue = strikethrough
? "\(strikethroughAccessibilityText), \(accessibilityValueText)"
: accessibilityValueText
} else {
accessibilityValue = strikethrough
? "\(strikethroughAccessibilityText)"
: accessibilityValueText
}
} }
//-------------------------------------------------- //--------------------------------------------------

View File

@ -47,7 +47,7 @@ open class RadioButtonGroup: SelectorGroupBase<RadioButtonItem>, SelectorGroupSi
$0.inputId = model.inputId $0.inputId = model.inputId
$0.hiddenValue = model.value $0.hiddenValue = model.value
$0.accessibilityLabel = model.accessibileText $0.accessibilityLabel = model.accessibileText
$0.accessibilityValue = "item \(index+1) of \(selectorModels.count)" $0.accessibilityValueText = "item \(index+1) of \(selectorModels.count)"
$0.labelText = model.labelText $0.labelText = model.labelText
$0.labelTextAttributes = model.labelTextAttributes $0.labelTextAttributes = model.labelTextAttributes
$0.childText = model.childText $0.childText = model.childText

View File

@ -13,7 +13,7 @@ import Combine
extension Tabs { extension Tabs {
@objc(VDSTab) @objc(VDSTab)
open class Tab: Control { open class Tab: Control, Groupable {
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Initializers // MARK: - Initializers
@ -89,6 +89,8 @@ extension Tabs {
open override var shouldHighlight: Bool { false } open override var shouldHighlight: Bool { false }
open var accessibilityValueText: String?
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Configuration // MARK: - Configuration
//-------------------------------------------------- //--------------------------------------------------
@ -178,6 +180,7 @@ extension Tabs {
open override func updateAccessibility() { open override func updateAccessibility() {
super.updateAccessibility() super.updateAccessibility()
accessibilityLabel = text accessibilityLabel = text
accessibilityValue = accessibilityValueText
} }
open override func layoutSubviews() { open override func layoutSubviews() {

View File

@ -303,7 +303,7 @@ open class Tabs: View {
tabItem.orientation = orientation tabItem.orientation = orientation
tabItem.surface = surface tabItem.surface = surface
tabItem.indicatorPosition = indicatorPosition tabItem.indicatorPosition = indicatorPosition
tabItem.accessibilityValue = "\(index+1) of \(tabViews.count) Tabs" tabItem.accessibilityValueText = "\(index+1) of \(tabViews.count) Tabs"
} }
} }

View File

@ -175,6 +175,7 @@ open class EntryFieldBase: Control, Changeable, FormFieldInternalValidatable {
open var statusIcon: Icon = Icon().with { open var statusIcon: Icon = Icon().with {
$0.size = .medium $0.size = .medium
$0.isAccessibilityElement = false
} }
open var labelText: String? { didSet { setNeedsUpdate() } } open var labelText: String? { didSet { setNeedsUpdate() } }

View File

@ -210,9 +210,21 @@ open class InputField: EntryFieldBase {
super.updateView() super.updateView()
textField.isEnabled = isEnabled textField.isEnabled = isEnabled
textField.isUserInteractionEnabled = isEnabled && !isReadOnly
textField.textColor = textFieldTextColorConfiguration.getColor(self) textField.textColor = textFieldTextColorConfiguration.getColor(self)
} }
open override func updateAccessibility() {
super.updateAccessibility()
let label = "\(isReadOnly ? "read only" : "")"
if let errorText, showError {
textField.accessibilityLabel = "\(label) ,error, \(errorText)"
} else {
textField.accessibilityLabel = label
}
textField.accessibilityHint = isReadOnly || !isEnabled ? "" : "Double tap to open."
}
open override func updateErrorLabel() { open override func updateErrorLabel() {
super.updateErrorLabel() super.updateErrorLabel()
@ -233,7 +245,6 @@ open class InputField: EntryFieldBase {
} else { } else {
successLabel.isHidden = true successLabel.isHidden = true
} }
} }
override func updateRules() { override func updateRules() {
@ -241,12 +252,6 @@ open class InputField: EntryFieldBase {
fieldType.handler().appendRules(self) fieldType.handler().appendRules(self)
} }
/// Used to update any Accessibility properties.
open override func updateAccessibility() {
super.updateAccessibility()
textField.accessibilityLabel = showError ? "error" : nil
}
open override var accessibilityElements: [Any]? { open override var accessibilityElements: [Any]? {
get { get {
var elements = [Any]() var elements = [Any]()

View File

@ -7,9 +7,10 @@
import Foundation import Foundation
import UIKit import UIKit
import Combine
@objc(VDSTextField) @objc(VDSTextField)
open class TextField: UITextField { open class TextField: UITextField, ViewProtocol, Errorable {
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Initializers // MARK: - Initializers
@ -29,8 +30,84 @@ open class TextField: UITextField {
initialSetup() initialSetup()
} }
var horizontalPadding: CGFloat = 0 //--------------------------------------------------
// MARK: - Combine Properties
//--------------------------------------------------
/// Set of Subscribers for any Publishers for this Control.
open var subscribers = Set<AnyCancellable>()
//--------------------------------------------------
// MARK: - Private Properties
//--------------------------------------------------
private var initialSetupPerformed = false
private var horizontalPadding: CGFloat = 0
//--------------------------------------------------
// MARK: - Properties
//--------------------------------------------------
/// Key of whether or not updateView() is called in setNeedsUpdate()
open var shouldUpdateView: Bool = true
open var surface: Surface = .light { didSet { setNeedsUpdate() } }
open var showError: Bool = false { didSet { setNeedsUpdate() } }
open var errorText: String? { didSet { setNeedsUpdate() } }
//--------------------------------------------------
// MARK: - Lifecycle
//--------------------------------------------------
open func initialSetup() {
if !initialSetupPerformed {
initialSetupPerformed = true
backgroundColor = .clear
translatesAutoresizingMaskIntoConstraints = false
setup()
setNeedsUpdate()
}
}
open func setup() {
let accessView = UIView(frame: .init(origin: .zero, size: .init(width: UIScreen.main.bounds.width, height: 44)))
accessView.backgroundColor = .white
accessView.addBorder(side: .top, width: 1, color: .lightGray)
let done = UIButton(type: .system)
done.setTitle("Done", for: .normal)
done.translatesAutoresizingMaskIntoConstraints = false
done.addTarget(self, action: #selector(doneButtonAction), for: .touchUpInside)
accessView.addSubview(done)
done.pinCenterY()
.pinTrailing(16)
inputAccessoryView = accessView
}
@objc func doneButtonAction() {
// Resigns the first responder status when 'Done' is tapped
resignFirstResponder()
}
open func updateView() {}
open func updateAccessibility() {
if let errorText, showError {
accessibilityLabel = "error, \(errorText)"
} else {
accessibilityLabel = nil
}
}
open func reset() {
shouldUpdateView = false
surface = .light
text = nil
shouldUpdateView = true
setNeedsUpdate()
}
//--------------------------------------------------
// MARK: - Overrides
//--------------------------------------------------
open override func textRect(forBounds bounds: CGRect) -> CGRect { open override func textRect(forBounds bounds: CGRect) -> CGRect {
let rect = super.textRect(forBounds: bounds) let rect = super.textRect(forBounds: bounds)
return rect.insetBy(dx: -horizontalPadding, dy: 0) return rect.insetBy(dx: -horizontalPadding, dy: 0)
@ -54,25 +131,6 @@ open class TextField: UITextField {
} }
} }
open func initialSetup() {
let accessView = UIView(frame: .init(origin: .zero, size: .init(width: UIScreen.main.bounds.width, height: 44)))
accessView.backgroundColor = .white
accessView.addBorder(side: .top, width: 1, color: .lightGray)
let done = UIButton(type: .system)
done.setTitle("Done", for: .normal)
done.translatesAutoresizingMaskIntoConstraints = false
done.addTarget(self, action: #selector(doneButtonAction), for: .touchUpInside)
accessView.addSubview(done)
done.pinCenterY()
.pinTrailing(16)
inputAccessoryView = accessView
}
@objc func doneButtonAction() {
// Resigns the first responder status when 'Done' is tapped
resignFirstResponder()
}
open override func becomeFirstResponder() -> Bool { open override func becomeFirstResponder() -> Bool {
let success = super.becomeFirstResponder() let success = super.becomeFirstResponder()
if isSecureTextEntry, let text { if isSecureTextEntry, let text {

View File

@ -193,13 +193,24 @@ open class TextArea: EntryFieldBase {
statusIcon.color = iconColorConfiguration.getColor(self) statusIcon.color = iconColorConfiguration.getColor(self)
containerView.layer.borderColor = isReadOnly ? readOnlyBorderColorConfiguration.getColor(self).cgColor : borderColorConfiguration.getColor(self).cgColor containerView.layer.borderColor = isReadOnly ? readOnlyBorderColorConfiguration.getColor(self).cgColor : borderColorConfiguration.getColor(self).cgColor
textView.isEditable = isReadOnly ? false : true textView.isEditable = !isEnabled || isReadOnly ? false : true
textView.backgroundColor = backgroundColorConfiguration.getColor(self) textView.backgroundColor = backgroundColorConfiguration.getColor(self)
textView.tintColor = iconColorConfiguration.getColor(self) textView.tintColor = iconColorConfiguration.getColor(self)
characterCounterLabel.surface = surface characterCounterLabel.surface = surface
highlightCharacterOverflow() highlightCharacterOverflow()
} }
open override func updateAccessibility() {
super.updateAccessibility()
let label = "\(isReadOnly ? "read only" : "")"
if let errorText, showError {
textView.accessibilityLabel = "\(label) ,error, \(errorText)"
} else {
textView.accessibilityLabel = label
}
textView.accessibilityHint = isReadOnly || !isEnabled ? "" : "Double tap to open."
}
override func updateRules() { override func updateRules() {
super.updateRules() super.updateRules()
@ -224,12 +235,6 @@ open class TextArea: EntryFieldBase {
return stackView return stackView
} }
/// Used to update any Accessibility properties.
open override func updateAccessibility() {
super.updateAccessibility()
textView.accessibilityLabel = showError ? "error" : nil
}
open override var accessibilityElements: [Any]? { open override var accessibilityElements: [Any]? {
get { get {
var elements = [Any]() var elements = [Any]()

View File

@ -11,7 +11,7 @@ import Combine
import VDSCoreTokens import VDSCoreTokens
@objc(VDSTextView) @objc(VDSTextView)
open class TextView: UITextView, ViewProtocol { open class TextView: UITextView, ViewProtocol, Errorable {
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Initializers // MARK: - Initializers
@ -66,6 +66,10 @@ open class TextView: UITextView, ViewProtocol {
$0.setSurfaceColors(VDSColor.elementsPrimaryOnlight, VDSColor.elementsPrimaryOndark, forDisabled: false) $0.setSurfaceColors(VDSColor.elementsPrimaryOnlight, VDSColor.elementsPrimaryOndark, forDisabled: false)
}.eraseToAnyColorable(){ didSet { setNeedsUpdate() }} }.eraseToAnyColorable(){ didSet { setNeedsUpdate() }}
open var showError: Bool = false { didSet { setNeedsUpdate() } }
open var errorText: String? { didSet { setNeedsUpdate() } }
open override var textColor: UIColor? { open override var textColor: UIColor? {
get { textColorConfiguration.getColor(self) } get { textColorConfiguration.getColor(self) }
set { } set { }
@ -102,7 +106,6 @@ open class TextView: UITextView, ViewProtocol {
} }
} }
open func setup() { open func setup() {
let accessView = UIView(frame: .init(origin: .zero, size: .init(width: UIScreen.main.bounds.width, height: 44))) let accessView = UIView(frame: .init(origin: .zero, size: .init(width: UIScreen.main.bounds.width, height: 44)))
accessView.backgroundColor = .white accessView.backgroundColor = .white
@ -126,7 +129,13 @@ open class TextView: UITextView, ViewProtocol {
updateLabel() updateLabel()
} }
open func updateAccessibility() {} open func updateAccessibility() {
if let errorText, showError {
accessibilityLabel = "error, \(errorText)"
} else {
accessibilityLabel = nil
}
}
open func reset() { open func reset() {
shouldUpdateView = false shouldUpdateView = false

View File

@ -206,12 +206,12 @@ open class Tilelet: TileContainerBase<Tilelet.Padding> {
/// Descriptive Icon positioned in the contentView. /// Descriptive Icon positioned in the contentView.
open var descriptiveIcon = Icon().with { open var descriptiveIcon = Icon().with {
$0.isAccessibilityElement = true $0.isAccessibilityElement = false
} }
/// Directional Icon positioned in the contentView. /// Directional Icon positioned in the contentView.
open var directionalIcon = Icon().with { open var directionalIcon = Icon().with {
$0.isAccessibilityElement = true $0.isAccessibilityElement = false
$0.name = .rightArrow $0.name = .rightArrow
} }

View File

@ -0,0 +1,14 @@
//
// Groupable.swift
// VDS
//
// Created by Matt Bruce on 5/24/24.
//
import Foundation
public protocol Groupable: Control {
/// Property used to add context to the Grouping of a set.
var accessibilityValueText: String? { get set }
}

View File

@ -1,3 +1,9 @@
1.0.65
----------------
- CXTDT-556996 - RadioboxGroup Accessibility - Voice over does not render the group position
- CXTDT-560458 - Dropdown & TextArea voiceover behaviour
- CXTDT-560485 - Tilelet - Accessibility
1.0.64 1.0.64
---------------- ----------------
- CXTDT-555846 - DropdownSelect - Tooltip Icon Spacing - CXTDT-555846 - DropdownSelect - Tooltip Icon Spacing