one column and progress accessibililty logic

This commit is contained in:
Kevin G Christiano 2020-06-02 16:43:16 -04:00
parent b77c7c79e4
commit 7a9f9bd2c5
7 changed files with 235 additions and 32 deletions

View File

@ -8,20 +8,30 @@
import Foundation
@objcMembers open class ProgressBar: UIProgressView, MVMCoreViewProtocol, MoleculeViewProtocol {
//--------------------------------------------------
// MARK: - Properties
//--------------------------------------------------
var progressBarModel: ProgressBarModel?
var thickness: CGFloat = 8.0 {
willSet(newValue) {
heightAnchor.constraint(equalToConstant: newValue).isActive = true
if progressBarModel?.roundedCorners ?? false {
layer.cornerRadius = newValue/2.0
layer.cornerRadius = newValue / 2.0
} else {
progressViewStyle = .bar
}
}
}
//--------------------------------------------------
// MARK: - Initializers
//--------------------------------------------------
public override init(frame: CGRect) {
super.init(frame: frame)
setupView()
@ -37,41 +47,49 @@ import Foundation
setupView()
}
// MARK: - MVMCoreViewProtocol
//--------------------------------------------------
// MARK: - Lifecycle
//--------------------------------------------------
public func setupView() {
clipsToBounds = true
translatesAutoresizingMaskIntoConstraints = false
thickness = 8
progress = 0
progressTintColor = UIColor.mfCerulean()
trackTintColor = UIColor.mfLightSilver()
progressTintColor = .mfCerulean()
trackTintColor = .mvmCoolGray3
}
public func updateView(_ size: CGFloat) {
}
public func updateView(_ size: CGFloat) { }
//--------------------------------------------------
// MARK: - MVMCoreViewProtocol
//--------------------------------------------------
//MARK: - MoleculeViewProtocol
public func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
guard let progressBarModel = model as? ProgressBarModel else { return }
self.progressBarModel = progressBarModel
thickness = progressBarModel.thickness ?? 8
progress = Float((progressBarModel.percent)/100.0)
progress = Float((progressBarModel.percent) / 100.0)
progressTintColor = progressBarModel.color.uiColor
if let backgroundColor = progressBarModel.backgroundColor {
trackTintColor = backgroundColor.uiColor
}
}
public func reset() {
thickness = 8
progress = 0
progressTintColor = UIColor.mfCerulean()
trackTintColor = UIColor.mfLightSilver()
progressTintColor = .mfCerulean()
trackTintColor = .mvmCoolGray3
}
public static func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {
return 8
}
}

View File

@ -7,24 +7,28 @@
//
import Foundation
@objcMembers open class ListProgressBarThin: TableViewCell {
//--------------------------------------------------
// MARK: - Outlets
//--------------------------------------------------
public let progressBar = ProgressBar()
public let leftHeadline = Label.commonLabelB1(true)
public let leftBody = Label.commonLabelB2(true)
public let leftHeadline = Label.createLabelBoldBodySmall(true)
public let leftBody = Label.createLabelBoldBodySmall(true)
public let rightBar = Line()
public let rightLabel = Label.commonLabelB2(true)
public let rightLabel = Label.createLabelBoldBodySmall(true)
private let barStackItem: StackItem
private let rightLabelStackItem: StackItem
public var labelStack: Stack<StackModel>
public var horizontalStack: Stack<StackModel>
public var stack: Stack<StackModel>
//------------------------------------------------------
// MARK: - Initializers
//------------------------------------------------------
public override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
//vertical stack with leftHeadline, leftBody
labelStack = Stack<StackModel>.createStack(with: [leftHeadline, leftBody], axis: .vertical, spacing: 2)
@ -34,9 +38,9 @@ import Foundation
rightLabelStackItem = StackItem(andContain: rightLabel)
let horizontalStackItems = [StackItem(andContain: labelStack), barStackItem, rightLabelStackItem]
let horizontalStackModel = StackModel(molecules: [StackItemModel(horizontalAlignment: .leading), StackItemModel(horizontalAlignment: .fill), StackItemModel(spacing: 5, horizontalAlignment: .fill)],
axis: .horizontal)
axis: .horizontal)
horizontalStack = Stack<StackModel>(with: horizontalStackModel, stackItems: horizontalStackItems)
//stack with all components
stack = Stack<StackModel>.createStack(with: [horizontalStack, progressBar], axis: .vertical, spacing: PaddingDefaultVerticalSpacing3)
super.init(style: style, reuseIdentifier: reuseIdentifier)
@ -49,19 +53,23 @@ import Foundation
open override func alignAccessoryToHero() -> CGPoint? {
// Ensures that the right items are centered with the arrow.
let heroCenter = super.alignAccessoryToHero()
if let heroCenter = heroCenter {
let convertedPoint = horizontalStack.convert(heroCenter, from: self)
barStackItem.containerHelper.alignCenterVerticalConstraint?.constant = convertedPoint.y - horizontalStack.bounds.midY
rightLabelStackItem.containerHelper.alignCenterVerticalConstraint?.constant = convertedPoint.y - horizontalStack.bounds.midY
}
return heroCenter
}
//-------------------------------------------------------
// MARK: - View Lifecycle
// MARK: - Lifecycle
//-------------------------------------------------------
open override func setupView() {
super.setupView()
rightBar.widthAnchor.constraint(equalToConstant: 20).isActive = true
rightLabel.setContentCompressionResistancePriority(UILayoutPriority(rawValue: 900), for: .horizontal)
rightLabel.setContentHuggingPriority(UILayoutPriority(rawValue: 900), for: .horizontal)
@ -70,19 +78,24 @@ import Foundation
stack.restack()
horizontalStack.restack()
labelStack.restack()
isAccessibilityElement = true
updateAccessibilityLabel()
}
//------------------------------------------------------
// MARK: - Molecule
//------------------------------------------------------
open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) {
open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
super.set(with: model, delegateObject, additionalData)
guard let model = model as? ListProgressBarThinModel else { return }
labelStack.updateContainedMolecules(with: [model.leftHeadline,
model.leftBody], delegateObject, additionalData)
labelStack.updateContainedMolecules(with: [model.leftHeadline, model.leftBody], delegateObject, additionalData)
progressBar.set(with: model.progressBar, delegateObject, additionalData)
rightBar.set(with: model.rightBar, delegateObject, additionalData)
rightLabel.set(with: model.rightLabel, delegateObject, additionalData)
updateAccessibilityLabel()
}
open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat {
@ -96,4 +109,31 @@ import Foundation
rightLabel.styleB2(true)
rightBar.setStyle(.medium)
}
//------------------------------------------------------
// MARK: - Accessibility
//------------------------------------------------------
func updateAccessibilityLabel() {
var message = ""
if let leftHeadlineText = leftHeadline.text {
message += leftHeadlineText + ", "
}
if let leftBodyText = leftBody.text {
message += leftBodyText + ", "
}
if let progressLabel = progressBar.accessibilityLabel, let progressValue = progressBar.accessibilityValue {
message += progressLabel + ", " + progressValue + ", "
}
if let rightLabelText = rightLabel.text {
message += rightLabelText + ", "
}
accessibilityLabel = message
}
}

View File

@ -7,7 +7,13 @@
//
import Foundation
public class ListProgressBarThinModel: ListItemModel, MoleculeModelProtocol {
//--------------------------------------------------
// MARK: - Properties
//--------------------------------------------------
public static var identifier = "listPrgBarThin"
public var progressBar: ProgressBarModel
public var leftHeadline: LabelModel
@ -15,6 +21,10 @@ public class ListProgressBarThinModel: ListItemModel, MoleculeModelProtocol {
public var rightBar: LineModel
public var rightLabel: LabelModel
//--------------------------------------------------
// MARK: - Initializer
//--------------------------------------------------
public init(progressBar: ProgressBarModel, leftHeadline: LabelModel, leftBody: LabelModel? = nil, rightBar: LineModel, rightLabel: LabelModel) {
self.progressBar = progressBar
self.leftHeadline = leftHeadline
@ -24,15 +34,26 @@ public class ListProgressBarThinModel: ListItemModel, MoleculeModelProtocol {
super.init()
}
//--------------------------------------------------
// MARK: - Method
//--------------------------------------------------
override public func setDefaults() {
super.setDefaults()
rightBar.type = .medium
if rightBar.backgroundColor == nil {
rightBar.backgroundColor = Color(uiColor: .gray)
}
leftHeadline.hero = 0
}
//--------------------------------------------------
// MARK: - Keys
//--------------------------------------------------
private enum CodingKeys: String, CodingKey {
case moleculeName
case progressBar
@ -42,6 +63,10 @@ public class ListProgressBarThinModel: ListItemModel, MoleculeModelProtocol {
case rightLabel
}
//--------------------------------------------------
// MARK: - Codec
//--------------------------------------------------
public required init(from decoder: Decoder) throws {
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
progressBar = try typeContainer.decode(ProgressBarModel.self, forKey:.progressBar)

View File

@ -43,17 +43,17 @@ import Foundation
super.setupView()
addMolecule(stack)
stack.restack()
updateAccessibilityLabel()
}
open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
super.set(with: model, delegateObject, additionalData)
guard let model = model as? ListOneColumnFullWidthTextAllTextAndLinksModel else { return }
stack.updateContainedMolecules(with: [model.eyebrow,
model.headline,
model.subHeadline,
model.body,
model.link],
stack.updateContainedMolecules(with: [model.eyebrow, model.headline, model.subHeadline, model.body, model.link],
delegateObject, additionalData)
updateAccessibilityLabel()
}
open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {
@ -67,4 +67,60 @@ import Foundation
subHeadline.styleBoldBodySmall(true)
body.styleRegularBodySmall(true)
}
func updateAccessibilityLabel() {
var message = ""
if let eyebrowLabel = eyebrow.text {
message += eyebrowLabel + ", "
}
if let headlineLabel = headline.text {
message += headlineLabel + ", "
}
if let headlineLabel = headline.text {
message += headlineLabel + ", "
}
if let bodyLabel = body.text {
message += bodyLabel
}
let linkShowing = link.titleLabel?.text?.count ?? 0 > 0
isAccessibilityElement = !linkShowing
link.isAccessibilityElement = linkShowing
if !linkShowing {
// Make whole cell focusable if no link.
accessibilityLabel = message
} else {
// Allow only radio button and link to be focused on.
var elements: [UIView] = []
if let eyeBrowText = eyebrow.text, !eyeBrowText.isEmpty {
elements.append(eyebrow)
}
if let headlineText = headline.text, !headlineText.isEmpty {
elements.append(headline)
}
if let subHeadlineText = subHeadline.text, !subHeadlineText.isEmpty {
elements.append(subHeadline)
}
if let bodyText = body.text, !bodyText.isEmpty {
elements.append(body)
}
if linkShowing {
elements.append(link)
}
accessibilityElements = elements
}
}
}

View File

@ -8,7 +8,12 @@
import Foundation
public class ListOneColumnFullWidthTextAllTextAndLinksModel: ListItemModel, MoleculeModelProtocol {
//--------------------------------------------------
// MARK: - Properties
//--------------------------------------------------
public static var identifier: String = "list1CTxt"
public var eyebrow: LabelModel?
public var headline : LabelModel?
@ -16,6 +21,10 @@ public class ListOneColumnFullWidthTextAllTextAndLinksModel: ListItemModel, Mole
public var body: LabelModel?
public var link : LinkModel?
//--------------------------------------------------
// MARK: - Initializer
//--------------------------------------------------
public init(eyebrow: LabelModel? = nil, headline: LabelModel? = nil, subHeadline: LabelModel? = nil, body: LabelModel? = nil, link: LinkModel? = nil) {
self.eyebrow = eyebrow
self.headline = headline
@ -25,6 +34,10 @@ public class ListOneColumnFullWidthTextAllTextAndLinksModel: ListItemModel, Mole
super.init()
}
//--------------------------------------------------
// MARK: - Keys
//--------------------------------------------------
private enum CodingKeys: String, CodingKey {
case moleculeName
case eyebrow
@ -34,6 +47,10 @@ public class ListOneColumnFullWidthTextAllTextAndLinksModel: ListItemModel, Mole
case link
}
//--------------------------------------------------
// MARK: - Codec
//--------------------------------------------------
required public init(from decoder: Decoder) throws {
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
eyebrow = try typeContainer.decodeIfPresent(LabelModel.self, forKey: .eyebrow)

View File

@ -8,28 +8,55 @@
import Foundation
@objcMembers open class ListOneColumnFullWidthTextBodyText: TableViewCell {
//-----------------------------------------------------
// MARK: - Outlets
//-----------------------------------------------------
public var headlineBody = HeadlineBody(frame: .zero)
public var headlineBody = HeadlineBody()
//-----------------------------------------------------
// MARK: - View Lifecycle
// MARK: - Lifecycle
//-----------------------------------------------------
override open func setupView() {
super.setupView()
addMolecule(headlineBody)
isAccessibilityElement = true
updateAccessibilityLabel()
}
open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?){
open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?){
super.set(with: model, delegateObject, additionalData)
guard let model = model as? ListOneColumnFullWidthTextBodyTextModel else { return }
headlineBody.set(with: model.headlineBody, delegateObject, additionalData)
updateAccessibilityLabel()
}
open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {
return 90
}
//-----------------------------------------------------
// MARK: - Accessibility
//-----------------------------------------------------
func updateAccessibilityLabel() {
var message = ""
if let headlineLabel = headlineBody.headlineLabel.text {
message += headlineLabel + ", "
}
if let messageLabel = headlineBody.messageLabel.text {
message += messageLabel
}
accessibilityLabel = message
}
}

View File

@ -8,26 +8,46 @@
import Foundation
public class ListOneColumnFullWidthTextBodyTextModel: ListItemModel, MoleculeModelProtocol {
//--------------------------------------------------
// MARK: - Properties
//--------------------------------------------------
public static var identifier: String = "list1CFWBdy"
public var headlineBody: HeadlineBodyModel
//--------------------------------------------------
// MARK: - Initializier
//--------------------------------------------------
public init(headlineBody: HeadlineBodyModel) {
self.headlineBody = headlineBody
super.init()
}
// Defaults to set
//--------------------------------------------------
// MARK: - Methods
//--------------------------------------------------
override public func setDefaults() {
super.setDefaults()
headlineBody.style = .item
}
//--------------------------------------------------
// MARK: - Keys
//--------------------------------------------------
private enum CodingKeys: String, CodingKey {
case moleculeName
case headlineBody
}
//--------------------------------------------------
// MARK: - Codec
//--------------------------------------------------
required public init(from decoder: Decoder) throws {
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
headlineBody = try typeContainer.decode(HeadlineBodyModel.self, forKey: .headlineBody)