Merge branch 'feature/buttonIcon' into 'develop'

initial cut for ButtonICon

See merge request BPHV_MIPS/vds_ios!69
This commit is contained in:
Bruce, Matt R 2023-05-17 14:31:39 +00:00
commit 4479bad76d
9 changed files with 541 additions and 132 deletions

View File

@ -47,6 +47,8 @@
EA5E30532950DDA60082B959 /* TitleLockup.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA5E30522950DDA60082B959 /* TitleLockup.swift */; };
EA5E3058295105A40082B959 /* Tilelet.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA5E3057295105A40082B959 /* Tilelet.swift */; };
EA5E305A29510F8B0082B959 /* EnumSubset.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA5E305929510F8B0082B959 /* EnumSubset.swift */; };
EA81410B2A0E8E3C004F60D2 /* ButtonIcon.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA81410A2A0E8E3C004F60D2 /* ButtonIcon.swift */; };
EA8141102A127066004F60D2 /* VDSColor.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA81410F2A127066004F60D2 /* VDSColor.swift */; };
EA89200428AECF4B006B9984 /* UITextField+Publisher.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA89200328AECF4B006B9984 /* UITextField+Publisher.swift */; };
EA89200628B526D6006B9984 /* CheckboxGroup.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA89200528B526D6006B9984 /* CheckboxGroup.swift */; };
EA89201328B568D8006B9984 /* RadioBox.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA89201228B568D8006B9984 /* RadioBox.swift */; };
@ -61,7 +63,6 @@
EA985BF22968B5BB00F2FF2E /* TitleLockupTextStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA985BF12968B5BB00F2FF2E /* TitleLockupTextStyle.swift */; };
EA985BF5296C60C000F2FF2E /* Icon.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA985BF4296C60C000F2FF2E /* Icon.swift */; };
EA985BF7296C665E00F2FF2E /* IconName.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA985BF6296C665E00F2FF2E /* IconName.swift */; };
EA985BF9296C710100F2FF2E /* IconColor.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA985BF8296C710100F2FF2E /* IconColor.swift */; };
EA985C1D296CD13600F2FF2E /* BundleManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA985C1C296CD13600F2FF2E /* BundleManager.swift */; };
EA985C23296E033A00F2FF2E /* TextArea.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA985C22296E033A00F2FF2E /* TextArea.swift */; };
EA985C2D296F03FE00F2FF2E /* TileletIconModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA985C2C296F03FE00F2FF2E /* TileletIconModels.swift */; };
@ -167,6 +168,8 @@
EA5E30522950DDA60082B959 /* TitleLockup.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TitleLockup.swift; sourceTree = "<group>"; };
EA5E3057295105A40082B959 /* Tilelet.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Tilelet.swift; sourceTree = "<group>"; };
EA5E305929510F8B0082B959 /* EnumSubset.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EnumSubset.swift; sourceTree = "<group>"; };
EA81410A2A0E8E3C004F60D2 /* ButtonIcon.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ButtonIcon.swift; sourceTree = "<group>"; };
EA81410F2A127066004F60D2 /* VDSColor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VDSColor.swift; sourceTree = "<group>"; };
EA89200328AECF4B006B9984 /* UITextField+Publisher.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UITextField+Publisher.swift"; sourceTree = "<group>"; };
EA89200528B526D6006B9984 /* CheckboxGroup.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CheckboxGroup.swift; sourceTree = "<group>"; };
EA89201228B568D8006B9984 /* RadioBox.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RadioBox.swift; sourceTree = "<group>"; };
@ -181,7 +184,6 @@
EA985BF12968B5BB00F2FF2E /* TitleLockupTextStyle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TitleLockupTextStyle.swift; sourceTree = "<group>"; };
EA985BF4296C60C000F2FF2E /* Icon.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Icon.swift; sourceTree = "<group>"; };
EA985BF6296C665E00F2FF2E /* IconName.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IconName.swift; sourceTree = "<group>"; };
EA985BF8296C710100F2FF2E /* IconColor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IconColor.swift; sourceTree = "<group>"; };
EA985C1C296CD13600F2FF2E /* BundleManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BundleManager.swift; sourceTree = "<group>"; };
EA985C22296E033A00F2FF2E /* TextArea.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextArea.swift; sourceTree = "<group>"; };
EA985C2C296F03FE00F2FF2E /* TileletIconModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TileletIconModels.swift; sourceTree = "<group>"; };
@ -412,6 +414,7 @@
EAB5FED329267EB300998C17 /* UIView.swift */,
EAB5FF0029424ACB00998C17 /* UIControl.swift */,
EA985C662970C21600F2FF2E /* VDSLayout.swift */,
EA81410F2A127066004F60D2 /* VDSColor.swift */,
);
path = Extensions;
sourceTree = "<group>";
@ -540,6 +543,14 @@
path = Tilelet;
sourceTree = "<group>";
};
EA81410C2A0E8E52004F60D2 /* ButtonIcon */ = {
isa = PBXGroup;
children = (
EA81410A2A0E8E3C004F60D2 /* ButtonIcon.swift */,
);
path = ButtonIcon;
sourceTree = "<group>";
};
EA89200B28B530F0006B9984 /* RadioBox */ = {
isa = PBXGroup;
children = (
@ -552,8 +563,8 @@
EA985BF3296C609E00F2FF2E /* Icon */ = {
isa = PBXGroup;
children = (
EA81410C2A0E8E52004F60D2 /* ButtonIcon */,
EA985BF4296C60C000F2FF2E /* Icon.swift */,
EA985BF8296C710100F2FF2E /* IconColor.swift */,
EA985BF6296C665E00F2FF2E /* IconName.swift */,
EA985C682971B90B00F2FF2E /* IconSize.swift */,
);
@ -810,6 +821,7 @@
EA4DB2FD28D3D0CA00103EE3 /* AnyEquatable.swift in Sources */,
EA5E305A29510F8B0082B959 /* EnumSubset.swift in Sources */,
EA985BF7296C665E00F2FF2E /* IconName.swift in Sources */,
EA8141102A127066004F60D2 /* VDSColor.swift in Sources */,
EAF7F0AF289B144C00B287F5 /* UnderlineLabelAttribute.swift in Sources */,
EAC925842911C63100091998 /* Colorable.swift in Sources */,
EAB5FEF5292D371F00998C17 /* ButtonBase.swift in Sources */,
@ -855,6 +867,7 @@
EA4DB18528CA967F00103EE3 /* SelectorGroupHandlerBase.swift in Sources */,
EAF7F0AB289B13FD00B287F5 /* TextStyleLabelAttribute.swift in Sources */,
EAB1D29C28A5618900DAE764 /* RadioButtonGroup.swift in Sources */,
EA81410B2A0E8E3C004F60D2 /* ButtonIcon.swift in Sources */,
EA985BE629688F6A00F2FF2E /* TileletBadgeModel.swift in Sources */,
EA336171288B19200071C351 /* VDS.docc in Sources */,
EA985BF02968A93600F2FF2E /* TitleLockupEyebrowModel.swift in Sources */,
@ -867,7 +880,6 @@
5F21D7BF28DCEB3D003E7CD6 /* Useable.swift in Sources */,
EAF7F0B7289C12A600B287F5 /* UITapGestureRecognizer.swift in Sources */,
EAB2376629E9952D00AABE9A /* UIApplication.swift in Sources */,
EA985BF9296C710100F2FF2E /* IconColor.swift in Sources */,
EAB5FED429267EB300998C17 /* UIView.swift in Sources */,
EAB2376829E9992800AABE9A /* TooltipAlertViewController.swift in Sources */,
EA33623E2892EE950071C351 /* UIDevice.swift in Sources */,

View File

@ -0,0 +1,380 @@
//
// ButtonIcon.swift
// VDS
//
// Created by Matt Bruce on 5/12/23.
//
import Foundation
import UIKit
import VDSColorTokens
@objc(VDSButtonIcon)
open class ButtonIcon: Control {
//--------------------------------------------------
// MARK: - Models
//--------------------------------------------------
//--------------------------------------------------
// MARK: - Enums
//--------------------------------------------------
public enum Kind: String, CaseIterable {
case ghost, lowContrast, highContrast
}
public enum SurfaceType: String, CaseIterable {
case colorFill, media
}
public enum Size: String, EnumSubset {
case large
case small
public var defaultValue: Icon.Size { .large }
public var containerSize: CGFloat {
switch self {
case .large:
return 44.0
case .small:
return 32.0
}
}
}
//--------------------------------------------------
// MARK: - Private Properties
//--------------------------------------------------
private var centerXConstraint: NSLayoutConstraint?
private var centerYConstraint: NSLayoutConstraint?
private var layoutGuideWidthConstraint: NSLayoutConstraint?
private var layoutGuideHeightConstraint: NSLayoutConstraint?
private var currentIconName: Icon.Name? {
if let selectedIconName {
return selectedIconName
} else {
return iconName
}
}
//--------------------------------------------------
// MARK: - Public Properties
//--------------------------------------------------
open var icon = Icon()
open var kind: Kind = .ghost { didSet { setNeedsUpdate() } }
open var surfaceType: SurfaceType = .colorFill { didSet { setNeedsUpdate() } }
open var iconName: Icon.Name? { didSet { setNeedsUpdate() } }
open var selectedIconName: Icon.Name? { didSet { setNeedsUpdate() } }
open var size: Size = .large { didSet { setNeedsUpdate() } }
open var customSize: Int? { didSet { setNeedsUpdate() }}
open var floating: Bool = false { didSet { setNeedsUpdate() } }
open var fitToIcon: Bool = false { didSet { setNeedsUpdate() } }
open var hideBorder: Bool = true { didSet { setNeedsUpdate() } }
open var iconOffset: CGPoint = .init(x: 0, y: 0) { didSet { setNeedsUpdate() } }
//--------------------------------------------------
// MARK: - Configuration
//--------------------------------------------------
private var iconColorConfig: AnyColorable {
if selectedIconName != nil {
return selectedIconColorConfig
} else {
if kind == .highContrast {
return highContrastIconColorConfig
} else {
return standardIconColorConfig
}
}
}
private var currentConfiguration: any Configuration {
switch kind {
case .ghost:
return GhostConfiguration()
case .lowContrast:
if surfaceType == .colorFill {
return floating ? LowContrastColorFillFloatingConfiguration() : LowContrastColorFillConfiguration()
} else {
return floating ? LowContrastMediaFloatingConfiguration() : LowContrastMediaConfiguration()
}
case .highContrast:
return floating ? HighContrastFloatingConfiguration() : HighContrastConfiguration()
}
}
private var standardIconColorConfig: 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.interactiveDisabledOndark, forState: .disabled)
}.eraseToAnyColorable()
}()
private var highContrastIconColorConfig: AnyColorable = {
return SurfaceColorConfiguration(VDSColor.elementsPrimaryOndark, VDSColor.elementsPrimaryOnlight).eraseToAnyColorable()
}()
private var selectedIconColorConfig: 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
var floating: Bool = false
var backgroundColorConfig: AnyColorable = {
SurfaceColorConfiguration(.clear, .clear).eraseToAnyColorable()
}()
}
private struct LowContrastColorFillConfiguration: Configuration {
var kind: Kind = .lowContrast
var surfaceType: SurfaceType = .colorFill
var floating: Bool = false
var backgroundColorConfig: AnyColorable = {
SurfaceColorConfiguration(VDSColor.paletteGray44.withAlphaComponent(0.06), VDSColor.paletteGray44.withAlphaComponent(0.26)).eraseToAnyColorable()
}()
}
private struct LowContrastColorFillFloatingConfiguration: Configuration {
var kind: Kind = .lowContrast
var surfaceType: SurfaceType = .colorFill
var floating: Bool = true
var backgroundColorConfig: AnyColorable = {
SurfaceColorConfiguration(VDSColor.backgroundPrimaryLight, .clear).eraseToAnyColorable()
}()
}
private struct LowContrastMediaConfiguration: Configuration, Borderable {
var kind: Kind = .lowContrast
var surfaceType: SurfaceType = .media
var floating: Bool = false
var backgroundColorConfig: AnyColorable = {
SurfaceColorConfiguration(VDSColor.backgroundPrimaryLight, .clear).eraseToAnyColorable()
}()
var borderWidth: CGFloat = 1.0
var borderColorConfig: AnyColorable = {
SurfaceColorConfiguration(VDSColor.elementsLowcontrastOnlight, .clear).eraseToAnyColorable()
}()
}
private struct LowContrastMediaFloatingConfiguration: Configuration, Dropshadowable {
var kind: Kind = .lowContrast
var surfaceType: SurfaceType = .media
var floating: Bool = true
var backgroundColorConfig: AnyColorable = {
SurfaceColorConfiguration(VDSColor.backgroundPrimaryLight, .clear).eraseToAnyColorable()
}()
var shadowColorConfig: AnyColorable = {
SurfaceColorConfiguration(VDSColor.backgroundPrimaryLight, .clear).eraseToAnyColorable()
}()
var shadowOpacity: CGFloat = 0.5
var shadowOffset: CGSize = .init(width: 1, height: 1)
var shadowRadius: CGFloat = 2
}
private struct HighContrastConfiguration: Configuration {
var kind: Kind = .highContrast
var surfaceType: SurfaceType = .colorFill
var floating: Bool = false
var backgroundColorConfig: AnyColorable = {
return ControlColorConfiguration().with {
$0.setSurfaceColors(VDSColor.backgroundPrimaryDark, VDSColor.backgroundPrimaryLight, forState: .normal)
$0.setSurfaceColors(VDSColor.interactiveActiveOnlight, VDSColor.interactiveActiveOndark, forState: .highlighted)
$0.setSurfaceColors(VDSColor.interactiveDisabledOnlight, VDSColor.interactiveDisabledOndark, forState: .disabled)
}.eraseToAnyColorable()
}()
}
private struct HighContrastFloatingConfiguration: Configuration {
var kind: Kind = .highContrast
var surfaceType: SurfaceType = .colorFill
var floating: Bool = true
var backgroundColorConfig: AnyColorable = {
return ControlColorConfiguration().with {
$0.setSurfaceColors(VDSColor.backgroundPrimaryLight, VDSColor.backgroundPrimaryLight, forState: .normal)
$0.setSurfaceColors(VDSColor.interactiveActiveOnlight, VDSColor.interactiveActiveOndark, forState: .highlighted)
$0.setSurfaceColors(VDSColor.interactiveDisabledOnlight, VDSColor.interactiveDisabledOndark, forState: .disabled)
}.eraseToAnyColorable()
}()
}
//--------------------------------------------------
// MARK: - Initializers
//--------------------------------------------------
required public init() {
super.init(frame: .zero)
}
public override init(frame: CGRect) {
super.init(frame: .zero)
}
public required init?(coder: NSCoder) {
super.init(coder: coder)
}
//--------------------------------------------------
// MARK: - Lifecycle
//--------------------------------------------------
open override func setup() {
super.setup()
//create a layoutGuide for the icon to key off of
let iconLayoutGuide = UILayoutGuide()
addLayoutGuide(iconLayoutGuide)
//add the icon
addSubview(icon)
//determines the height/width of the icon
layoutGuideWidthConstraint = iconLayoutGuide.widthAnchor.constraint(equalToConstant: size.containerSize)
layoutGuideHeightConstraint = iconLayoutGuide.heightAnchor.constraint(equalToConstant: size.containerSize)
//determines the center point of the icon
centerXConstraint = icon.centerXAnchor.constraint(equalTo: iconLayoutGuide.centerXAnchor, constant: 0)
centerYConstraint = icon.centerYAnchor.constraint(equalTo: iconLayoutGuide.centerYAnchor, constant: 0)
//activate the constraints
NSLayoutConstraint.activate([layoutGuideWidthConstraint!,
layoutGuideHeightConstraint!,
centerXConstraint!,
centerYConstraint!,
iconLayoutGuide.topAnchor.constraint(equalTo: topAnchor),
iconLayoutGuide.bottomAnchor.constraint(equalTo: bottomAnchor),
iconLayoutGuide.leadingAnchor.constraint(equalTo: leadingAnchor),
iconLayoutGuide.trailingAnchor.constraint(equalTo: trailingAnchor)])
}
open override func reset() {
super.reset()
shouldUpdateView = false
kind = .ghost
surfaceType = .colorFill
size = .large
floating = false
hideBorder = true
iconOffset = .init(x: 0, y: 0)
iconName = nil
shouldUpdateView = true
setNeedsUpdate()
}
open override func updateView() {
super.updateView()
//ensure there is an icon to set
if let currentIconName {
icon.name = currentIconName
let color = iconColorConfig.getColor(self)
icon.color = color
icon.size = size.value
icon.customSize = customSize
} else {
icon.reset()
}
setNeedsLayout()
}
open override func layoutSubviews() {
super.layoutSubviews()
let currentConfig = currentConfiguration
backgroundColor = currentConfig.backgroundColorConfig.getColor(self)
// calculate center point for child view with offset
let childCenter = CGPoint(x: center.x + iconOffset.x, y: center.y + iconOffset.y)
centerXConstraint?.constant = childCenter.x - center.x
centerYConstraint?.constant = childCenter.y - center.y
//updating current container size
var iconLayoutSize = size.containerSize
if let customSize {
iconLayoutSize = CGFloat(customSize)
}
// check to see if this is fitToIcon
if fitToIcon && kind == .ghost {
iconLayoutSize = size.value.dimensions.width
layer.cornerRadius = 0
} else {
layer.cornerRadius = min(frame.width, frame.height) / 2.0
}
layoutGuideWidthConstraint?.constant = iconLayoutSize
layoutGuideHeightConstraint?.constant = iconLayoutSize
//border
if let borderable = currentConfig as? Borderable {
layer.borderColor = borderable.borderColorConfig.getColor(self).cgColor
layer.borderWidth = borderable.borderWidth
icon.layer.borderWidth = borderable.borderWidth
} else {
layer.borderColor = nil
layer.borderWidth = 0
icon.layer.borderWidth = 0
}
if let dropshadowable = currentConfig as? Dropshadowable {
layer.masksToBounds = false
layer.shadowColor = dropshadowable.shadowColorConfig.getColor(self).cgColor
layer.shadowOpacity = Float(dropshadowable.shadowOpacity)
layer.shadowOffset = dropshadowable.shadowOffset
layer.shadowRadius = dropshadowable.shadowRadius
layer.shadowPath = UIBezierPath(rect: bounds).cgPath
layer.shouldRasterize = true
layer.rasterizationScale = UIScreen.main.scale
} else {
layer.shadowOpacity = 0
layer.shadowRadius = 0
layer.shadowPath = nil
}
}
}
// MARK: AppleGuidlinesTouchable
extension ButtonIcon: AppleGuidlinesTouchable {
override open func point(inside point: CGPoint, with event: UIEvent?) -> Bool {
Self.acceptablyOutsideBounds(point: point, bounds: bounds)
}
open override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
let view = super.hitTest(point, with: event)
if view == icon {
return self
}
return view
}
}
private protocol Borderable {
var borderWidth: CGFloat { get set }
var borderColorConfig: AnyColorable { get set }
}
private protocol Dropshadowable {
var shadowColorConfig: AnyColorable { get set }
var shadowOpacity: CGFloat { get set }
var shadowOffset: CGSize { get set }
var shadowRadius: CGFloat { get set }
}
private protocol Configuration {
var kind: ButtonIcon.Kind { get set }
var surfaceType: ButtonIcon.SurfaceType { get set }
var floating: Bool { get set }
var backgroundColorConfig: AnyColorable { get set }
}

View File

@ -28,7 +28,14 @@ open class Icon: View {
$0.clipsToBounds = true
}
open var color: Color = .black { didSet { setNeedsUpdate() }}
open var color: UIColor = VDSColor.paletteBlack {
didSet {
if let hex = color.hexString, !UIColor.isVDSColor(color: color) {
print("icon.color is not a VDSColor. Hex: \(hex) is not a supported color")
}
setNeedsUpdate()
}
}
open var size: Size = .medium { didSet { setNeedsUpdate() }}
open var name: Name? { didSet { setNeedsUpdate() }}
open var customSize: Int? { didSet { setNeedsUpdate() }}
@ -57,7 +64,7 @@ open class Icon: View {
open override func reset() {
super.reset()
color = .black
color = VDSColor.paletteBlack
imageView.image = nil
}
@ -67,12 +74,12 @@ open class Icon: View {
open override func updateView() {
super.updateView()
//get the color for the image
var imageColor = color.value
var imageColor = color
//ensure the correct color for white/black colors
if surface == .dark && color == Color.black {
if surface == .dark && color == VDSColor.paletteBlack {
imageColor = VDSColor.elementsPrimaryOndark
} else if surface == .light && color == Color.black {
} else if surface == .light && color == VDSColor.paletteBlack {
imageColor = VDSColor.elementsPrimaryOnlight
}

View File

@ -1,115 +0,0 @@
//
// IconColor.swift
// VDS
//
// Created by Matt Bruce on 1/9/23.
//
import Foundation
import VDSColorTokens
import UIKit
extension Icon {
public enum Color: String, CaseIterable {
case black
case white
case red
case gray95
case gray85
case gray65
case gray44
case gray20
case gray11
case orange94
case orange83
case orange71
case orange58
case orange41
case orange24
case orange17
case yellow94
case yellow87
case yellow74
case yellow53
case yellow39
case yellow20
case yellow15
case blue94
case blue82
case blue62
case blue46
case blue38
case blue21
case blue15
case green91
case green77
case green61
case green36
case green26
case green15
case green10
case pink87
case pink76
case pink62
case pink46
case pink25
case purple85
case purple75
case purple60
case purple39
case purple20
// Map each color name to its corresponding UIColor object.
public var value: UIColor {
switch self {
case .black: return VDSColor.paletteBlack
case .white: return VDSColor.paletteWhite
case .red: return VDSColor.paletteRed
case .gray95: return VDSColor.paletteGray95
case .gray85: return VDSColor.paletteGray85
case .gray65: return VDSColor.paletteGray65
case .gray44: return VDSColor.paletteGray44
case .gray20: return VDSColor.paletteGray20
case .gray11: return VDSColor.paletteGray11
case .orange94: return VDSColor.paletteOrange94
case .orange83: return VDSColor.paletteOrange83
case .orange71: return VDSColor.paletteOrange71
case .orange58: return VDSColor.paletteOrange58
case .orange41: return VDSColor.paletteOrange41
case .orange24: return VDSColor.paletteOrange24
case .orange17: return VDSColor.paletteOrange17
case .yellow94: return VDSColor.paletteYellow94
case .yellow87: return VDSColor.paletteYellow87
case .yellow74: return VDSColor.paletteYellow74
case .yellow53: return VDSColor.paletteYellow53
case .yellow39: return VDSColor.paletteYellow39
case .yellow20: return VDSColor.paletteYellow20
case .yellow15: return VDSColor.paletteYellow15
case .blue94: return VDSColor.paletteBlue94
case .blue82: return VDSColor.paletteBlue82
case .blue62: return VDSColor.paletteBlue62
case .blue46: return VDSColor.paletteBlue46
case .blue38: return VDSColor.paletteBlue38
case .blue21: return VDSColor.paletteBlue21
case .blue15: return VDSColor.paletteBlue15
case .green91: return VDSColor.paletteGreen91
case .green77: return VDSColor.paletteGreen77
case .green61: return VDSColor.paletteGreen61
case .green36: return VDSColor.paletteGreen36
case .green26: return VDSColor.paletteGreen26
case .green15: return VDSColor.paletteGreen15
case .green10: return VDSColor.paletteGreen10
case .pink87: return VDSColor.palettePink87
case .pink76: return VDSColor.palettePink76
case .pink62: return VDSColor.palettePink62
case .pink46: return VDSColor.palettePink46
case .pink25: return VDSColor.palettePink25
case .purple85: return VDSColor.palettePurple85
case .purple75: return VDSColor.palettePurple75
case .purple60: return VDSColor.palettePurple60
case .purple39: return VDSColor.palettePurple39
case .purple20: return VDSColor.palettePurple20
}
}
}
}

View File

@ -274,7 +274,7 @@ open class Notification: View {
}
private func updateIcons() {
let iconColor = surface == .dark ? Icon.Color.white : Icon.Color.black
let iconColor = surface == .dark ? VDSColor.paletteWhite : VDSColor.paletteBlack
typeIcon.name = type.styleIconName()
typeIcon.color = iconColor
closeButton.color = iconColor

View File

@ -311,7 +311,7 @@ open class EntryField: Control, Changeable {
errorLabel.disabled = disabled
errorLabel.isHidden = false
icon.name = .error
icon.color = .black
icon.color = VDSColor.paletteBlack
icon.surface = surface
icon.isHidden = disabled
} else {

View File

@ -177,7 +177,7 @@ open class InputField: EntryField, UITextFieldDelegate {
successLabel.isHidden = false
errorLabel.isHidden = true
icon.name = .checkmarkAlt
icon.color = .black
icon.color = VDSColor.paletteBlack
icon.surface = surface
icon.isHidden = disabled
} else {

View File

@ -121,11 +121,7 @@ extension UIView {
extension UIView {
internal func removeDebugBorder() {
layer.sublayers?.forEach({ layer in
if layer.name?.hasPrefix("debug") ?? false {
layer.removeFromSuperlayer()
}
})
layer.remove(layerName: "debug")
}
internal func addDebugBorder(color: UIColor = .red) {
@ -177,3 +173,13 @@ extension UIView {
}
}
}
extension CALayer {
func remove(layerName: String) {
sublayers?.forEach({ layer in
if layer.name?.hasPrefix(layerName) ?? false {
layer.removeFromSuperlayer()
}
})
}
}

View File

@ -0,0 +1,119 @@
//
// VDSColor.swift
// VDS
//
// Created by Matt Bruce on 5/15/23.
//
import Foundation
import VDSColorTokens
extension VDSColor {
public enum Color: String, CaseIterable {
case paletteBlack
case paletteWhite
case paletteRed
case paletteGray95
case paletteGray85
case paletteGray65
case paletteGray44
case paletteGray20
case paletteGray11
case paletteOrange94
case paletteOrange83
case paletteOrange71
case paletteOrange58
case paletteOrange41
case paletteOrange24
case paletteOrange17
case paletteYellow94
case paletteYellow87
case paletteYellow74
case paletteYellow53
case paletteYellow39
case paletteYellow20
case paletteYellow15
case paletteBlue94
case paletteBlue82
case paletteBlue62
case paletteBlue46
case paletteBlue38
case paletteBlue21
case paletteBlue15
case paletteGreen91
case paletteGreen77
case paletteGreen61
case paletteGreen36
case paletteGreen26
case paletteGreen15
case paletteGreen10
case palettePink87
case palettePink76
case palettePink62
case palettePink46
case palettePink25
case palettePurple85
case palettePurple75
case palettePurple60
case palettePurple39
case palettePurple20
case backgroundPrimaryLight
case backgroundPrimaryDark
case backgroundSecondaryLight
case backgroundSecondaryDark
case backgroundBrandhighlight
case feedbackErrorOnlight
case feedbackErrorOndark
case feedbackErrorBackgroundOnlight
case feedbackErrorBackgroundOndark
case feedbackWarningOnlight
case feedbackWarningOndark
case feedbackWarningBackgroundOnlight
case feedbackWarningBackgroundOndark
case feedbackInformationOnlight
case feedbackInformationOndark
case feedbackInformationBackgroundOnlight
case feedbackInformationBackgroundOndark
case feedbackSuccessOnlight
case feedbackSuccessOndark
case feedbackSuccessBackgroundOnlight
case feedbackSuccessBackgroundOndark
case interactiveActiveOnlight
case interactiveActiveOndark
case interactiveDisabledOnlight
case interactiveDisabledOndark
case interactiveScrollthumbOnlight
case interactiveScrollthumbOndark
case interactiveScrollthumbHoverOnlight
case interactiveScrollthumbHoverOndark
case interactiveScrolltrackOnlight
case interactiveScrolltrackOndark
case elementsPrimaryOnlight
case elementsPrimaryOndark
case elementsSecondaryOnlight
case elementsSecondaryOndark
case elementsBrandhighlight
case elementsLowcontrastOnlight
case elementsLowcontrastOndark
// Map each color name to its corresponding UIColor object.
public var uiColor: UIColor {
do {
let color = try VDSColor.getTokenByString(tokenName: "VDSColor.\(rawValue)")
return color
} catch {
print(error)
return VDSColor.paletteBlack
}
}
}
}
extension UIColor {
public static func isVDSColor(color: UIColor) -> Bool {
guard let hex = color.hexString else { return false }
let found = VDSColor.Color.allCases.first{ $0.uiColor.hexString == hex }
guard let _ = found else { return false}
return true
}
}