Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Create Textarea component #724

Merged
merged 5 commits into from
Nov 27, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added Snapshots/iPad/TextareaTests/testTextarea.1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
41 changes: 19 additions & 22 deletions Sources/Orbit/Components/Checkbox.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,30 +17,27 @@ public struct Checkbox: View {
@Binding var isChecked: Bool

public var body: some View {
SwiftUI.Button(
action: {
if isHapticsEnabled {
HapticsProvider.sendHapticFeedback(.light(0.5))
}

isChecked.toggle()
},
label: {
if title.isEmpty == false || description.isEmpty == false {
VStack(alignment: .leading, spacing: 1) {
Text(title)
.textColor(labelColor)
.fontWeight(.medium)
.accessibility(.checkboxTitle)

Text(description)
.textSize(.small)
.textColor(descriptionColor)
.accessibility(.checkboxDescription)
}
SwiftUI.Button {
if isHapticsEnabled {
HapticsProvider.sendHapticFeedback(.light(0.5))
}

isChecked.toggle()
} label: {
if title.isEmpty == false || description.isEmpty == false {
VStack(alignment: .leading, spacing: 1) {
Text(title)
.textColor(labelColor)
.fontWeight(.medium)
.accessibility(.checkboxTitle)

Text(description)
.textSize(.small)
.textColor(descriptionColor)
.accessibility(.checkboxDescription)
}
}
)
}
.buttonStyle(
CheckboxButtonStyle(state: state, isChecked: isChecked)
)
Expand Down
41 changes: 19 additions & 22 deletions Sources/Orbit/Components/ChoiceTile.swift
Original file line number Diff line number Diff line change
Expand Up @@ -29,31 +29,28 @@ public struct ChoiceTile<Content: View, Icon: View, Header: View, Illustration:
@ViewBuilder let illustration: Illustration

public var body: some View {
SwiftUI.Button(
action: {
if isHapticsEnabled {
HapticsProvider.sendHapticFeedback(.light(0.3))
SwiftUI.Button {
if isHapticsEnabled {
HapticsProvider.sendHapticFeedback(.light(0.3))
}

action()
} label: {
HStack(spacing: 0) {
VStack(alignment: contentAlignment, spacing: padding) {
headerRow
content
messageView
centerIndicator
}

action()
},
label: {
HStack(spacing: 0) {
VStack(alignment: contentAlignment, spacing: padding) {
headerRow
content
messageView
centerIndicator
}

TextStrut()
.padding(.vertical, .xxSmall) // Minimum 52pt @ normal size
}
.frame(maxWidth: idealSize.horizontal == true ? nil: .infinity, alignment: .leading)
.overlay(indicatorOverlay, alignment: indicatorAlignment)
.padding(padding)
TextStrut()
.padding(.vertical, .xxSmall) // Minimum 52pt @ normal size
}
)
.frame(maxWidth: idealSize.horizontal == true ? nil: .infinity, alignment: .leading)
.overlay(indicatorOverlay, alignment: indicatorAlignment)
.padding(padding)
}
.buttonStyle(
TileButtonStyle(isSelected: isSelected)
)
Expand Down
69 changes: 35 additions & 34 deletions Sources/Orbit/Components/InputField.swift
Original file line number Diff line number Diff line change
@@ -1,14 +1,39 @@
import SwiftUI
import UIKit

/// Also known as textbox. Offers users a simple input for a form.
/// Orbit component that offers a simple text input. The component is an equivalent of the native `TextField` component.
///
/// When you have additional information or helpful examples, include prompt text to help users along.
/// The InputField is created with an optional label and a binding to a string value.
///
/// ```swift
/// InputField("Label", value: $email, prompt: "E-mail")
/// .keyboardType(.emailAddress)
/// .returnKeyType(.done)
/// .focused($isEmailFocused)
/// .inputFieldReturnAction {
/// // Action after the value is submitted
/// }
/// ```
///
/// For secure version, the `passwordStrength` hint can be provided.
///
/// ```swift
/// InputField(
/// "Password",
/// value: $password,
/// isSecure: true,
/// passwordStrength: passwordStrength,
/// message: .help("Must be at least 8 characters long")
/// )
/// ```
///
/// The custom Orbit version of ``TextField`` component is used internally.
/// The component uses a custom ``TextField`` component (implemented using `UITextField`) that represents the native `TextField`.
///
/// ### Layout
///
/// The component expands horizontally.
///
/// - Note: [Orbit definition](https://orbit.kiwi/components/inputfield/)
/// - Important: Component expands horizontally unless prevented by `fixedSize` modifier.
public struct InputField<Prefix: View, Suffix: View>: View, TextFieldBuildable {

@Environment(\.inputFieldBeginEditingAction) private var inputFieldBeginEditingAction
Expand Down Expand Up @@ -41,18 +66,8 @@ public struct InputField<Prefix: View, Suffix: View>: View, TextFieldBuildable {
var shouldDeleteBackwardAction: (String) -> Bool = { _ in true }

public var body: some View {
FieldWrapper(
defaultLabel,
message: message,
messageHeight: $messageHeight
) {
InputContent(
state: state,
label: compactLabel,
message: message,
isFocused: isFocused,
isPlaceholder: value.isEmpty
) {
FieldWrapper(defaultLabel, message: message, messageHeight: $messageHeight) {
InputContent(state: state, label: compactLabel, message: message, isFocused: isFocused) {
textField
} prefix: {
prefix
Expand Down Expand Up @@ -131,18 +146,11 @@ public struct InputField<Prefix: View, Suffix: View>: View, TextFieldBuildable {

public extension InputField {

/// Creates Orbit InputField component.
///
/// The keyboard related modifiers can be used directly on this component to modify the keyboard behaviour:
/// - `autocapitalization()`
/// - `autocorrectionDisabled()`
/// - `keyboardType()`
/// - `textContentType()`
/// Creates Orbit ``InputField`` component.
///
/// - Parameters:
/// - message: Optional message below the InputField.
/// - message: Optional message below the text field.
/// - messageHeight: Binding to the current height of the optional message.
/// - suffixAction: Optional action when suffix icon is tapped.
init(
_ label: String = "",
value: Binding<String>,
Expand Down Expand Up @@ -173,18 +181,11 @@ public extension InputField {
}
}

/// Creates Orbit InputField component with custom prefix or suffix.
///
/// The keyboard related modifiers can be used directly on this component to modify the keyboard behaviour:
/// - `autocapitalization()`
/// - `autocorrectionDisabled()`
/// - `keyboardType()`
/// - `textContentType()`
/// Creates Orbit ``InputField`` component with custom prefix or suffix.
///
/// - Parameters:
/// - message: Optional message below the InputField.
/// - message: Optional message below the text field.
/// - messageHeight: Binding to the current height of the optional message.
/// - suffixAction: Optional action when suffix icon is tapped.
init(
_ label: String = "",
value: Binding<String>,
Expand Down
41 changes: 19 additions & 22 deletions Sources/Orbit/Components/Radio.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,30 +17,27 @@ public struct Radio: View {
@Binding var isChecked: Bool

public var body: some View {
SwiftUI.Button(
action: {
if isHapticsEnabled {
HapticsProvider.sendHapticFeedback(.light(0.5))
}

isChecked.toggle()
},
label: {
if title.isEmpty == false || description.isEmpty == false {
VStack(alignment: .leading, spacing: 1) {
Text(title)
.textColor(labelColor)
.fontWeight(.medium)
.accessibility(.radioTitle)

Text(description)
.textSize(.small)
.textColor(descriptionColor)
.accessibility(.radioDescription)
}
SwiftUI.Button {
if isHapticsEnabled {
HapticsProvider.sendHapticFeedback(.light(0.5))
}

isChecked.toggle()
} label: {
if title.isEmpty == false || description.isEmpty == false {
VStack(alignment: .leading, spacing: 1) {
Text(title)
.textColor(labelColor)
.fontWeight(.medium)
.accessibility(.radioTitle)

Text(description)
.textSize(.small)
.textColor(descriptionColor)
.accessibility(.radioDescription)
}
}
)
}
.buttonStyle(
RadioButtonStyle(state: state, isChecked: isChecked)
)
Expand Down
36 changes: 14 additions & 22 deletions Sources/Orbit/Components/Select.swift
Original file line number Diff line number Diff line change
Expand Up @@ -24,33 +24,25 @@ public struct Select<Prefix: View, Suffix: View>: View {
@ViewBuilder private let suffix: Suffix

public var body: some View {
FieldWrapper(
defaultLabel,
message: message,
messageHeight: $messageHeight
) {
SwiftUI.Button(
action: {
if isHapticsEnabled {
HapticsProvider.sendHapticFeedback(.light(0.5))
}

action()
},
label: {
Text(value ?? prompt)
.textColor(valueColor)
.accessibility(.selectValue)
.padding(.horizontal, .small)
.padding(.vertical, verticalTextPadding)
FieldWrapper(defaultLabel, message: message, messageHeight: $messageHeight) {
SwiftUI.Button {
if isHapticsEnabled {
HapticsProvider.sendHapticFeedback(.light(0.5))
}
)

action()
} label: {
Text(value ?? prompt)
.textColor(valueColor)
.accessibility(.selectValue)
.padding(.horizontal, .small)
.padding(.vertical, verticalTextPadding)
}
.buttonStyle(
InputContentButtonStyle(
state: state,
label: compactLabel,
message: message,
isPlaceholder: value == nil
message: message
) {
prefix
.accessibility(.selectPrefix)
Expand Down
45 changes: 21 additions & 24 deletions Sources/Orbit/Components/Tag.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,34 +17,31 @@ public struct Tag<Icon: View>: View, PotentiallyEmptyView {

public var body: some View {
if isEmpty == false {
SwiftUI.Button(
action: {
if isHapticsEnabled {
HapticsProvider.sendHapticFeedback(.light(0.5))
SwiftUI.Button {
if isHapticsEnabled {
HapticsProvider.sendHapticFeedback(.light(0.5))
}

isSelected.toggle()
} label: {
HStack(spacing: 0) {
if idealSize.horizontal == false {
Spacer(minLength: 0)
}

HStack(spacing: 6) {
icon
.font(.system(size: Text.Size.normal.value))

Text(label)
}
.fixedSize(horizontal: true, vertical: false)

isSelected.toggle()
},
label: {
HStack(spacing: 0) {
if idealSize.horizontal == false {
Spacer(minLength: 0)
}

HStack(spacing: 6) {
icon
.font(.system(size: Text.Size.normal.value))

Text(label)
}
.fixedSize(horizontal: true, vertical: false)

if idealSize.horizontal == false {
Spacer(minLength: 0)
}
if idealSize.horizontal == false {
Spacer(minLength: 0)
}
}
)
}
.buttonStyle(
TagButtonStyle(
style: style,
Expand Down
Loading
Loading