diff --git a/WooCommerce/Classes/POS/Presentation/CardReaderConnection/UI States/PointOfSaleItemListErrorView.swift b/WooCommerce/Classes/POS/Presentation/CardReaderConnection/UI States/PointOfSaleItemListErrorView.swift index 0ea4050129e..b80c3121f76 100644 --- a/WooCommerce/Classes/POS/Presentation/CardReaderConnection/UI States/PointOfSaleItemListErrorView.swift +++ b/WooCommerce/Classes/POS/Presentation/CardReaderConnection/UI States/PointOfSaleItemListErrorView.swift @@ -13,19 +13,25 @@ struct PointOfSaleItemListErrorView: View { var body: some View { VStack { Spacer() - VStack(alignment: .center) { - POSErrorExclamationMark() - .padding(.bottom) + VStack(alignment: .center, spacing: POSSpacing.none) { + POSErrorExclamationMark(size: .large) + + Spacer().frame(height: PointOfSaleCardPresentPaymentLayout.imageAndTextSpacing) + Text(error.title) .accessibilityAddTraits(.isHeader) .foregroundStyle(Color.posOnSurface) .font(.posHeadingBold) - .padding(.bottom, PointOfSaleItemListErrorLayout.verticalPadding) + + Spacer().frame(height: PointOfSaleCardPresentPaymentLayout.textSpacing) + Text(error.subtitle) .foregroundStyle(Color.posOnSurface) .font(.posBodyLargeRegular()) .padding([.leading, .trailing]) - .padding(.bottom, PointOfSaleItemListErrorLayout.verticalPadding) + + Spacer().frame(height: PointOfSaleCardPresentPaymentLayout.textAndButtonSpacing) + Button(action: { onRetry?() }, label: { diff --git a/WooCommerce/Classes/POS/Presentation/CardReaderConnection/UI States/Reader Messages/PointOfSaleCardPresentPaymentLayout.swift b/WooCommerce/Classes/POS/Presentation/CardReaderConnection/UI States/Reader Messages/PointOfSaleCardPresentPaymentLayout.swift index 215f631e148..91b40c53ba8 100644 --- a/WooCommerce/Classes/POS/Presentation/CardReaderConnection/UI States/Reader Messages/PointOfSaleCardPresentPaymentLayout.swift +++ b/WooCommerce/Classes/POS/Presentation/CardReaderConnection/UI States/Reader Messages/PointOfSaleCardPresentPaymentLayout.swift @@ -3,11 +3,9 @@ import Foundation enum PointOfSaleCardPresentPaymentLayout { static let headerSize: CGSize = .init(width: 156, height: 156) static let imageAndTextSpacing: CGFloat = POSSpacing.large - static let textAndButtonSpacing: CGFloat = POSSpacing.xLarge + static let textAndButtonSpacing: CGFloat = POSSpacing.xxLarge static let textSpacing: CGFloat = POSSpacing.small static let buttonSpacing: CGFloat = POSSpacing.large - static let errorIconSize: CGFloat = 64 - static let largeErrorIconSize: CGFloat = 84 static let horizontalPadding: CGFloat = POSPadding.xxLarge static let errorContentMaxWidth: CGFloat = 604 } diff --git a/WooCommerce/Classes/POS/Presentation/CardReaderConnection/UI States/Reader Messages/PointOfSaleCardPresentPaymentValidatingOrderErrorMessageView.swift b/WooCommerce/Classes/POS/Presentation/CardReaderConnection/UI States/Reader Messages/PointOfSaleCardPresentPaymentValidatingOrderErrorMessageView.swift index ab867c5b3df..8b72c0d06f5 100644 --- a/WooCommerce/Classes/POS/Presentation/CardReaderConnection/UI States/Reader Messages/PointOfSaleCardPresentPaymentValidatingOrderErrorMessageView.swift +++ b/WooCommerce/Classes/POS/Presentation/CardReaderConnection/UI States/Reader Messages/PointOfSaleCardPresentPaymentValidatingOrderErrorMessageView.swift @@ -9,7 +9,7 @@ struct PointOfSaleCardPresentPaymentValidatingOrderErrorMessageView: View { var body: some View { VStack(alignment: .center, spacing: POSSpacing.none) { - POSErrorExclamationMark() + POSErrorExclamationMark(size: .large) .matchedGeometryEffect(id: animation.iconTransitionId, in: animation.namespace, properties: .position) Spacer() diff --git a/WooCommerce/Classes/POS/Presentation/CardReaderConnection/UI States/Reader Messages/Presented Views/PointOfSaleCardPresentPaymentCaptureFailedView.swift b/WooCommerce/Classes/POS/Presentation/CardReaderConnection/UI States/Reader Messages/Presented Views/PointOfSaleCardPresentPaymentCaptureFailedView.swift index d1b7a7b8bf9..86d7729954d 100644 --- a/WooCommerce/Classes/POS/Presentation/CardReaderConnection/UI States/Reader Messages/Presented Views/PointOfSaleCardPresentPaymentCaptureFailedView.swift +++ b/WooCommerce/Classes/POS/Presentation/CardReaderConnection/UI States/Reader Messages/Presented Views/PointOfSaleCardPresentPaymentCaptureFailedView.swift @@ -5,7 +5,7 @@ struct PointOfSaleCardPresentPaymentCaptureFailedView: View { var body: some View { VStack(alignment: .center, spacing: POSSpacing.none) { - POSErrorExclamationMark() + POSErrorExclamationMark(size: .large) .accessibilityAddTraits(.isHeader) Spacer() diff --git a/WooCommerce/Classes/POS/Presentation/Item Selector/ItemListErrorCardView.swift b/WooCommerce/Classes/POS/Presentation/Item Selector/ItemListErrorCardView.swift index 2fe3615428d..275ab3afc6d 100644 --- a/WooCommerce/Classes/POS/Presentation/Item Selector/ItemListErrorCardView.swift +++ b/WooCommerce/Classes/POS/Presentation/Item Selector/ItemListErrorCardView.swift @@ -8,7 +8,7 @@ struct ItemListErrorCardView: View { var body: some View { HStack(spacing: Constants.cardSpacing) { - POSErrorExclamationMark(size: 48) + POSErrorExclamationMark(size: .small) .frame(width: min(Constants.productCardSize * scale, Constants.maximumProductCardSize), height: Constants.productCardSize * scale) @@ -35,7 +35,7 @@ struct ItemListErrorCardView: View { .font(Constants.itemTitleFont) } .buttonStyle(POSOutlinedButtonStyle(size: .normal)) - .frame(maxWidth: Constants.accessoryButtonMaxWidth * scale) + .fixedSize(horizontal: true, vertical: false) .padding(Constants.accessoryButtonPadding * (1 / scale)) } .frame(maxWidth: .infinity, idealHeight: Constants.productCardSize * scale) diff --git a/WooCommerce/Classes/POS/Presentation/Item Selector/PointOfSaleItemListCardConstants.swift b/WooCommerce/Classes/POS/Presentation/Item Selector/PointOfSaleItemListCardConstants.swift index 0aa110b3a94..1f4074ff852 100644 --- a/WooCommerce/Classes/POS/Presentation/Item Selector/PointOfSaleItemListCardConstants.swift +++ b/WooCommerce/Classes/POS/Presentation/Item Selector/PointOfSaleItemListCardConstants.swift @@ -10,7 +10,6 @@ enum PointOfSaleItemListCardConstants { static let verticalTextPadding: CGFloat = POSPadding.small static let itemTitleFont: POSFontStyle = .posBodyLargeBold static let itemDetailFont: POSFontStyle = .posBodyLargeRegular() - static let accessoryButtonMaxWidth: CGFloat = 136 static let accessoryButtonPadding: CGFloat = POSPadding.medium static let backgroundColor: Color = .posSurfaceContainerLowest static let titleColor: Color = .posOnSurface diff --git a/WooCommerce/Classes/POS/Presentation/Order Messages/PointOfSaleOrderSyncErrorMessageView.swift b/WooCommerce/Classes/POS/Presentation/Order Messages/PointOfSaleOrderSyncErrorMessageView.swift index 715ebe7af78..eadc2a91bf3 100644 --- a/WooCommerce/Classes/POS/Presentation/Order Messages/PointOfSaleOrderSyncErrorMessageView.swift +++ b/WooCommerce/Classes/POS/Presentation/Order Messages/PointOfSaleOrderSyncErrorMessageView.swift @@ -6,10 +6,11 @@ struct PointOfSaleOrderSyncErrorMessageView: View { var body: some View { HStack(alignment: .center) { Spacer() - VStack(alignment: .center, spacing: Constants.headerSpacing) { + VStack(alignment: .center, spacing: POSSpacing.none) { Spacer() - POSErrorExclamationMark() - VStack(alignment: .center, spacing: Constants.textSpacing) { + POSErrorExclamationMark(size: .large) + Spacer().frame(height: PointOfSaleCardPresentPaymentLayout.imageAndTextSpacing) + VStack(alignment: .center, spacing: PointOfSaleCardPresentPaymentLayout.textSpacing) { Text(viewModel.title) .foregroundStyle(Color.posOnSurface) .font(.posHeadingBold) @@ -19,11 +20,12 @@ struct PointOfSaleOrderSyncErrorMessageView: View { .font(.posBodyLargeRegular()) .padding([.leading, .trailing]) } - Spacer() + Spacer().frame(height: PointOfSaleCardPresentPaymentLayout.textAndButtonSpacing) Button(viewModel.actionModel.title, action: viewModel.actionModel.handler) .buttonStyle(POSFilledButtonStyle(size: .normal)) .padding([.leading, .trailing], Constants.buttonSidePadding) .padding([.bottom], Constants.buttonBottomPadding) + Spacer() } .multilineTextAlignment(.center) Spacer() diff --git a/WooCommerce/Classes/POS/Presentation/Order Messages/PointOfSaleOrderSyncErrorMessageViewModel.swift b/WooCommerce/Classes/POS/Presentation/Order Messages/PointOfSaleOrderSyncErrorMessageViewModel.swift index 37e007a9f96..010da6ff29a 100644 --- a/WooCommerce/Classes/POS/Presentation/Order Messages/PointOfSaleOrderSyncErrorMessageViewModel.swift +++ b/WooCommerce/Classes/POS/Presentation/Order Messages/PointOfSaleOrderSyncErrorMessageViewModel.swift @@ -29,8 +29,8 @@ private extension PointOfSaleOrderSyncErrorMessageViewModel { ) static let actionTitle = NSLocalizedString( - "pointOfSale.orderSync.error.retry", - value: "Retry", + "pointOfSale.orderSync.error.tryAgain", + value: "Try again", comment: "Button title to retry synchronizing order and calculating order totals" ) } diff --git a/WooCommerce/Classes/POS/Presentation/Reusable Views/POSErrorExclamationMark.swift b/WooCommerce/Classes/POS/Presentation/Reusable Views/POSErrorExclamationMark.swift index 7ed45cd430a..86427cb8cec 100644 --- a/WooCommerce/Classes/POS/Presentation/Reusable Views/POSErrorExclamationMark.swift +++ b/WooCommerce/Classes/POS/Presentation/Reusable Views/POSErrorExclamationMark.swift @@ -3,8 +3,8 @@ import SwiftUI struct POSErrorExclamationMark: View { @Environment(\.dynamicTypeSize) private var dynamicTypeSize - private let size: CGFloat - init(size: CGFloat = PointOfSaleCardPresentPaymentLayout.errorIconSize) { + private let size: POSErrorAndAlertIconSize + init(size: POSErrorAndAlertIconSize = .medium) { self.size = size } @@ -12,14 +12,17 @@ struct POSErrorExclamationMark: View { Image(decorative: PointOfSaleAssets.exclamationMark.imageName) .resizable() .aspectRatio(contentMode: .fit) - .frame(maxHeight: size) + .frame(maxHeight: size.dimension) .layoutPriority(-1) - .foregroundStyle(Color.posAlert) .accessibilityHidden(true) .renderedIf(!dynamicTypeSize.isAccessibilitySize) } } #Preview { - POSErrorExclamationMark() + HStack { + POSErrorExclamationMark(size: .small) + POSErrorExclamationMark(size: .medium) + POSErrorExclamationMark(size: .large) + } } diff --git a/WooCommerce/Classes/POS/Presentation/Reusable Views/POSErrorXMark.swift b/WooCommerce/Classes/POS/Presentation/Reusable Views/POSErrorXMark.swift index 97afe1b064c..746729a6eb9 100644 --- a/WooCommerce/Classes/POS/Presentation/Reusable Views/POSErrorXMark.swift +++ b/WooCommerce/Classes/POS/Presentation/Reusable Views/POSErrorXMark.swift @@ -5,7 +5,7 @@ struct POSErrorXMark: View { var body: some View { Image(decorative: PointOfSaleAssets.error.imageName) - .font(.system(size: PointOfSaleCardPresentPaymentLayout.largeErrorIconSize)) + .font(.system(size: POSErrorAndAlertIconSize.large.dimension)) .foregroundStyle(Color.posAlert) .accessibilityHidden(true) .renderedIf(!dynamicTypeSize.isAccessibilitySize) diff --git a/WooCommerce/Classes/POS/Utils/POSErrorAndAlertIconSize.swift b/WooCommerce/Classes/POS/Utils/POSErrorAndAlertIconSize.swift new file mode 100644 index 00000000000..58a52b38ca6 --- /dev/null +++ b/WooCommerce/Classes/POS/Utils/POSErrorAndAlertIconSize.swift @@ -0,0 +1,20 @@ +import Foundation + +/// Various sizes of error and alert icons in POS. +/// Design ref: 1qcjzXitBHU7xPnpCOWnNM-fi-1114_19201 +enum POSErrorAndAlertIconSize { + case small + case medium + case large + + var dimension: CGFloat { + switch self { + case .small: + return 40.0 + case .medium: + return 56.0 + case .large: + return 80.0 + } + } +} diff --git a/WooCommerce/WooCommerce.xcodeproj/project.pbxproj b/WooCommerce/WooCommerce.xcodeproj/project.pbxproj index ed29ca954c6..a43a92487bb 100644 --- a/WooCommerce/WooCommerce.xcodeproj/project.pbxproj +++ b/WooCommerce/WooCommerce.xcodeproj/project.pbxproj @@ -623,6 +623,7 @@ 02EFF81A2ABC28BA0015ABB2 /* GiftCardInputViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02EFF8192ABC28BA0015ABB2 /* GiftCardInputViewModelTests.swift */; }; 02F1E6BD2A39805C00C3E4C7 /* ProductDescriptionAICoordinatorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02F1E6BC2A39805C00C3E4C7 /* ProductDescriptionAICoordinatorTests.swift */; }; 02F36F472978349500D97EA0 /* DomainPurchaseSuccessView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02F36F462978349500D97EA0 /* DomainPurchaseSuccessView.swift */; }; + 02F3884C2D6C38BB00619396 /* POSErrorAndAlertIconSize.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02F3884B2D6C38BB00619396 /* POSErrorAndAlertIconSize.swift */; }; 02F3A6842A618CD7004CD2E8 /* WordPressMediaLibraryPickerCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02F3A6832A618CD7004CD2E8 /* WordPressMediaLibraryPickerCoordinator.swift */; }; 02F3A6862A619270004CD2E8 /* WordPressMediaLibraryImagePickerCoordinatorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02F3A6852A619270004CD2E8 /* WordPressMediaLibraryImagePickerCoordinatorTests.swift */; }; 02F49ADA23BF356E00FA0BFA /* TitleAndTextFieldTableViewCell.ViewModel+State.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02F49AD923BF356E00FA0BFA /* TitleAndTextFieldTableViewCell.ViewModel+State.swift */; }; @@ -3839,6 +3840,7 @@ 02EFF8192ABC28BA0015ABB2 /* GiftCardInputViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GiftCardInputViewModelTests.swift; sourceTree = ""; }; 02F1E6BC2A39805C00C3E4C7 /* ProductDescriptionAICoordinatorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProductDescriptionAICoordinatorTests.swift; sourceTree = ""; }; 02F36F462978349500D97EA0 /* DomainPurchaseSuccessView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DomainPurchaseSuccessView.swift; sourceTree = ""; }; + 02F3884B2D6C38BB00619396 /* POSErrorAndAlertIconSize.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = POSErrorAndAlertIconSize.swift; sourceTree = ""; }; 02F3A6832A618CD7004CD2E8 /* WordPressMediaLibraryPickerCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WordPressMediaLibraryPickerCoordinator.swift; sourceTree = ""; }; 02F3A6852A619270004CD2E8 /* WordPressMediaLibraryImagePickerCoordinatorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WordPressMediaLibraryImagePickerCoordinatorTests.swift; sourceTree = ""; }; 02F49AD923BF356E00FA0BFA /* TitleAndTextFieldTableViewCell.ViewModel+State.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "TitleAndTextFieldTableViewCell.ViewModel+State.swift"; sourceTree = ""; }; @@ -7182,6 +7184,7 @@ 68625DE52D4134D50042B231 /* DynamicVStack.swift */, 02055B132D5DAB6400E51059 /* POSCornerRadiusStyle.swift */, 020564972D5DC96600E51059 /* POSShadowStyle.swift */, + 02F3884B2D6C38BB00619396 /* POSErrorAndAlertIconSize.swift */, ); path = Utils; sourceTree = ""; @@ -16878,6 +16881,7 @@ 20E188842AD059A50053E945 /* TapToPayEducationContactlessLimitView.swift in Sources */, EE8A30452B74948C001D7C66 /* OrderAttributionInfo+Origin.swift in Sources */, 205B7ECF2C19FD5200D14A36 /* PointOfSalePaymentSuccessViewModel.swift in Sources */, + 02F3884C2D6C38BB00619396 /* POSErrorAndAlertIconSize.swift in Sources */, 026D4652295D763B0037F59A /* CountryCode+FlagEmoji.swift in Sources */, B9F3DAAD29BB71B100DDD545 /* CollectPaymentAppIntent.swift in Sources */, 011D7A352CEC87B70007C187 /* CardPresentModalErrorEmailSent.swift in Sources */,