diff --git a/Info.plist b/Info.plist index cdc82fc..034ea6c 100644 --- a/Info.plist +++ b/Info.plist @@ -5,6 +5,7 @@ UIAppFonts Nunito-Regular.ttf + Nunito-SemiBold.ttf NunitoSans_7pt_Condensed-Bold.ttf diff --git a/MoreChess.xcodeproj/project.pbxproj b/MoreChess.xcodeproj/project.pbxproj index 51c6aa4..6cc2e50 100644 --- a/MoreChess.xcodeproj/project.pbxproj +++ b/MoreChess.xcodeproj/project.pbxproj @@ -44,7 +44,7 @@ B9FAC92E2BB04A01002A20F7 /* PlayCondition.swift in Sources */ = {isa = PBXBuildFile; fileRef = B9FAC92D2BB04A01002A20F7 /* PlayCondition.swift */; }; B9FAC9302BB05325002A20F7 /* GameView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B9FAC92F2BB05325002A20F7 /* GameView.swift */; }; B9FAC9342BB053CC002A20F7 /* LobbyView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B9FAC9332BB053CC002A20F7 /* LobbyView.swift */; }; - B9FAC9372BB054C2002A20F7 /* SolidButtonStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = B9FAC9362BB054C2002A20F7 /* SolidButtonStyle.swift */; }; + B9FAC9372BB054C2002A20F7 /* ButtonStyles.swift in Sources */ = {isa = PBXBuildFile; fileRef = B9FAC9362BB054C2002A20F7 /* ButtonStyles.swift */; }; B9FAC9392BB0586C002A20F7 /* LobbyState.swift in Sources */ = {isa = PBXBuildFile; fileRef = B9FAC9382BB0586C002A20F7 /* LobbyState.swift */; }; B9FAC93D2BB058DB002A20F7 /* ServiceType.swift in Sources */ = {isa = PBXBuildFile; fileRef = B9FAC93C2BB058DB002A20F7 /* ServiceType.swift */; }; B9FAC93F2BB059CD002A20F7 /* GameService.swift in Sources */ = {isa = PBXBuildFile; fileRef = B9FAC93E2BB059CD002A20F7 /* GameService.swift */; }; @@ -62,6 +62,10 @@ B9FAC9592BB2F92E002A20F7 /* Nunito-Regular.ttf in Resources */ = {isa = PBXBuildFile; fileRef = B9FAC9572BB2F92E002A20F7 /* Nunito-Regular.ttf */; }; B9FAC95B2BB2FD0C002A20F7 /* Typography.swift in Sources */ = {isa = PBXBuildFile; fileRef = B9FAC95A2BB2FD0C002A20F7 /* Typography.swift */; }; B9FAC95C2BB2FD0C002A20F7 /* Typography.swift in Sources */ = {isa = PBXBuildFile; fileRef = B9FAC95A2BB2FD0C002A20F7 /* Typography.swift */; }; + B9FAC9602BB30D8F002A20F7 /* StyleConstants.swift in Sources */ = {isa = PBXBuildFile; fileRef = B9FAC95F2BB30D8F002A20F7 /* StyleConstants.swift */; }; + B9FAC9612BB30D8F002A20F7 /* StyleConstants.swift in Sources */ = {isa = PBXBuildFile; fileRef = B9FAC95F2BB30D8F002A20F7 /* StyleConstants.swift */; }; + B9FAC9632BB30F40002A20F7 /* Nunito-SemiBold.ttf in Resources */ = {isa = PBXBuildFile; fileRef = B9FAC9622BB30F40002A20F7 /* Nunito-SemiBold.ttf */; }; + B9FAC9642BB30F40002A20F7 /* Nunito-SemiBold.ttf in Resources */ = {isa = PBXBuildFile; fileRef = B9FAC9622BB30F40002A20F7 /* Nunito-SemiBold.ttf */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -116,7 +120,7 @@ B9FAC92D2BB04A01002A20F7 /* PlayCondition.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlayCondition.swift; sourceTree = ""; }; B9FAC92F2BB05325002A20F7 /* GameView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GameView.swift; sourceTree = ""; }; B9FAC9332BB053CC002A20F7 /* LobbyView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LobbyView.swift; sourceTree = ""; }; - B9FAC9362BB054C2002A20F7 /* SolidButtonStyle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SolidButtonStyle.swift; sourceTree = ""; }; + B9FAC9362BB054C2002A20F7 /* ButtonStyles.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ButtonStyles.swift; sourceTree = ""; }; B9FAC9382BB0586C002A20F7 /* LobbyState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LobbyState.swift; sourceTree = ""; }; B9FAC93C2BB058DB002A20F7 /* ServiceType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServiceType.swift; sourceTree = ""; }; B9FAC93E2BB059CD002A20F7 /* GameService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GameService.swift; sourceTree = ""; }; @@ -132,6 +136,8 @@ B9FAC9572BB2F92E002A20F7 /* Nunito-Regular.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Nunito-Regular.ttf"; sourceTree = ""; }; B9FAC95A2BB2FD0C002A20F7 /* Typography.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Typography.swift; sourceTree = ""; }; B9FAC95E2BB2FE66002A20F7 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + B9FAC95F2BB30D8F002A20F7 /* StyleConstants.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StyleConstants.swift; sourceTree = ""; }; + B9FAC9622BB30F40002A20F7 /* Nunito-SemiBold.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Nunito-SemiBold.ttf"; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -325,7 +331,7 @@ B9FAC9352BB054A2002A20F7 /* Elements */ = { isa = PBXGroup; children = ( - B9FAC9362BB054C2002A20F7 /* SolidButtonStyle.swift */, + B9FAC9362BB054C2002A20F7 /* ButtonStyles.swift */, B9FAC9482BB06C91002A20F7 /* SimpleNavigationBackButton.swift */, B9FAC94A2BB06FB2002A20F7 /* WaitingView.swift */, ); @@ -361,6 +367,7 @@ B9FAC94E2BB2E833002A20F7 /* Color.swift */, B9FAC95A2BB2FD0C002A20F7 /* Typography.swift */, B9FAC9502BB2F46D002A20F7 /* Style.swift */, + B9FAC95F2BB30D8F002A20F7 /* StyleConstants.swift */, ); path = Resources; sourceTree = ""; @@ -369,6 +376,7 @@ isa = PBXGroup; children = ( B9FAC9572BB2F92E002A20F7 /* Nunito-Regular.ttf */, + B9FAC9622BB30F40002A20F7 /* Nunito-SemiBold.ttf */, B9FAC9532BB2F706002A20F7 /* NunitoSans_7pt_Condensed-Bold.ttf */, ); path = Fonts; @@ -503,6 +511,7 @@ B9FAC9192BAF070C002A20F7 /* Launch Screen.storyboard in Resources */, B9FAC9582BB2F92E002A20F7 /* Nunito-Regular.ttf in Resources */, B95CE53B2AD4CB5E00978591 /* Assets.xcassets in Resources */, + B9FAC9632BB30F40002A20F7 /* Nunito-SemiBold.ttf in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -510,6 +519,7 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( + B9FAC9642BB30F40002A20F7 /* Nunito-SemiBold.ttf in Resources */, B9FAC9592BB2F92E002A20F7 /* Nunito-Regular.ttf in Resources */, B95CE53C2AD4CB5E00978591 /* Assets.xcassets in Resources */, B9FAC9552BB2F706002A20F7 /* NunitoSans_7pt_Condensed-Bold.ttf in Resources */, @@ -546,10 +556,11 @@ B9FAC92E2BB04A01002A20F7 /* PlayCondition.swift in Sources */, B9FAC9392BB0586C002A20F7 /* LobbyState.swift in Sources */, B9FAC9112BAEF492002A20F7 /* PositioningState.swift in Sources */, - B9FAC9372BB054C2002A20F7 /* SolidButtonStyle.swift in Sources */, + B9FAC9372BB054C2002A20F7 /* ButtonStyles.swift in Sources */, B9FAC9412BB05A63002A20F7 /* LobbyInteractor.swift in Sources */, B94B61B32B461DD200C998F3 /* GridCoordinate.swift in Sources */, B9FAC9242BAF1E9F002A20F7 /* Board.swift in Sources */, + B9FAC9602BB30D8F002A20F7 /* StyleConstants.swift in Sources */, B9FAC9472BB06C0C002A20F7 /* ClientView.swift in Sources */, B95CE5392AD4CB5E00978591 /* ContentView.swift in Sources */, B9FAC92C2BAF3102002A20F7 /* MoveValidator.swift in Sources */, @@ -586,6 +597,7 @@ B90F55AD2BA6289800874F00 /* PieceView.swift in Sources */, B94B61B12B461D3200C998F3 /* Piece.swift in Sources */, B90F55AA2BA61F6E00874F00 /* MovesView.swift in Sources */, + B9FAC9612BB30D8F002A20F7 /* StyleConstants.swift in Sources */, B9FAC95C2BB2FD0C002A20F7 /* Typography.swift in Sources */, B94B61F62B68F8D700C998F3 /* PieceGenerator.swift in Sources */, ); diff --git a/Shared/Assets.xcassets/Gray.colorset/Contents.json b/Shared/Assets.xcassets/Gray.colorset/Contents.json new file mode 100644 index 0000000..d8a6892 --- /dev/null +++ b/Shared/Assets.xcassets/Gray.colorset/Contents.json @@ -0,0 +1,38 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0.664", + "green" : "0.664", + "red" : "0.664" + } + }, + "idiom" : "universal" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0.921", + "green" : "0.921", + "red" : "0.921" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Shared/MoreChessApp.swift b/Shared/MoreChessApp.swift index ec03438..da21145 100644 --- a/Shared/MoreChessApp.swift +++ b/Shared/MoreChessApp.swift @@ -10,7 +10,7 @@ import SwiftUI @main struct MoreChessApp: App { - /* + init() { for family in UIFont.familyNames { print("\(family)") @@ -19,7 +19,7 @@ struct MoreChessApp: App { } } } - */ + var body: some Scene { WindowGroup { diff --git a/Shared/Presentation/Elements/ButtonStyles.swift b/Shared/Presentation/Elements/ButtonStyles.swift new file mode 100644 index 0000000..7ed225e --- /dev/null +++ b/Shared/Presentation/Elements/ButtonStyles.swift @@ -0,0 +1,154 @@ +// +// ButtonStyles.swift +// MoreChess (iOS) +// +// Created by Richard Adem on 3/24/24. +// + +import SwiftUI + +struct PrimaryButtonStyle: ButtonStyle { + @Environment(\.isEnabled) private var isEnabled + + func makeBody(configuration: Configuration) -> some View { + + var backgroundColor: Color { + if isEnabled == false { + // Disabled + Color.disabled + } else if configuration.isPressed { + // Highlighted, just the background changes. + Color.accentColor.opacity(StyleConstants.highlightedOpacity) + } else { + // Normal + Color.accentColor + } + } + + configuration.label + .padding(12) + .font(StyleFont.button) + .strikethrough(isEnabled == false, color: Color.disabled) + .foregroundStyle(Color.background) + .background{ + RoundedRectangle(cornerRadius: StyleConstants.cornerRadius) + .fill(backgroundColor) + .animation(.easeOut(duration: StyleConstants.animationTime), + value: configuration.isPressed) + } + } +} + +struct SecondaryButtonStyle: ButtonStyle { + @Environment(\.isEnabled) private var isEnabled + + func makeBody(configuration: Configuration) -> some View { + + var backgroundColor: Color { + if isEnabled == false { + // Disabled + Color.disabled + } else if configuration.isPressed { + // Highlighted + Color.accentColor + } else { + // Normal + Color.accentColor + } + } + + configuration.label + .padding(10) + .font(StyleFont.button) + .strikethrough(isEnabled == false, color: Color.disabled) + .foregroundStyle(Color.accentColor) + .background{ + RoundedRectangle(cornerRadius: StyleConstants.cornerRadius) + .stroke(backgroundColor, lineWidth: StyleConstants.lineWidth) + .animation(.easeOut(duration: StyleConstants.animationTime), + value: configuration.isPressed) + } + // Change whole button on pressed. + .opacity(configuration.isPressed ? StyleConstants.highlightedOpacity : 1.0) + } +} + +struct SolidButtonStyle: ButtonStyle { + func makeBody(configuration: Configuration) -> some View { + configuration.label + .padding() + .background(Color.accentColor) + .foregroundStyle(Color.background) + .font(.headline) + .clipShape(Capsule()) + .scaleEffect(configuration.isPressed ? 1.2 : 1) + .animation(.easeOut(duration: StyleConstants.animationTime), value: configuration.isPressed) + } +} + +struct FunkyButtonStyle: ButtonStyle { + + @Environment(\.colorScheme) var colorScheme + + fileprivate struct CurvedLine: Shape { + func path(in rect: CGRect) -> Path { + Path { path in + path.move(to: CGPoint(x: rect.minX, y: rect.minY)) + path.addQuadCurve(to: CGPoint(x: rect.maxX, y: rect.midY), + control: CGPoint(x: rect.width * 1.0, y: rect.height * -0.4)) + + } + } + } + + func makeBody(configuration: Configuration) -> some View { + let foregroundColor = colorScheme == .dark ? Color.foreground : Color.background + + configuration.label + .padding() + .background(LinearGradient(gradient: Gradient(colors: [.accentColor, .black]), + startPoint: .top, + endPoint: .bottom)) + .overlay{ + VStack { + CurvedLine() + .stroke(.white, style: StrokeStyle(lineWidth: 4, lineCap: .round)) + .frame(height: 10) + .padding(.vertical, 6) + .padding(.leading, 19) + .padding(.trailing, 14) + Spacer() + } + } + .foregroundStyle(foregroundColor) + .font(.headline) + .clipShape(Capsule()) + .scaleEffect(configuration.isPressed ? 1.2 : 1) + .rotationEffect(.degrees(configuration.isPressed ? 30 : 0)) + .animation(.easeOut(duration: StyleConstants.animationTime), value: configuration.isPressed) + } +} + +#Preview { + VStack { + + Button("Button") { }.buttonStyle(PrimaryButtonStyle()) + Button("Disabled") { }.buttonStyle(PrimaryButtonStyle()) + .disabled(true) + + Button("Button") { }.buttonStyle(SecondaryButtonStyle()) + Button("Disabled") { }.buttonStyle(SecondaryButtonStyle()) + .disabled(true) + + + Button("Press Me") { } + .buttonStyle(SolidButtonStyle()) + + Button("Press Me") { } + .buttonStyle(FunkyButtonStyle()) + + Button("Very long text for a button") { } + .buttonStyle(FunkyButtonStyle()) + } + .style() +} diff --git a/Shared/Presentation/Elements/SolidButtonStyle.swift b/Shared/Presentation/Elements/SolidButtonStyle.swift deleted file mode 100644 index 318ef79..0000000 --- a/Shared/Presentation/Elements/SolidButtonStyle.swift +++ /dev/null @@ -1,28 +0,0 @@ -// -// SolidButtonStyle.swift -// MoreChess (iOS) -// -// Created by Richard Adem on 3/24/24. -// - -import SwiftUI - -struct SolidButtonStyle: ButtonStyle { - func makeBody(configuration: Configuration) -> some View { - configuration.label - .padding() - .background(.tint) - .foregroundStyle(Color.background) - .font(.headline) - .clipShape(Capsule()) - .scaleEffect(configuration.isPressed ? 1.2 : 1) - .animation(.easeOut(duration: 0.2), value: configuration.isPressed) - } -} - -#Preview { - Button("Press Me") { - } - .buttonStyle(SolidButtonStyle()) - .style() -} diff --git a/Shared/Presentation/Lobby/LobbyView.swift b/Shared/Presentation/Lobby/LobbyView.swift index 5381498..e219088 100644 --- a/Shared/Presentation/Lobby/LobbyView.swift +++ b/Shared/Presentation/Lobby/LobbyView.swift @@ -38,12 +38,12 @@ struct LobbyView: View { Button("Host") { lobbyInteractor.select(serviceType: .host) } - .buttonStyle(SolidButtonStyle()) + .buttonStyle(PrimaryButtonStyle()) Button("Join") { lobbyInteractor.select(serviceType: .client) } - .buttonStyle(SolidButtonStyle()) + .buttonStyle(PrimaryButtonStyle()) } // HStack } .style() diff --git a/Shared/Resources/Color.swift b/Shared/Resources/Color.swift index 2bca157..6a94cb5 100644 --- a/Shared/Resources/Color.swift +++ b/Shared/Resources/Color.swift @@ -8,6 +8,12 @@ import SwiftUI extension Color { + + // Functional Colors static let foreground = Color("Foreground") static let background = Color("Background") + static let disabled = Color.brandedGray + + // Defined Colors + static let brandedGray = Color("Gray") } diff --git a/Shared/Resources/Fonts/Nunito-SemiBold.ttf b/Shared/Resources/Fonts/Nunito-SemiBold.ttf new file mode 100644 index 0000000..1326a7d Binary files /dev/null and b/Shared/Resources/Fonts/Nunito-SemiBold.ttf differ diff --git a/Shared/Resources/StyleConstants.swift b/Shared/Resources/StyleConstants.swift new file mode 100644 index 0000000..19a4ca7 --- /dev/null +++ b/Shared/Resources/StyleConstants.swift @@ -0,0 +1,18 @@ +// +// StyleConstants.swift +// MoreChess +// +// Created by Richard Adem on 3/26/24. +// + +import Foundation + +enum StyleConstants { + // Layout + static let lineWidth: CGFloat = 2 + static let highlightedOpacity: CGFloat = 0.25 + static let cornerRadius: CGFloat = 8 + + // Animation + static let animationTime: TimeInterval = 0.2 +} diff --git a/Shared/Resources/Typography.swift b/Shared/Resources/Typography.swift index 7b8aa1a..ba61b31 100644 --- a/Shared/Resources/Typography.swift +++ b/Shared/Resources/Typography.swift @@ -10,6 +10,7 @@ import SwiftUI enum CustomFontNames { static let nunitoSansCondensedBold = "NunitoSans7ptCondensed-Bold" static let nunitoRegular = "Nunito-Regular" + static let nunitoSemiBold = "Nunito-SemiBold" } struct StyleFont { @@ -21,4 +22,8 @@ struct StyleFont { let scaledSize = UIFontMetrics.default.scaledValue(for: 16) return Font.custom(CustomFontNames.nunitoRegular, size: scaledSize) } + static let button: Font = { + let scaledSize = UIFontMetrics.default.scaledValue(for: 18) + return Font.custom(CustomFontNames.nunitoSemiBold, size: scaledSize) + }() }