Merge branch 'mbruce/bugfix' into 'develop'

Merge of bugs

See merge request BPHV_MIPS/vds_ios!236
This commit is contained in:
Bruce, Matt R 2024-05-28 20:31:38 +00:00
commit 0d8b0ab79e
14 changed files with 93 additions and 31 deletions

View File

@ -126,7 +126,7 @@ open class CalendarBase: Control, Changeable {
/// Called once when a view is initialized and is used to Setup additional UI or other constants and configurations. /// Called once when a view is initialized and is used to Setup additional UI or other constants and configurations.
open override func setup() { open override func setup() {
super.setup() super.setup()
isAccessibilityElement = true isAccessibilityElement = false
accessibilityLabel = "Calendar" accessibilityLabel = "Calendar"
addSubview(containerView) addSubview(containerView)
containerView containerView

View File

@ -31,6 +31,8 @@ class CalendarFooterReusableView: UICollectionReusableView {
internal var containerView = View().with { internal var containerView = View().with {
$0.clipsToBounds = true $0.clipsToBounds = true
$0.isAccessibilityElement = true
$0.accessibilityLabel = "Legend"
} }
private let flowLayout = LeftAlignedCollectionViewFlowLayout().with { private let flowLayout = LeftAlignedCollectionViewFlowLayout().with {
@ -39,7 +41,7 @@ class CalendarFooterReusableView: UICollectionReusableView {
$0.minimumInteritemSpacing = VDSLayout.space4X $0.minimumInteritemSpacing = VDSLayout.space4X
$0.scrollDirection = .vertical $0.scrollDirection = .vertical
} }
open lazy var legendCollectionView = UICollectionView(frame: .zero, collectionViewLayout: flowLayout).with { open lazy var legendCollectionView = UICollectionView(frame: .zero, collectionViewLayout: flowLayout).with {
$0.isScrollEnabled = false $0.isScrollEnabled = false
$0.translatesAutoresizingMaskIntoConstraints = false $0.translatesAutoresizingMaskIntoConstraints = false
@ -55,7 +57,8 @@ class CalendarFooterReusableView: UICollectionReusableView {
} }
private var topConstraint: NSLayoutConstraint? private var topConstraint: NSLayoutConstraint?
private var legendLabels: [Label] = []
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Initializers // MARK: - Initializers
//-------------------------------------------------- //--------------------------------------------------
@ -69,6 +72,13 @@ class CalendarFooterReusableView: UICollectionReusableView {
setUp() setUp()
} }
open override var accessibilityElements: [Any]? {
get {
return [containerView, legendLabels]
}
set { super.accessibilityElements = newValue }
}
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Private Methods // MARK: - Private Methods
//-------------------------------------------------- //--------------------------------------------------
@ -94,6 +104,7 @@ class CalendarFooterReusableView: UICollectionReusableView {
func update(with surface: Surface, indicators: [CalendarBase.CalendarIndicatorModel]) { func update(with surface: Surface, indicators: [CalendarBase.CalendarIndicatorModel]) {
self.items = indicators self.items = indicators
self.surface = surface self.surface = surface
legendLabels.removeAll()
legendCollectionView.reloadData() legendCollectionView.reloadData()
var height = legendCollectionView.collectionViewLayout.collectionViewContentSize.height var height = legendCollectionView.collectionViewLayout.collectionViewContentSize.height
@ -124,6 +135,7 @@ extension CalendarFooterReusableView: UICollectionViewDelegate, UICollectionView
surface: self.surface, surface: self.surface,
clearFullcircle: indexPath.row == 1, clearFullcircle: indexPath.row == 1,
drawSemiCircle: indexPath.row == 2) drawSemiCircle: indexPath.row == 2)
legendLabels.append(cell.title)
return cell return cell
} }
@ -144,12 +156,12 @@ private class LegendCollectionViewCell: UICollectionViewCell {
private let indicatorColorConfiguration = SurfaceColorConfiguration(VDSColor.elementsSecondaryOnlight, VDSColor.elementsSecondaryOndark) private let indicatorColorConfiguration = SurfaceColorConfiguration(VDSColor.elementsSecondaryOnlight, VDSColor.elementsSecondaryOndark)
private var title: Label = Label().with { open var title: Label = Label().with {
$0.translatesAutoresizingMaskIntoConstraints = false $0.translatesAutoresizingMaskIntoConstraints = false
$0.textAlignment = .left $0.textAlignment = .left
$0.numberOfLines = 1 $0.numberOfLines = 1
$0.textStyle = .bodySmall $0.textStyle = .bodySmall
$0.isAccessibilityElement = false $0.isAccessibilityElement = true
$0.backgroundColor = .clear $0.backgroundColor = .clear
} }

View File

@ -86,7 +86,7 @@ class CalendarHeaderReusableView: UICollectionReusableView {
$0.numberOfLines = 1 $0.numberOfLines = 1
$0.textStyle = .boldBodySmall $0.textStyle = .boldBodySmall
$0.backgroundColor = .clear $0.backgroundColor = .clear
$0.isAccessibilityElement = false $0.isAccessibilityElement = true
} }
internal let daysOfWeek = Date.capitalizedFirstLettersOfWeekdays internal let daysOfWeek = Date.capitalizedFirstLettersOfWeekdays
@ -212,7 +212,7 @@ private class collectionViewCell: UICollectionViewCell {
$0.numberOfLines = 1 $0.numberOfLines = 1
$0.textStyle = .bodySmall $0.textStyle = .bodySmall
$0.backgroundColor = .clear $0.backgroundColor = .clear
$0.isAccessibilityElement = false $0.isAccessibilityElement = true
} }
//-------------------------------------------------- //--------------------------------------------------

View File

@ -186,8 +186,11 @@ open class DatePicker: EntryFieldBase, DatePickerViewControllerDelegate, UIPopov
internal func didSelectDate(_ controller: DatePickerViewController, date: Date) { internal func didSelectDate(_ controller: DatePickerViewController, date: Date) {
selectedDate = date selectedDate = date
controller.dismiss(animated: true) controller.dismiss(animated: true) { [weak self] in
sendActions(for: .valueChanged) guard let self else { return }
self.sendActions(for: .valueChanged)
UIAccessibility.post(notification: .layoutChanged, argument: self.fieldStackView)
}
} }
public func adaptivePresentationStyle(for controller: UIPresentationController) -> UIModalPresentationStyle { public func adaptivePresentationStyle(for controller: UIPresentationController) -> UIModalPresentationStyle {

View File

@ -148,7 +148,7 @@ open class DropdownSelect: EntryFieldBase {
optionsPicker.isHidden = true optionsPicker.isHidden = true
dropdownField.inputView = optionsPicker dropdownField.inputView = optionsPicker
dropdownField.inputAccessoryView = { dropdownField.inputAccessoryView = {
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: containerSize.height)))
accessView.backgroundColor = .white accessView.backgroundColor = .white
accessView.addBorder(side: .top, width: 1, color: .lightGray) accessView.addBorder(side: .top, width: 1, color: .lightGray)
let done = UIButton(type: .system) let done = UIButton(type: .system)
@ -168,6 +168,7 @@ open class DropdownSelect: EntryFieldBase {
self?.launchPicker() self?.launchPicker()
} }
.store(in: &subscribers) .store(in: &subscribers)
containerView.height(44)
} }
open override func getFieldContainer() -> UIView { open override func getFieldContainer() -> UIView {
@ -267,7 +268,7 @@ open class DropdownSelect: EntryFieldBase {
open override func updateErrorLabel() { open override func updateErrorLabel() {
super.updateErrorLabel() super.updateErrorLabel()
if !showError && !hasInternalError { if !showError && !hasInternalError || !optionsPicker.isHidden {
statusIcon.name = .downCaret statusIcon.name = .downCaret
} }
statusIcon.surface = surface statusIcon.surface = surface
@ -348,6 +349,7 @@ extension DropdownSelect: UIPickerViewDelegate, UIPickerViewDataSource {
} }
optionsPicker.isHidden = !optionsPicker.isHidden optionsPicker.isHidden = !optionsPicker.isHidden
updateContainerView() updateContainerView()
updateErrorLabel()
} }
public func numberOfComponents(in pickerView: UIPickerView) -> Int { public func numberOfComponents(in pickerView: UIPickerView) -> Int {

View File

@ -141,7 +141,7 @@ open class Label: UILabel, ViewProtocol, UserInfoable {
setNeedsUpdate() setNeedsUpdate()
} }
} }
///AttributedText that will be used in the label. ///AttributedText that will be used in the label.
override open var attributedText: NSAttributedString? { override open var attributedText: NSAttributedString? {
didSet { didSet {
@ -169,7 +169,16 @@ open class Label: UILabel, ViewProtocol, UserInfoable {
} }
/// Whether the View is enabled or not. /// Whether the View is enabled or not.
open override var isEnabled: Bool { didSet { setNeedsUpdate() } } /// Since the UILabel itselfs draws a different color for the "disabled state", I have to track
/// local variable to deal with color and always enforce this UILabel is always enabled.
private var _fakeIsEnabled: Bool = true
open override var isEnabled: Bool {
get { true }
set {
_fakeIsEnabled = newValue
setNeedsUpdate()
}
}
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Configuration Properties // MARK: - Configuration Properties
@ -282,7 +291,21 @@ open class Label: UILabel, ViewProtocol, UserInfoable {
styleAttributedText(attributedText) styleAttributedText(attributedText)
} }
} }
private struct FakeEnabled: Enabling, Surfaceable {
var surface: Surface
var isEnabled: Bool
}
/// Var to deal with the UILabel.isEnabled property causing issues with
/// textColor when it is false, I am now using a struct to draw and manage
/// colors instead of this class itself and this class will always be enabled
private var _textColor: UIColor {
let fake = FakeEnabled(surface: surface, isEnabled: _fakeIsEnabled)
return textColorConfiguration.getColor(fake)
}
private func styleText(_ newValue: String!) { private func styleText(_ newValue: String!) {
defer { invalidateIntrinsicContentSize() } defer { invalidateIntrinsicContentSize() }
guard let newValue, !newValue.isEmpty else { guard let newValue, !newValue.isEmpty else {
@ -293,15 +316,13 @@ open class Label: UILabel, ViewProtocol, UserInfoable {
} }
accessibilityCustomActions = [] accessibilityCustomActions = []
//create the primary string //create the primary string
let mutableText = NSMutableAttributedString.mutableText(for: newValue, let mutableText = NSMutableAttributedString.mutableText(for: newValue,
textStyle: textStyle, textStyle: textStyle,
useScaledFont: useScaledFont, useScaledFont: useScaledFont,
textColor: textColorConfiguration.getColor(self), textColor: _textColor,
alignment: textAlignment, alignment: textAlignment,
lineBreakMode: lineBreakMode) lineBreakMode: lineBreakMode)
applyAttributes(mutableText) applyAttributes(mutableText)
// Set attributed text to match typography // Set attributed text to match typography

View File

@ -101,6 +101,14 @@ open class EntryFieldBase: Control, Changeable, FormFieldInternalValidatable {
/// This is set by a local method. /// This is set by a local method.
internal var bottomContainerView: UIView! internal var bottomContainerView: UIView!
internal var containerBackgroundColor: UIColor {
if showError || hasInternalError {
return backgroundColorConfiguration.getColor(self)
} else {
return transparentBackground ? .clear : backgroundColorConfiguration.getColor(self)
}
}
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Constraints // MARK: - Constraints
//-------------------------------------------------- //--------------------------------------------------
@ -139,7 +147,7 @@ open class EntryFieldBase: Control, Changeable, FormFieldInternalValidatable {
$0.setSurfaceColors(VDSColor.elementsPrimaryOnlight, VDSColor.elementsPrimaryOnlight, forState: [.focused, .error]) $0.setSurfaceColors(VDSColor.elementsPrimaryOnlight, VDSColor.elementsPrimaryOnlight, forState: [.focused, .error])
$0.setSurfaceColors(VDSColor.interactiveDisabledOnlight, VDSColor.interactiveDisabledOndark, forState: .disabled) $0.setSurfaceColors(VDSColor.interactiveDisabledOnlight, VDSColor.interactiveDisabledOndark, forState: .disabled)
$0.setSurfaceColors(VDSColor.feedbackErrorOnlight, VDSColor.feedbackErrorOndark, forState: .error) $0.setSurfaceColors(VDSColor.feedbackErrorOnlight, VDSColor.feedbackErrorOndark, forState: .error)
$0.setSurfaceColors(VDSColor.interactiveDisabledOnlight, VDSColor.interactiveDisabledOndark, forState: [.disabled,.error]) $0.setSurfaceColors(VDSFormControlsColor.borderReadonlyOnlight, VDSFormControlsColor.borderReadonlyOndark, forState: .readonly)
} }
internal let iconColorConfiguration = ControlColorConfiguration().with { internal let iconColorConfiguration = ControlColorConfiguration().with {
@ -192,8 +200,13 @@ open class EntryFieldBase: Control, Changeable, FormFieldInternalValidatable {
open override var state: UIControl.State { open override var state: UIControl.State {
get { get {
var state = super.state var state = super.state
if showError || hasInternalError { if isEnabled {
state.insert(.error) if !isReadOnly && (showError || hasInternalError){
state.insert(.error)
}
if isReadOnly {
state.insert(.readonly)
}
} }
return state return state
} }
@ -436,7 +449,7 @@ open class EntryFieldBase: Control, Changeable, FormFieldInternalValidatable {
} }
internal func updateContainerView() { internal func updateContainerView() {
containerView.backgroundColor = backgroundColorConfiguration.getColor(self) containerView.backgroundColor = containerBackgroundColor
containerView.layer.borderColor = borderColorConfiguration.getColor(self).cgColor containerView.layer.borderColor = borderColorConfiguration.getColor(self).cgColor
containerView.layer.borderWidth = VDSFormControls.borderWidth containerView.layer.borderWidth = VDSFormControls.borderWidth
containerView.layer.cornerRadius = VDSFormControls.borderRadius containerView.layer.cornerRadius = VDSFormControls.borderRadius

View File

@ -34,6 +34,14 @@ open class InputField: EntryFieldBase {
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Private Properties // MARK: - Private Properties
//-------------------------------------------------- //--------------------------------------------------
internal override var containerBackgroundColor: UIColor {
if showSuccess {
return backgroundColorConfiguration.getColor(self)
} else {
return super.containerBackgroundColor
}
}
internal override var minWidth: CGFloat { fieldType.handler().minWidth } internal override var minWidth: CGFloat { fieldType.handler().minWidth }
internal override var maxWidth: CGFloat { internal override var maxWidth: CGFloat {
let frameWidth = frame.size.width let frameWidth = frame.size.width

View File

@ -163,9 +163,6 @@ open class TextArea: EntryFieldBase {
textViewHeightConstraint = textView.heightAnchor.constraint(greaterThanOrEqualToConstant: containerSize.height) textViewHeightConstraint = textView.heightAnchor.constraint(greaterThanOrEqualToConstant: containerSize.height)
textViewHeightConstraint?.isActive = true textViewHeightConstraint?.isActive = true
backgroundColorConfiguration.setSurfaceColors(VDSColor.feedbackSuccessBackgroundOnlight, VDSColor.feedbackSuccessBackgroundOndark, forState: .success)
borderColorConfiguration.setSurfaceColors(VDSColor.feedbackSuccessOnlight, VDSColor.feedbackSuccessOndark, forState: .success)
borderColorConfiguration.setSurfaceColors(VDSColor.elementsPrimaryOnlight, VDSColor.elementsPrimaryOndark, forState: .focused)
characterCounterLabel.textColorConfiguration = primaryColorConfiguration.eraseToAnyColorable() characterCounterLabel.textColorConfiguration = primaryColorConfiguration.eraseToAnyColorable()
bottomContainerStackView.spacing = VDSLayout.space2X bottomContainerStackView.spacing = VDSLayout.space2X
@ -190,11 +187,7 @@ open class TextArea: EntryFieldBase {
textViewHeightConstraint?.constant = minHeight.value textViewHeightConstraint?.constant = minHeight.value
characterCounterLabel.text = getCharacterCounterText() characterCounterLabel.text = getCharacterCounterText()
statusIcon.color = iconColorConfiguration.getColor(self)
containerView.layer.borderColor = isReadOnly ? readOnlyBorderColorConfiguration.getColor(self).cgColor : borderColorConfiguration.getColor(self).cgColor
textView.isEditable = !isEnabled || isReadOnly ? false : true textView.isEditable = !isEnabled || isReadOnly ? false : true
textView.backgroundColor = backgroundColorConfiguration.getColor(self)
textView.tintColor = iconColorConfiguration.getColor(self) textView.tintColor = iconColorConfiguration.getColor(self)
characterCounterLabel.surface = surface characterCounterLabel.surface = surface
highlightCharacterOverflow() highlightCharacterOverflow()

View File

@ -341,6 +341,10 @@ open class TileContainerBase<PaddingType: DefaultValuing>: Control where Padding
super.updateAccessibility() super.updateAccessibility()
containerView.isAccessibilityElement = onClickSubscriber != nil containerView.isAccessibilityElement = onClickSubscriber != nil
containerView.accessibilityHint = "Double tap to open." containerView.accessibilityHint = "Double tap to open."
containerView.accessibilityLabel = nil
if let views = accessibilityElements?.compactMap({ $0 as? UIView }), !views.isEmpty {
containerView.setAccessibilityLabel(for: views)
}
} }
open override var accessibilityElements: [Any]? { open override var accessibilityElements: [Any]? {

View File

@ -535,7 +535,6 @@ open class Tilelet: TileContainerBase<Tilelet.Padding> {
descriptiveIcon.colorConfiguration = descriptiveIconModel.colorConfiguration descriptiveIcon.colorConfiguration = descriptiveIconModel.colorConfiguration
descriptiveIcon.size = descriptiveIconModel.size descriptiveIcon.size = descriptiveIconModel.size
descriptiveIcon.surface = backgroundColorSurface descriptiveIcon.surface = backgroundColorSurface
descriptiveIcon.accessibilityLabel = descriptiveIconModel.accessibleText
showIconContainerView = true showIconContainerView = true
} }
@ -544,7 +543,6 @@ open class Tilelet: TileContainerBase<Tilelet.Padding> {
directionalIcon.colorConfiguration = directionalIconModel.colorConfiguration directionalIcon.colorConfiguration = directionalIconModel.colorConfiguration
directionalIcon.size = directionalIconModel.size.value directionalIcon.size = directionalIconModel.size.value
directionalIcon.surface = backgroundColorSurface directionalIcon.surface = backgroundColorSurface
directionalIcon.accessibilityLabel = directionalIconModel.accessibleText
showIconContainerView = true showIconContainerView = true
} }

View File

@ -274,6 +274,7 @@ open class TitleLockup: View {
if subTitleModel != nil { if subTitleModel != nil {
elements.append(subTitleLabel) elements.append(subTitleLabel)
} }
setAccessibilityLabel(for: elements.compactMap({$0 as? UIView}))
accessibilityElements = elements.count > 0 ? elements : nil accessibilityElements = elements.count > 0 ? elements : nil
} }

View File

@ -15,4 +15,7 @@ extension UIControl.State {
/// State for Success /// State for Success
public static var success = UIControl.State(rawValue: 1 << 17) public static var success = UIControl.State(rawValue: 1 << 17)
/// State for Success
public static var readonly = UIControl.State(rawValue: 1 << 18)
} }

View File

@ -1,8 +1,12 @@
1.0.65 1.0.65
---------------- ----------------
- CXTDT-556996 - RadioboxGroup Accessibility - Voice over does not render the group position - CXTDT-556996 - RadioboxGroup Accessibility - Voice over does not render the group position
- CXTDT-560458 - Dropdown & TextArea voiceover behaviour - CXTDT-560458 - Dropdown / TextArea - Accessibility
- CXTDT-560485 - Tilelet - Accessibility - CXTDT-560485 - Tilelet - Accessibility
- CXTDT-559318 - Calendar - Accessibility
- CXTDT-563189 - Dropdown Select Readonly Border color
- CXTDT-555854 - Dropdown Select - spacing issues
- CXTDT-563194 - Dropdown Select - missing transparentBackground option
1.0.64 1.0.64
---------------- ----------------