         translatesAutoresizingMaskIntoConstraints = false
 
         addConstraints([
-            NSLayoutConstraint(item: textField, attribute: .top, relatedBy: .equal, toItem: self, attribute: .top, multiplier: 1, constant: 9),
-            NSLayoutConstraint(item: textField, attribute: .bottom, relatedBy: .equal, toItem: self, attribute: .bottomMargin, multiplier: 1, constant: 0),
-            NSLayoutConstraint(item: textField, attribute: .width, relatedBy: .equal, toItem: self, attribute: .width, multiplier: 0.7, constant: -8),
-            NSLayoutConstraint(item: textField, attribute: .leading, relatedBy: .equal, toItem: self, attribute: .leadingMargin, multiplier: 1, constant: 8),
-            NSLayoutConstraint(item: button, attribute: .width, relatedBy: .equal, toItem: self, attribute: .width, multiplier: 0.3, constant: 0),
-            NSLayoutConstraint(item: button, attribute: .top, relatedBy: .equal, toItem: self, attribute: .top, multiplier: 1, constant: 9),
-            NSLayoutConstraint(item: button, attribute: .bottom, relatedBy: .equal, toItem: self, attribute: .bottomMargin, multiplier: 1, constant: 0),
-            NSLayoutConstraint(item: button, attribute: .trailing, relatedBy: .equal, toItem: self, attribute: .trailingMargin, multiplier: 1, constant: 0),
-            NSLayoutConstraint(item: separator, attribute: .width, relatedBy: .equal, toItem: self, attribute: .width, multiplier: 1, constant: 0),
-            NSLayoutConstraint(item: separator, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1, constant: 1),
-            NSLayoutConstraint(item: separator, attribute: .top, relatedBy: .equal, toItem: self, attribute: .top, multiplier: 1, constant: 0),
-            NSLayoutConstraint(item: separator, attribute: .centerX, relatedBy: .equal, toItem: self, attribute: .centerX, multiplier: 1, constant: 0),
+            messageTextField.heightAnchor.constraint(equalToConstant: ChatInputView.Constants.textFieldHeight),
+            chatStack.leadingAnchor.constraint(equalTo: layoutMarginsGuide.leadingAnchor),
+            chatStack.trailingAnchor.constraint(equalTo: layoutMarginsGuide.trailingAnchor),
+            chatStack.centerYAnchor.constraint(equalTo: centerYAnchor),
+            separator.leadingAnchor.constraint(equalTo: leadingAnchor),
+            separator.trailingAnchor.constraint(equalTo: trailingAnchor),
+            separator.topAnchor.constraint(equalTo: topAnchor),
+            separator.heightAnchor.constraint(equalToConstant: 1),
         ])
     }
 
-    override func layoutSubviews() {
-        super.layoutSubviews()
-        textField.layer.cornerRadius = textField.frame.height / 2
-    }
-
     @objc func didTapSendButton() {
-        delegate?.didTapSendButton(text: textField.text ?? "")
+        guard let text = messageTextField.text, text.canBeSent else {
+            return
+        }
+        delegate?.didTapSendButton(text: text)
     }
 
     public func resetInput() {
-        textField.text = ""
+        messageTextField.text?.removeAll()
+        messageTextField.sendActions(for: .editingChanged)
     }
 
     @discardableResult
     override func resignFirstResponder() -> Bool {
-        return textField.resignFirstResponder()
+        return messageTextField.resignFirstResponder()
     }
 
     @objc
     func textFieldDidChange(_ textField: UITextField) {
         if let text = textField.text {
-            button.isEnabled = !text.isEmpty
+            sendButton.isEnabled = text.canBeSent
         }
     }
+}
 
-    // MARK: UITextFieldDelegate
-
-    func textFieldShouldReturn(_ textField: UITextField) -> Bool {
-        if (textField.text ?? "") != "" {
-            didTapSendButton()
-            return true
-        }
-        return false
+private extension String {
+    var canBeSent: Bool {
+        return !self.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty
     }
 }

    }

    private func commonInit() {
        addSubview(textField)
        addSubview(button)
        addSubview(separator)

        textField.delegate = self

        configureConstraints()
    }

}

class ChatInputView: UIView, UITextFieldDelegate {
    struct Constants {
        static let textFieldHeight = CGFloat(46.0)
    }

    @objc
    dynamic var sendMessageButtonColor: UIColor? {
        willSet {
            sendButton.setTitleColor(newValue, for: .normal)
            sendButton.setTitleColor(newValue?.withAlphaComponent(0.4), for: .disabled)
            sendButton.setTitleColor(newValue?.withAlphaComponent(0.4), for: .highlighted)
        }
    }

    @objc
    dynamic var textViewTextColor: UIColor? {
        willSet {
            messageTextField.textColor = newValue
        }
    }

    weak var delegate: ChatInputDelegate?

    private let messageTextField: UITextField = {
        let textField = TextFieldWithInsets()
        textField.isOpaque = false
        textField.translatesAutoresizingMaskIntoConstraints = false
