Merge branch 'feature/buttonIcon' into 'develop'
VDS Components - VDS Brand 3.0 Button Icon for IOS See merge request BPHV_MIPS/vds_ios!147
This commit is contained in:
commit
a317125072
@ -7,6 +7,8 @@
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
18792A902B7431F2008C0D29 /* ButtonIconBadgeIndicatorModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18792A8F2B7431F2008C0D29 /* ButtonIconBadgeIndicatorModel.swift */; };
|
||||
18BDEE822B75316E00452358 /* ButtonIconChangeLog.txt in Resources */ = {isa = PBXBuildFile; fileRef = 18BDEE812B75316E00452358 /* ButtonIconChangeLog.txt */; };
|
||||
445BA07829C07B3D0036A7C5 /* Notification.swift in Sources */ = {isa = PBXBuildFile; fileRef = 445BA07729C07B3D0036A7C5 /* Notification.swift */; };
|
||||
44604AD429CE186A00E62B51 /* NotificationButtonModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 44604AD329CE186A00E62B51 /* NotificationButtonModel.swift */; };
|
||||
44604AD729CE196600E62B51 /* Line.swift in Sources */ = {isa = PBXBuildFile; fileRef = 44604AD629CE196600E62B51 /* Line.swift */; };
|
||||
@ -169,6 +171,8 @@
|
||||
/* End PBXContainerItemProxy section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
18792A8F2B7431F2008C0D29 /* ButtonIconBadgeIndicatorModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ButtonIconBadgeIndicatorModel.swift; sourceTree = "<group>"; };
|
||||
18BDEE812B75316E00452358 /* ButtonIconChangeLog.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = ButtonIconChangeLog.txt; sourceTree = "<group>"; };
|
||||
445BA07729C07B3D0036A7C5 /* Notification.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Notification.swift; sourceTree = "<group>"; };
|
||||
44604AD329CE186A00E62B51 /* NotificationButtonModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationButtonModel.swift; sourceTree = "<group>"; };
|
||||
44604AD629CE196600E62B51 /* Line.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Line.swift; sourceTree = "<group>"; };
|
||||
@ -674,6 +678,8 @@
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
EA81410A2A0E8E3C004F60D2 /* ButtonIcon.swift */,
|
||||
18792A8F2B7431F2008C0D29 /* ButtonIconBadgeIndicatorModel.swift */,
|
||||
18BDEE812B75316E00452358 /* ButtonIconChangeLog.txt */,
|
||||
);
|
||||
path = ButtonIcon;
|
||||
sourceTree = "<group>";
|
||||
@ -942,6 +948,7 @@
|
||||
EAEEECAF2B1FC2BA00531FC2 /* ToggleViewChangeLog.txt in Resources */,
|
||||
EAEEEC922B1F807300531FC2 /* BadgeChangeLog.txt in Resources */,
|
||||
EAEEEC9E2B1F8F7700531FC2 /* ButtonGroupChangeLog.txt in Resources */,
|
||||
18BDEE822B75316E00452358 /* ButtonIconChangeLog.txt in Resources */,
|
||||
EA3362062891E14D0071C351 /* VerizonNHGeTX-Regular.otf in Resources */,
|
||||
EA3362052891E14D0071C351 /* VerizonNHGeDS-Bold.otf in Resources */,
|
||||
EAEEECA02B1F908200531FC2 /* BadgeIndicatorChangeLog.txt in Resources */,
|
||||
@ -1064,6 +1071,7 @@
|
||||
EA5E30532950DDA60082B959 /* TitleLockup.swift in Sources */,
|
||||
EAD062B02A3B873E0015965D /* BadgeIndicator.swift in Sources */,
|
||||
EAA5EEB528ECBFB4003B3210 /* ImageLabelAttribute.swift in Sources */,
|
||||
18792A902B7431F2008C0D29 /* ButtonIconBadgeIndicatorModel.swift in Sources */,
|
||||
EA0B18062A9E2D2D00F2D0CD /* SelectorItemBase.swift in Sources */,
|
||||
EAB5FF0129424ACB00998C17 /* UIControl.swift in Sources */,
|
||||
EA985BF5296C60C000F2FF2E /* Icon.swift in Sources */,
|
||||
|
||||
@ -8,12 +8,13 @@
|
||||
import Foundation
|
||||
import UIKit
|
||||
import VDSColorTokens
|
||||
import Combine
|
||||
|
||||
/// A button icon is an interactive element that visually communicates the action it triggers via an icon.
|
||||
/// It usually represents a supplementary or utilitarian action. A button icon can stand alone, but often
|
||||
/// exists in a group when there are several actions that can be performed.
|
||||
@objc(VDSButtonIcon)
|
||||
open class ButtonIcon: Control {
|
||||
open class ButtonIcon: Control, Changeable, FormFieldable {
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Initializers
|
||||
@ -42,7 +43,7 @@ open class ButtonIcon: Control {
|
||||
public enum SurfaceType: String, CaseIterable {
|
||||
case colorFill, media
|
||||
}
|
||||
|
||||
|
||||
/// Enum used to describe the size of button icon.
|
||||
public enum Size: String, EnumSubset {
|
||||
case large
|
||||
@ -67,17 +68,45 @@ open class ButtonIcon: Control {
|
||||
private var centerYConstraint: NSLayoutConstraint?
|
||||
private var layoutGuideWidthConstraint: NSLayoutConstraint?
|
||||
private var layoutGuideHeightConstraint: NSLayoutConstraint?
|
||||
private var badgeIndicatorLeadingConstraint: NSLayoutConstraint?
|
||||
private var badgeIndicatorTrailingConstraint: NSLayoutConstraint?
|
||||
private var badgeIndicatorCenterXConstraint: NSLayoutConstraint?
|
||||
private var badgeIndicatorCenterYConstraint: NSLayoutConstraint?
|
||||
private var currentIconName: Icon.Name? {
|
||||
if let selectedIconName {
|
||||
if let selectedIconName, isSelected {
|
||||
return selectedIconName
|
||||
} else {
|
||||
return iconName
|
||||
}
|
||||
}
|
||||
|
||||
private var badgeIndicatorOffset: CGPoint {
|
||||
switch (size, kind) {
|
||||
case (.small, .ghost):
|
||||
return .init(x: 1, y: 0)
|
||||
case (.large, .ghost):
|
||||
return .init(x: 1, y: 1)
|
||||
case (.small, .lowContrast), (.small, .highContrast):
|
||||
return .init(x: 4, y: 4)
|
||||
case (.large, .lowContrast), (.large, .highContrast):
|
||||
return .init(x: 6, y: 6)
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Public Properties
|
||||
//--------------------------------------------------
|
||||
|
||||
///Badge Indicator object used to render for the ButtonIcon.
|
||||
open var badgeIndicator = BadgeIndicator().with {
|
||||
$0.translatesAutoresizingMaskIntoConstraints = false
|
||||
$0.size = .small
|
||||
$0.isHidden = true
|
||||
}
|
||||
|
||||
/// If set, this is used to render the badge indicator.
|
||||
open var badgeIndicatorModel: BadgeIndicatorModel? { didSet { setNeedsUpdate() } }
|
||||
|
||||
/// Icon object used to render out the Icon for this ButtonIcon.
|
||||
open var icon = Icon().with { $0.isUserInteractionEnabled = false }
|
||||
|
||||
@ -107,22 +136,40 @@ open class ButtonIcon: Control {
|
||||
|
||||
/// If set to true, the button icon will not have a border.
|
||||
open var hideBorder: Bool = true { didSet { setNeedsUpdate() } }
|
||||
|
||||
/// If provided, the badge indicator will present.
|
||||
open var showBadgeIndicator: Bool = false { didSet { setNeedsUpdate() } }
|
||||
|
||||
/// If true, button will be rendered as selected, when it is selectable.
|
||||
open var selectable: Bool = false {
|
||||
didSet {
|
||||
//unselect
|
||||
if !selectable && isSelected {
|
||||
isSelected = false
|
||||
}
|
||||
setNeedsUpdate()
|
||||
}
|
||||
}
|
||||
|
||||
/// Used to move the icon inside the button in both x and y axis.
|
||||
open var iconOffset: CGPoint = .init(x: 0, y: 0) { didSet { setNeedsUpdate() } }
|
||||
|
||||
|
||||
open var onChangeSubscriber: AnyCancellable?
|
||||
|
||||
open var inputId: String? { didSet { setNeedsUpdate() } }
|
||||
|
||||
open var value: AnyHashable? { didSet { setNeedsUpdate() } }
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Configuration
|
||||
//--------------------------------------------------
|
||||
private var iconColorConfiguration: AnyColorable {
|
||||
if selectedIconName != nil {
|
||||
return selectedIconColorConfiguration
|
||||
if kind == .highContrast {
|
||||
return highContrastIconColorConfiguration
|
||||
} else if kind == .lowContrast {
|
||||
return (surfaceType == .colorFill) ? lowContrastIconColorConfiguration : (floating ? lowContrastIconColorConfiguration : standardIconColorConfiguration)
|
||||
} else {
|
||||
if kind == .highContrast {
|
||||
return highContrastIconColorConfiguration
|
||||
} else {
|
||||
return standardIconColorConfiguration
|
||||
}
|
||||
return standardIconColorConfiguration
|
||||
}
|
||||
}
|
||||
|
||||
@ -147,7 +194,19 @@ open class ButtonIcon: Control {
|
||||
return ControlColorConfiguration().with {
|
||||
$0.setSurfaceColors(VDSColor.elementsPrimaryOnlight, VDSColor.elementsPrimaryOndark, forState: .normal)
|
||||
$0.setSurfaceColors(VDSColor.interactiveActiveOnlight, VDSColor.interactiveActiveOndark, forState: .highlighted)
|
||||
$0.setSurfaceColors(VDSColor.interactiveDisabledOnlight, VDSColor.interactiveDisabledOndark, forState: .disabled)
|
||||
$0.setSurfaceColors(VDSColor.interactiveDisabledOnlight, VDSColor.interactiveDisabledOndark, forState: .disabled)
|
||||
$0.setSurfaceColors(VDSColor.elementsPrimaryOnlight, VDSColor.elementsPrimaryOndark, forState: .selected)
|
||||
$0.setSurfaceColors(VDSColor.interactiveDisabledOnlight, VDSColor.interactiveDisabledOndark, forState: [.selected, .disabled])
|
||||
}.eraseToAnyColorable()
|
||||
}()
|
||||
|
||||
private var lowContrastIconColorConfiguration: AnyColorable = {
|
||||
return ControlColorConfiguration().with {
|
||||
$0.setSurfaceColors(VDSColor.elementsPrimaryOnlight, VDSColor.elementsPrimaryOndark, forState: .normal)
|
||||
$0.setSurfaceColors(VDSColor.interactiveActiveOnlight, VDSColor.interactiveActiveOndark, forState: .highlighted)
|
||||
$0.setSurfaceColors(VDSColor.interactiveDisabledOnlight, VDSColor.paletteBlack.withAlphaComponent(0.70), forState: .disabled)
|
||||
$0.setSurfaceColors(VDSColor.elementsPrimaryOnlight, VDSColor.elementsPrimaryOndark, forState: .selected)
|
||||
$0.setSurfaceColors(VDSColor.interactiveDisabledOnlight, VDSColor.paletteBlack.withAlphaComponent(0.70), forState: [.selected, .disabled])
|
||||
}.eraseToAnyColorable()
|
||||
}()
|
||||
|
||||
@ -155,14 +214,6 @@ open class ButtonIcon: Control {
|
||||
return SurfaceColorConfiguration(VDSColor.elementsPrimaryOndark, VDSColor.elementsPrimaryOnlight).eraseToAnyColorable()
|
||||
}()
|
||||
|
||||
private var selectedIconColorConfiguration: AnyColorable = {
|
||||
return ControlColorConfiguration().with {
|
||||
$0.setSurfaceColors(VDSColor.elementsBrandhighlight, VDSColor.elementsPrimaryOndark, forState: .normal)
|
||||
$0.setSurfaceColors(VDSColor.interactiveActiveOnlight, VDSColor.interactiveActiveOndark, forState: .highlighted)
|
||||
$0.setSurfaceColors(VDSColor.interactiveDisabledOnlight, VDSColor.interactiveDisabledOndark, forState: .disabled)
|
||||
}.eraseToAnyColorable()
|
||||
}()
|
||||
|
||||
private struct GhostConfiguration: Configuration {
|
||||
var kind: Kind = .ghost
|
||||
var surfaceType: SurfaceType = .colorFill
|
||||
@ -181,13 +232,19 @@ open class ButtonIcon: Control {
|
||||
}()
|
||||
}
|
||||
|
||||
private struct LowContrastColorFillFloatingConfiguration: Configuration {
|
||||
private struct LowContrastColorFillFloatingConfiguration: Configuration, Dropshadowable {
|
||||
var kind: Kind = .lowContrast
|
||||
var surfaceType: SurfaceType = .colorFill
|
||||
var floating: Bool = true
|
||||
var backgroundColorConfiguration: AnyColorable = {
|
||||
SurfaceColorConfiguration(VDSColor.backgroundPrimaryLight, .clear).eraseToAnyColorable()
|
||||
SurfaceColorConfiguration(VDSColor.paletteWhite, VDSColor.paletteGray20).eraseToAnyColorable()
|
||||
}()
|
||||
var shadowColorConfiguration: AnyColorable = {
|
||||
SurfaceColorConfiguration(VDSColor.paletteBlack, VDSColor.paletteBlack).eraseToAnyColorable()
|
||||
}()
|
||||
var shadowOpacity: CGFloat = 0.16
|
||||
var shadowOffset: CGSize = .init(width: 0, height: 2)
|
||||
var shadowRadius: CGFloat = 4
|
||||
}
|
||||
|
||||
private struct LowContrastMediaConfiguration: Configuration, Borderable {
|
||||
@ -195,11 +252,11 @@ open class ButtonIcon: Control {
|
||||
var surfaceType: SurfaceType = .media
|
||||
var floating: Bool = false
|
||||
var backgroundColorConfiguration: AnyColorable = {
|
||||
SurfaceColorConfiguration(VDSColor.backgroundPrimaryLight, .clear).eraseToAnyColorable()
|
||||
SurfaceColorConfiguration(VDSColor.backgroundPrimaryLight, VDSColor.backgroundPrimaryDark).eraseToAnyColorable()
|
||||
}()
|
||||
var borderWidth: CGFloat = 1.0
|
||||
var borderColorConfiguration: AnyColorable = {
|
||||
SurfaceColorConfiguration(VDSColor.elementsLowcontrastOnlight, .clear).eraseToAnyColorable()
|
||||
SurfaceColorConfiguration(VDSColor.elementsLowcontrastOnlight, VDSColor.elementsLowcontrastOndark).eraseToAnyColorable()
|
||||
}()
|
||||
}
|
||||
|
||||
@ -208,14 +265,14 @@ open class ButtonIcon: Control {
|
||||
var surfaceType: SurfaceType = .media
|
||||
var floating: Bool = true
|
||||
var backgroundColorConfiguration: AnyColorable = {
|
||||
SurfaceColorConfiguration(VDSColor.backgroundPrimaryLight, .clear).eraseToAnyColorable()
|
||||
SurfaceColorConfiguration(VDSColor.paletteWhite, VDSColor.paletteGray20).eraseToAnyColorable()
|
||||
}()
|
||||
var shadowColorConfiguration: AnyColorable = {
|
||||
SurfaceColorConfiguration(VDSColor.paletteBlack, .clear).eraseToAnyColorable()
|
||||
SurfaceColorConfiguration(VDSColor.paletteBlack, VDSColor.paletteBlack).eraseToAnyColorable()
|
||||
}()
|
||||
var shadowOpacity: CGFloat = 0.16
|
||||
var shadowOffset: CGSize = .init(width: 0, height: 2)
|
||||
var shadowRadius: CGFloat = 2
|
||||
var shadowRadius: CGFloat = 4
|
||||
}
|
||||
|
||||
private struct HighContrastConfiguration: Configuration {
|
||||
@ -225,33 +282,49 @@ open class ButtonIcon: Control {
|
||||
var backgroundColorConfiguration: AnyColorable = {
|
||||
return ControlColorConfiguration().with {
|
||||
$0.setSurfaceColors(VDSColor.backgroundPrimaryDark, VDSColor.backgroundPrimaryLight, forState: .normal)
|
||||
$0.setSurfaceColors(VDSColor.backgroundPrimaryDark, VDSColor.backgroundPrimaryLight, forState: .selected)
|
||||
$0.setSurfaceColors(VDSColor.interactiveActiveOnlight, VDSColor.interactiveActiveOndark, forState: .highlighted)
|
||||
$0.setSurfaceColors(VDSColor.interactiveDisabledOnlight, VDSColor.interactiveDisabledOndark, forState: .disabled)
|
||||
$0.setSurfaceColors(VDSColor.interactiveDisabledOnlight, VDSColor.interactiveDisabledOndark, forState: [.selected, .disabled])
|
||||
}.eraseToAnyColorable()
|
||||
|
||||
}()
|
||||
}
|
||||
|
||||
private struct HighContrastFloatingConfiguration: Configuration {
|
||||
private struct HighContrastFloatingConfiguration: Configuration, Dropshadowable {
|
||||
var kind: Kind = .highContrast
|
||||
var surfaceType: SurfaceType = .colorFill
|
||||
var floating: Bool = true
|
||||
var backgroundColorConfiguration: AnyColorable = {
|
||||
return ControlColorConfiguration().with {
|
||||
$0.setSurfaceColors(VDSColor.backgroundPrimaryLight, VDSColor.backgroundPrimaryLight, forState: .normal)
|
||||
$0.setSurfaceColors(VDSColor.paletteGray20, VDSColor.paletteWhite, forState: .normal)
|
||||
$0.setSurfaceColors(VDSColor.paletteGray20, VDSColor.paletteWhite, forState: .selected)
|
||||
$0.setSurfaceColors(VDSColor.interactiveActiveOnlight, VDSColor.interactiveActiveOndark, forState: .highlighted)
|
||||
$0.setSurfaceColors(VDSColor.interactiveDisabledOnlight, VDSColor.interactiveDisabledOndark, forState: .disabled)
|
||||
$0.setSurfaceColors(VDSColor.interactiveActiveOnlight, VDSColor.interactiveActiveOndark, forState: [.selected, .highlighted])
|
||||
$0.setSurfaceColors(VDSColor.interactiveDisabledOnlight, VDSColor.interactiveDisabledOndark, forState: [.selected, .disabled])
|
||||
}.eraseToAnyColorable()
|
||||
}()
|
||||
var shadowColorConfiguration: AnyColorable = {
|
||||
SurfaceColorConfiguration(VDSColor.paletteBlack, VDSColor.paletteBlack).eraseToAnyColorable()
|
||||
}()
|
||||
var shadowOpacity: CGFloat = 0.16
|
||||
var shadowOffset: CGSize = .init(width: 0, height: 2)
|
||||
var shadowRadius: CGFloat = 6
|
||||
}
|
||||
|
||||
|
||||
private var badgeIndicatorDefaultSize: CGSize = .zero
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Overrides
|
||||
//--------------------------------------------------
|
||||
/// Called once when a view is initialized and is used to Setup additional UI or other constants and configurations.
|
||||
open override func setup() {
|
||||
super.setup()
|
||||
|
||||
isAccessibilityElement = true
|
||||
accessibilityTraits = .image
|
||||
accessibilityElements = [badgeIndicator]
|
||||
|
||||
//create a layoutGuide for the icon to key off of
|
||||
let iconLayoutGuide = UILayoutGuide()
|
||||
addLayoutGuide(iconLayoutGuide)
|
||||
@ -259,10 +332,21 @@ open class ButtonIcon: Control {
|
||||
//add the icon
|
||||
addSubview(icon)
|
||||
|
||||
//add badgeIndicator
|
||||
addSubview(badgeIndicator)
|
||||
badgeIndicator.isHidden = !showBadgeIndicator
|
||||
badgeIndicatorDefaultSize = badgeIndicator.frame.size
|
||||
|
||||
//determines the height/width of the icon
|
||||
layoutGuideWidthConstraint = iconLayoutGuide.width(constant: size.containerSize)
|
||||
layoutGuideHeightConstraint = iconLayoutGuide.height(constant: size.containerSize)
|
||||
|
||||
badgeIndicatorLeadingConstraint = badgeIndicator.leadingAnchor.constraint(equalTo: icon.centerXAnchor)
|
||||
badgeIndicatorTrailingConstraint = badgeIndicator.trailingAnchor.constraint(equalTo: icon.centerXAnchor)
|
||||
badgeIndicatorCenterXConstraint = badgeIndicator.centerXAnchor.constraint(equalTo: icon.centerXAnchor)
|
||||
badgeIndicatorCenterYConstraint = icon.centerYAnchor.constraint(equalTo: badgeIndicator.centerYAnchor)
|
||||
badgeIndicatorCenterYConstraint?.isActive = true
|
||||
|
||||
badgeIndicatorLeadingConstraint?.isActive = true
|
||||
//pin layout guide
|
||||
iconLayoutGuide
|
||||
.pinTop()
|
||||
@ -277,6 +361,24 @@ open class ButtonIcon: Control {
|
||||
centerYConstraint?.activate()
|
||||
}
|
||||
|
||||
/// Executed on initialization for this View.
|
||||
open override func initialSetup() {
|
||||
super.initialSetup()
|
||||
onClick = { control in
|
||||
guard control.isEnabled else { return }
|
||||
if control.selectedIconName != nil && control.selectable {
|
||||
control.toggle()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// This will change the state of the Selector and execute the actionBlock if provided.
|
||||
open func toggle() {
|
||||
//removed error
|
||||
isSelected.toggle()
|
||||
sendActions(for: .valueChanged)
|
||||
}
|
||||
|
||||
/// Resets to default settings.
|
||||
open override func reset() {
|
||||
super.reset()
|
||||
@ -288,6 +390,10 @@ open class ButtonIcon: Control {
|
||||
hideBorder = true
|
||||
iconOffset = .init(x: 0, y: 0)
|
||||
iconName = nil
|
||||
selectedIconName = nil
|
||||
showBadgeIndicator = false
|
||||
selectable = false
|
||||
badgeIndicatorModel = nil
|
||||
shouldUpdateView = true
|
||||
setNeedsUpdate()
|
||||
}
|
||||
@ -306,6 +412,7 @@ open class ButtonIcon: Control {
|
||||
} else {
|
||||
icon.reset()
|
||||
}
|
||||
updateBadgeIndicator()
|
||||
setNeedsLayout()
|
||||
}
|
||||
|
||||
@ -338,7 +445,7 @@ open class ButtonIcon: Control {
|
||||
layoutGuideHeightConstraint?.constant = iconLayoutSize
|
||||
|
||||
//border
|
||||
if let borderable = currentConfig as? Borderable {
|
||||
if let borderable = currentConfig as? Borderable, hideBorder {
|
||||
layer.borderColor = borderable.borderColorConfiguration.getColor(self).cgColor
|
||||
layer.borderWidth = borderable.borderWidth
|
||||
} else {
|
||||
@ -351,10 +458,70 @@ open class ButtonIcon: Control {
|
||||
} else {
|
||||
removeDropShadow()
|
||||
}
|
||||
|
||||
badgeIndicatorCenterXConstraint?.constant = badgeIndicatorOffset.x + badgeIndicatorDefaultSize.width/2
|
||||
badgeIndicatorCenterYConstraint?.constant = badgeIndicatorOffset.y + badgeIndicatorDefaultSize.height/2
|
||||
badgeIndicatorLeadingConstraint?.constant = badgeIndicatorOffset.x
|
||||
badgeIndicatorTrailingConstraint?.constant = badgeIndicatorOffset.x + badgeIndicatorDefaultSize.width
|
||||
|
||||
if showBadgeIndicator {
|
||||
updateExpandDirectionalConstraints()
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Private Methods
|
||||
//--------------------------------------------------
|
||||
private func updateBadgeIndicator() {
|
||||
badgeIndicator.isHidden = !showBadgeIndicator
|
||||
|
||||
guard let badgeIndicatorModel else {
|
||||
badgeIndicator.isHidden = true
|
||||
return
|
||||
}
|
||||
|
||||
badgeIndicator.surface = surface
|
||||
badgeIndicator.kind = badgeIndicatorModel.kind
|
||||
badgeIndicator.fillColor = badgeIndicatorModel.fillColor
|
||||
badgeIndicator.size = badgeIndicatorModel.size
|
||||
badgeIndicator.maximumDigits = badgeIndicatorModel.maximumDigits
|
||||
badgeIndicator.width = badgeIndicatorModel.width
|
||||
badgeIndicator.height = badgeIndicatorModel.height
|
||||
badgeIndicator.number = badgeIndicatorModel.number
|
||||
badgeIndicator.leadingCharacter = badgeIndicatorModel.leadingCharacter
|
||||
badgeIndicator.trailingText = badgeIndicatorModel.trailingText
|
||||
badgeIndicator.dotSize = badgeIndicatorModel.dotSize
|
||||
badgeIndicator.verticalPadding = badgeIndicatorModel.verticalPadding
|
||||
badgeIndicator.horizontalPadding = badgeIndicatorModel.horizontalPadding
|
||||
badgeIndicator.hideDot = badgeIndicatorModel.hideDot
|
||||
badgeIndicator.hideBorder = badgeIndicatorModel.hideBorder
|
||||
}
|
||||
|
||||
private func updateExpandDirectionalConstraints() {
|
||||
guard let badgeIndicatorModel else { return }
|
||||
switch badgeIndicatorModel.expandDirection {
|
||||
case .right:
|
||||
badgeIndicatorLeadingConstraint?.isActive = true
|
||||
badgeIndicatorTrailingConstraint?.isActive = false
|
||||
badgeIndicatorCenterXConstraint?.isActive = false
|
||||
case .center:
|
||||
badgeIndicatorLeadingConstraint?.isActive = false
|
||||
badgeIndicatorTrailingConstraint?.isActive = false
|
||||
badgeIndicatorCenterXConstraint?.isActive = true
|
||||
case .left:
|
||||
badgeIndicatorLeadingConstraint?.isActive = false
|
||||
badgeIndicatorCenterXConstraint?.isActive = false
|
||||
badgeIndicatorTrailingConstraint?.isActive = true
|
||||
}
|
||||
}
|
||||
|
||||
/// Used to update any Accessibility properties.
|
||||
open override func updateAccessibility() {
|
||||
super.updateAccessibility()
|
||||
setAccessibilityLabel(for: [icon, badgeIndicator.label])
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// MARK: AppleGuidelinesTouchable
|
||||
extension ButtonIcon: AppleGuidelinesTouchable {
|
||||
/// Overrides to ensure that the touch point meets a minimum of the minimumTappableArea.
|
||||
|
||||
@ -0,0 +1,82 @@
|
||||
//
|
||||
// ButtonIconBadgeIndicatorModel.swift
|
||||
// VDS
|
||||
//
|
||||
// Created by Kanamarlapudi, Vasavi on 08/02/24.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
extension ButtonIcon {
|
||||
|
||||
//Model that represents the options available for the Badge Indicator
|
||||
public struct BadgeIndicatorModel {
|
||||
/// Enum used to describe the badge indicator direction of icon button determining the expand direction.
|
||||
public enum ExpandDirection: String, CaseIterable {
|
||||
case right, center, left
|
||||
}
|
||||
|
||||
/// Applies expand direction to Badge Indicator if shows badge indicator.
|
||||
public var expandDirection: ExpandDirection = .right
|
||||
|
||||
/// Kind that will be used for the badge indicator.
|
||||
public var kind: BadgeIndicator.Kind
|
||||
|
||||
/// Fill color that will be used for the badge indicator.
|
||||
public var fillColor: BadgeIndicator.FillColor
|
||||
|
||||
/// Size that will be used for the badge indicator.
|
||||
public var size: BadgeIndicator.Size
|
||||
|
||||
/// Number of digits that will be used for the badge indicator.
|
||||
public var maximumDigits: BadgeIndicator.MaximumDigits
|
||||
|
||||
/// Max width that will be used for the badge indicator.
|
||||
public var width: CGFloat?
|
||||
|
||||
/// Max height that will be used for the badge indicator.
|
||||
public var height: CGFloat?
|
||||
|
||||
/// Number that will be used for the badge indicator.
|
||||
public var number: Int?
|
||||
|
||||
/// Leading Character that will be used for the badge indicator.
|
||||
public var leadingCharacter: String?
|
||||
|
||||
/// Trailing Text height that will be used for the badge indicator.
|
||||
public var trailingText: String?
|
||||
|
||||
/// Dot Size that will be used for the badge indicator.
|
||||
public var dotSize: CGFloat?
|
||||
|
||||
/// Vertical Padding that will be used for the badge indicator.
|
||||
public var verticalPadding: CGFloat?
|
||||
|
||||
/// Horizontal Padding that will be used for the badge indicator.
|
||||
public var horizontalPadding: CGFloat?
|
||||
|
||||
/// Hide Dot that will be used for the badge indicator.
|
||||
public var hideDot: Bool = false
|
||||
|
||||
/// Hide Border that will be used for the badge indicator.
|
||||
public var hideBorder: Bool = false
|
||||
|
||||
public init(kind: BadgeIndicator.Kind = .simple, fillColor: BadgeIndicator.FillColor = .red, expandDirection: ExpandDirection = .right, size: BadgeIndicator.Size = .xxlarge, maximumDigits: BadgeIndicator.MaximumDigits = .two, width: CGFloat? = nil, height: CGFloat? = nil, number: Int? = nil, leadingCharacter: String = "", trailingText: String = "", dotSize: CGFloat? = nil, verticalPadding: CGFloat? = nil, horizontalPadding: CGFloat? = nil, hideDot: Bool = false, hideBorder: Bool = false) {
|
||||
self.kind = kind
|
||||
self.fillColor = fillColor
|
||||
self.expandDirection = expandDirection
|
||||
self.size = size
|
||||
self.maximumDigits = maximumDigits
|
||||
self.width = width
|
||||
self.height = height
|
||||
self.number = number
|
||||
self.leadingCharacter = leadingCharacter
|
||||
self.trailingText = trailingText
|
||||
self.dotSize = dotSize
|
||||
self.verticalPadding = verticalPadding
|
||||
self.horizontalPadding = horizontalPadding
|
||||
self.hideDot = hideDot
|
||||
self.hideBorder = hideBorder
|
||||
}
|
||||
}
|
||||
}
|
||||
79
VDS/Components/Icon/ButtonIcon/ButtonIconChangeLog.txt
Normal file
79
VDS/Components/Icon/ButtonIcon/ButtonIconChangeLog.txt
Normal file
@ -0,0 +1,79 @@
|
||||
|
||||
03/30/2023
|
||||
----------------
|
||||
- Dev handoff
|
||||
|
||||
04/06/2023
|
||||
----------------
|
||||
- Changed component name to Button Icon.
|
||||
|
||||
04/13/2023
|
||||
----------------
|
||||
- Dev handoff (additional states)
|
||||
|
||||
04/20/2023
|
||||
----------------
|
||||
- Added Selectable and Selected properties in Configuration.
|
||||
|
||||
05/01/2023
|
||||
----------------
|
||||
- Added fitToIcon prop for Ghost variation.
|
||||
|
||||
05/03/2023
|
||||
----------------
|
||||
- Updated drop shadows for light and dark floating buttons (all states)
|
||||
- Removed border from all floating buttons
|
||||
- Updated all dark floating button backgrounds to gray.20
|
||||
- Disabled icons on gray.20 changed to palette.black 70% opacity for floating buttons
|
||||
- Reduce Inside focusborderPosition to 1px
|
||||
|
||||
05/25/2023
|
||||
----------------
|
||||
- Added hideBorder prop back to Configurations
|
||||
- Added showBadgeIndicator prop to Configurations
|
||||
- Added Hit Area support for Button Icon with Badge Indicator
|
||||
- Added Elements page for Badge Indicator with default settings and offset information
|
||||
- Updated Badge Indicator Offset to be based on center of Icon container
|
||||
|
||||
05/30/2023
|
||||
----------------
|
||||
- Added expandDirection prop to Configurations under Badge Indicator section.
|
||||
|
||||
06/02/2023
|
||||
----------------
|
||||
- Added Additional Border Color specification if hideBorder=True on Low Contrast hover states.
|
||||
|
||||
06/12/2023
|
||||
----------------
|
||||
- Ghost Icon Cart position updated from {1,2} to {1,1}.
|
||||
|
||||
06/13/2023
|
||||
----------------
|
||||
- Updated Drop shadow properties layout in States.
|
||||
|
||||
06/29/2023
|
||||
----------------
|
||||
- Updated Badge Indicator simple dot size to 4px.
|
||||
|
||||
08/18/2023
|
||||
----------------
|
||||
- Updated default icon color for all selected Button Icon states to element.primary.onlight for light surfaces and element.primary.ondark for dark surfaces.
|
||||
- Added a dev note that this default color can be set to a custom color (like red).
|
||||
|
||||
11/16/2023
|
||||
----------------
|
||||
- Added component tokens
|
||||
- Applied component tokens throughout states
|
||||
- Applied semantic inverse to primary element, background states on light and dark surfaces
|
||||
|
||||
12/1/2023
|
||||
----------------
|
||||
- Reapplied component token updates to Ghost States
|
||||
|
||||
1/9/2024
|
||||
----------------
|
||||
- Fixed incorrect Low Contrast border token
|
||||
|
||||
1/25/2024
|
||||
----------------
|
||||
- Removed redundant opacity specs in States (dark surface).
|
||||
Loading…
Reference in New Issue
Block a user