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

Add inline label support to Select #603

Merged
merged 8 commits into from
Jun 23, 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 modified Snapshots/iPad/SelectTests/testSelects.1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified Snapshots/iPhone/SelectTests/testSelects.1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
111 changes: 55 additions & 56 deletions Sources/Orbit/Components/InputField.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,17 @@ public struct InputField<Prefix: View, Suffix: View>: View, TextFieldBuildable {
@State private var isEditing: Bool = false
@State private var isSecureTextRedacted: Bool = true

private var label: String
private let label: String
@Binding private var value: String
private var prompt: String
private var state: InputState
private var style: InputFieldStyle
@ViewBuilder private let prefix: Prefix
@ViewBuilder private let suffix: Suffix

private var isSecure: Bool
private var passwordStrength: PasswordStrengthIndicator.PasswordStrength?
private var message: Message?
private let prompt: String
private let state: InputState
private let labelStyle: InputLabelStyle
@ViewBuilder private var prefix: Prefix
@ViewBuilder private var suffix: Suffix

private let isSecure: Bool
private let passwordStrength: PasswordStrengthIndicator.PasswordStrength?
private let message: Message?
@Binding private var messageHeight: CGFloat

// Builder properties (keyboard related)
Expand All @@ -44,7 +44,12 @@ public struct InputField<Prefix: View, Suffix: View>: View, TextFieldBuildable {
message: message,
messageHeight: $messageHeight
) {
InputContent(state: state, message: message, isEditing: isEditing) {
InputContent(
state: state,
message: message,
isEditing: isEditing,
isPlaceholder: value.isEmpty
) {
HStack(alignment: .firstTextBaseline, spacing: .small) {
compactLabel
textField
Expand All @@ -71,15 +76,21 @@ public struct InputField<Prefix: View, Suffix: View>: View, TextFieldBuildable {
}
}

@ViewBuilder private var compactLabel: some View {
FieldLabel(compactFieldLabel)
.textColor(value.isEmpty ? .inkDark : .inkLight)
.padding(.leading, prefix.isEmpty ? .small : 0)
}

@ViewBuilder private var textField: some View {
TextField(
value: $value,
prompt: prompt,
isSecureTextEntry: isSecure && isSecureTextRedacted,
font: .orbit(size: Text.Size.normal.value * sizeCategory.ratio, weight: .regular),
state: state,
leadingPadding: leadingPadding,
trailingPadding: trailingPadding
leadingPadding: textFieldLeadingPadding,
trailingPadding: textFieldTrailingPadding
)
.returnKeyType(returnKeyType)
.autocorrectionDisabled(isAutocorrectionDisabled)
Expand All @@ -98,15 +109,6 @@ public struct InputField<Prefix: View, Suffix: View>: View, TextFieldBuildable {
}
}

@ViewBuilder private var compactLabel: some View {
if style == .compact {
Text(label)
.textColor(compactLabelColor)
.fontWeight(.medium)
.padding(.leading, prefix.isEmpty ? .small : 0)
}
}

@ViewBuilder private var secureTextRedactedButton: some View {
if showSecureTextRedactedButton {
IconButton(isSecureTextRedacted ? .visibility : .visibilityOff) {
Expand All @@ -116,27 +118,26 @@ public struct InputField<Prefix: View, Suffix: View>: View, TextFieldBuildable {
}

private var fieldLabel: String {
switch style {
switch labelStyle {
case .default: return label
case .compact: return ""
}
}

private var messageDescription: String {
message?.description ?? ""
}

private var compactLabelColor: Color {
value.description.isEmpty ? .inkDark : .inkLight
private var compactFieldLabel: String {
switch labelStyle {
case .default: return ""
case .compact: return label
}
}

private var leadingPadding: CGFloat {
prefix.isEmpty && style == .default
private var textFieldLeadingPadding: CGFloat {
prefix.isEmpty && labelStyle == .default
? .small
: 0
}

private var trailingPadding: CGFloat {
private var textFieldTrailingPadding: CGFloat {
suffix.isEmpty ? .small : 0
}

Expand Down Expand Up @@ -166,7 +167,7 @@ public extension InputField {
suffix: Icon.Symbol? = nil,
prompt: String = "",
state: InputState = .default,
style: InputFieldStyle = .default,
labelStyle: InputLabelStyle = .default,
isSecure: Bool = false,
passwordStrength: PasswordStrengthIndicator.PasswordStrength? = nil,
message: Message? = nil,
Expand All @@ -177,7 +178,7 @@ public extension InputField {
value: value,
prompt: prompt,
state: state,
style: style,
labelStyle: labelStyle,
isSecure: isSecure,
passwordStrength: passwordStrength,
message: message,
Expand Down Expand Up @@ -206,7 +207,7 @@ public extension InputField {
value: Binding<String>,
prompt: String = "",
state: InputState = .default,
style: InputFieldStyle = .default,
labelStyle: InputLabelStyle = .default,
isSecure: Bool = false,
passwordStrength: PasswordStrengthIndicator.PasswordStrength? = nil,
message: Message? = nil,
Expand All @@ -218,7 +219,7 @@ public extension InputField {
self._value = value
self.prompt = prompt
self.state = state
self.style = style
self.labelStyle = labelStyle
self.isSecure = isSecure
self.passwordStrength = passwordStrength
self.message = message
Expand All @@ -228,17 +229,6 @@ public extension InputField {
}
}

// MARK: - Types

/// Style variant for Orbit InputField component.
public enum InputFieldStyle {

/// Style with label positioned above the InputField.
case `default`
/// Style with compact label positioned inside the InputField.
case compact
}

// MARK: - Identifiers
public extension AccessibilityID {

Expand Down Expand Up @@ -300,6 +290,15 @@ struct InputFieldPreviews: PreviewProvider {
StateWrapper(value) { state in
InputField("Secure", value: state, prefix: .grid, prompt: prompt, state: .default, isSecure: true)
}
StateWrapper(value) { state in
InputField("Compact", value: state, prefix: .grid, prompt: prompt, state: .default, labelStyle: .compact)
}
StateWrapper("") { state in
InputField("Compact", value: state, prefix: .grid, prompt: prompt, state: .default, labelStyle: .compact)
}
StateWrapper("") { state in
InputField("Compact", value: state, prompt: prompt, state: .default, labelStyle: .compact)
}
}
.padding(.medium)
.previewDisplayName()
Expand All @@ -317,10 +316,10 @@ struct InputFieldPreviews: PreviewProvider {
InputField(label, value: state, prefix: .grid, suffix: .grid, prompt: prompt, state: .default)
}
StateWrapper("") { state in
InputField(label, value: state, prefix: .grid, suffix: .grid, prompt: prompt, state: .default)
InputField("Inline", value: state, prefix: .grid, suffix: .grid, prompt: prompt, state: .default, labelStyle: .compact)
}
StateWrapper(value) { state in
InputField("Secure", value: state, prefix: .grid, prompt: prompt, state: .default, isSecure: true)
InputField("Inline", value: state, prefix: .grid, prompt: prompt, state: .default, labelStyle: .compact)
}
}
.frame(width: 100)
Expand All @@ -342,10 +341,10 @@ struct InputFieldPreviews: PreviewProvider {
}

Group {
inputField(value: longValue, prefix: .none, suffix: .none, message: .none, style: .compact)
inputField(value: "", prefix: .none, suffix: .none, message: .none, style: .compact)
inputField(value: "", message: .error(errorMessage), style: .compact)
inputField(value: value, message: .error(errorMessage), style: .compact)
inputField(value: longValue, prefix: .none, suffix: .none, message: .none, labelStyle: .compact)
inputField(value: "", prefix: .none, suffix: .none, message: .none, labelStyle: .compact)
inputField(value: "", message: .error(errorMessage), labelStyle: .compact)
inputField(value: value, message: .error(errorMessage), labelStyle: .compact)
}
}
.padding(.medium)
Expand Down Expand Up @@ -409,7 +408,7 @@ struct InputFieldPreviews: PreviewProvider {
.textLinkColor(.status(.critical))
.textAccentColor(.orangeNormal)

inputField("Compact", style: .compact)
inputField("Compact", labelStyle: .compact)

HStack(spacing: .medium) {
inputField(value: "No label")
Expand Down Expand Up @@ -437,7 +436,7 @@ struct InputFieldPreviews: PreviewProvider {
isSecure: Bool = false,
passwordStrength: PasswordStrengthIndicator.PasswordStrength? = nil,
message: Message? = nil,
style: InputFieldStyle = .default
labelStyle: InputLabelStyle = .default
) -> some View {
StateWrapper(value) { value in
InputField(
Expand All @@ -447,7 +446,7 @@ struct InputFieldPreviews: PreviewProvider {
suffix: suffix,
prompt: prompt,
state: state,
style: style,
labelStyle: labelStyle,
isSecure: isSecure,
passwordStrength: passwordStrength,
message: message
Expand Down
Loading