diff --git a/Core/DesignSystem/Resources/Color.xcassets/backgroundLinearTop.colorset/Contents.json b/Core/DesignSystem/Resources/Color.xcassets/backgroundLinearTop.colorset/Contents.json new file mode 100644 index 0000000..c1cb2dc --- /dev/null +++ b/Core/DesignSystem/Resources/Color.xcassets/backgroundLinearTop.colorset/Contents.json @@ -0,0 +1,20 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0xFF", + "green" : "0x6F", + "red" : "0x00" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Core/DesignSystem/Resources/Color.xcassets/buttonLinearBottom.colorset/Contents.json b/Core/DesignSystem/Resources/Color.xcassets/buttonLinearBottom.colorset/Contents.json new file mode 100644 index 0000000..414157d --- /dev/null +++ b/Core/DesignSystem/Resources/Color.xcassets/buttonLinearBottom.colorset/Contents.json @@ -0,0 +1,20 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0xF6", + "green" : "0x7A", + "red" : "0x36" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Core/DesignSystem/Resources/Color.xcassets/buttonLinearTop.colorset/Contents.json b/Core/DesignSystem/Resources/Color.xcassets/buttonLinearTop.colorset/Contents.json new file mode 100644 index 0000000..259ae4c --- /dev/null +++ b/Core/DesignSystem/Resources/Color.xcassets/buttonLinearTop.colorset/Contents.json @@ -0,0 +1,20 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0xF7", + "green" : "0x91", + "red" : "0x4B" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Core/DesignSystem/Resources/Image.xcassets/loginBackground.imageset/Contents.json b/Core/DesignSystem/Resources/Image.xcassets/loginBackground.imageset/Contents.json new file mode 100644 index 0000000..d61b245 --- /dev/null +++ b/Core/DesignSystem/Resources/Image.xcassets/loginBackground.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "Mark-in.png", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Core/DesignSystem/Resources/Image.xcassets/loginBackground.imageset/Mark-in.png b/Core/DesignSystem/Resources/Image.xcassets/loginBackground.imageset/Mark-in.png new file mode 100644 index 0000000..c2a17d8 Binary files /dev/null and b/Core/DesignSystem/Resources/Image.xcassets/loginBackground.imageset/Mark-in.png differ diff --git a/Core/DesignSystem/Sources/Components/Buttons/MarkAddButton.swift b/Core/DesignSystem/Sources/Components/Buttons/MarkAddButton.swift new file mode 100644 index 0000000..77b4d19 --- /dev/null +++ b/Core/DesignSystem/Sources/Components/Buttons/MarkAddButton.swift @@ -0,0 +1,41 @@ +// +// MarkAddButton.swift +// DesignSystem +// +// Created by 이정동 on 6/7/25. +// + +import SwiftUI + +#if os(macOS) +public struct MarkAddButton: View { + + private let action: () -> Void + + public init(_ action: @escaping () -> Void) { + self.action = action + } + + public var body: some View { + Button { + action() + } label: { + Text("추가") + .padding(.vertical, 4) + .padding(.horizontal, 14) + .foregroundStyle(.markWhite) + .background(LinearGradient.button) + .font(.pretendard(size: 14, weight: .medium)) + .markRoundedOutline(cornerRadius: 6) + } + .buttonStyle(.plain) + } +} + + +#Preview { + MarkAddButton { + + } +} +#endif diff --git a/Core/DesignSystem/Sources/Components/Buttons/MarkCancelButton.swift b/Core/DesignSystem/Sources/Components/Buttons/MarkCancelButton.swift new file mode 100644 index 0000000..4a9ba87 --- /dev/null +++ b/Core/DesignSystem/Sources/Components/Buttons/MarkCancelButton.swift @@ -0,0 +1,43 @@ +// +// MarkCancelButton.swift +// DesignSystem +// +// Created by 이정동 on 6/7/25. +// + +import SwiftUI + +#if os(macOS) +public struct MarkCancelButton: View { + private let action: () -> Void + + public init(_ action: @escaping () -> Void) { + self.action = action + } + + public var body: some View { + Button { + action() + } label: { + Text("취소") + .padding(.vertical, 4) + .padding(.horizontal, 14) + .foregroundStyle(.markBlack) + .background(.markWhite) + .font(.pretendard(size: 14, weight: .medium)) + .markRoundedOutline( + cornerRadius: 6, + lineWidth: 0.5, + lineColor: .markBlack10 + ) + } + .buttonStyle(.plain) + } +} + +#Preview { + MarkCancelButton { + + } +} +#endif diff --git a/Core/DesignSystem/Sources/Components/TextFields/MarkTextField.swift b/Core/DesignSystem/Sources/Components/TextFields/MarkTextField.swift new file mode 100644 index 0000000..dab26f7 --- /dev/null +++ b/Core/DesignSystem/Sources/Components/TextFields/MarkTextField.swift @@ -0,0 +1,34 @@ +// +// MarkTextField.swift +// DesignSystem +// +// Created by 이정동 on 6/9/25. +// + +import SwiftUI + +#if os(macOS) +public struct MarkTextField: View { + + @Binding var text: String + let placeholder: String + + public init( + text: Binding, + placeholder: String = "" + ) { + self._text = text + self.placeholder = placeholder + } + + public var body: some View { + TextField("", text: $text, prompt: Text(placeholder)) + .textFieldStyle(.roundedBorder) + } +} + +#Preview { + @Previewable @State var text = "" + MarkTextField(text: $text, placeholder: "입력") +} +#endif diff --git a/Core/DesignSystem/Sources/Color.swift b/Core/DesignSystem/Sources/Resouce+Ext/Color+Ext.swift similarity index 84% rename from Core/DesignSystem/Sources/Color.swift rename to Core/DesignSystem/Sources/Resouce+Ext/Color+Ext.swift index cc3f3d4..9741455 100644 --- a/Core/DesignSystem/Sources/Color.swift +++ b/Core/DesignSystem/Sources/Resouce+Ext/Color+Ext.swift @@ -54,3 +54,17 @@ public extension ShapeStyle where Self == Color { static var markBackground: Self { .background } } + +public extension LinearGradient { + static let background = Self( + colors: [.backgroundLinearTop, .background], + startPoint: .top, + endPoint: .bottom + ) + + static let button = Self( + colors: [.buttonLinearTop, .buttonLinearBottom], + startPoint: .top, + endPoint: .bottom + ) +} diff --git a/Core/DesignSystem/Sources/Font.swift b/Core/DesignSystem/Sources/Resouce+Ext/Font+Ext.swift similarity index 100% rename from Core/DesignSystem/Sources/Font.swift rename to Core/DesignSystem/Sources/Resouce+Ext/Font+Ext.swift diff --git a/Core/DesignSystem/Sources/Image.swift b/Core/DesignSystem/Sources/Resouce+Ext/Image+Ext.swift similarity index 81% rename from Core/DesignSystem/Sources/Image.swift rename to Core/DesignSystem/Sources/Resouce+Ext/Image+Ext.swift index 2197ff5..7985209 100644 --- a/Core/DesignSystem/Sources/Image.swift +++ b/Core/DesignSystem/Sources/Resouce+Ext/Image+Ext.swift @@ -11,4 +11,5 @@ public extension ImageResource { static let sampleImage: ImageResource = .test static let apple: ImageResource = .appleLogo static let google: ImageResource = .googleLogo + static let backgroundLogo: ImageResource = .loginBackground } diff --git a/Core/DesignSystem/Sources/ViewModifiers/RoundedOutlineModifier.swift b/Core/DesignSystem/Sources/ViewModifiers/RoundedOutlineModifier.swift new file mode 100644 index 0000000..60477f8 --- /dev/null +++ b/Core/DesignSystem/Sources/ViewModifiers/RoundedOutlineModifier.swift @@ -0,0 +1,43 @@ +// +// RoundedStrokeModifier.swift +// DesignSystem +// +// Created by 이정동 on 6/7/25. +// + +import SwiftUI + +struct RoundedOutlineModifier: ViewModifier { + + let cornerRadius: CGFloat + let lineWidth: CGFloat + let lineColor: Color + + func body(content: Content) -> some View { + content + .clipShape( + RoundedRectangle(cornerRadius: cornerRadius) + ) + .overlay(content: { + RoundedRectangle(cornerRadius: cornerRadius) + .stroke(lineWidth: lineWidth) + .fill(lineColor) + }) + } +} + +public extension View { + func markRoundedOutline( + cornerRadius: CGFloat, + lineWidth: CGFloat = 0, + lineColor: Color = .clear + ) -> some View { + self.modifier( + RoundedOutlineModifier( + cornerRadius: cornerRadius, + lineWidth: lineWidth, + lineColor: lineColor + ) + ) + } +} diff --git a/Mark-In/Sources/Feature/AddFolder/AddFolderView.swift b/Mark-In/Sources/Feature/AddFolder/AddFolderView.swift index c3d8837..1cf78de 100644 --- a/Mark-In/Sources/Feature/AddFolder/AddFolderView.swift +++ b/Mark-In/Sources/Feature/AddFolder/AddFolderView.swift @@ -29,8 +29,7 @@ struct AddFolderView: View { Text("폴더를 추가:") .frame(maxWidth: .infinity, alignment: .leading) - TextField("", text: $name, prompt: Text("제목")) - .textFieldStyle(.roundedBorder) + MarkTextField(text: $title, placeholder: "제목") .padding(.top, 14) .disabled(isSaving) @@ -41,39 +40,19 @@ struct AddFolderView: View { .scaleEffect(0.4, anchor: .center) } - Button { + MarkCancelButton { dismiss() - } label: { - Text("취소") - .padding(.vertical, 4) - .padding(.horizontal, 14) - .foregroundStyle(.markBlack) - .background(.markWhite) - .clipShape(RoundedRectangle(cornerRadius: 6)) - .overlay { - RoundedRectangle(cornerRadius: 6) - .stroke(.markBlack10, lineWidth: 0.5) - } } .disabled(isSaving) - Button { + MarkAddButton { let writeFolder = WriteFolder(name: name) store.send(.didTapAddFolderButton(writeFolder)) - } label: { - Text("추가") - .padding(.vertical, 4) - .padding(.horizontal, 14) - .foregroundStyle(.markWhite) - .background(.markPoint) - .clipShape(RoundedRectangle(cornerRadius: 6)) } .disabled(name.isEmpty || isSaving) } .frame(maxWidth: .infinity, alignment: .trailing) .padding(.top, 18) - .font(.pretendard(size: 14, weight: .medium)) - .buttonStyle(.plain) } .padding(20) .frame(width: 400) diff --git a/Mark-In/Sources/Feature/AddLink/AddLinkView.swift b/Mark-In/Sources/Feature/AddLink/AddLinkView.swift index 2a4b662..9c46425 100644 --- a/Mark-In/Sources/Feature/AddLink/AddLinkView.swift +++ b/Mark-In/Sources/Feature/AddLink/AddLinkView.swift @@ -56,11 +56,9 @@ struct AddLinkView: View { .pickerStyle(.menu) .labelsHidden() - TextField("", text: $url, prompt: Text("주소")) - .textFieldStyle(.roundedBorder) + MarkTextField(text: $url, placeholder: "주소") - TextField("", text: $title, prompt: Text("제목(선택)")) - .textFieldStyle(.roundedBorder) + MarkTextField(text: $title, placeholder: "제목(선택)") } .padding(.top, 14) .disabled(isSaving) @@ -73,43 +71,23 @@ struct AddLinkView: View { .scaleEffect(0.4, anchor: .center) } - Button { + MarkCancelButton { dismiss() - } label: { - Text("취소") - .padding(.vertical, 4) - .padding(.horizontal, 14) - .foregroundStyle(.markBlack) - .background(.markWhite) - .clipShape(RoundedRectangle(cornerRadius: 6)) - .overlay { - RoundedRectangle(cornerRadius: 6) - .stroke(.markBlack10, lineWidth: 0.5) - } } .disabled(isSaving) - Button { + MarkAddButton { let link = WriteLink( url: url, title: title.isEmpty ? nil : title, folderID: currentFolder.id ) store.send(.addLinkButtonTapped(link: link)) - } label: { - Text("추가") - .padding(.vertical, 4) - .padding(.horizontal, 14) - .foregroundStyle(.markWhite) - .background(.markPoint) - .clipShape(RoundedRectangle(cornerRadius: 6)) } .disabled(url.isEmpty || isSaving) } .frame(maxWidth: .infinity, alignment: .trailing) .padding(.top, 18) - .font(.pretendard(size: 14, weight: .medium)) - .buttonStyle(.plain) } .padding(20) .frame(width: 400) diff --git a/Mark-In/Sources/Feature/Login/LoginView.swift b/Mark-In/Sources/Feature/Login/LoginView.swift index adc4098..f6fef75 100644 --- a/Mark-In/Sources/Feature/Login/LoginView.swift +++ b/Mark-In/Sources/Feature/Login/LoginView.swift @@ -20,12 +20,12 @@ struct LoginView: View { var body: some View { ZStack { - LinearGradient( - colors: [.markPoint, .markWhite], - startPoint: .top, - endPoint: .bottom - ) - .ignoresSafeArea() + LinearGradient.background + .ignoresSafeArea() + + Image(.backgroundLogo) + .resizable() + .aspectRatio(contentMode: .fill) VStack(spacing: 28) { headerView @@ -158,14 +158,11 @@ private struct SignInButton: View { .contentShape(Rectangle()) } .buttonStyle(.plain) - .clipShape( - RoundedRectangle(cornerRadius: 10) + .markRoundedOutline( + cornerRadius: 10, + lineWidth: 0.5, + lineColor: .markBlack30 ) - .overlay(content: { - RoundedRectangle(cornerRadius: 10) - .stroke(lineWidth: 0.5) - .fill(.markBlack30) - }) } } diff --git a/Mark-In/Sources/Feature/Main/LinkListView.swift b/Mark-In/Sources/Feature/Main/LinkListView.swift index 47c29ff..66036f5 100644 --- a/Mark-In/Sources/Feature/Main/LinkListView.swift +++ b/Mark-In/Sources/Feature/Main/LinkListView.swift @@ -112,13 +112,11 @@ private struct LinkCell: View { .padding([.top, .bottom], 12) .background(.markWhite) } - .clipShape( - RoundedRectangle(cornerRadius: 6) + .markRoundedOutline( + cornerRadius: 6, + lineWidth: 0.5, + lineColor: .markBlack20 ) - .overlay(content: { - RoundedRectangle(cornerRadius: 6) - .stroke(.markBlack20, lineWidth: 0.5) - }) .contextMenu { Button { store.send(.deleteLinkButtonTapped(link: link))