CXTDT-552825 - Tilelet - Accessibility – The role of button is not provided for the tilelet.

CXTDT-552834 - TileContainer - Accessibility – Voice over is not rendering the information present click state.

Signed-off-by: Matt Bruce <matt.bruce@verizon.com>
This commit is contained in:
Matt Bruce 2024-05-03 09:30:02 -05:00
parent 2bfac96281
commit 77f8dfa3d8
6 changed files with 80 additions and 42 deletions

View File

@ -111,27 +111,19 @@ open class TileContainerBase<PaddingType: DefaultValuing>: Control where Padding
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Public Properties // MARK: - Public Properties
//-------------------------------------------------- //--------------------------------------------------
public override var onClickSubscriber: AnyCancellable? {
didSet {
if onClickSubscriber != nil {
isAccessibilityElement = true
accessibilityTraits = .link
accessibilityHint = "Double tap to open."
} else {
isAccessibilityElement = false
accessibilityTraits.remove(.link)
}
}
}
/// This takes an image source url and applies it as a background image. /// This takes an image source url and applies it as a background image.
open var backgroundImage: UIImage? { didSet { setNeedsUpdate() } } open var backgroundImage: UIImage? { didSet { setNeedsUpdate() } }
/// This is the container in which views will be pinned.
open var contentView = View().with {
$0.isUserInteractionEnabled = false
}
/// This is the container in which views will be pinned. /// This is the container in which views will be pinned.
open var containerView = View().with { open var containerView = View().with {
$0.isUserInteractionEnabled = false $0.isUserInteractionEnabled = false
} }
/// This is the view used to show the high light color for a onClick. /// This is the view used to show the high light color for a onClick.
open var highlightView = View().with { open var highlightView = View().with {
$0.isUserInteractionEnabled = false $0.isUserInteractionEnabled = false
@ -232,6 +224,7 @@ open class TileContainerBase<PaddingType: DefaultValuing>: Control where Padding
/// 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 = false
let layoutGuide = UILayoutGuide() let layoutGuide = UILayoutGuide()
addLayoutGuide(layoutGuide) addLayoutGuide(layoutGuide)
@ -240,11 +233,13 @@ open class TileContainerBase<PaddingType: DefaultValuing>: Control where Padding
.pinLeading() .pinLeading()
.pinTrailing(0, .defaultHigh) .pinTrailing(0, .defaultHigh)
.pinBottom(0, .defaultHigh) .pinBottom(0, .defaultHigh)
addSubview(backgroundImageView) addSubview(backgroundImageView)
addSubview(containerView) addSubview(containerView)
containerView.addSubview(contentView)
addSubview(highlightView) addSubview(highlightView)
containerView.pinToSuperView()
widthConstraint = layoutGuide.widthAnchor.constraint(equalToConstant: 0) widthConstraint = layoutGuide.widthAnchor.constraint(equalToConstant: 0)
heightGreaterThanConstraint = layoutGuide.heightAnchor.constraint(greaterThanOrEqualToConstant: 44.0) heightGreaterThanConstraint = layoutGuide.heightAnchor.constraint(greaterThanOrEqualToConstant: 44.0)
@ -253,7 +248,7 @@ open class TileContainerBase<PaddingType: DefaultValuing>: Control where Padding
heightConstraint = layoutGuide.heightAnchor.constraint(equalToConstant: 0) heightConstraint = layoutGuide.heightAnchor.constraint(equalToConstant: 0)
backgroundImageView.pinToSuperView() backgroundImageView.pinToSuperView()
backgroundImageView.setContentHuggingPriority(.defaultLow, for: .horizontal) backgroundImageView.setContentHuggingPriority(.defaultLow, for: .horizontal)
backgroundImageView.setContentHuggingPriority(.defaultLow, for: .vertical) backgroundImageView.setContentHuggingPriority(.defaultLow, for: .vertical)
backgroundImageView.setContentCompressionResistancePriority(.defaultLow, for: .horizontal) backgroundImageView.setContentCompressionResistancePriority(.defaultLow, for: .horizontal)
@ -261,10 +256,10 @@ open class TileContainerBase<PaddingType: DefaultValuing>: Control where Padding
backgroundImageView.isUserInteractionEnabled = false backgroundImageView.isUserInteractionEnabled = false
backgroundImageView.isHidden = true backgroundImageView.isHidden = true
containerTopConstraint = containerView.pinTop(anchor: layoutGuide.topAnchor, constant: padding.value) containerTopConstraint = contentView.pinTop(anchor: layoutGuide.topAnchor, constant: padding.value)
containerBottomConstraint = layoutGuide.pinBottom(anchor: containerView.bottomAnchor, constant: padding.value) containerBottomConstraint = layoutGuide.pinBottom(anchor: contentView.bottomAnchor, constant: padding.value)
containerLeadingConstraint = containerView.pinLeading(anchor: layoutGuide.leadingAnchor, constant: padding.value) containerLeadingConstraint = contentView.pinLeading(anchor: layoutGuide.leadingAnchor, constant: padding.value)
containerTrailingConstraint = layoutGuide.pinTrailing(anchor: containerView.trailingAnchor, constant: padding.value) containerTrailingConstraint = layoutGuide.pinTrailing(anchor: contentView.trailingAnchor, constant: padding.value)
highlightView.pin(layoutGuide) highlightView.pin(layoutGuide)
highlightView.isHidden = true highlightView.isHidden = true
@ -291,7 +286,7 @@ open class TileContainerBase<PaddingType: DefaultValuing>: Control where Padding
shouldUpdateView = true shouldUpdateView = true
setNeedsUpdate() setNeedsUpdate()
} }
/// Used to make changes to the View based off a change events or from local properties. /// Used to make changes to the View based off a change events or from local properties.
open override func updateView() { open override func updateView() {
super.updateView() super.updateView()
@ -339,6 +334,30 @@ open class TileContainerBase<PaddingType: DefaultValuing>: Control where Padding
} }
} }
open override func updateAccessibility() {
super.updateAccessibility()
containerView.isAccessibilityElement = onClickSubscriber != nil
containerView.accessibilityHint = "Double tap to open."
}
open override var accessibilityElements: [Any]? {
get {
var items = [Any]()
if containerView.isAccessibilityElement {
if !accessibilityTraits.contains(.button) && !accessibilityTraits.contains(.link) {
containerView.accessibilityTraits = .button
} else {
containerView.accessibilityTraits = accessibilityTraits
}
items.append(containerView)
}
items.append(contentsOf: contentView.subviews.filter({ $0.isAccessibilityElement == true }))
return items
}
set {}
}
/// Used to update frames for the added CAlayers to our view /// Used to update frames for the added CAlayers to our view
open override func layoutSubviews() { open override func layoutSubviews() {
super.layoutSubviews() super.layoutSubviews()
@ -353,7 +372,7 @@ open class TileContainerBase<PaddingType: DefaultValuing>: Control where Padding
/// This will place a view within the contentView of this component. /// This will place a view within the contentView of this component.
public func addContentView(_ view: UIView, shouldPin: Bool = true) { public func addContentView(_ view: UIView, shouldPin: Bool = true) {
view.removeFromSuperview() view.removeFromSuperview()
containerView.addSubview(view) contentView.addSubview(view)
if shouldPin { if shouldPin {
view.pinToSuperView() view.pinToSuperView()
} }

View File

@ -201,10 +201,13 @@ open class Tilelet: TileContainerBase<Tilelet.Padding> {
} }
/// Descriptive Icon positioned in the contentView. /// Descriptive Icon positioned in the contentView.
open var descriptiveIcon = Icon() open var descriptiveIcon = Icon().with {
$0.isAccessibilityElement = true
}
/// 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.name = .rightArrow $0.name = .rightArrow
} }
@ -407,24 +410,30 @@ open class Tilelet: TileContainerBase<Tilelet.Padding> {
} }
/// Used to update any Accessibility properties. /// Used to update any Accessibility properties.
open override func updateAccessibility() { open override var accessibilityElements: [Any]? {
super.updateAccessibility()
var elements = [Any]() get {
if badgeModel != nil { var elements = [Any]()
elements.append(badge) if let superElements = super.accessibilityElements {
elements.append(contentsOf: superElements)
}
if badgeModel != nil {
elements.append(badge)
}
if titleModel != nil || subTitleModel != nil || eyebrowModel != nil {
elements.append(titleLockup)
}
if descriptiveIconModel != nil {
elements.append(descriptiveIcon)
}
if directionalIconModel != nil {
elements.append(directionalIcon)
}
return elements
} }
if titleModel != nil || subTitleModel != nil || eyebrowModel != nil {
elements.append(titleLockup) set {}
}
if descriptiveIconModel != nil {
elements.append(descriptiveIcon)
}
if directionalIconModel != nil {
elements.append(directionalIcon)
}
accessibilityElements = elements.count > 0 ? elements : nil
setAccessibilityLabel(for: [badge.label, titleLockup.eyebrowLabel, titleLockup.titleLabel, titleLockup.subTitleLabel])
} }
//-------------------------------------------------- //--------------------------------------------------
@ -482,7 +491,7 @@ open class Tilelet: TileContainerBase<Tilelet.Padding> {
titleLockupWidthConstraint = NSLayoutConstraint(item: titleLockup, titleLockupWidthConstraint = NSLayoutConstraint(item: titleLockup,
attribute: .width, attribute: .width,
relatedBy: .equal, relatedBy: .equal,
toItem: containerView, toItem: contentView,
attribute: .width, attribute: .width,
multiplier: percentage / 100, multiplier: percentage / 100,
constant: 0.0) constant: 0.0)
@ -521,12 +530,14 @@ open class Tilelet: TileContainerBase<Tilelet.Padding> {
descriptiveIcon.name = descriptiveIconModel.name descriptiveIcon.name = descriptiveIconModel.name
descriptiveIcon.size = descriptiveIconModel.size descriptiveIcon.size = descriptiveIconModel.size
descriptiveIcon.surface = descriptiveIconModel.surface descriptiveIcon.surface = descriptiveIconModel.surface
descriptiveIcon.accessibilityLabel = descriptiveIconModel.accessibleText
showIconContainerView = true showIconContainerView = true
} }
if let directionalIconModel { if let directionalIconModel {
directionalIcon.size = directionalIconModel.size directionalIcon.size = directionalIconModel.size
directionalIcon.surface = directionalIconModel.surface directionalIcon.surface = directionalIconModel.surface
directionalIcon.accessibilityLabel = "Right arrow"
showIconContainerView = true showIconContainerView = true
} }

View File

@ -18,11 +18,15 @@ extension Tilelet {
/// Enum for a preset height and width for the icon. /// Enum for a preset height and width for the icon.
public var size: Icon.Size public var size: Icon.Size
/// Accessible Text for the Icon
var accessibleText: String
/// Current Surface and this is used to pass down to child objects that implement Surfacable /// Current Surface and this is used to pass down to child objects that implement Surfacable
public var surface: Surface public var surface: Surface
public init(name: Icon.Name = .multipleDocuments, size: Icon.Size = .medium, surface: Surface = .dark) { public init(name: Icon.Name = .multipleDocuments, size: Icon.Size = .medium, accessibleText: String? = nil, surface: Surface = .dark) {
self.name = name self.name = name
self.accessibleText = accessibleText ?? name.rawValue
self.size = size self.size = size
self.surface = surface self.surface = surface
} }

View File

@ -29,6 +29,7 @@ extension Changeable {
} else { } else {
onChangeSubscriber = nil onChangeSubscriber = nil
} }
setNeedsUpdate()
} }
} }
} }

View File

@ -30,6 +30,7 @@ extension Clickable {
} else { } else {
onClickSubscriber = nil onClickSubscriber = nil
} }
setNeedsUpdate()
} }
} }
} }

View File

@ -6,6 +6,8 @@
- CXTDT-552071 - Text Area - Entering text - CXTDT-552071 - Text Area - Entering text
- CXTDT-552060 - Text Area - Placeholder text - CXTDT-552060 - Text Area - Placeholder text
- CXTDT-552842 - Breadcrumbs - Accessibility - CXTDT-552842 - Breadcrumbs - Accessibility
- CXTDT-552825 - Tilelet - Accessibility The role of button is not provided for the tilelet.
- CXTDT-552834 - TileContainer - Accessibility Voice over is not rendering the information present click state.
1.0.60 1.0.60