Skip to content

Commit e99b66b

Browse files
authored
Merge pull request #7995 from woocommerce/feat/7891-design-polishes
Account creation: design polishes - fonts, ToS link, text field focus styles
2 parents fb7325e + 14df3c3 commit e99b66b

File tree

4 files changed

+84
-8
lines changed

4 files changed

+84
-8
lines changed

WooCommerce/Classes/ViewRelated/Authentication/AccountCreationForm.swift

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,10 @@ final class AccountCreationFormHostingController: UIHostingController<AccountCre
3535

3636
/// A form that allows the user to create a WPCOM account with an email and password.
3737
struct AccountCreationForm: View {
38-
@Environment(\.customOpenURL) var customOpenURL
38+
private enum Field: Hashable {
39+
case email
40+
case password
41+
}
3942

4043
/// Triggered when the account is created and the app is authenticated.
4144
var completion: (() -> Void) = {}
@@ -46,6 +49,9 @@ struct AccountCreationForm: View {
4649
@ObservedObject private var viewModel: AccountCreationFormViewModel
4750

4851
@State private var isPerformingTask = false
52+
@State private var tosURL: URL?
53+
54+
@FocusState private var focusedField: Field?
4955

5056
init(viewModel: AccountCreationFormViewModel) {
5157
self.viewModel = viewModel
@@ -82,22 +88,35 @@ struct AccountCreationForm: View {
8288

8389
// Form fields.
8490
VStack(spacing: Layout.verticalSpacingBetweenFields) {
91+
// Email field.
8592
AccountCreationFormFieldView(viewModel: .init(header: Localization.emailFieldTitle,
8693
placeholder: Localization.emailFieldPlaceholder,
8794
keyboardType: .emailAddress,
8895
text: $viewModel.email,
8996
isSecure: false,
90-
errorMessage: viewModel.emailErrorMessage))
97+
errorMessage: viewModel.emailErrorMessage,
98+
isFocused: focusedField == .email))
99+
.focused($focusedField, equals: .email)
91100
.disabled(isPerformingTask)
101+
102+
// Password field.
92103
AccountCreationFormFieldView(viewModel: .init(header: Localization.passwordFieldTitle,
93104
placeholder: Localization.passwordFieldPlaceholder,
94105
keyboardType: .default,
95106
text: $viewModel.password,
96107
isSecure: true,
97-
errorMessage: viewModel.passwordErrorMessage))
108+
errorMessage: viewModel.passwordErrorMessage,
109+
isFocused: focusedField == .password))
110+
.focused($focusedField, equals: .password)
98111
.disabled(isPerformingTask)
112+
113+
// Terms of Service link.
99114
AttributedText(tosAttributedText)
100115
.attributedTextLinkColor(Color(.textLink))
116+
.environment(\.customOpenURL) { url in
117+
tosURL = url
118+
}
119+
.safariSheet(url: $tosURL)
101120
}
102121

103122
// CTA to submit the form.

WooCommerce/Classes/ViewRelated/Authentication/AccountCreationFormFieldView.swift

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ struct AccountCreationFormFieldViewModel {
1414
let isSecure: Bool
1515
/// Optional error message shown below the text field.
1616
let errorMessage: String?
17+
/// Whether the content in the text field is focused.
18+
let isFocused: Bool
1719
}
1820

1921
/// A field in the account creation form. Currently, there are two fields - email and password.
@@ -27,14 +29,14 @@ struct AccountCreationFormFieldView: View {
2729
var body: some View {
2830
VStack(alignment: .leading, spacing: Layout.verticalSpacing) {
2931
Text(viewModel.header)
30-
.bodyStyle()
32+
.subheadlineStyle()
3133
if viewModel.isSecure {
3234
SecureField(viewModel.placeholder, text: viewModel.text)
33-
.textFieldStyle(.roundedBorder)
35+
.textFieldStyle(RoundedBorderTextFieldStyle(focused: viewModel.isFocused))
3436
.keyboardType(viewModel.keyboardType)
3537
} else {
3638
TextField(viewModel.placeholder, text: viewModel.text)
37-
.textFieldStyle(.roundedBorder)
39+
.textFieldStyle(RoundedBorderTextFieldStyle(focused: viewModel.isFocused))
3840
.keyboardType(viewModel.keyboardType)
3941
}
4042
if let errorMessage = viewModel.errorMessage {
@@ -58,12 +60,14 @@ struct AccountCreationFormField_Previews: PreviewProvider {
5860
keyboardType: .emailAddress,
5961
text: .constant(""),
6062
isSecure: false,
61-
errorMessage: nil))
63+
errorMessage: nil,
64+
isFocused: true))
6265
AccountCreationFormFieldView(viewModel: .init(header: "Choose a password",
6366
placeholder: "Password",
6467
keyboardType: .default,
6568
text: .constant("w"),
6669
isSecure: true,
67-
errorMessage: "Too simple"))
70+
errorMessage: "Too simple",
71+
isFocused: false))
6872
}
6973
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import SwiftUI
2+
3+
/// Text field has a rounded border that has a thicker border and brighter border color when the field is focused.
4+
struct RoundedBorderTextFieldStyle: TextFieldStyle {
5+
private let focused: Bool
6+
private let focusedBorderColor: Color
7+
private let unfocusedBorderColor: Color
8+
9+
init(focused: Bool,
10+
focusedBorderColor: Color = Defaults.focusedBorderColor,
11+
unfocusedBorderColor: Color = Defaults.unfocusedBorderColor) {
12+
self.focused = focused
13+
self.focusedBorderColor = focusedBorderColor
14+
self.unfocusedBorderColor = unfocusedBorderColor
15+
}
16+
17+
func _body(configuration: TextField<Self._Label>) -> some View {
18+
configuration
19+
.padding(10)
20+
.background(
21+
RoundedRectangle(cornerRadius: 8, style: .continuous)
22+
.stroke(focused ? focusedBorderColor: unfocusedBorderColor,
23+
lineWidth: focused ? 2: 1)
24+
)
25+
}
26+
}
27+
28+
extension RoundedBorderTextFieldStyle {
29+
enum Defaults {
30+
static let focusedBorderColor: Color = .init(uiColor: .brand)
31+
static let unfocusedBorderColor: Color = .gray
32+
}
33+
}
34+
35+
struct TextFieldStyles_Previews: PreviewProvider {
36+
static var previews: some View {
37+
VStack {
38+
TextField("placeholder", text: .constant("focused"))
39+
.textFieldStyle(RoundedBorderTextFieldStyle(focused: true))
40+
TextField("placeholder", text: .constant("unfocused"))
41+
.textFieldStyle(RoundedBorderTextFieldStyle(focused: false))
42+
TextField("placeholder", text: .constant("focused with a different color"))
43+
.textFieldStyle(RoundedBorderTextFieldStyle(focused: true, focusedBorderColor: .orange))
44+
TextField("placeholder", text: .constant("unfocused with a different color"))
45+
.textFieldStyle(RoundedBorderTextFieldStyle(focused: false, unfocusedBorderColor: .cyan))
46+
}
47+
.preferredColorScheme(.dark)
48+
}
49+
}

WooCommerce/WooCommerce.xcodeproj/project.pbxproj

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -414,6 +414,7 @@
414414
02EA6BFA2435E92600FFF90A /* KingfisherImageDownloader+ImageDownloadable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02EA6BF92435E92600FFF90A /* KingfisherImageDownloader+ImageDownloadable.swift */; };
415415
02EA6BFC2435EC3500FFF90A /* MockImageDownloader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02EA6BFB2435EC3500FFF90A /* MockImageDownloader.swift */; };
416416
02EAA4C8290F992B00918DAB /* LoggedOutStoreCreationCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02EAA4C7290F992B00918DAB /* LoggedOutStoreCreationCoordinator.swift */; };
417+
02EAA4CA2911004B00918DAB /* TextFieldStyles.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02EAA4C92911004B00918DAB /* TextFieldStyles.swift */; };
417418
02ECD1DF24FF48D000735BE5 /* PaginationTracker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02ECD1DE24FF48D000735BE5 /* PaginationTracker.swift */; };
418419
02ECD1E124FF496200735BE5 /* PaginationTrackerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02ECD1E024FF496200735BE5 /* PaginationTrackerTests.swift */; };
419420
02ECD1E424FF5E0B00735BE5 /* AddProductCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02ECD1E324FF5E0B00735BE5 /* AddProductCoordinator.swift */; };
@@ -2357,6 +2358,7 @@
23572358
02EA6BF92435E92600FFF90A /* KingfisherImageDownloader+ImageDownloadable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "KingfisherImageDownloader+ImageDownloadable.swift"; sourceTree = "<group>"; };
23582359
02EA6BFB2435EC3500FFF90A /* MockImageDownloader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockImageDownloader.swift; sourceTree = "<group>"; };
23592360
02EAA4C7290F992B00918DAB /* LoggedOutStoreCreationCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoggedOutStoreCreationCoordinator.swift; sourceTree = "<group>"; };
2361+
02EAA4C92911004B00918DAB /* TextFieldStyles.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextFieldStyles.swift; sourceTree = "<group>"; };
23602362
02ECD1DE24FF48D000735BE5 /* PaginationTracker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PaginationTracker.swift; sourceTree = "<group>"; };
23612363
02ECD1E024FF496200735BE5 /* PaginationTrackerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PaginationTrackerTests.swift; sourceTree = "<group>"; };
23622364
02ECD1E324FF5E0B00735BE5 /* AddProductCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddProductCoordinator.swift; sourceTree = "<group>"; };
@@ -5962,6 +5964,7 @@
59625964
03076D39290C22BE008EE839 /* WebView.swift */,
59635965
03076D35290C162E008EE839 /* WebViewSheet.swift */,
59645966
03076D37290C223D008EE839 /* WooNavigationSheet.swift */,
5967+
02EAA4C92911004B00918DAB /* TextFieldStyles.swift */,
59655968
);
59665969
path = "SwiftUI Components";
59675970
sourceTree = "<group>";
@@ -10321,6 +10324,7 @@
1032110324
AE6C4FDF28A15BFE00EAC00D /* FeatureAnnouncementCardCell.swift in Sources */,
1032210325
CE5F462723AAC8C0006B1A5C /* RefundDetailsViewModel.swift in Sources */,
1032310326
D8815B132638686200EDAD62 /* CardPresentModalError.swift in Sources */,
10327+
02EAA4CA2911004B00918DAB /* TextFieldStyles.swift in Sources */,
1032410328
453DBF8E2387F34A006762A5 /* UICollectionViewCell+Helpers.swift in Sources */,
1032510329
45B9C63E23A8E50D007FC4C5 /* ProductPriceSettingsViewController.swift in Sources */,
1032610330
318853362639FC9C00F66A9C /* CardReaderSettingsPresentingViewController.swift in Sources */,

0 commit comments

Comments
 (0)