From 2630dc43bf23c4192478a195c3575f594a287dc9 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Mon, 19 Dec 2022 14:41:22 -0600 Subject: [PATCH] added TitleLockup Signed-off-by: Matt Bruce --- VDS.xcodeproj/project.pbxproj | 12 ++ VDS/Components/TitleLockup/TitleLockup.swift | 204 +++++++++++++++++++ 2 files changed, 216 insertions(+) create mode 100644 VDS/Components/TitleLockup/TitleLockup.swift diff --git a/VDS.xcodeproj/project.pbxproj b/VDS.xcodeproj/project.pbxproj index 2389cfb7..0a4e82e2 100644 --- a/VDS.xcodeproj/project.pbxproj +++ b/VDS.xcodeproj/project.pbxproj @@ -42,6 +42,7 @@ EA4DB30228DCBCA500103EE3 /* Badge.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA4DB30128DCBCA500103EE3 /* Badge.swift */; }; EA5E304C294CBDD00082B959 /* TileContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA5E304B294CBDD00082B959 /* TileContainer.swift */; }; EA5E304E294CC7F00082B959 /* VDSColor.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA5E304D294CC7F00082B959 /* VDSColor.swift */; }; + EA5E30532950DDA60082B959 /* TitleLockup.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA5E30522950DDA60082B959 /* TitleLockup.swift */; }; EA89200228AECF2A006B9984 /* UIButton+Publisher.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA89200128AECF2A006B9984 /* UIButton+Publisher.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 */; }; @@ -139,6 +140,7 @@ EA4DB30128DCBCA500103EE3 /* Badge.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Badge.swift; sourceTree = ""; }; EA5E304B294CBDD00082B959 /* TileContainer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TileContainer.swift; sourceTree = ""; }; EA5E304D294CC7F00082B959 /* VDSColor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VDSColor.swift; sourceTree = ""; }; + EA5E30522950DDA60082B959 /* TitleLockup.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TitleLockup.swift; sourceTree = ""; }; EA89200128AECF2A006B9984 /* UIButton+Publisher.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIButton+Publisher.swift"; sourceTree = ""; }; EA89200328AECF4B006B9984 /* UITextField+Publisher.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UITextField+Publisher.swift"; sourceTree = ""; }; EA89200528B526D6006B9984 /* CheckboxGroup.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CheckboxGroup.swift; sourceTree = ""; }; @@ -318,6 +320,7 @@ EA1F265F28B945070033E859 /* RadioSwatch */, EAC925852911C9DE00091998 /* TextFields */, EA5E304A294CBDBB0082B959 /* TileContainer */, + EA5E30512950DD8D0082B959 /* TitleLockup */, EA3361A0288B1E6F0071C351 /* Toggle */, ); path = Components; @@ -444,6 +447,14 @@ path = TileContainer; sourceTree = ""; }; + EA5E30512950DD8D0082B959 /* TitleLockup */ = { + isa = PBXGroup; + children = ( + EA5E30522950DDA60082B959 /* TitleLockup.swift */, + ); + path = TitleLockup; + sourceTree = ""; + }; EA89200B28B530F0006B9984 /* RadioBox */ = { isa = PBXGroup; children = ( @@ -716,6 +727,7 @@ EAF7F0AB289B13FD00B287F5 /* TypographicalStyleLabelAttribute.swift in Sources */, EAB1D29C28A5618900DAE764 /* RadioButtonGroup.swift in Sources */, EA336171288B19200071C351 /* VDS.docc in Sources */, + EA5E30532950DDA60082B959 /* TitleLockup.swift in Sources */, EAA5EEB528ECBFB4003B3210 /* ImageLabelAttribute.swift in Sources */, EAB5FF0129424ACB00998C17 /* UIControl.swift in Sources */, EAB1D2E628AE842000DAE764 /* Publisher+Bind.swift in Sources */, diff --git a/VDS/Components/TitleLockup/TitleLockup.swift b/VDS/Components/TitleLockup/TitleLockup.swift new file mode 100644 index 00000000..4f79e7a0 --- /dev/null +++ b/VDS/Components/TitleLockup/TitleLockup.swift @@ -0,0 +1,204 @@ +// +// TitleLockup.swift +// VDS +// +// Created by Matt Bruce on 12/19/22. +// + +import Foundation +import UIKit +import VDSColorTokens +import Combine + +public enum TitleLockupTextPosition: String, Codable, CaseIterable { + case left, center + + var labelTextPosition: TextPosition { + switch self { + case .left: + return .left + case .center: + return .center + } + } +} + +public enum TitleLockupitleTypographicalStyle: String, Codable, CaseIterable { + case FeatureMedium + case BoldFeatureMedium + case FeatureSmall + case BoldFeatureSmall + case FeatureXSmall + case BoldFeatureXSmall + + case Title2XLarge + case BoldTitle2XLarge + case TitleXLarge + case BoldTitleXLarge + case TitleLarge + case BoldTitleLarge + case TitleMedium + case BoldTitleMedium + case TitleSmall + case BoldTitleSmall + + public var typographicalStyle: TypographicalStyle { + return TypographicalStyle(rawValue: self.rawValue) ?? .BoldFeatureXSmall + } +} + +public enum TitleLockupOtherTypographicalStyle: String, Codable, CaseIterable { + case BodyLarge + case BoldBodyLarge + case BodyMedium + case BoldBodyMedium + case BodySmall + case BoldBodySmall + + public var typographicalStyle: TypographicalStyle { + return TypographicalStyle(rawValue: self.rawValue) ?? .BodyLarge + } +} + +@objc(VDSTitleLockup) +open class TitleLockup: View { + + //-------------------------------------------------- + // 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: - Private Properties + //-------------------------------------------------- + private var stackView = UIStackView().with { + $0.translatesAutoresizingMaskIntoConstraints = false + $0.axis = .vertical + $0.distribution = .fill + } + + //-------------------------------------------------- + // MARK: - Configuration Properties + //-------------------------------------------------- + // Sizes are from InVision design specs. + + + //-------------------------------------------------- + // MARK: - Public Properties + //-------------------------------------------------- + open var textPosition: TitleLockupTextPosition = .left { didSet { didChange() }} + + //style + open var titleTypograpicalStyle: TitleLockupitleTypographicalStyle = .BoldFeatureXSmall { didSet { didChange() }} + open var otherTypograpicalStyle: TitleLockupOtherTypographicalStyle = .BodyLarge { didSet { didChange() }} + + //first row + open var eyebrowLabel = Label().with { + $0.setContentCompressionResistancePriority(.required, for: .vertical) + } + open var eyebrowText: String = "" { didSet { didChange() }} + open var eyebrowTextAttributes: [any LabelAttributeModel]? { didSet { didChange() }} + + //second row + open var titleLabel = Label().with { + $0.setContentCompressionResistancePriority(.required, for: .vertical) + } + open var titleText: String = "" { didSet { didChange() }} + open var titleTextAttributes: [any LabelAttributeModel]? { didSet { didChange() }} + + //third row + open var subTitleLabel = Label().with { + $0.setContentCompressionResistancePriority(.required, for: .vertical) + } + open var subTitleText: String = "" { didSet { didChange() }} + open var subTitleTextAttributes: [any LabelAttributeModel]? { didSet { didChange() }} + open var subTitleColor: Use = .primary { didSet { didChange() }} + //-------------------------------------------------- + // MARK: - Lifecycle + //-------------------------------------------------- + open override func setup() { + super.setup() + + isAccessibilityElement = true + accessibilityTraits = .button + addSubview(stackView) + + stackView.spacing = 0.0 + + stackView.addArrangedSubview(eyebrowLabel) + stackView.addArrangedSubview(titleLabel) + stackView.addArrangedSubview(subTitleLabel) + + //pin stackview to edges + stackView.pinToSuperView() + } + + public override func reset() { + super.reset() + titleLabel.reset() + eyebrowLabel.reset() + subTitleLabel.reset() + + textPosition = .left + + eyebrowText = "" + titleText = "" + subTitleText = "" + + titleTypograpicalStyle = .BoldFeatureXSmall + otherTypograpicalStyle = .BodyLarge + + } + + //-------------------------------------------------- + // MARK: - State + //-------------------------------------------------- + open override func updateView() { + super.updateView() + + let allLabelsTextPosition = textPosition.labelTextPosition + + eyebrowLabel.textPosition = allLabelsTextPosition + eyebrowLabel.typograpicalStyle = otherTypograpicalStyle.typographicalStyle + eyebrowLabel.text = eyebrowText + eyebrowLabel.attributes = eyebrowTextAttributes + eyebrowLabel.surface = surface + + titleLabel.textPosition = allLabelsTextPosition + titleLabel.typograpicalStyle = titleTypograpicalStyle.typographicalStyle + titleLabel.text = titleText + titleLabel.attributes = titleTextAttributes + titleLabel.surface = surface + + subTitleLabel.textPosition = allLabelsTextPosition + subTitleLabel.typograpicalStyle = otherTypograpicalStyle.typographicalStyle + subTitleLabel.text = subTitleText + subTitleLabel.attributes = subTitleTextAttributes + subTitleLabel.surface = surface + subTitleLabel.disabled = subTitleColor == .secondary + + //if both first 2 rows not empty set spacing + if !eyebrowText.isEmpty && !titleText.isEmpty { + stackView.spacing = 12.0 + } else { + stackView.spacing = 0.0 + } + + //if either first 2 rows not empty and subtile not empty, create space else collapse + if (!eyebrowText.isEmpty || !titleText.isEmpty) && !subTitleText.isEmpty { + stackView.setCustomSpacing(24.0, after: titleLabel) + } else if (!eyebrowText.isEmpty || !titleText.isEmpty) && subTitleText.isEmpty { + stackView.setCustomSpacing(0.0, after: titleLabel) + } + } +}