refactored the 3 buttons to use basebutton

Signed-off-by: Matt Bruce <matt.bruce@verizon.com>
This commit is contained in:
Matt Bruce 2022-11-22 13:08:07 -06:00
parent 372dd0cfd0
commit 1a45cfa6c1
3 changed files with 158 additions and 165 deletions

View File

@ -11,26 +11,14 @@ import VDSColorTokens
import VDSFormControlsTokens
import Combine
public protocol Buttonable: UIControl, Surfaceable, Disabling {
var availableSizes: [ButtonSize] { get }
var text: String? { get set }
var intrinsicContentSize: CGSize { get }
}
public enum ButtonSize: String, Codable, CaseIterable {
case large
case small
}
@objc(VDSButton)
open class Button: UIButton, Buttonable, Handlerable, ViewProtocol, Resettable, Useable {
open class Button: BaseButton, Useable {
//--------------------------------------------------
// MARK: - Combine Properties
//--------------------------------------------------
public var subject = PassthroughSubject<Void, Never>()
public var subscribers = Set<AnyCancellable>()
//--------------------------------------------------
// MARK: - Private Properties
//--------------------------------------------------
@ -42,31 +30,21 @@ open class Button: UIButton, Buttonable, Handlerable, ViewProtocol, Resettable,
//--------------------------------------------------
// MARK: - Properties
//--------------------------------------------------
public var availableSizes: [ButtonSize] { [.large, .small] }
open override var availableSizes: [ButtonSize] { [.large, .small] }
open var text: String? { didSet { didChange() } }
open var use: Use = .primary { didSet { didChange() }}
open var size: ButtonSize = .large { didSet { didChange() }}
open var width: CGFloat? { didSet { didChange() }}
open var surface: Surface = .light { didSet { didChange() }}
open var disabled: Bool = false { didSet { isEnabled = !disabled } }
open override var isEnabled: Bool {
get { !disabled }
set {
if disabled != !newValue {
disabled = !newValue
}
isUserInteractionEnabled = isEnabled
didChange()
}
open override var textColor: UIColor {
buttonTitleColorConfiguration.getColor(self)
}
open override var typograpicalStyle: TypographicalStyle {
size == .large ? TypographicalStyle.BoldBodyLarge : TypographicalStyle.BoldBodySmall
}
//--------------------------------------------------
// MARK: - Configuration Properties
@ -76,23 +54,35 @@ open class Button: UIButton, Buttonable, Handlerable, ViewProtocol, Resettable,
$0.primary.enabled.darkColor = VDSColor.backgroundPrimaryLight
$0.primary.disabled.lightColor = VDSColor.interactiveDisabledOnlight
$0.primary.disabled.darkColor = VDSColor.interactiveDisabledOndark
$0.primaryHighlighted.lightColor = VDSColor.interactiveActiveOnlight
$0.primaryHighlighted.darkColor = VDSColor.interactiveActiveOndark
$0.secondary.enabled.lightColor = UIColor.clear
$0.secondary.enabled.darkColor = UIColor.clear
$0.secondary.disabled.lightColor = UIColor.clear
$0.secondary.disabled.darkColor = UIColor.clear
$0.secondaryHighlighted.lightColor = UIColor.clear
$0.secondaryHighlighted.darkColor = UIColor.clear
}
private var buttonBorderColorConfiguration = UseableColorConfiguration().with {
$0.primary.enabled.lightColor = VDSColor.elementsPrimaryOndark
$0.primary.enabled.darkColor = VDSColor.elementsPrimaryOnlight
$0.primary.disabled.lightColor = VDSColor.interactiveDisabledOnlight
$0.primary.disabled.darkColor = VDSColor.interactiveDisabledOndark
$0.primaryHighlighted.lightColor = VDSColor.elementsPrimaryOndark
$0.primaryHighlighted.darkColor = VDSColor.elementsPrimaryOnlight
$0.secondary.enabled.lightColor = VDSColor.elementsPrimaryOnlight
$0.secondary.enabled.darkColor = VDSColor.elementsPrimaryOndark
$0.secondary.disabled.lightColor = VDSColor.interactiveDisabledOnlight
$0.secondary.disabled.darkColor = VDSColor.interactiveDisabledOndark
$0.secondaryHighlighted.lightColor = VDSColor.interactiveActiveOnlight
$0.secondaryHighlighted.darkColor = VDSColor.interactiveActiveOndark
}
private var buttonTitleColorConfiguration = UseableColorConfiguration().with {
@ -100,11 +90,17 @@ open class Button: UIButton, Buttonable, Handlerable, ViewProtocol, Resettable,
$0.primary.enabled.darkColor = VDSColor.elementsPrimaryOnlight
$0.primary.disabled.lightColor = VDSColor.elementsPrimaryOndark
$0.primary.disabled.darkColor = VDSColor.elementsPrimaryOnlight
$0.primaryHighlighted.lightColor = VDSColor.elementsPrimaryOndark
$0.primaryHighlighted.darkColor = VDSColor.elementsPrimaryOnlight
$0.secondary.enabled.lightColor = VDSColor.elementsPrimaryOnlight
$0.secondary.enabled.darkColor = VDSColor.elementsPrimaryOndark
$0.secondary.disabled.lightColor = VDSColor.interactiveDisabledOnlight
$0.secondary.disabled.darkColor = VDSColor.interactiveDisabledOndark
$0.secondaryHighlighted.lightColor = VDSColor.interactiveActiveOnlight
$0.secondaryHighlighted.darkColor = VDSColor.interactiveActiveOndark
}
//--------------------------------------------------
@ -112,91 +108,57 @@ open class Button: UIButton, Buttonable, Handlerable, ViewProtocol, Resettable,
//--------------------------------------------------
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()
}
//--------------------------------------------------
// MARK: - Public Functions
//--------------------------------------------------
open func initialSetup() {
if !initialSetupPerformed {
backgroundColor = .clear
translatesAutoresizingMaskIntoConstraints = false
accessibilityCustomActions = []
accessibilityTraits = .staticText
setup()
setupDidChangeEvent()
updateView()
}
}
open func setup() {
translatesAutoresizingMaskIntoConstraints = false
titleLabel?.adjustsFontSizeToFitWidth = false
titleLabel?.lineBreakMode = .byTruncatingTail
open override func setup() {
super.setup()
//only 1 of the 2 widths can be on at the same time
widthConstraint = widthAnchor.constraint(equalToConstant: 0)
minWidthConstraint = widthAnchor.constraint(greaterThanOrEqualToConstant: size.minimumWidth)
//height
heightConstraint = heightAnchor.constraint(equalToConstant: size.height)
heightConstraint = heightAnchor.constraint(equalToConstant: 0)
heightConstraint?.isActive = true
}
open func reset() {
surface = .light
disabled = false
open override func reset() {
super.reset()
use = .primary
width = nil
size = .large
accessibilityCustomActions = []
accessibilityTraits = .staticText
}
//--------------------------------------------------
// MARK: - Overrides
//--------------------------------------------------
override open var intrinsicContentSize: CGSize {
let intrinsicContentSize = super.intrinsicContentSize
let adjustedWidth = intrinsicContentSize.width + titleEdgeInsets.left + titleEdgeInsets.right
let adjustedHeight = intrinsicContentSize.height + titleEdgeInsets.top + titleEdgeInsets.bottom
return CGSize(width: adjustedWidth, height: adjustedHeight)
}
open func updateView() {
open override func updateView() {
super.updateView()
let bgColor = buttonBackgroundColorConfiguration.getColor(self)
let borderColor = buttonBorderColorConfiguration.getColor(self)
let titleColor = buttonTitleColorConfiguration.getColor(self)
let borderWidth = use == .secondary ? 1.0 : 0.0
let buttonHeight = size.height
let cornerRadius = buttonHeight / 2
let cornerRadius = size.cornerRadius
let minWidth = size.minimumWidth
let font = size == .large ? TypographicalStyle.BoldBodyLarge.font : TypographicalStyle.BoldBodySmall.font
let edgeInsets = size.edgeInsets
setTitle(text ?? "No Text", for: .normal)
titleLabel?.font = font
backgroundColor = bgColor
setTitleColor(titleColor, for: .normal)
layer.borderColor = borderColor.cgColor
layer.cornerRadius = cornerRadius
layer.borderWidth = borderWidth
contentEdgeInsets = edgeInsets
minWidthConstraint?.constant = minWidth
heightConstraint?.constant = buttonHeight
@ -215,17 +177,23 @@ open class Button: UIButton, Buttonable, Handlerable, ViewProtocol, Resettable,
//--------------------------------------------------
private class UseableColorConfiguration: ObjectColorable {
typealias ObjectType = Disabling & Surfaceable & Useable
typealias ObjectType = Buttonable & Useable
public var primary = DisabledSurfaceColorConfiguration()
public var secondary = DisabledSurfaceColorConfiguration()
public var primaryHighlighted = SurfaceColorConfiguration()
public var secondaryHighlighted = SurfaceColorConfiguration()
required public init(){}
public func getColor(_ object: ObjectType) -> UIColor {
return object.use == .primary ? primary.getColor(object) : secondary.getColor(object)
if object.isHighlighted {
return object.use == .primary ? primaryHighlighted.getColor(object) : secondaryHighlighted.getColor(object)
} else {
return object.use == .primary ? primary.getColor(object) : secondary.getColor(object)
}
}
}
}
}
extension ButtonSize {
@ -239,6 +207,10 @@ extension ButtonSize {
}
}
public var cornerRadius: CGFloat {
height / 2
}
public var minimumWidth: CGFloat {
switch self {
case .large:
@ -267,7 +239,6 @@ extension ButtonSize {
}
extension Use {
public var color: UIColor {
return self == .primary ? VDSColor.backgroundPrimaryDark : .clear
}

View File

@ -12,23 +12,40 @@ import VDSFormControlsTokens
import Combine
@objc(VDSTextLink)
open class TextLink: Control, Buttonable {
open class TextLink: BaseButton {
//--------------------------------------------------
// MARK: - Private Properties
//--------------------------------------------------
private var heightConstraint: NSLayoutConstraint?
private var label = Label()
private var lineHeightConstraint: NSLayoutConstraint?
//--------------------------------------------------
// MARK: - Properties
//--------------------------------------------------
open var text: String? { didSet { didChange() } }
open var size: ButtonSize = .large { didSet { didChange() }}
public var availableSizes: [ButtonSize] { [.large, .small] }
open override var availableSizes: [ButtonSize] { [.large, .small] }
open override var typograpicalStyle: TypographicalStyle {
size == .large ? TypographicalStyle.BodyLarge : TypographicalStyle.BodySmall
}
open override var textColor: UIColor {
textColorConfiguration.getColor(self)
}
private var textColorConfiguration = HighlightDisabledSurfaceColorConfiguration().with {
$0.disabled.lightColor = VDSColor.elementsSecondaryOnlight
$0.disabled.darkColor = VDSColor.elementsSecondaryOndark
$0.enabled.lightColor = VDSColor.elementsPrimaryOnlight
$0.enabled.darkColor = VDSColor.elementsPrimaryOndark
$0.highlighted.lightColor = VDSColor.interactiveActiveOnlight
$0.highlighted.darkColor = VDSColor.interactiveActiveOndark
}
private var height: CGFloat {
switch size {
case .large:
@ -43,49 +60,42 @@ open class TextLink: Control, Buttonable {
//--------------------------------------------------
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()
}
private var line = UIView().with {
$0.translatesAutoresizingMaskIntoConstraints = false
}
//--------------------------------------------------
// MARK: - Public Functions
//--------------------------------------------------
open override func initialSetup() {
super.initialSetup()
}
open override func setup() {
super.setup()
addSubview(label)
//add tapGesture to self
publisher(for: UITapGestureRecognizer()).sink { [weak self] _ in
self?.sendActions(for: .touchUpInside)
}.store(in: &subscribers)
//pin stackview to edges
label.pinToSuperView()
label.numberOfLines = 1
if let titleLabel {
addSubview(line)
line.pinLeading(titleLabel.leadingAnchor)
line.pinTrailing(titleLabel.trailingAnchor)
line.pinTop(titleLabel.bottomAnchor, 1)
lineHeightConstraint = line.heightAnchor.constraint(equalToConstant: 1.0)
lineHeightConstraint?.isActive = true
}
heightConstraint = heightAnchor.constraint(equalToConstant: height)
heightConstraint?.isActive = true
}
open override func reset() {
super.reset()
label.reset()
size = .large
text = nil
size = .large
accessibilityCustomActions = []
accessibilityTraits = .staticText
}
@ -93,17 +103,32 @@ open class TextLink: Control, Buttonable {
//--------------------------------------------------
// MARK: - Overrides
//--------------------------------------------------
override open var intrinsicContentSize: CGSize {
return CGSize(width: label.intrinsicContentSize.width, height: height)
}
open override func updateView() {
label.surface = surface
label.disabled = disabled
label.typograpicalStyle = size == .large ? TypographicalStyle.BodyLarge : TypographicalStyle.BodySmall
label.text = text ?? ""
label.attributes = [UnderlineLabelAttribute(location: 0, length: label.text!.count)]
//need to set the properties so the super class
//can render out the label correctly
heightConstraint?.constant = height
lineHeightConstraint?.constant = isHighlighted ? 2.0 : 1.0
line.backgroundColor = textColor
//always call last so the label is rendered
super.updateView()
}
}
class HighlightDisabledSurfaceColorConfiguration: ObjectColorable {
typealias ObjectType = Buttonable
public var highlighted = SurfaceColorConfiguration()
public var disabled = SurfaceColorConfiguration()
public var enabled = SurfaceColorConfiguration()
required public init(){}
public func getColor(_ object: any ObjectType) -> UIColor {
if object.isHighlighted {
return highlighted.getColor(object)
} else {
return object.disabled ? disabled.getColor(object) : enabled.getColor(object)
}
}
}

View File

@ -16,103 +16,103 @@ public enum TextLinkCaretPosition: String, CaseIterable {
}
@objc(VDSTextLinkCaret)
open class TextLinkCaret: Control, Buttonable {
open class TextLinkCaret: BaseButton {
//--------------------------------------------------
// MARK: - Private Properties
//--------------------------------------------------
private var heightConstraint: NSLayoutConstraint?
private var label = Label().with {
$0.typograpicalStyle = TypographicalStyle.BoldBodyLarge
open override var typograpicalStyle: TypographicalStyle {
TypographicalStyle.BoldBodyLarge
}
private var caretView = CaretView().with {
$0.size = CaretView.CaretSize.small(.vertical)
$0.lineWidth = 2
}
private var imageAttribute: ImageLabelAttribute?
open override var attributes: [any LabelAttributeModel]? {
guard let imageAttribute else { return nil }
return [imageAttribute]
}
//--------------------------------------------------
// MARK: - Properties
//--------------------------------------------------
public var availableSizes: [ButtonSize] { [.large] }
open var text: String? { didSet { didChange() } }
public override var availableSizes: [ButtonSize] { [.large] }
open var iconPosition: TextLinkCaretPosition = .right { didSet { didChange() } }
private var height: CGFloat {
44
}
private var _text: String?
open override var text: String? {
get{ _text }
set {
var updatedText = newValue ?? ""
updatedText = iconPosition == .right ? "\(updatedText) " : " \(updatedText)"
_text = updatedText
didChange()
}
}
open override var textColor: UIColor {
textColorConfiguration.getColor(self)
}
private var textColorConfiguration = HighlightDisabledSurfaceColorConfiguration().with {
$0.disabled.lightColor = VDSColor.elementsSecondaryOnlight
$0.disabled.darkColor = VDSColor.elementsSecondaryOndark
$0.enabled.lightColor = VDSColor.elementsPrimaryOnlight
$0.enabled.darkColor = VDSColor.elementsPrimaryOndark
$0.highlighted.lightColor = VDSColor.interactiveActiveOnlight
$0.highlighted.darkColor = VDSColor.interactiveActiveOndark
}
//--------------------------------------------------
// 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()
}
//--------------------------------------------------
// MARK: - Public Functions
//--------------------------------------------------
open override func initialSetup() {
super.initialSetup()
}
open override func setup() {
super.setup()
//add tapGesture to self
publisher(for: UITapGestureRecognizer()).sink { [weak self] _ in
self?.sendActions(for: .touchUpInside)
}.store(in: &subscribers)
//constraints
heightAnchor.constraint(greaterThanOrEqualToConstant: height).isActive = true
let size = caretView.size!.dimensions()
caretView.frame = .init(x: 0, y: 0, width: size.width, height: size.height)
addSubview(label)
label.pinToSuperView()
label.numberOfLines = 1
}
//--------------------------------------------------
// MARK: - Constraints
//--------------------------------------------------
private var caretLeadingConstraint: NSLayoutConstraint?
private var caretTrailingConstraint: NSLayoutConstraint?
private var labelConstraint: NSLayoutConstraint?
open override func reset() {
super.reset()
label.reset()
label.typograpicalStyle = TypographicalStyle.BoldBodyLarge
text = nil
iconPosition = .right
accessibilityCustomActions = []
accessibilityTraits = .staticText
}
//--------------------------------------------------
// MARK: - Overrides
//--------------------------------------------------
override open var intrinsicContentSize: CGSize {
var itemWidth = label.intrinsicContentSize.width
var itemWidth = super.intrinsicContentSize.width
if let caretWidth = caretView.size?.dimensions().width {
itemWidth += caretWidth
}
@ -121,22 +121,19 @@ open class TextLinkCaret: Control, Buttonable {
open override func updateView() {
let updatedText = text ?? ""
var updatedText = text ?? ""
caretView.surface = surface
caretView.disabled = disabled
caretView.direction = iconPosition == .right ? CaretView.Direction.right : CaretView.Direction.left
let image = caretView.getImage()
let location = iconPosition == .right ? updatedText.count + 1 : 0
let textColor = label.textColorConfiguration.getColor(self)
let imageAttribute = ImageLabelAttribute(location: location,
let location = iconPosition == .right ? updatedText.count : 0
imageAttribute = ImageLabelAttribute(location: location,
image: image,
tintColor: textColor)
label.surface = surface
label.disabled = disabled
label.text = iconPosition == .right ? "\(updatedText) " : " \(updatedText)"
label.attributes = [imageAttribute]
super.updateView()
}
}