Skip to content

Commit

Permalink
Detailed customization of InputField
Browse files Browse the repository at this point in the history
Allow CustomTextField with no icon #409
  • Loading branch information
cocojoe committed Apr 21, 2017
1 parent b1924cc commit e8dcb97
Show file tree
Hide file tree
Showing 6 changed files with 103 additions and 42 deletions.
23 changes: 16 additions & 7 deletions App/ViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -82,19 +82,28 @@ class ViewController: UIViewController {
.classic()
.withOptions {
applyDefaultOptions(&$0)
$0.customSignupFields = [
CustomTextField(name: "first_name", placeholder: "First Name"),
CustomTextField(name: "last_name", placeholder: "Last Name")
]
}
.withStyle {
// Header
$0.title = "Phantom Inc."
$0.headerBlur = .extraLight
$0.logo = LazyImage(name: "icn_phantom")
$0.primaryColor = UIColor ( red: 0.6784, green: 0.5412, blue: 0.7333, alpha: 1.0 )
$0.socialSeperatorTextColor = UIColor.red
// Social
$0.socialSeperatorTextColor = UIColor(red: 0.192, green: 0.200, blue: 0.302, alpha: 1.00)
// Input Field
$0.inputTextColor = UIColor(red: 0.192, green: 0.200, blue: 0.302, alpha: 1.00)
$0.inputPlaceholderTextColor = UIColor(red: 0.659, green: 0.553, blue: 0.722, alpha: 1.00)
$0.inputBorderColor = UIColor(red: 0.192, green: 0.200, blue: 0.302, alpha: 1.00)
$0.inputBorderColorError = UIColor(red: 0.545, green: 0.016, blue: 0.000, alpha: 1.00)
$0.inputIconBackgroundColor = UIColor(red: 0.192, green: 0.200, blue: 0.302, alpha: 1.00)
$0.inputBackgroundColor = UIColor(red: 0.980, green: 0.980, blue: 0.980, alpha: 1.00)
$0.inputIconColor = UIColor.white
}
.withConnections { connections in
connections.social(name: "facebook", style: .Facebook)
connections.social(name: "google-oauth2", style: .Google)
connections.database(name: "Username-Password-Authentication", requiresUsername: true)
}
},
actionButton(withTitle: "LOGIN WITH DB") {
return Lock
Expand Down Expand Up @@ -132,7 +141,7 @@ class ViewController: UIViewController {
.withConnections { connections in
connections.social(name: "facebook", style: .Facebook)
connections.social(name: "google-oauth2", style: .Google)
connections.database(name: "Username-Password-Authentication", requiresUsername: true)
connections.database(name: "Username-Password-Authentication", requiresUsername: false)
}
},
actionButton(withTitle: "LOGIN WITH SOCIAL") {
Expand Down
4 changes: 2 additions & 2 deletions Lock/CustomTextField.swift
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,13 @@ public struct CustomTextField {

let name: String
let placeholder: String
let icon: LazyImage
let icon: LazyImage?
let keyboardType: UIKeyboardType
let autocorrectionType: UITextAutocorrectionType
let secure: Bool
let validation: (String?) -> Error?

public init(name: String, placeholder: String, icon: LazyImage, keyboardType: UIKeyboardType = .default, autocorrectionType: UITextAutocorrectionType = .default, secure: Bool = false, validation: @escaping (String?) -> Error? = nonEmpty) {
public init(name: String, placeholder: String, icon: LazyImage? = nil, keyboardType: UIKeyboardType = .default, autocorrectionType: UITextAutocorrectionType = .default, secure: Bool = false, validation: @escaping (String?) -> Error? = nonEmpty) {
self.name = name
self.placeholder = placeholder
self.icon = icon
Expand Down
57 changes: 34 additions & 23 deletions Lock/InputField.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,18 +22,20 @@

import UIKit

class InputField: UIView, UITextFieldDelegate {
class InputField: UIView, UITextFieldDelegate, Stylable {

weak var containerView: UIView?
weak var textField: UITextField?
weak var iconView: UIImageView?
weak var iconContainer: UIView?
weak var errorLabel: UILabel?

weak var nextField: InputField?

private weak var errorLabelTopPadding: NSLayoutConstraint?

private weak var textFieldLeftAnchor: NSLayoutConstraint?
private(set) var state: State = .invalid(nil)
private weak var borderColor: UIColor?
private weak var borderColorError: UIColor?

private lazy var debounceShowError: () -> Void = debounce(0.8, queue: DispatchQueue.global(qos: DispatchQoS.QoSClass.userInitiated), action: { [weak self] in self?.needsToUpdateState() })

Expand All @@ -53,7 +55,12 @@ class InputField: UIView, UITextFieldDelegate {
self.textField?.autocorrectionType = .no
self.textField?.autocapitalizationType = .none
self.textField?.keyboardType = type.keyboardType
self.iconView?.image = type.icon.image(compatibleWithTraits: self.traitCollection)
if let icon = type.icon {
self.iconView?.image = icon.image(compatibleWithTraits: self.traitCollection)
} else if let textField = self.textField, let container = self.containerView {
self.iconContainer?.removeFromSuperview()
textFieldLeftAnchor = constraintEqual(anchor: textField.leftAnchor, toAnchor: container.leftAnchor, constant: 16)
}
}
}

Expand Down Expand Up @@ -110,8 +117,13 @@ class InputField: UIView, UITextFieldDelegate {
func needsToUpdateState() {
Queue.main.async {
self.errorLabel?.text = self.state.text
self.containerView?.layer.borderColor = self.state.color.cgColor
self.errorLabelTopPadding?.constant = self.state.padding
switch self.state {
case .valid:
self.containerView?.layer.borderColor = self.borderColor?.cgColor
case .invalid:
self.containerView?.layer.borderColor = self.borderColorError?.cgColor
}
}
}

Expand Down Expand Up @@ -149,7 +161,7 @@ class InputField: UIView, UITextFieldDelegate {
constraintEqual(anchor: iconContainer.heightAnchor, toAnchor: iconContainer.widthAnchor)
iconContainer.translatesAutoresizingMaskIntoConstraints = false

constraintEqual(anchor: textField.leftAnchor, toAnchor: iconContainer.rightAnchor, constant: 16)
self.textFieldLeftAnchor = constraintEqual(anchor: textField.leftAnchor, toAnchor: iconContainer.rightAnchor, constant: 16)
constraintEqual(anchor: textField.topAnchor, toAnchor: container.topAnchor)
constraintEqual(anchor: textField.rightAnchor, toAnchor: container.rightAnchor, constant: -16)
constraintEqual(anchor: textField.bottomAnchor, toAnchor: container.bottomAnchor)
Expand All @@ -160,17 +172,17 @@ class InputField: UIView, UITextFieldDelegate {
constraintEqual(anchor: iconView.centerYAnchor, toAnchor: iconContainer.centerYAnchor)
iconView.translatesAutoresizingMaskIntoConstraints = false

iconContainer.backgroundColor = UIColor ( red: 0.9333, green: 0.9333, blue: 0.9333, alpha: 1.0 )
iconView.tintColor = UIColor ( red: 0.5725, green: 0.5804, blue: 0.5843, alpha: 1.0 )
iconContainer.backgroundColor = Style.Auth0.inputIconBackgroundColor
iconView.tintColor = Style.Auth0.inputIconColor
textField.addTarget(self, action: #selector(textChanged), for: .editingChanged)
textField.delegate = self
textField.font = UIFont.systemFont(ofSize: 17)
errorLabel.textColor = .red
errorLabel.text = nil
errorLabel.numberOfLines = 0

self.textField = textField
self.iconView = iconView
self.iconContainer = iconContainer
self.containerView = container
self.errorLabel = errorLabel

Expand All @@ -180,7 +192,7 @@ class InputField: UIView, UITextFieldDelegate {
self.containerView?.layer.borderWidth = 1
self.type = .email
self.errorLabel?.text = State.valid.text
self.containerView?.layer.borderColor = State.valid.color.cgColor
self.containerView?.layer.borderColor = Style.Auth0.inputBorderColor.cgColor
}

override var intrinsicContentSize: CGSize {
Expand All @@ -202,15 +214,6 @@ class InputField: UIView, UITextFieldDelegate {
}
}

var color: UIColor {
switch self {
case .valid:
return UIColor ( red: 0.9333, green: 0.9333, blue: 0.9333, alpha: 1.0 )
case .invalid:
return UIColor.red
}
}

var padding: CGFloat {
switch self {
case .invalid where self.text != nil:
Expand Down Expand Up @@ -255,7 +258,7 @@ class InputField: UIView, UITextFieldDelegate {
case password
case phone
case oneTimePassword
case custom(name: String, placeholder: String, icon: LazyImage, keyboardType: UIKeyboardType, autocorrectionType: UITextAutocorrectionType, secure: Bool)
case custom(name: String, placeholder: String, icon: LazyImage?, keyboardType: UIKeyboardType, autocorrectionType: UITextAutocorrectionType, secure: Bool)

var placeholder: String? {
switch self {
Expand Down Expand Up @@ -287,7 +290,7 @@ class InputField: UIView, UITextFieldDelegate {
return false
}

var icon: LazyImage {
var icon: LazyImage? {
switch self {
case .email:
return lazyImage(named: "ic_mail")
Expand Down Expand Up @@ -334,11 +337,19 @@ class InputField: UIView, UITextFieldDelegate {
}
}
}
}

extension InputField: Stylable {
// MARK: - Styable

func apply(style: Style) {
self.borderColor = style.inputBorderColor
self.borderColorError = style.inputBorderColorError
self.textField?.textColor = style.inputTextColor
self.textField?.attributedPlaceholder = NSAttributedString(string: self.textField?.placeholder ?? "",
attributes: [NSForegroundColorAttributeName: style.inputPlaceholderTextColor])
self.containerView?.backgroundColor = style.inputBackgroundColor
self.containerView?.layer.borderColor = style.inputBorderColor.cgColor
self.errorLabel?.textColor = style.inputBorderColorError
self.iconContainer?.backgroundColor = style.inputIconBackgroundColor
self.iconView?.tintColor = style.inputIconColor
}
}
26 changes: 22 additions & 4 deletions Lock/Style.swift
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,10 @@ public struct Style {
public var backgroundColor = UIColor.white

/// Lock disabled component color
public var disabledColor = UIColor ( red: 0.8902, green: 0.898, blue: 0.9059, alpha: 1.0 )
public var disabledColor = UIColor(red: 0.8902, green: 0.898, blue: 0.9059, alpha: 1.0 )

/// Lock disabled component text color
public var disabledTextColor = UIColor ( red: 0.5725, green: 0.5804, blue: 0.5843, alpha: 1.0 )
public var disabledTextColor = UIColor(red: 0.5725, green: 0.5804, blue: 0.5843, alpha: 1.0 )

/// Primary button tint color
public var buttonTintColor = UIColor.white
Expand Down Expand Up @@ -71,10 +71,28 @@ public struct Style {
public var oauth2: [String: AuthStyle] = [:]

/// Social seperator label
public var socialSeperatorTextColor = UIColor ( red: 0.0, green: 0.0, blue: 0.0, alpha: 0.54 )
public var socialSeperatorTextColor = UIColor(red: 0.0, green: 0.0, blue: 0.0, alpha: 0.54)

/// Input field text color
public var inputTextColor = UIColor.red
public var inputTextColor = UIColor.black

/// Input field placeholder text color
public var inputPlaceholderTextColor = UIColor(red: 0.780, green: 0.780, blue: 0.804, alpha: 1.00)

/// Input field border color default
public var inputBorderColor = UIColor(red: 0.9333, green: 0.9333, blue: 0.9333, alpha: 1.0)

/// Input field border color invalid
public var inputBorderColorError = UIColor.red

/// Input field background color
public var inputBackgroundColor = UIColor.white

/// Input field icon background color
public var inputIconBackgroundColor = UIColor(red: 0.9333, green: 0.9333, blue: 0.9333, alpha: 1.0)

/// Input field icon color
public var inputIconColor = UIColor(red: 0.5725, green: 0.5804, blue: 0.5843, alpha: 1.0 )

var headerMask: UIImage? {
let image = self.logo.image(compatibleWithTraits: nil)
Expand Down
30 changes: 29 additions & 1 deletion LockSnapshot/LockSnapshot.swift
Original file line number Diff line number Diff line change
Expand Up @@ -37,13 +37,41 @@ class LockSnapshot: XCTestCase {
}

func testClassic() {

let app = XCUIApplication()

app.buttons["LOGIN WITH CDN CLASSIC"].tap()
snapshot("1A-Lock-Classic-Database-Social-Login")

app.textFields["Email"].tap()
app.textFields["Email"].typeText("foo")
snapshot("2A-Lock-Classic-Database-Social-Login-Input-Error")

app.scrollViews.otherElements.buttons["Sign Up"].tap()
snapshot("3A-Lock-Classic-Database-Social-Signup")

app.textFields["Email"].tap()
app.textFields["Email"].typeText("foo")
snapshot("4A-Lock-Classic-Database-Social-Signup-Input-Error")
}

func testClassicCustom() {

let app = XCUIApplication()

app.buttons["LOGIN WITH CUSTOM STYLE"].tap()
snapshot("1B-Lock-Classic-Database-Social-Login-Custom")
snapshot("1B-Lock-Classic-Custom-Database-Social-Login")

app.textFields["Email"].tap()
app.textFields["Email"].typeText("foo")
snapshot("2B-Lock-Classic-Custom-Database-Social-Login-Input-Error")

app.scrollViews.otherElements.buttons["Sign Up"].tap()
snapshot("3B-Lock-Classic-Custom-Database-Social-Signup")

app.textFields["Email"].tap()
app.textFields["Email"].typeText("foo")
snapshot("4B-Lock-Classic-Custom-Database-Social-Signup-Input-Error")
}

}
5 changes: 0 additions & 5 deletions fastlane/Fastfile
Original file line number Diff line number Diff line change
Expand Up @@ -85,11 +85,6 @@ platform :ios do
ENV["FASTLANE_HIDE_TIMESTAMP"] = "false"
end

desc "UI Screenshots"
lane :screenshots do
snapshot
end

desc "Releases the library to Cocoapods & Github Releases and updates README/CHANGELOG"
desc "You need to specify the type of release with the `bump` parameter with the values [major|minor|patch]"
lane :release do |options|
Expand Down

0 comments on commit e8dcb97

Please sign in to comment.