Merge branch 'develop' of https://gitlab.verizon.com/BPHV_MIPS/vds_ios.git into feature/atomic_vds_titleLockup

This commit is contained in:
Matt Bruce 2024-02-21 15:13:10 -06:00
commit e381f47dfd
5 changed files with 258 additions and 51 deletions

View File

@ -14,6 +14,8 @@
44604AD729CE196600E62B51 /* Line.swift in Sources */ = {isa = PBXBuildFile; fileRef = 44604AD629CE196600E62B51 /* Line.swift */; };
5F21D7BF28DCEB3D003E7CD6 /* Useable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F21D7BE28DCEB3D003E7CD6 /* Useable.swift */; };
5FC35BE328D51405004EBEAC /* Button.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5FC35BE228D51405004EBEAC /* Button.swift */; };
7115BD3C2B84C0C200E0A610 /* TileContainerChangeLog.txt in Resources */ = {isa = PBXBuildFile; fileRef = 7115BD3B2B84C0C200E0A610 /* TileContainerChangeLog.txt */; };
71BFA70A2B7F70E6000DCE33 /* Dropshadowable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 71BFA7092B7F70E6000DCE33 /* Dropshadowable.swift */; };
71C02B382B7BD98F00E93E66 /* NotificationChangeLog.txt in Resources */ = {isa = PBXBuildFile; fileRef = 71C02B372B7BD98F00E93E66 /* NotificationChangeLog.txt */; };
EA0B18022A9E236900F2D0CD /* SelectorGroupBase.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA0B18012A9E236900F2D0CD /* SelectorGroupBase.swift */; };
EA0B18052A9E2D2D00F2D0CD /* SelectorBase.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA0B18032A9E2D2D00F2D0CD /* SelectorBase.swift */; };
@ -178,6 +180,8 @@
44604AD629CE196600E62B51 /* Line.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Line.swift; sourceTree = "<group>"; };
5F21D7BE28DCEB3D003E7CD6 /* Useable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Useable.swift; sourceTree = "<group>"; };
5FC35BE228D51405004EBEAC /* Button.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Button.swift; sourceTree = "<group>"; };
7115BD3B2B84C0C200E0A610 /* TileContainerChangeLog.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = TileContainerChangeLog.txt; sourceTree = "<group>"; };
71BFA7092B7F70E6000DCE33 /* Dropshadowable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Dropshadowable.swift; sourceTree = "<group>"; };
71C02B372B7BD98F00E93E66 /* NotificationChangeLog.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = NotificationChangeLog.txt; sourceTree = "<group>"; };
EA0B18012A9E236900F2D0CD /* SelectorGroupBase.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SelectorGroupBase.swift; sourceTree = "<group>"; };
EA0B18032A9E2D2D00F2D0CD /* SelectorBase.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SelectorBase.swift; sourceTree = "<group>"; };
@ -556,6 +560,7 @@
EA3361B7288B2AAA0071C351 /* ViewProtocol.swift */,
EAB1D2CC28ABE76000DAE764 /* Withable.swift */,
5F21D7BE28DCEB3D003E7CD6 /* Useable.swift */,
71BFA7092B7F70E6000DCE33 /* Dropshadowable.swift */,
);
path = Protocols;
sourceTree = "<group>";
@ -644,6 +649,7 @@
isa = PBXGroup;
children = (
EA5E304B294CBDD00082B959 /* TileContainer.swift */,
7115BD3B2B84C0C200E0A610 /* TileContainerChangeLog.txt */,
);
path = TileContainer;
sourceTree = "<group>";
@ -936,6 +942,7 @@
buildActionMask = 2147483647;
files = (
EAEEECA42B1F934600531FC2 /* IconChangeLog.txt in Resources */,
7115BD3C2B84C0C200E0A610 /* TileContainerChangeLog.txt in Resources */,
EA3362042891E14D0071C351 /* VerizonNHGeTX-Bold.otf in Resources */,
71C02B382B7BD98F00E93E66 /* NotificationChangeLog.txt in Resources */,
EAEEECA72B1F952000531FC2 /* TabsChangeLog.txt in Resources */,
@ -992,6 +999,7 @@
EAB2376229E9880400AABE9A /* TrailingTooltipLabel.swift in Sources */,
EAB2376A29E9E59100AABE9A /* TooltipLaunchable.swift in Sources */,
EAB2375D29E8789100AABE9A /* Tooltip.swift in Sources */,
71BFA70A2B7F70E6000DCE33 /* Dropshadowable.swift in Sources */,
EA0D1C452A6AD73000E5C127 /* RawRepresentable.swift in Sources */,
EA985C23296E033A00F2FF2E /* TextArea.swift in Sources */,
EAF7F0B3289B1ADC00B287F5 /* ActionLabelAttribute.swift in Sources */,

View File

@ -454,9 +454,9 @@ open class ButtonIcon: Control, Changeable, FormFieldable {
}
if let dropshadowable = currentConfig as? Dropshadowable {
addDropShadow(config: dropshadowable)
addDropShadow(dropshadowable)
} else {
removeDropShadow()
removeDropShadows()
}
badgeIndicatorCenterXConstraint?.constant = badgeIndicatorOffset.x + badgeIndicatorDefaultSize.width/2
@ -530,37 +530,11 @@ extension ButtonIcon: AppleGuidelinesTouchable {
}
}
extension UIView {
fileprivate func addDropShadow(config: Dropshadowable) {
layer.masksToBounds = false
layer.shadowColor = config.shadowColorConfiguration.getColor(self).cgColor
layer.shadowOpacity = Float(config.shadowOpacity)
layer.shadowOffset = config.shadowOffset
layer.shadowRadius = config.shadowRadius
layer.shouldRasterize = true
layer.rasterizationScale = UIScreen.main.scale
layer.shadowPath = UIBezierPath(roundedRect: bounds, cornerRadius: layer.cornerRadius).cgPath
}
fileprivate func removeDropShadow() {
layer.shadowOpacity = 0
layer.shadowRadius = 0
layer.shadowPath = nil
}
}
private protocol Borderable {
var borderWidth: CGFloat { get set }
var borderColorConfiguration: AnyColorable { get set }
}
private protocol Dropshadowable {
var shadowColorConfiguration: 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 }

View File

@ -32,20 +32,36 @@ open class TileContainer: Control {
// MARK: - Enums
//--------------------------------------------------
/// Enum used to describe the background color choices used for this component.
public enum BackgroundColor: String, CaseIterable {
public enum BackgroundColor: Equatable {
case primary
case secondary
case white
case black
case gray
case transparent
case custom(String)
private var reflectedValue: String { String(reflecting: self) }
public static func == (lhs: Self, rhs: Self) -> Bool {
lhs.reflectedValue == rhs.reflectedValue
}
}
/// Enum used to describe the background effect choices used for this component.
public enum BackgroundEffect {
case transparency
case gradient(String, String)
case none
}
/// Enum used to describe the padding choices used for this component.
public enum Padding: String, CaseIterable {
public enum Padding {
case padding2X
case padding4X
case padding6X
case padding8X
case padding12X
case custom(CGFloat)
public var value: CGFloat {
switch self {
@ -59,6 +75,8 @@ open class TileContainer: Control {
return VDSLayout.Spacing.space8X.value
case .padding12X:
return VDSLayout.Spacing.space12X.value
case .custom(let padding):
return padding
}
}
}
@ -106,8 +124,11 @@ open class TileContainer: Control {
open var aspectRatio: AspectRatio = .ratio1x1 { didSet { setNeedsUpdate() } }
/// Sets the background color for the component.
open var color: BackgroundColor = .white { didSet { setNeedsUpdate() } }
open var color: BackgroundColor = .secondary { didSet { setNeedsUpdate() } }
/// Sets the background effect for the component.
open var backgroundEffect: BackgroundEffect = .none { didSet { setNeedsUpdate() } }
/// Sets the inside padding for the component
open var padding: Padding = .padding4X { didSet { setNeedsUpdate() } }
@ -165,6 +186,7 @@ open class TileContainer: Control {
private let cornerRadius = VDSFormControls.borderradius * 2
private var backgroundColorConfiguration = BackgroundColorConfiguration()
private var dropshadowConfiguration = DropshadowConfiguration()
private var borderColorConfiguration = SurfaceColorConfiguration().with {
$0.lightColor = VDSColor.elementsLowcontrastOnlight
@ -201,24 +223,20 @@ open class TileContainer: Control {
addSubview(highlightView)
widthConstraint = layoutGuide.widthAnchor.constraint(equalToConstant: 0)
widthConstraint?.priority = .defaultHigh
heightGreaterThanConstraint = layoutGuide.heightAnchor.constraint(greaterThanOrEqualToConstant: 44.0)
heightGreaterThanConstraint?.isActive = false
heightConstraint = layoutGuide.heightAnchor.constraint(equalToConstant: 0)
heightConstraint?.priority = .defaultHigh
backgroundImageView.pin(layoutGuide)
backgroundImageView.isUserInteractionEnabled = false
backgroundImageView.isHidden = true
containerView.backgroundColor = .clear
containerTopConstraint = containerView.pinTop(anchor: layoutGuide.topAnchor, constant: padding.value)
containerBottomConstraint = containerView.pinBottom(anchor: layoutGuide.bottomAnchor, constant: padding.value)
containerBottomConstraint = layoutGuide.pinBottom(anchor: containerView.bottomAnchor, constant: padding.value)
containerLeadingConstraint = containerView.pinLeading(anchor: layoutGuide.leadingAnchor, constant: padding.value)
containerTrailingConstraint = containerView.pinTrailing(anchor: layoutGuide.trailingAnchor, constant: padding.value)
containerTrailingConstraint = layoutGuide.pinTrailing(anchor: containerView.trailingAnchor, constant: padding.value)
highlightView.pin(layoutGuide)
highlightView.isHidden = true
@ -228,7 +246,6 @@ open class TileContainer: Control {
layer.cornerRadius = cornerRadius
backgroundImageView.layer.cornerRadius = cornerRadius
highlightView.layer.cornerRadius = cornerRadius
}
/// Resets to default settings.
@ -268,8 +285,8 @@ open class TileContainer: Control {
containerTopConstraint?.constant = padding.value
containerLeadingConstraint?.constant = padding.value
containerBottomConstraint?.constant = -padding.value
containerTrailingConstraint?.constant = -padding.value
containerBottomConstraint?.constant = padding.value
containerTrailingConstraint?.constant = padding.value
if let width, aspectRatio == .none && height == nil{
widthConstraint?.constant = width
@ -293,6 +310,12 @@ open class TileContainer: Control {
widthConstraint?.isActive = false
heightConstraint?.isActive = false
}
if showDropShadows, surface == .light {
addDropShadow(dropshadowConfiguration)
} else {
removeDropShadows()
}
applyBackgroundEffects()
}
//--------------------------------------------------
@ -310,6 +333,36 @@ open class TileContainer: Control {
//--------------------------------------------------
// MARK: - Private Methods
//--------------------------------------------------
private func applyBackgroundEffects() {
let color = backgroundColorConfiguration.getColor(self)
var alphaConfiguration: CGFloat = 1.0
let imageFallbackColor = imageFallbackColorConfiguration.getColor(self)
switch backgroundEffect {
case .transparency:
alphaConfiguration = 0.8
removeGradientLayer()
case .gradient(let firstColor, let secondColor):
alphaConfiguration = 1.0
addGradientLayer(with: UIColor(hexString: firstColor), secondColor: UIColor(hexString: secondColor))
backgroundImageView.isHidden = true
backgroundImageView.alpha = 1.0
case .none:
alphaConfiguration = 1.0
removeGradientLayer()
}
if let backgroundImage {
backgroundImageView.image = backgroundImage
backgroundImageView.isHidden = false
backgroundImageView.alpha = alphaConfiguration
backgroundColor = imageFallbackColor.withAlphaComponent(alphaConfiguration)
} else {
backgroundImageView.isHidden = true
backgroundImageView.alpha = 1.0
backgroundColor = color.withAlphaComponent(alphaConfiguration)
}
}
private func ratioSize(for width: CGFloat) -> CGSize {
var height: CGFloat = width
@ -343,22 +396,40 @@ open class TileContainer: Control {
}
extension TileContainer {
class BackgroundColorConfiguration: ObjectColorable {
struct DropshadowConfiguration: Dropshadowable {
var shadowColorConfiguration: AnyColorable = SurfaceColorConfiguration().with {
$0.lightColor = VDSColor.elementsPrimaryOnlight
}.eraseToAnyColorable()
var shadowOpacity: CGFloat = 0.01
var shadowOffset: CGSize = .init(width: 0, height: 6)
var shadowRadius: CGFloat = 3
}
final class BackgroundColorConfiguration: ObjectColorable {
typealias ObjectType = TileContainer
let primaryColorConfig = SurfaceColorConfiguration(VDSColor.backgroundPrimaryLight, VDSColor.backgroundPrimaryDark)
let secondaryColorConfig = SurfaceColorConfiguration(VDSColor.backgroundSecondaryLight, VDSColor.backgroundSecondaryDark)
let grayColorConfig = SurfaceColorConfiguration(VDSColor.backgroundSecondaryLight, VDSColor.backgroundSecondaryDark)
let whiteColorConfig = SurfaceColorConfiguration(VDSColor.paletteWhite, VDSColor.paletteWhite)
let blackColorConfig = SurfaceColorConfiguration(VDSColor.paletteBlack, VDSColor.paletteBlack)
required init() { }
func getColor(_ object: TileContainer) -> UIColor {
switch object.color {
case .primary:
primaryColorConfig.getColor(object.surface)
case .secondary:
secondaryColorConfig.getColor(object.surface)
case .white:
return VDSColor.backgroundPrimaryLight
whiteColorConfig.getColor(object.surface)
case .black:
return VDSColor.backgroundPrimaryDark
case .gray:
return VDSColor.backgroundSecondaryLight
case .transparent:
return UIColor.clear
blackColorConfig.getColor(object.surface)
case .custom(let hexCode):
UIColor(hexString: hexCode)
}
}
}

View File

@ -0,0 +1,90 @@
MM/DD/YYYY
----------------
02/01/2022
----------------
- ACTION | Migrated Spec file from working file into VDS Brand 3.0 Core SPECs & Test App.
02/02/2022
----------------
- Elements | Added option for user to manually define a custom Padding valueElements.
- Elements | Removed option for 40px Padding
- Elements | Added background options of Hex code and Transparency.
02/07/2022
----------------
- Anatomy | Updated descriptions to simplify. (Removed “Tile” from many)
02/08/2022
----------------
- Elements | Background color section updated
- Elements | Removed option for 20px Padding value
- Configurations | Surface section added
- Configurations | Multiple sections updated
- Behaviors | Interaction section added
- States | Multiple sections updated/moved
- ACTION | Sent to Accessibility Team to review
02/14/2022
----------------
- ACTION | Received sign off from Accessibility
- ACTION | Sent to Talia for design review
02/21/2022
----------------
- Elements | Background colors and tokens updated.
- ACTION | Ready for dev review.
02/22/2022
----------------
- Elements | Background names updated to infer surface prop selection.
- ACTION | Web dev handoff completed.
12/15/2022
----------------
- States | Android drop shadow specs added, along with screenshot to the right of specs.
- States | Added "(web only)" to any instance of "keyboard focus".
- States | Replaced focus border pixel and style & spacing values with tokens.
- Elements | Updated border color values to use element tokens.
- Configurations | Updated border and drop shadow section titles to “Show border” and “Show drop shadow.”
01/18/2023
----------------
- Anatomy | Updated item #2 to “Padding” from “Container Internal Padding”
05/11/2023
----------------
- Removed showdropshadow prop from Configurations (dropshadow will be on automatically now for Surface=Light)
- Updated states frame to remove states featuring dropshadow suppression, clarified state names, and removed inaccurate dev notes.
06/15/2023
----------------
- Added showDropShadow prop back into Configurations.
- Moved Padding to Configurations
11/09/2023
----------------
- Updated showBorder section to match API prop names/values.
- Moved Padding to Configurations.
11/20/2023
----------------
- Added corner radius token in the Anatomy
- Updated visuals to reflect new corner radius value - 12px
- Updated focus border corner radius to 14px
- View changes
11/27/2023
----------------
- Updated “border radius” to “corner radius” in Anatomy
- Updated “focus border radius” to “focus corner radius” in States
- View changes
12/14/2023
----------------
- Added backgroundColor configuration section, removed Background Colors element section
- Added secondary, primary backgroundColor options
- Simplified backgroundImage section to remove backgroundColor example
- Added background property section, with examples
- Deprecated the gray backgroundColor option
- View changes

View File

@ -0,0 +1,64 @@
//
// Dropshadowable.swift
// VDS
//
// Created by Bandaru, Krishna Kishore on 16/02/24.
//
import Foundation
import UIKit
protocol Dropshadowable {
var shadowColorConfiguration: AnyColorable { get set }
var shadowOpacity: CGFloat { get set }
var shadowOffset: CGSize { get set }
var shadowRadius: CGFloat { get set }
}
extension ViewProtocol where Self: UIView {
func addDropShadow(_ config: Dropshadowable) {
removeDropShadows()
layer.backgroundColor = backgroundColor?.cgColor
layer.masksToBounds = false
let shadowPath = UIBezierPath(roundedRect: bounds, cornerRadius: layer.cornerRadius)
let shadowLayer = CALayer()
shadowLayer.shadowPath = shadowPath.cgPath
shadowLayer.frame = bounds
shadowLayer.position = center
shadowLayer.backgroundColor = UIColor.clear.cgColor
shadowLayer.cornerRadius = layer.cornerRadius
shadowLayer.shadowColor = config.shadowColorConfiguration.getColor(self).cgColor
shadowLayer.shadowOpacity = Float(config.shadowOpacity)
shadowLayer.shadowOffset = .init(width: config.shadowOffset.width, height: config.shadowOffset.height)
shadowLayer.shadowRadius = config.shadowRadius
shadowLayer.name = "dropShadowLayer"
shadowLayer.shouldRasterize = true
shadowLayer.rasterizationScale = UIScreen.main.scale
layer.insertSublayer(shadowLayer, at: 0)
}
func removeDropShadows() {
layer.sublayers?.removeAll { $0.name == "dropShadowLayer" }
}
func addGradientLayer(with firstColor: UIColor, secondColor: UIColor) {
removeGradientLayer()
let gradientLayer = CAGradientLayer()
gradientLayer.frame = bounds
gradientLayer.startPoint = CGPoint(x: 0, y: 1)
gradientLayer.endPoint = CGPoint(x: 1, y: 0)
gradientLayer.position = center
gradientLayer.shouldRasterize = true
gradientLayer.rasterizationScale = UIScreen.main.scale
gradientLayer.cornerRadius = layer.cornerRadius
gradientLayer.colors = [firstColor.cgColor, secondColor.cgColor]
gradientLayer.name = "gradientLayer"
layer.insertSublayer(gradientLayer, at: 0)
}
func removeGradientLayer() {
layer.sublayers?.removeAll { $0.name == "gradientLayer" }
}
}