From 72f2b09255e540c7750529f48adc5b1bec3da6ad Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Thu, 14 Sep 2023 11:47:24 -0500 Subject: [PATCH] refactored everything in the buttons classes to remove buttonable and push configuration inside enums for the classes in question Signed-off-by: Matt Bruce --- VDS/Components/Buttons/Button/Button.swift | 99 +++++++++---------- VDS/Components/Buttons/ButtonBase.swift | 20 ---- .../Buttons/ButtonGroup/ButtonGroup.swift | 4 +- .../ButtonGroup/ButtonGroupConstants.swift | 12 +-- .../ButtonGroupPositionLayout.swift | 36 +++---- .../Buttons/TextLink/TextLink.swift | 26 +++-- .../Buttons/TextLinkCaret/TextLinkCaret.swift | 13 +-- 7 files changed, 87 insertions(+), 123 deletions(-) diff --git a/VDS/Components/Buttons/Button/Button.swift b/VDS/Components/Buttons/Button/Button.swift index 81f10b6e..60d8d0fd 100644 --- a/VDS/Components/Buttons/Button/Button.swift +++ b/VDS/Components/Buttons/Button/Button.swift @@ -11,19 +11,13 @@ import VDSColorTokens import VDSFormControlsTokens import Combine -/// Enum used to describe the size of a buttonable. -public enum ButtonSize: String, CaseIterable { - case large - case small -} - /// A button is an interactive element that triggers an action. Buttons are prominent and attention-getting, with more visual emphasis than any of the Text Link components. For this reason, buttons are best suited for critical and driving actions. This class can be used within a ``ButtonGroup``. /// /// If you are using AutoLayoutConstraints you have a combination of Leading/Left and Trailing/Right NSLayoutConstraints, /// you need to ensure that one of these Horizontal Contraints is not constraint of "equatTo". If you are to pin the left/right edges /// to its parent this object will stretch to the parent's width. @objc(VDSButton) -open class Button: ButtonBase, Useable, Buttonable { +open class Button: ButtonBase, Useable { //-------------------------------------------------- // MARK: - Initializers @@ -40,6 +34,50 @@ open class Button: ButtonBase, Useable, Buttonable { super.init(coder: coder) } + //-------------------------------------------------- + // MARK: - Enums + //-------------------------------------------------- + /// Enum used to describe the size. + public enum Size: String, CaseIterable { + case large + case small + + /// Height for this size of button. + public var height: CGFloat { + switch self { + case .large: + return 44 + case .small: + return 32 + } + } + + /// Corner radius for this size of button. + public var cornerRadius: CGFloat { + height / 2 + } + + /// Minimum width for this size of button. + public var minimumWidth: CGFloat { + switch self { + case .large: + return 76 + case .small: + return 60 + } + } + + /// EdgeInsets for this size of button. + public var edgeInsets: UIEdgeInsets { + switch self { + case .large: + return .axis(horizontal: 24, vertical: 12) + case .small: + return .axis(horizontal: 16, vertical: 8) + } + } + } + //-------------------------------------------------- // MARK: - Private Properties //-------------------------------------------------- @@ -48,11 +86,8 @@ open class Button: ButtonBase, Useable, Buttonable { //-------------------------------------------------- // MARK: - Public Properties //-------------------------------------------------- - /// The ButtonSize available to this type of Buttonable. - open override var availableSizes: [ButtonSize] { [.large, .small] } - /// The ButtonSize for ths Button. - open var size: ButtonSize = .large { didSet { setNeedsUpdate() } } + open var size: Size = .large { didSet { setNeedsUpdate() } } /// The Use for this Button. open var use: Use = .primary { didSet { setNeedsUpdate() } } @@ -183,48 +218,6 @@ open class Button: ButtonBase, Useable, Buttonable { } } -internal extension ButtonSize { - - var height: CGFloat { - switch self { - case .large: - return 44 - case .small: - return 32 - } - } - - var cornerRadius: CGFloat { - height / 2 - } - - var minimumWidth: CGFloat { - switch self { - case .large: - return 76 - case .small: - return 60 - } - } - - var edgeInsets: UIEdgeInsets { - var verticalPadding = 0.0 - var horizontalPadding = 0.0 - switch self { - case .large: - verticalPadding = 12 - horizontalPadding = 24 - break - case .small: - verticalPadding = 8 - horizontalPadding = 16 - break - } - return UIEdgeInsets(top: verticalPadding, left: horizontalPadding, bottom: verticalPadding, right: horizontalPadding) - } - -} - extension Use { public var color: UIColor { return self == .primary ? VDSColor.backgroundPrimaryDark : .clear diff --git a/VDS/Components/Buttons/ButtonBase.swift b/VDS/Components/Buttons/ButtonBase.swift index 2c377d1c..83627736 100644 --- a/VDS/Components/Buttons/ButtonBase.swift +++ b/VDS/Components/Buttons/ButtonBase.swift @@ -11,18 +11,6 @@ import VDSColorTokens import VDSFormControlsTokens import Combine -public protocol Buttonable: UIControl, Surfaceable, Enabling { - - /// The ButtonSize available to this type of Buttonable. - var availableSizes: [ButtonSize] { get } - - /// The Text that will show up in the TitleLabel for this Buttonable. - var text: String? { get set } - - /// The natural size for the receiving view, considering only properties of the view itself. - var intrinsicContentSize: CGSize { get } -} - /// Base class used for UIButton type classes. @objc(VDSButtonBase) open class ButtonBase: UIButton, ViewProtocol, UserInfoable, Clickable { @@ -45,11 +33,6 @@ open class ButtonBase: UIButton, ViewProtocol, UserInfoable, Clickable { initialSetup() } - //-------------------------------------------------- - // MARK: - Configuration Properties - //-------------------------------------------------- - private let hitAreaHeight = 44.0 - //-------------------------------------------------- // MARK: - Combine Properties //-------------------------------------------------- @@ -75,9 +58,6 @@ open class ButtonBase: UIButton, ViewProtocol, UserInfoable, Clickable { /// Key of whether or not updateView() is called in setNeedsUpdate() open var shouldUpdateView: Bool = true - /// The ButtonSize available to this type of Buttonable. - open var availableSizes: [ButtonSize] { [] } - open var surface: Surface = .light { didSet { setNeedsUpdate() } } /// Text that will be used in the titleLabel. diff --git a/VDS/Components/Buttons/ButtonGroup/ButtonGroup.swift b/VDS/Components/Buttons/ButtonGroup/ButtonGroup.swift index 5f764754..4a563f63 100644 --- a/VDS/Components/Buttons/ButtonGroup/ButtonGroup.swift +++ b/VDS/Components/Buttons/ButtonGroup/ButtonGroup.swift @@ -60,7 +60,7 @@ open class ButtonGroup: View { open var alignment: Alignment = .center { didSet { setNeedsUpdate() } } /// Array of Buttonable Views that are shown in the group. - open var buttons: [Buttonable] = [] { didSet { setNeedsUpdate() } } + open var buttons: [ButtonBase] = [] { didSet { setNeedsUpdate() } } private var _childWidth: ChildWidth? @@ -205,7 +205,7 @@ extension ButtonGroup: UICollectionViewDataSource, UICollectionViewDelegate { } extension ButtonGroup : ButtongGroupPositionLayoutDelegate { - func collectionView(_ collectionView: UICollectionView, buttonableAtIndexPath indexPath: IndexPath) -> Buttonable { + func collectionView(_ collectionView: UICollectionView, buttonBaseAtIndexPath indexPath: IndexPath) -> ButtonBase { buttons[indexPath.row] } } diff --git a/VDS/Components/Buttons/ButtonGroup/ButtonGroupConstants.swift b/VDS/Components/Buttons/ButtonGroup/ButtonGroupConstants.swift index ff8605d0..150b8928 100644 --- a/VDS/Components/Buttons/ButtonGroup/ButtonGroupConstants.swift +++ b/VDS/Components/Buttons/ButtonGroup/ButtonGroupConstants.swift @@ -14,13 +14,13 @@ struct ButtonGroupConstants { case horizontal, vertical } - /// This will determine the spacing that will go between 2 buttonables either horizontally or vertically + /// This will determine the spacing that will go between 2 ButtonBases either horizontally or vertically /// - Parameters: /// - axis: horizontal/vertical - /// - primary: first buttonable - /// - neighboring: next buttonable based off of axis + /// - primary: first ButtonBase + /// - neighboring: next ButtonBase based off of axis /// - Returns: float value - static func getSpacing(for axis: ButtonSpacingAxis, with primary: Buttonable, neighboring: Buttonable) -> CGFloat { + static func getSpacing(for axis: ButtonSpacingAxis, with primary: ButtonBase, neighboring: ButtonBase) -> CGFloat { //large button if let button = primary as? Button, button.size == .large { @@ -87,7 +87,7 @@ struct ButtonGroupConstants { // - /// Gets the tallest buttonables within the row + /// Gets the tallest ButtonBases within the row /// - Parameter row: Row that includes the attributes /// - Returns: Array of [ButtonLayoutAttributes] of the tallest items private static func getTallestAttributes(for row: ButtonCollectionViewRow) -> [ButtonLayoutAttributes] { @@ -122,7 +122,7 @@ struct ButtonGroupConstants { primaryTallestAttributes.forEach { primaryAttribute in neighboringTallestAttributes.forEach { neighboringTallestAttribute in - let space = getSpacing(for: .vertical, with: primaryAttribute.buttonable!, neighboring: neighboringTallestAttribute.buttonable!) + let space = getSpacing(for: .vertical, with: primaryAttribute.button!, neighboring: neighboringTallestAttribute.button!) if space > largestVerticalSpace { largestVerticalSpace = space } diff --git a/VDS/Components/Buttons/ButtonGroup/ButtonGroupPositionLayout.swift b/VDS/Components/Buttons/ButtonGroup/ButtonGroupPositionLayout.swift index 8f375d3a..c1a315eb 100644 --- a/VDS/Components/Buttons/ButtonGroup/ButtonGroupPositionLayout.swift +++ b/VDS/Components/Buttons/ButtonGroup/ButtonGroupPositionLayout.swift @@ -82,7 +82,7 @@ class ButtonCollectionViewRow { } } - if buttonWidth >= ButtonSize.large.minimumWidth { + if buttonWidth >= Button.Size.large.minimumWidth { if testSize <= buttonAvailableSpace { for attribute in attributes { if attribute.isButton { @@ -122,25 +122,25 @@ class ButtonCollectionViewRow { protocol ButtongGroupPositionLayoutDelegate: AnyObject { func collectionView(_ collectionView: UICollectionView, sizeForItemAtIndexPath indexPath: IndexPath) -> CGSize - func collectionView(_ collectionView: UICollectionView, buttonableAtIndexPath indexPath: IndexPath) -> any Buttonable + func collectionView(_ collectionView: UICollectionView, buttonBaseAtIndexPath indexPath: IndexPath) -> ButtonBase } class ButtonLayoutAttributes: UICollectionViewLayoutAttributes{ var spacing: CGFloat = 0 - var buttonable: Buttonable? + var button: ButtonBase? var isButton: Bool { - guard buttonable is Button else { return false } + guard button is Button else { return false } return true } convenience init(spacing: CGFloat, - buttonable: Buttonable, + button: ButtonBase, forCellWith indexPath: IndexPath) { self.init(forCellWith: indexPath) self.spacing = spacing - self.buttonable = buttonable + self.button = button } } @@ -173,7 +173,7 @@ class ButtonGroupPositionLayout: UICollectionViewLayout { // Variables to track individual item width and cumultative height of all items as they are being laid out. var itemSize: CGSize = .zero - // get number of buttonables + // get number of buttons let totalItems = collectionView.numberOfItems(inSection: section) //create rows @@ -190,10 +190,10 @@ class ButtonGroupPositionLayout: UICollectionViewLayout { // create the indexPath let indexPath = IndexPath(item: item, section: section) - // get the rect size of the buttonable + // get the rect size of the button itemSize = delegate.collectionView(collectionView, sizeForItemAtIndexPath: indexPath) - // determine if the current buttonable will fit in the row + // determine if the current button will fit in the row let rowItemCount = rows.last?.attributes.count ?? 0 if (layoutWidthIterator + itemSize.width) > collectionViewWidth || (rowQuantity > 0 && rowItemCount == rowQuantity) { @@ -209,26 +209,26 @@ class ButtonGroupPositionLayout: UICollectionViewLayout { rows.append(ButtonCollectionViewRow()) } - // get the buttonable - let itemButtonable = delegate.collectionView(collectionView, buttonableAtIndexPath: indexPath) + // get the button + let itemButtonBase = delegate.collectionView(collectionView, buttonBaseAtIndexPath: indexPath) // see if there is another item in the array let nextItem = item + 1 - // if so, get the buttonable + // if so, get the button // and get the spacing based of the - // current buttonable and the next buttonable + // current button and the next button if nextItem < totalItems { - //get the next buttonable - let neighbor = delegate.collectionView(collectionView, buttonableAtIndexPath: IndexPath(item: nextItem, section: section)) + //get the next button + let neighbor = delegate.collectionView(collectionView, buttonBaseAtIndexPath: IndexPath(item: nextItem, section: section)) - // get the spacing to go between the current and next buttonable - itemSpacing = ButtonGroupConstants.getSpacing(for: .horizontal, with: itemButtonable, neighboring: neighbor) + // get the spacing to go between the current and next button + itemSpacing = ButtonGroupConstants.getSpacing(for: .horizontal, with: itemButtonBase, neighboring: neighbor) } // create the custom layout attribute - let attributes = ButtonLayoutAttributes(spacing: itemSpacing, buttonable: itemButtonable, forCellWith: indexPath) + let attributes = ButtonLayoutAttributes(spacing: itemSpacing, button: itemButtonBase, forCellWith: indexPath) attributes.frame = CGRect(x: 0, y: 0, width: itemSize.width, height: itemSize.height) // add it to the array diff --git a/VDS/Components/Buttons/TextLink/TextLink.swift b/VDS/Components/Buttons/TextLink/TextLink.swift index 556c2c63..dcb4a46d 100644 --- a/VDS/Components/Buttons/TextLink/TextLink.swift +++ b/VDS/Components/Buttons/TextLink/TextLink.swift @@ -18,7 +18,7 @@ import Combine /// you need to ensure that one of these Horizontal Contraints is not constraint of "equatTo". If you are to pin the left/right edges /// to its parent this object will stretch to the parent's width. @objc(VDSTextLink) -open class TextLink: ButtonBase, Buttonable { +open class TextLink: ButtonBase { //-------------------------------------------------- // MARK: - Initializers //-------------------------------------------------- @@ -34,6 +34,15 @@ open class TextLink: ButtonBase, Buttonable { super.init(coder: coder) } + //-------------------------------------------------- + // MARK: - Enums + //-------------------------------------------------- + /// Enum used to describe the size. + public enum Size: String, CaseIterable { + case large + case small + } + //-------------------------------------------------- // MARK: - Private Properties //-------------------------------------------------- @@ -46,11 +55,9 @@ open class TextLink: ButtonBase, Buttonable { //-------------------------------------------------- // MARK: - Public Properties //-------------------------------------------------- - open var size: ButtonSize = .large { didSet { setNeedsUpdate() } } + /// The ButtonSize available. + open var size: Size = .large { didSet { setNeedsUpdate() } } - /// The ButtonSize available to this type of Buttonable. - open override var availableSizes: [ButtonSize] { [.large, .small] } - open override var textStyle: TextStyle { size == .large ? TextStyle.bodyLarge : TextStyle.bodySmall } @@ -66,15 +73,6 @@ open class TextLink: ButtonBase, Buttonable { $0.setSurfaceColors(VDSColor.interactiveActiveOnlight, VDSColor.interactiveActiveOndark, forState: .highlighted) } - private var height: CGFloat { - switch size { - case .large: - return 44 - case .small: - return 32 - } - } - /// The natural size for the receiving view, considering only properties of the view itself. open override var intrinsicContentSize: CGSize { return titleLabel?.intrinsicContentSize ?? super.intrinsicContentSize diff --git a/VDS/Components/Buttons/TextLinkCaret/TextLinkCaret.swift b/VDS/Components/Buttons/TextLinkCaret/TextLinkCaret.swift index 9b05a226..fd990720 100644 --- a/VDS/Components/Buttons/TextLinkCaret/TextLinkCaret.swift +++ b/VDS/Components/Buttons/TextLinkCaret/TextLinkCaret.swift @@ -18,7 +18,7 @@ import Combine /// you need to ensure that one of these Horizontal Contraints is not constraint of "equatTo". If you are to pin the left/right edges /// to its parent this object will stretch to the parent's width. @objc(VDSTextLinkCaret) -open class TextLinkCaret: ButtonBase, Buttonable { +open class TextLinkCaret: ButtonBase { //-------------------------------------------------- // MARK: - Initializers //-------------------------------------------------- @@ -41,14 +41,10 @@ open class TextLinkCaret: ButtonBase, Buttonable { public enum IconPosition: String, CaseIterable { case left, right } - + //-------------------------------------------------- // MARK: - Private Properties //-------------------------------------------------- - private var height: CGFloat { - 44 - } - private var textColorConfiguration = ControlColorConfiguration().with { $0.setSurfaceColors(VDSColor.elementsPrimaryOnlight, VDSColor.elementsPrimaryOndark, forState: .normal) $0.setSurfaceColors(VDSColor.interactiveDisabledOnlight, VDSColor.interactiveDisabledOndark, forState: .disabled) @@ -59,10 +55,7 @@ open class TextLinkCaret: ButtonBase, Buttonable { //-------------------------------------------------- // MARK: - Public Properties - //-------------------------------------------------- - /// The ButtonSize available to this type of Buttonable. - public override var availableSizes: [ButtonSize] { [.large] } - + //-------------------------------------------------- /// Determines icon position of Caret. open var iconPosition: IconPosition = .right { didSet { setNeedsUpdate() } }