diff --git a/Examples/DemosApp/DemosApp/ComponentsPreview/Helpers/PreviewPickers.swift b/Examples/DemosApp/DemosApp/ComponentsPreview/Helpers/PreviewPickers.swift index 4645fa94..e442e134 100644 --- a/Examples/DemosApp/DemosApp/ComponentsPreview/Helpers/PreviewPickers.swift +++ b/Examples/DemosApp/DemosApp/ComponentsPreview/Helpers/PreviewPickers.swift @@ -23,7 +23,7 @@ struct AutocapitalizationPicker: View { @Binding var selection: TextAutocapitalization var body: some View { - Picker("Autocapitalization", selection: $selection) { + Picker("Autocapitalization", selection: self.$selection) { Text("Never").tag(TextAutocapitalization.never) Text("Characters").tag(TextAutocapitalization.characters) Text("Words").tag(TextAutocapitalization.words) @@ -203,13 +203,25 @@ struct CaptionFontPicker: View { } } +struct InputStylePicker: View { + @Binding var selection: InputStyle + + var body: some View { + Picker("Style", selection: self.$selection) { + Text("Light").tag(InputStyle.light) + Text("Bordered").tag(InputStyle.bordered) + Text("Faded").tag(InputStyle.faded) + } + } +} + // MARK: - KeyboardTypePicker struct KeyboardTypePicker: View { @Binding var selection: UIKeyboardType var body: some View { - Picker("Keyboard Type", selection: $selection) { + Picker("Keyboard Type", selection: self.$selection) { Text("Default").tag(UIKeyboardType.default) Text("asciiCapable").tag(UIKeyboardType.asciiCapable) Text("numbersAndPunctuation").tag(UIKeyboardType.numbersAndPunctuation) @@ -260,7 +272,7 @@ struct SubmitTypePicker: View { @Binding var selection: SubmitType var body: some View { - Picker("Submit Type", selection: $selection) { + Picker("Submit Type", selection: self.$selection) { Text("done").tag(SubmitType.done) Text("go").tag(SubmitType.go) Text("join").tag(SubmitType.join) diff --git a/Examples/DemosApp/DemosApp/ComponentsPreview/PreviewPages/InputFieldPreview.swift b/Examples/DemosApp/DemosApp/ComponentsPreview/PreviewPages/InputFieldPreview.swift index f511e2ba..1b74b659 100644 --- a/Examples/DemosApp/DemosApp/ComponentsPreview/PreviewPages/InputFieldPreview.swift +++ b/Examples/DemosApp/DemosApp/ComponentsPreview/PreviewPages/InputFieldPreview.swift @@ -61,11 +61,7 @@ struct InputFieldPreview: View { Toggle("Required", isOn: self.$model.isRequired) Toggle("Secure Input", isOn: self.$model.isSecureInput) SizePicker(selection: self.$model.size) - Picker("Style", selection: self.$model.style) { - Text("Light").tag(InputFieldVM.Style.light) - Text("Bordered").tag(InputFieldVM.Style.bordered) - Text("Faded").tag(InputFieldVM.Style.faded) - } + InputStylePicker(selection: self.$model.style) SubmitTypePicker(selection: self.$model.submitType) UniversalColorPicker( title: "Tint Color", diff --git a/Examples/DemosApp/DemosApp/ComponentsPreview/PreviewPages/TextInputPreview.swift b/Examples/DemosApp/DemosApp/ComponentsPreview/PreviewPages/TextInputPreview.swift index 978ee110..40ee622e 100644 --- a/Examples/DemosApp/DemosApp/ComponentsPreview/PreviewPages/TextInputPreview.swift +++ b/Examples/DemosApp/DemosApp/ComponentsPreview/PreviewPages/TextInputPreview.swift @@ -60,6 +60,7 @@ struct TextInputPreviewPreview: View { } )) SizePicker(selection: self.$model.size) + InputStylePicker(selection: self.$model.style) SubmitTypePicker(selection: self.$model.submitType) UniversalColorPicker( title: "Tint Color", diff --git a/Sources/ComponentsKit/Components/InputField/Models/InputFieldStyle.swift b/Sources/ComponentsKit/Components/InputField/Models/InputFieldStyle.swift deleted file mode 100644 index 52741b34..00000000 --- a/Sources/ComponentsKit/Components/InputField/Models/InputFieldStyle.swift +++ /dev/null @@ -1,13 +0,0 @@ -import Foundation - -extension InputFieldVM { - /// The input fields appearance style. - public enum Style: Hashable { - /// An input field with a partially transparent background. - case light - /// An input field with a transparent background and a border. - case bordered - /// An input field with a partially transparent background and a border. - case faded - } -} diff --git a/Sources/ComponentsKit/Components/InputField/Models/InputFieldVM.swift b/Sources/ComponentsKit/Components/InputField/Models/InputFieldVM.swift index dd9c2f88..fba374c2 100644 --- a/Sources/ComponentsKit/Components/InputField/Models/InputFieldVM.swift +++ b/Sources/ComponentsKit/Components/InputField/Models/InputFieldVM.swift @@ -65,7 +65,7 @@ public struct InputFieldVM: ComponentVM { /// The visual style of the input field. /// /// Defaults to `.light`. - public var style: Style = .light + public var style: InputStyle = .light /// The type of the submit button on the keyboard. /// diff --git a/Sources/ComponentsKit/Components/TextInput/Models/TextInputVM.swift b/Sources/ComponentsKit/Components/TextInput/Models/TextInputVM.swift index 274cce4b..84dab608 100644 --- a/Sources/ComponentsKit/Components/TextInput/Models/TextInputVM.swift +++ b/Sources/ComponentsKit/Components/TextInput/Models/TextInputVM.swift @@ -52,6 +52,11 @@ public struct TextInputVM: ComponentVM { /// Defaults to `.medium`. public var size: ComponentSize = .medium + /// The visual style of the text input. + /// + /// Defaults to `.light`. + public var style: InputStyle = .light + /// The type of the submit button on the keyboard. /// /// Defaults to `.return`. @@ -89,7 +94,12 @@ extension TextInputVM { } var backgroundColor: UniversalColor { - return self.color?.background ?? .content1 + switch self.style { + case .light, .faded: + return self.color?.background ?? .content1 + case .bordered: + return .background + } } var foregroundColor: UniversalColor { @@ -105,6 +115,26 @@ extension TextInputVM { } } + var borderWidth: CGFloat { + switch self.style { + case .light: + return 0 + case .bordered, .faded: + switch self.size { + case .small: + return BorderWidth.small.value + case .medium: + return BorderWidth.medium.value + case .large: + return BorderWidth.large.value + } + } + } + + var borderColor: UniversalColor { + return (self.color?.main ?? .content3).enabled(self.isEnabled) + } + var minTextInputHeight: CGFloat { let numberOfRows: Int if let maxRows { @@ -117,7 +147,7 @@ extension TextInputVM { var maxTextInputHeight: CGFloat { if let maxRows { - return self.height(forRows: maxRows) + return self.height(forRows: max(maxRows, self.minRows)) } else { return 10_000 } diff --git a/Sources/ComponentsKit/Components/TextInput/SUTextInput.swift b/Sources/ComponentsKit/Components/TextInput/SUTextInput.swift index 0ca46401..bd90dcb3 100644 --- a/Sources/ComponentsKit/Components/TextInput/SUTextInput.swift +++ b/Sources/ComponentsKit/Components/TextInput/SUTextInput.swift @@ -55,14 +55,23 @@ public struct SUTextInput: View { TextEditor(text: self.$text) .contentMargins(self.model.contentPadding) .transparentScrollBackground() - .frame(minHeight: self.model.minTextInputHeight) - .frame(height: max( - self.model.minTextInputHeight, - min( - self.model.maxTextInputHeight, - self.textEditorPreferredHeight + .frame( + minHeight: self.model.minTextInputHeight, + idealHeight: max( + self.model.minTextInputHeight, + min( + self.model.maxTextInputHeight, + self.textEditorPreferredHeight + ) + ), + maxHeight: max( + self.model.minTextInputHeight, + min( + self.model.maxTextInputHeight, + self.textEditorPreferredHeight + ) ) - )) + ) .lineSpacing(0) .font(self.model.preferredFont.font) .foregroundStyle(self.model.foregroundColor.color) @@ -124,6 +133,15 @@ public struct SUTextInput: View { cornerRadius: self.model.adaptedCornerRadius() ) ) + .overlay( + RoundedRectangle( + cornerRadius: self.model.cornerRadius.value() + ) + .stroke( + self.model.borderColor.color, + lineWidth: self.model.borderWidth + ) + ) } } diff --git a/Sources/ComponentsKit/Components/TextInput/UKTextInput.swift b/Sources/ComponentsKit/Components/TextInput/UKTextInput.swift index ab169844..7710feda 100644 --- a/Sources/ComponentsKit/Components/TextInput/UKTextInput.swift +++ b/Sources/ComponentsKit/Components/TextInput/UKTextInput.swift @@ -79,6 +79,12 @@ open class UKTextInput: UIView, UKComponent { self.addSubview(self.placeholderLabel) self.textView.delegate = self + + if #available(iOS 17.0, *) { + self.registerForTraitChanges([UITraitUserInterfaceStyle.self]) { (view: Self, _: UITraitCollection) in + view.handleTraitChanges() + } + } } // MARK: - Style @@ -157,7 +163,18 @@ open class UKTextInput: UIView, UKComponent { return CGSize(width: width, height: height) } - // MARK: - Helpers + open override func traitCollectionDidChange( + _ previousTraitCollection: UITraitCollection? + ) { + super.traitCollectionDidChange(previousTraitCollection) + self.handleTraitChanges() + } + + // MARK: Helpers + + @objc private func handleTraitChanges() { + Self.Style.mainView(self, model: self.model) + } private func handleTextChanges() { self.onValueChange(self.text) @@ -187,6 +204,8 @@ extension UKTextInput { static func mainView(_ view: UIView, model: TextInputVM) { view.backgroundColor = model.backgroundColor.uiColor view.layer.cornerRadius = model.adaptedCornerRadius(for: view.bounds.height) + view.layer.borderColor = model.borderColor.cgColor + view.layer.borderWidth = model.borderWidth } static func textView( diff --git a/Sources/ComponentsKit/Shared/Types/InputStyle.swift b/Sources/ComponentsKit/Shared/Types/InputStyle.swift new file mode 100644 index 00000000..34da511c --- /dev/null +++ b/Sources/ComponentsKit/Shared/Types/InputStyle.swift @@ -0,0 +1,11 @@ +import Foundation + +/// The appearance style of inputs. +public enum InputStyle: Hashable { + /// An input with a partially transparent background. + case light + /// An input with a transparent background and a border. + case bordered + /// An input with a partially transparent background and a border. + case faded +}