From 20173d9d20dbe8a5d30a6592fde59a52d2a38b86 Mon Sep 17 00:00:00 2001 From: opficdev Date: Tue, 22 Sep 2026 18:22:46 +0900 Subject: [PATCH 01/17] =?UTF-8?q?refactor:=20=EC=BB=A4=EC=8A=A4=ED=85=80?= =?UTF-8?q?=20=ED=83=91=EB=B0=94=20=EB=B2=84=ED=8A=BC=20=ED=81=AC=EA=B8=B0?= =?UTF-8?q?=EC=99=80=20=EA=B3=B5=ED=86=B5=20=EC=8A=A4=ED=83=80=EC=9D=BC=20?= =?UTF-8?q?=ED=86=B5=ED=95=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Sources/Goal/Create/GoalCreateView.swift | 10 +--- .../GoalCreateTodoSelectionSheet.swift | 12 +---- .../Record/Editor/RecordEditorView.swift | 12 +---- .../Record/GoalDetail/GoalDetailView.swift | 8 +--- .../Record/GoalDetail/GoalTodoLinkSheet.swift | 14 +----- .../History/RecordVersionHistoryView.swift | 4 +- .../HomeTab/Sources/Home/HomeView.swift | 16 +------ .../HomeTab/Sources/Search/SearchView.swift | 4 +- .../Sources/Extension/View+.swift | 47 ++++++++++++++++--- .../Sources/Todo/Editor/TodoEditorView.swift | 23 ++------- .../Todo/Editor/TodoPropertiesView.swift | 8 +--- .../Sources/Profile/ProfileView.swift | 2 +- 12 files changed, 58 insertions(+), 102 deletions(-) diff --git a/Application/Presentation/Development/Sources/Goal/Create/GoalCreateView.swift b/Application/Presentation/Development/Sources/Goal/Create/GoalCreateView.swift index 60d55234..e041f56b 100644 --- a/Application/Presentation/Development/Sources/Goal/Create/GoalCreateView.swift +++ b/Application/Presentation/Development/Sources/Goal/Create/GoalCreateView.swift @@ -13,10 +13,6 @@ public struct GoalCreateView: View { @Environment(\.dismiss) private var dismiss @State private var store: StoreOf @FocusState private var focusedField: GoalCreateField? - @ScaledMetric(relativeTo: .title) private var iconSize = UIFont.preferredFont( - forTextStyle: .title2, - compatibleWith: UITraitCollection(preferredContentSizeCategory: .large) - ).lineHeight private let onCompletion: (DevelopmentGoal) -> Void public init(onCompletion: @escaping (DevelopmentGoal) -> Void = { _ in }) { @@ -42,7 +38,6 @@ public struct GoalCreateView: View { } .safeAreaInset(edge: .top, spacing: 0) { GoalCreateTopBar( - iconSize: iconSize, isSaving: store.isSaving, onClose: dismiss.callAsFunction ) @@ -76,7 +71,6 @@ public struct GoalCreateView: View { } private struct GoalCreateTopBar: View { - let iconSize: CGFloat let isSaving: Bool let onClose: () -> Void @@ -89,13 +83,11 @@ private struct GoalCreateTopBar: View { Button(action: onClose) { if #available(iOS 26.0, *) { Image(systemName: "xmark") - .frame(width: iconSize, height: iconSize) - .font(.title) } else { Text(RecordPresentation.text("common_close")) } } - .topBarButtonStyle() + .topBarButtonStyle(usesTextBeforeIOS26: true) .disabled(isSaving) Spacer() diff --git a/Application/Presentation/Development/Sources/Goal/TodoSelection/GoalCreateTodoSelectionSheet.swift b/Application/Presentation/Development/Sources/Goal/TodoSelection/GoalCreateTodoSelectionSheet.swift index a0e9f0bc..5625b24f 100644 --- a/Application/Presentation/Development/Sources/Goal/TodoSelection/GoalCreateTodoSelectionSheet.swift +++ b/Application/Presentation/Development/Sources/Goal/TodoSelection/GoalCreateTodoSelectionSheet.swift @@ -10,10 +10,6 @@ import PresentationShared struct GoalCreateTodoSelectionSheet: View { @Bindable var store: StoreOf - @ScaledMetric(relativeTo: .title) private var iconSize = UIFont.preferredFont( - forTextStyle: .title2, - compatibleWith: UITraitCollection(preferredContentSizeCategory: .large) - ).lineHeight var body: some View { ScrollView { @@ -94,28 +90,24 @@ struct GoalCreateTodoSelectionSheet: View { } label: { if #available(iOS 26.0, *) { Image(systemName: "xmark") - .frame(width: iconSize, height: iconSize) - .font(.title) } else { Text(RecordPresentation.text("common_close")) } } - .topBarButtonStyle(color: Color.surface) + .topBarButtonStyle(color: Color.surface, usesTextBeforeIOS26: true) Spacer() Button { store.send(.view(.save)) } label: { if #available(iOS 26.0, *) { Image(systemName: "checkmark") - .frame(width: iconSize, height: iconSize) .foregroundStyle(Color.primary) - .font(.title) } else { Text(RecordPresentation.text("development_goal_todo_done")) .foregroundStyle(Color.accent) } } - .topBarButtonStyle(color: Color.surface) + .topBarButtonStyle(color: Color.surface, usesTextBeforeIOS26: true) } } .padding(.horizontal, 16) diff --git a/Application/Presentation/Development/Sources/Record/Editor/RecordEditorView.swift b/Application/Presentation/Development/Sources/Record/Editor/RecordEditorView.swift index f049b8b4..564e3306 100644 --- a/Application/Presentation/Development/Sources/Record/Editor/RecordEditorView.swift +++ b/Application/Presentation/Development/Sources/Record/Editor/RecordEditorView.swift @@ -13,10 +13,6 @@ public struct RecordEditorView: View { @Environment(\.dismiss) private var dismiss @State private var store: StoreOf @FocusState private var focusedField: Field? - @ScaledMetric(relativeTo: .title) private var iconSize = UIFont.preferredFont( - forTextStyle: .title2, - compatibleWith: UITraitCollection(preferredContentSizeCategory: .large) - ).lineHeight private let onCompletion: () -> Void public init( @@ -71,13 +67,11 @@ public struct RecordEditorView: View { } label: { if #available(iOS 26.0, *) { Image(systemName: "xmark") - .frame(width: iconSize, height: iconSize) - .font(.title) } else { Text(RecordPresentation.text("common_close")) } } - .topBarButtonStyle() + .topBarButtonStyle(usesTextBeforeIOS26: true) .disabled(store.isLoading) Spacer() Text(RecordPresentation.text( @@ -93,15 +87,13 @@ public struct RecordEditorView: View { } label: { if #available(iOS 26.0, *) { Image(systemName: "checkmark") - .frame(width: iconSize, height: iconSize) .foregroundStyle(Color.primary) - .font(.title) } else { Text(RecordPresentation.text("development_record_save")) .foregroundStyle(Color.accent) } } - .topBarButtonStyle(color: Color.surface) + .topBarButtonStyle(color: Color.surface, usesTextBeforeIOS26: true) .disabled(!store.isReadyToSave) } .padding(.horizontal) diff --git a/Application/Presentation/Development/Sources/Record/GoalDetail/GoalDetailView.swift b/Application/Presentation/Development/Sources/Record/GoalDetail/GoalDetailView.swift index 5e86515e..ccb591d5 100644 --- a/Application/Presentation/Development/Sources/Record/GoalDetail/GoalDetailView.swift +++ b/Application/Presentation/Development/Sources/Record/GoalDetail/GoalDetailView.swift @@ -106,19 +106,13 @@ public struct GoalDetailView: View { Spacer() if let status = store.goalStatus { Image(systemName: "ellipsis") - .font(.title3.weight(.semibold)) - .frame(width: 28, height: 28) .prominentMenu( items: statusMenuItems(status), isEnabled: !store.isLoading && !store.isTransitioning ) { status in store.send(.view(.selectStatus(status))) } - .adaptiveButtonStyle( - shape: .circle, - color: .surface, - glassEffect: .enabled - ) + .topBarButtonStyle(color: .surface) } } .padding(.horizontal) diff --git a/Application/Presentation/Development/Sources/Record/GoalDetail/GoalTodoLinkSheet.swift b/Application/Presentation/Development/Sources/Record/GoalDetail/GoalTodoLinkSheet.swift index 5721e6f2..88ce2d3c 100644 --- a/Application/Presentation/Development/Sources/Record/GoalDetail/GoalTodoLinkSheet.swift +++ b/Application/Presentation/Development/Sources/Record/GoalDetail/GoalTodoLinkSheet.swift @@ -11,10 +11,6 @@ import PresentationShared struct GoalTodoLinkSheet: View { @Bindable var store: StoreOf - @ScaledMetric(relativeTo: .title) private var iconSize = UIFont.preferredFont( - forTextStyle: .title2, - compatibleWith: UITraitCollection(preferredContentSizeCategory: .large) - ).lineHeight var body: some View { ScrollView { @@ -53,19 +49,15 @@ struct GoalTodoLinkSheet: View { } label: { if #available(iOS 26.0, *) { Image(systemName: "xmark") - .frame(width: iconSize, height: iconSize) - .font(.title) } else { Text(RecordPresentation.text("common_close")) } } - .topBarButtonStyle(color: Color.surface) + .topBarButtonStyle(color: Color.surface, usesTextBeforeIOS26: true) .disabled(store.isUpdating) Spacer() HStack(spacing: 8) { Image(systemName: "ellipsis") - .font(.title3.weight(.semibold)) - .frame(width: iconSize, height: iconSize) .prominentMenu( items: clearSelectionMenuItems, isEnabled: store.canClearSelection @@ -78,15 +70,13 @@ struct GoalTodoLinkSheet: View { } label: { if #available(iOS 26.0, *) { Image(systemName: "checkmark") - .frame(width: iconSize, height: iconSize) .foregroundStyle(Color.primary) - .font(.title) } else { Text(RecordPresentation.text("development_goal_todo_done")) .foregroundStyle(Color.accent) } } - .topBarButtonStyle(color: Color.surface) + .topBarButtonStyle(color: Color.surface, usesTextBeforeIOS26: true) .disabled(!store.canSave) } } diff --git a/Application/Presentation/Development/Sources/Record/History/RecordVersionHistoryView.swift b/Application/Presentation/Development/Sources/Record/History/RecordVersionHistoryView.swift index 225e5252..048e5f32 100644 --- a/Application/Presentation/Development/Sources/Record/History/RecordVersionHistoryView.swift +++ b/Application/Presentation/Development/Sources/Record/History/RecordVersionHistoryView.swift @@ -270,10 +270,8 @@ struct RecordBackButton: View { var body: some View { Button(action: action) { Image(systemName: "chevron.left") - .font(.title3.weight(.semibold)) - .frame(width: 28, height: 28) } - .adaptiveButtonStyle(shape: .circle, color: .surface, glassEffect: .enabled) + .topBarButtonStyle(color: .surface) } } diff --git a/Application/Presentation/HomeTab/Sources/Home/HomeView.swift b/Application/Presentation/HomeTab/Sources/Home/HomeView.swift index c7e0b687..c4f8cc09 100644 --- a/Application/Presentation/HomeTab/Sources/Home/HomeView.swift +++ b/Application/Presentation/HomeTab/Sources/Home/HomeView.swift @@ -118,26 +118,14 @@ public struct HomeView: View { store.send(.store(.setPresentation(.searchView, true))) } label: { Image(systemName: "magnifyingglass") - .font(.title3.weight(.semibold)) - .frame(width: 28, height: 28) } - .adaptiveButtonStyle( - shape: .circle, - color: .surface, - glassEffect: .enabled - ) + .topBarButtonStyle(color: .surface) Button { store.send(.store(.setPresentation(.contentPicker, true))) } label: { Image(systemName: "plus") - .font(.title3.weight(.semibold)) - .frame(width: 28, height: 28) } - .adaptiveButtonStyle( - shape: .circle, - color: .surface, - glassEffect: .enabled - ) + .topBarButtonStyle(color: .surface) .disabled(!store.isNetworkConnected) } .padding(.bottom, 8) diff --git a/Application/Presentation/HomeTab/Sources/Search/SearchView.swift b/Application/Presentation/HomeTab/Sources/Search/SearchView.swift index 91150ee8..4d33e341 100644 --- a/Application/Presentation/HomeTab/Sources/Search/SearchView.swift +++ b/Application/Presentation/HomeTab/Sources/Search/SearchView.swift @@ -61,10 +61,8 @@ struct SearchView: View { } label: { Image(systemName: "chevron.left") .foregroundStyle(Color.textSecondary) - .font(.title) - .padding(6) } - .adaptiveButtonStyle(shape: .circle, color: .border, glassEffect: .enabled) + .topBarButtonStyle(color: .border) SearchField(store: store) } .frame(maxWidth: .infinity, alignment: .leading) diff --git a/Application/Presentation/PresentationShared/Sources/Extension/View+.swift b/Application/Presentation/PresentationShared/Sources/Extension/View+.swift index 61b59fc3..9717b279 100644 --- a/Application/Presentation/PresentationShared/Sources/Extension/View+.swift +++ b/Application/Presentation/PresentationShared/Sources/Extension/View+.swift @@ -13,13 +13,16 @@ public enum AdaptiveButtonGlassEffect { } public extension View { - @ViewBuilder - func topBarButtonStyle(color: Color = .clear) -> some View { - if #available(iOS 26.0, *) { - adaptiveButtonStyle(shape: .circle, color: color, glassEffect: .enabled) - } else { - adaptiveButtonStyle(color: color, glassEffect: .enabled) - } + func topBarButtonStyle( + color: Color = .clear, + usesTextBeforeIOS26: Bool = false, + glassEffect: AdaptiveButtonGlassEffect = .enabled + ) -> some View { + modifier(TopBarButtonStyleModifier( + color: color, + usesTextBeforeIOS26: usesTextBeforeIOS26, + glassEffect: glassEffect + )) } func toolbarBackground(_ color: Color) -> some View { @@ -156,3 +159,33 @@ public extension View { } } } + +private struct TopBarButtonStyleModifier: ViewModifier { + @ScaledMetric(relativeTo: .title) private var iconSize = UIFont.preferredFont( + forTextStyle: .title2, + compatibleWith: UITraitCollection(preferredContentSizeCategory: .large) + ).lineHeight + let color: Color + let usesTextBeforeIOS26: Bool + let glassEffect: AdaptiveButtonGlassEffect + + private var isIcon: Bool { + if #available(iOS 26.0, *) { + true + } else { + !usesTextBeforeIOS26 + } + } + + func body(content: Content) -> some View { + let label = content + .font(isIcon ? .title : nil) + .frame(width: isIcon ? iconSize : nil, height: isIcon ? iconSize : nil) + + if isIcon { + label.adaptiveButtonStyle(shape: .circle, color: color, glassEffect: glassEffect) + } else { + label.adaptiveButtonStyle(color: color, glassEffect: glassEffect) + } + } +} diff --git a/Application/Presentation/PresentationShared/Sources/Todo/Editor/TodoEditorView.swift b/Application/Presentation/PresentationShared/Sources/Todo/Editor/TodoEditorView.swift index 0e63a62d..c9a33ebf 100644 --- a/Application/Presentation/PresentationShared/Sources/Todo/Editor/TodoEditorView.swift +++ b/Application/Presentation/PresentationShared/Sources/Todo/Editor/TodoEditorView.swift @@ -166,10 +166,6 @@ private struct ToolBar: View { let showsActions: Bool let onClose: () -> Void let onSubmit: () -> Void - @ScaledMetric(relativeTo: .title) private var iconSize = UIFont.preferredFont( - forTextStyle: .title1, - compatibleWith: UITraitCollection(preferredContentSizeCategory: .large) - ).lineHeight var body: some View { HStack { @@ -178,13 +174,11 @@ private struct ToolBar: View { } label: { if #available(iOS 26.0, *) { Image(systemName: "xmark") - .frame(width: iconSize, height: iconSize) - .font(.title) } else { Text(String(localized: "common_close", bundle: PresentationResources.bundle)) } } - .adaptiveButtonStyle(shape: .circle, glassEffect: .enabled) + .topBarButtonStyle(usesTextBeforeIOS26: true) Spacer() Text(store.navigationTitle) .font(.title3.bold()) @@ -201,10 +195,6 @@ private struct ToolBar: View { struct EditorToolbarActions: View { let store: StoreOf let onSubmit: () -> Void - @ScaledMetric(relativeTo: .title) private var iconSize = UIFont.preferredFont( - forTextStyle: .title1, - compatibleWith: UITraitCollection(preferredContentSizeCategory: .large) - ).lineHeight var body: some View { HStack { @@ -212,30 +202,25 @@ struct EditorToolbarActions: View { store.send(.showInspector(.options)) } label: { Image(systemName: "info.circle") - .frame(width: iconSize, height: iconSize) .foregroundStyle(Color.primary) } - .font(.title) - .adaptiveButtonStyle(shape: .circle, color: Color.surface, glassEffect: .enabled) + .topBarButtonStyle(color: Color.surface) if store.isLoading { ProgressView() - .frame(width: iconSize, height: iconSize) - .adaptiveButtonStyle(shape: .circle, color: Color.surface, glassEffect: .enabled) + .topBarButtonStyle(color: Color.surface) } else { Button { onSubmit() } label: { if #available(iOS 26.0, *) { Image(systemName: "checkmark") - .frame(width: iconSize, height: iconSize) .foregroundStyle(Color.primary) - .font(.title) } else { Text(String(localized: "todo_manage_save", bundle: PresentationResources.bundle)) .foregroundStyle(Color.primary) } } - .adaptiveButtonStyle(shape: .circle, color: Color.surface, glassEffect: .enabled) + .topBarButtonStyle(color: Color.surface, usesTextBeforeIOS26: true) .disabled(!store.isReadyToSubmit) } } diff --git a/Application/Presentation/PresentationShared/Sources/Todo/Editor/TodoPropertiesView.swift b/Application/Presentation/PresentationShared/Sources/Todo/Editor/TodoPropertiesView.swift index e9cce042..85492ba2 100644 --- a/Application/Presentation/PresentationShared/Sources/Todo/Editor/TodoPropertiesView.swift +++ b/Application/Presentation/PresentationShared/Sources/Todo/Editor/TodoPropertiesView.swift @@ -12,10 +12,6 @@ import Core public struct TodoPropertiesView: View { @Bindable var store: StoreOf @FocusState private var isTagFieldFocused: Bool - @ScaledMetric(relativeTo: .title) private var iconSize = UIFont.preferredFont( - forTextStyle: .title1, - compatibleWith: UITraitCollection(preferredContentSizeCategory: .large) - ).lineHeight var showsEditorActions = false var onSubmit: () -> Void = {} let onClose: () -> Void @@ -53,11 +49,9 @@ public struct TodoPropertiesView: View { onClose() } label: { Image(systemName: "checkmark") - .frame(width: iconSize, height: iconSize) .foregroundStyle(Color.primary) } - .font(.title) - .adaptiveButtonStyle(shape: .circle, color: Color.surface, glassEffect: .enabled) + .topBarButtonStyle(color: Color.surface) } } .padding(.horizontal) diff --git a/Application/Presentation/ProfileTab/Sources/Profile/ProfileView.swift b/Application/Presentation/ProfileTab/Sources/Profile/ProfileView.swift index 2d19cd10..834856a5 100644 --- a/Application/Presentation/ProfileTab/Sources/Profile/ProfileView.swift +++ b/Application/Presentation/ProfileTab/Sources/Profile/ProfileView.swift @@ -84,7 +84,7 @@ public struct ProfileView: View { Image(systemName: "gearshape") .foregroundStyle(Color.textTertiary) } - .adaptiveButtonStyle() + .topBarButtonStyle(glassEffect: .disabled) } Text("꾸준히 쌓아온 개발 기록을 확인하세요") .foregroundStyle(Color.textSecondary) From 623b3f9a44d88150b7fd1e0599a88404ff295683 Mon Sep 17 00:00:00 2001 From: opficdev Date: Tue, 22 Sep 2026 18:29:29 +0900 Subject: [PATCH 02/17] =?UTF-8?q?ui:=20=ED=83=91=EB=B0=94=20=EB=B2=84?= =?UTF-8?q?=ED=8A=BC=20=EC=95=84=EC=9D=B4=EC=BD=98=20=EA=B8=80=EA=BC=B4?= =?UTF-8?q?=EC=9D=84=20title2=EB=A1=9C=20=EC=A1=B0=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../PresentationShared/Sources/Extension/View+.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Application/Presentation/PresentationShared/Sources/Extension/View+.swift b/Application/Presentation/PresentationShared/Sources/Extension/View+.swift index 9717b279..837d679c 100644 --- a/Application/Presentation/PresentationShared/Sources/Extension/View+.swift +++ b/Application/Presentation/PresentationShared/Sources/Extension/View+.swift @@ -179,7 +179,7 @@ private struct TopBarButtonStyleModifier: ViewModifier { func body(content: Content) -> some View { let label = content - .font(isIcon ? .title : nil) + .font(isIcon ? .title2 : nil) .frame(width: isIcon ? iconSize : nil, height: isIcon ? iconSize : nil) if isIcon { From bf2dbf3766a490e3e1753bc07ffe92cb17ad6cf5 Mon Sep 17 00:00:00 2001 From: opficdev Date: Tue, 22 Sep 2026 23:26:03 +0900 Subject: [PATCH 03/17] =?UTF-8?q?ui:=20iOS=20=EB=B2=84=EC=A0=84=EB=B3=84?= =?UTF-8?q?=20=EC=BB=A4=EC=8A=A4=ED=85=80=20=ED=83=91=EB=B0=94=20=EB=B2=84?= =?UTF-8?q?=ED=8A=BC=20=EA=B5=AC=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Sources/Goal/Create/GoalCreateView.swift | 2 +- .../GoalCreateTodoSelectionSheet.swift | 5 +- .../Record/Editor/RecordEditorView.swift | 5 +- .../Record/GoalDetail/GoalDetailView.swift | 43 +++++++--- .../Record/GoalDetail/GoalTodoLinkSheet.swift | 38 ++++++--- .../History/RecordVersionHistoryView.swift | 15 +++- .../HomeTab/Sources/Home/HomeView.swift | 53 ++++++++++--- .../HomeTab/Sources/Search/SearchView.swift | 26 ++++-- .../Sources/Extension/View+.swift | 44 ++++------- .../Sources/Todo/Editor/TodoEditorView.swift | 79 +++++++++++++------ .../Todo/Editor/TodoPropertiesView.swift | 27 +++++-- .../Sources/Profile/ProfileView.swift | 21 +++-- 12 files changed, 246 insertions(+), 112 deletions(-) diff --git a/Application/Presentation/Development/Sources/Goal/Create/GoalCreateView.swift b/Application/Presentation/Development/Sources/Goal/Create/GoalCreateView.swift index e041f56b..a2494530 100644 --- a/Application/Presentation/Development/Sources/Goal/Create/GoalCreateView.swift +++ b/Application/Presentation/Development/Sources/Goal/Create/GoalCreateView.swift @@ -87,7 +87,7 @@ private struct GoalCreateTopBar: View { Text(RecordPresentation.text("common_close")) } } - .topBarButtonStyle(usesTextBeforeIOS26: true) + .topBarButtonStyle() .disabled(isSaving) Spacer() diff --git a/Application/Presentation/Development/Sources/Goal/TodoSelection/GoalCreateTodoSelectionSheet.swift b/Application/Presentation/Development/Sources/Goal/TodoSelection/GoalCreateTodoSelectionSheet.swift index 5625b24f..87b8bab7 100644 --- a/Application/Presentation/Development/Sources/Goal/TodoSelection/GoalCreateTodoSelectionSheet.swift +++ b/Application/Presentation/Development/Sources/Goal/TodoSelection/GoalCreateTodoSelectionSheet.swift @@ -94,20 +94,19 @@ struct GoalCreateTodoSelectionSheet: View { Text(RecordPresentation.text("common_close")) } } - .topBarButtonStyle(color: Color.surface, usesTextBeforeIOS26: true) + .topBarButtonStyle(legacyColor: Color.surface) Spacer() Button { store.send(.view(.save)) } label: { if #available(iOS 26.0, *) { Image(systemName: "checkmark") - .foregroundStyle(Color.primary) } else { Text(RecordPresentation.text("development_goal_todo_done")) .foregroundStyle(Color.accent) } } - .topBarButtonStyle(color: Color.surface, usesTextBeforeIOS26: true) + .topBarButtonStyle(legacyColor: Color.surface) } } .padding(.horizontal, 16) diff --git a/Application/Presentation/Development/Sources/Record/Editor/RecordEditorView.swift b/Application/Presentation/Development/Sources/Record/Editor/RecordEditorView.swift index 564e3306..3d693ed5 100644 --- a/Application/Presentation/Development/Sources/Record/Editor/RecordEditorView.swift +++ b/Application/Presentation/Development/Sources/Record/Editor/RecordEditorView.swift @@ -71,7 +71,7 @@ public struct RecordEditorView: View { Text(RecordPresentation.text("common_close")) } } - .topBarButtonStyle(usesTextBeforeIOS26: true) + .topBarButtonStyle() .disabled(store.isLoading) Spacer() Text(RecordPresentation.text( @@ -87,13 +87,12 @@ public struct RecordEditorView: View { } label: { if #available(iOS 26.0, *) { Image(systemName: "checkmark") - .foregroundStyle(Color.primary) } else { Text(RecordPresentation.text("development_record_save")) .foregroundStyle(Color.accent) } } - .topBarButtonStyle(color: Color.surface, usesTextBeforeIOS26: true) + .topBarButtonStyle(legacyColor: Color.surface) .disabled(!store.isReadyToSave) } .padding(.horizontal) diff --git a/Application/Presentation/Development/Sources/Record/GoalDetail/GoalDetailView.swift b/Application/Presentation/Development/Sources/Record/GoalDetail/GoalDetailView.swift index ccb591d5..1e53bba3 100644 --- a/Application/Presentation/Development/Sources/Record/GoalDetail/GoalDetailView.swift +++ b/Application/Presentation/Development/Sources/Record/GoalDetail/GoalDetailView.swift @@ -101,18 +101,43 @@ public struct GoalDetailView: View { private var topBar: some View { HStack { - RecordBackButton(action: dismiss.callAsFunction) + if #available(iOS 26.0, *) { + Button(action: dismiss.callAsFunction) { + Image(systemName: "xmark") + } + .topBarButtonStyle() .disabled(store.isTransitioning) + } else { + RecordBackButton(action: dismiss.callAsFunction) + .disabled(store.isTransitioning) + } Spacer() if let status = store.goalStatus { - Image(systemName: "ellipsis") - .prominentMenu( - items: statusMenuItems(status), - isEnabled: !store.isLoading && !store.isTransitioning - ) { status in - store.send(.view(.selectStatus(status))) - } - .topBarButtonStyle(color: .surface) + if #available(iOS 26.0, *) { + Image(systemName: "ellipsis") + .prominentMenu( + items: statusMenuItems(status), + isEnabled: !store.isLoading && !store.isTransitioning + ) { status in + store.send(.view(.selectStatus(status))) + } + .topBarButtonStyle() + } else { + Image(systemName: "ellipsis") + .font(.title3.weight(.semibold)) + .frame(width: 28, height: 28) + .prominentMenu( + items: statusMenuItems(status), + isEnabled: !store.isLoading && !store.isTransitioning + ) { status in + store.send(.view(.selectStatus(status))) + } + .adaptiveButtonStyle( + shape: .circle, + color: .surface, + glassEffect: .enabled + ) + } } } .padding(.horizontal) diff --git a/Application/Presentation/Development/Sources/Record/GoalDetail/GoalTodoLinkSheet.swift b/Application/Presentation/Development/Sources/Record/GoalDetail/GoalTodoLinkSheet.swift index 88ce2d3c..03d065e4 100644 --- a/Application/Presentation/Development/Sources/Record/GoalDetail/GoalTodoLinkSheet.swift +++ b/Application/Presentation/Development/Sources/Record/GoalDetail/GoalTodoLinkSheet.swift @@ -10,6 +10,10 @@ import Domain import PresentationShared struct GoalTodoLinkSheet: View { + @ScaledMetric(relativeTo: .title) private var iconSize = UIFont.preferredFont( + forTextStyle: .title2, + compatibleWith: UITraitCollection(preferredContentSizeCategory: .large) + ).lineHeight @Bindable var store: StoreOf var body: some View { @@ -53,30 +57,42 @@ struct GoalTodoLinkSheet: View { Text(RecordPresentation.text("common_close")) } } - .topBarButtonStyle(color: Color.surface, usesTextBeforeIOS26: true) + .topBarButtonStyle(legacyColor: Color.surface) .disabled(store.isUpdating) Spacer() HStack(spacing: 8) { - Image(systemName: "ellipsis") - .prominentMenu( - items: clearSelectionMenuItems, - isEnabled: store.canClearSelection - ) { _ in - store.send(.view(.clearSelection)) - } - .topBarButtonStyle(color: Color.surface) + if #available(iOS 26.0, *) { + Image(systemName: "ellipsis") + .prominentMenu( + items: clearSelectionMenuItems, + isEnabled: store.canClearSelection + ) { _ in + store.send(.view(.clearSelection)) + } + .topBarButtonStyle() + } else { + Image(systemName: "ellipsis") + .font(.title3.weight(.semibold)) + .frame(width: iconSize, height: iconSize) + .prominentMenu( + items: clearSelectionMenuItems, + isEnabled: store.canClearSelection + ) { _ in + store.send(.view(.clearSelection)) + } + .topBarButtonStyle(legacyColor: Color.surface) + } Button { store.send(.view(.save)) } label: { if #available(iOS 26.0, *) { Image(systemName: "checkmark") - .foregroundStyle(Color.primary) } else { Text(RecordPresentation.text("development_goal_todo_done")) .foregroundStyle(Color.accent) } } - .topBarButtonStyle(color: Color.surface, usesTextBeforeIOS26: true) + .topBarButtonStyle(legacyColor: Color.surface) .disabled(!store.canSave) } } diff --git a/Application/Presentation/Development/Sources/Record/History/RecordVersionHistoryView.swift b/Application/Presentation/Development/Sources/Record/History/RecordVersionHistoryView.swift index 048e5f32..f013ad7c 100644 --- a/Application/Presentation/Development/Sources/Record/History/RecordVersionHistoryView.swift +++ b/Application/Presentation/Development/Sources/Record/History/RecordVersionHistoryView.swift @@ -268,10 +268,19 @@ struct RecordBackButton: View { let action: () -> Void var body: some View { - Button(action: action) { - Image(systemName: "chevron.left") + if #available(iOS 26.0, *) { + Button(action: action) { + Image(systemName: "chevron.left") + } + .topBarButtonStyle() + } else { + Button(action: action) { + Image(systemName: "chevron.left") + .font(.title3.weight(.semibold)) + .frame(width: 28, height: 28) + } + .adaptiveButtonStyle(shape: .circle, color: .surface, glassEffect: .enabled) } - .topBarButtonStyle(color: .surface) } } diff --git a/Application/Presentation/HomeTab/Sources/Home/HomeView.swift b/Application/Presentation/HomeTab/Sources/Home/HomeView.swift index c4f8cc09..fadb6445 100644 --- a/Application/Presentation/HomeTab/Sources/Home/HomeView.swift +++ b/Application/Presentation/HomeTab/Sources/Home/HomeView.swift @@ -114,19 +114,50 @@ public struct HomeView: View { Text("DevLog") .font(.largeTitle.weight(.bold)) Spacer() - Button { - store.send(.store(.setPresentation(.searchView, true))) - } label: { - Image(systemName: "magnifyingglass") + if #available(iOS 26.0, *) { + Button { + store.send(.store(.setPresentation(.searchView, true))) + } label: { + Image(systemName: "magnifyingglass") + } + .topBarButtonStyle() + } else { + Button { + store.send(.store(.setPresentation(.searchView, true))) + } label: { + Image(systemName: "magnifyingglass") + .font(.title3.weight(.semibold)) + .frame(width: 28, height: 28) + } + .adaptiveButtonStyle( + shape: .circle, + color: .surface, + glassEffect: .enabled + ) } - .topBarButtonStyle(color: .surface) - Button { - store.send(.store(.setPresentation(.contentPicker, true))) - } label: { - Image(systemName: "plus") + if #available(iOS 26.0, *) { + Button { + store.send(.store(.setPresentation(.contentPicker, true))) + } label: { + Image(systemName: "plus") + } + .topBarButtonStyle() + .disabled(!store.isNetworkConnected) + } else { + Button { + store.send(.store(.setPresentation(.contentPicker, true))) + } label: { + Image(systemName: "plus") + .font(.title3.weight(.semibold)) + .frame(width: 28, height: 28) + } + .adaptiveButtonStyle( + shape: .circle, + color: .surface, + glassEffect: .enabled + ) + .disabled(!store.isNetworkConnected) } - .topBarButtonStyle(color: .surface) - .disabled(!store.isNetworkConnected) } .padding(.bottom, 8) .background(Color.appBackground) diff --git a/Application/Presentation/HomeTab/Sources/Search/SearchView.swift b/Application/Presentation/HomeTab/Sources/Search/SearchView.swift index 4d33e341..ae0e6539 100644 --- a/Application/Presentation/HomeTab/Sources/Search/SearchView.swift +++ b/Application/Presentation/HomeTab/Sources/Search/SearchView.swift @@ -55,14 +55,26 @@ struct SearchView: View { private var topBar: some View { VStack(alignment: .leading) { - Button { - store.send(.binding(.set(\.isSearching, false))) - dismiss() - } label: { - Image(systemName: "chevron.left") - .foregroundStyle(Color.textSecondary) + if #available(iOS 26.0, *) { + Button { + store.send(.binding(.set(\.isSearching, false))) + dismiss() + } label: { + Image(systemName: "xmark") + } + .topBarButtonStyle() + } else { + Button { + store.send(.binding(.set(\.isSearching, false))) + dismiss() + } label: { + Image(systemName: "chevron.left") + .foregroundStyle(Color.textSecondary) + .font(.title) + .padding(6) + } + .adaptiveButtonStyle(shape: .circle, color: .border, glassEffect: .enabled) } - .topBarButtonStyle(color: .border) SearchField(store: store) } .frame(maxWidth: .infinity, alignment: .leading) diff --git a/Application/Presentation/PresentationShared/Sources/Extension/View+.swift b/Application/Presentation/PresentationShared/Sources/Extension/View+.swift index 837d679c..e11973e6 100644 --- a/Application/Presentation/PresentationShared/Sources/Extension/View+.swift +++ b/Application/Presentation/PresentationShared/Sources/Extension/View+.swift @@ -13,16 +13,13 @@ public enum AdaptiveButtonGlassEffect { } public extension View { - func topBarButtonStyle( - color: Color = .clear, - usesTextBeforeIOS26: Bool = false, - glassEffect: AdaptiveButtonGlassEffect = .enabled - ) -> some View { - modifier(TopBarButtonStyleModifier( - color: color, - usesTextBeforeIOS26: usesTextBeforeIOS26, - glassEffect: glassEffect - )) + @ViewBuilder + func topBarButtonStyle(legacyColor: Color = .clear) -> some View { + if #available(iOS 26.0, *) { + modifier(TopBarButtonStyleModifier()) + } else { + adaptiveButtonStyle(color: legacyColor, glassEffect: .enabled) + } } func toolbarBackground(_ color: Color) -> some View { @@ -160,32 +157,19 @@ public extension View { } } +@available(iOS 26.0, *) private struct TopBarButtonStyleModifier: ViewModifier { @ScaledMetric(relativeTo: .title) private var iconSize = UIFont.preferredFont( forTextStyle: .title2, compatibleWith: UITraitCollection(preferredContentSizeCategory: .large) ).lineHeight - let color: Color - let usesTextBeforeIOS26: Bool - let glassEffect: AdaptiveButtonGlassEffect - - private var isIcon: Bool { - if #available(iOS 26.0, *) { - true - } else { - !usesTextBeforeIOS26 - } - } func body(content: Content) -> some View { - let label = content - .font(isIcon ? .title2 : nil) - .frame(width: isIcon ? iconSize : nil, height: isIcon ? iconSize : nil) - - if isIcon { - label.adaptiveButtonStyle(shape: .circle, color: color, glassEffect: glassEffect) - } else { - label.adaptiveButtonStyle(color: color, glassEffect: glassEffect) - } + content + .font(.title2.weight(.semibold)) + .foregroundStyle(Color.primary) + .frame(width: iconSize, height: iconSize) + .padding(9) + .glassEffect(.regular, in: .circle) } } diff --git a/Application/Presentation/PresentationShared/Sources/Todo/Editor/TodoEditorView.swift b/Application/Presentation/PresentationShared/Sources/Todo/Editor/TodoEditorView.swift index c9a33ebf..8c3a8dcf 100644 --- a/Application/Presentation/PresentationShared/Sources/Todo/Editor/TodoEditorView.swift +++ b/Application/Presentation/PresentationShared/Sources/Todo/Editor/TodoEditorView.swift @@ -162,6 +162,10 @@ public struct TodoEditorView: View { } private struct ToolBar: View { + @ScaledMetric(relativeTo: .title) private var iconSize = UIFont.preferredFont( + forTextStyle: .title1, + compatibleWith: UITraitCollection(preferredContentSizeCategory: .large) + ).lineHeight let store: StoreOf let showsActions: Bool let onClose: () -> Void @@ -169,16 +173,21 @@ private struct ToolBar: View { var body: some View { HStack { - Button { - onClose() - } label: { - if #available(iOS 26.0, *) { + if #available(iOS 26.0, *) { + Button { + onClose() + } label: { Image(systemName: "xmark") - } else { + } + .topBarButtonStyle() + } else { + Button { + onClose() + } label: { Text(String(localized: "common_close", bundle: PresentationResources.bundle)) } + .adaptiveButtonStyle(shape: .circle, glassEffect: .enabled) } - .topBarButtonStyle(usesTextBeforeIOS26: true) Spacer() Text(store.navigationTitle) .font(.title3.bold()) @@ -193,35 +202,61 @@ private struct ToolBar: View { } struct EditorToolbarActions: View { + @ScaledMetric(relativeTo: .title) private var iconSize = UIFont.preferredFont( + forTextStyle: .title1, + compatibleWith: UITraitCollection(preferredContentSizeCategory: .large) + ).lineHeight let store: StoreOf let onSubmit: () -> Void var body: some View { HStack { - Button { - store.send(.showInspector(.options)) - } label: { - Image(systemName: "info.circle") - .foregroundStyle(Color.primary) - } - .topBarButtonStyle(color: Color.surface) - if store.isLoading { - ProgressView() - .topBarButtonStyle(color: Color.surface) + if #available(iOS 26.0, *) { + Button { + store.send(.showInspector(.options)) + } label: { + Image(systemName: "info.circle") + } + .topBarButtonStyle() } else { Button { - onSubmit() + store.send(.showInspector(.options)) } label: { - if #available(iOS 26.0, *) { + Image(systemName: "info.circle") + .frame(width: iconSize, height: iconSize) + .foregroundStyle(Color.primary) + } + .font(.title) + .adaptiveButtonStyle(shape: .circle, color: Color.surface, glassEffect: .enabled) + } + if store.isLoading { + if #available(iOS 26.0, *) { + ProgressView() + .topBarButtonStyle() + } else { + ProgressView() + .frame(width: iconSize, height: iconSize) + .adaptiveButtonStyle(shape: .circle, color: Color.surface, glassEffect: .enabled) + } + } else { + if #available(iOS 26.0, *) { + Button { + onSubmit() + } label: { Image(systemName: "checkmark") - .foregroundStyle(Color.primary) - } else { + } + .topBarButtonStyle() + .disabled(!store.isReadyToSubmit) + } else { + Button { + onSubmit() + } label: { Text(String(localized: "todo_manage_save", bundle: PresentationResources.bundle)) .foregroundStyle(Color.primary) } + .adaptiveButtonStyle(shape: .circle, color: Color.surface, glassEffect: .enabled) + .disabled(!store.isReadyToSubmit) } - .topBarButtonStyle(color: Color.surface, usesTextBeforeIOS26: true) - .disabled(!store.isReadyToSubmit) } } } diff --git a/Application/Presentation/PresentationShared/Sources/Todo/Editor/TodoPropertiesView.swift b/Application/Presentation/PresentationShared/Sources/Todo/Editor/TodoPropertiesView.swift index 85492ba2..b77404d5 100644 --- a/Application/Presentation/PresentationShared/Sources/Todo/Editor/TodoPropertiesView.swift +++ b/Application/Presentation/PresentationShared/Sources/Todo/Editor/TodoPropertiesView.swift @@ -10,6 +10,10 @@ import ComposableArchitecture import Core public struct TodoPropertiesView: View { + @ScaledMetric(relativeTo: .title) private var iconSize = UIFont.preferredFont( + forTextStyle: .title1, + compatibleWith: UITraitCollection(preferredContentSizeCategory: .large) + ).lineHeight @Bindable var store: StoreOf @FocusState private var isTagFieldFocused: Bool var showsEditorActions = false @@ -45,13 +49,24 @@ public struct TodoPropertiesView: View { if showsEditorActions { EditorToolbarActions(store: store, onSubmit: onSubmit) } else { - Button { - onClose() - } label: { - Image(systemName: "checkmark") - .foregroundStyle(Color.primary) + if #available(iOS 26.0, *) { + Button { + onClose() + } label: { + Image(systemName: "xmark") + } + .topBarButtonStyle() + } else { + Button { + onClose() + } label: { + Image(systemName: "checkmark") + .frame(width: iconSize, height: iconSize) + .foregroundStyle(Color.primary) + } + .font(.title) + .adaptiveButtonStyle(shape: .circle, color: Color.surface, glassEffect: .enabled) } - .topBarButtonStyle(color: Color.surface) } } .padding(.horizontal) diff --git a/Application/Presentation/ProfileTab/Sources/Profile/ProfileView.swift b/Application/Presentation/ProfileTab/Sources/Profile/ProfileView.swift index 834856a5..fc0d1876 100644 --- a/Application/Presentation/ProfileTab/Sources/Profile/ProfileView.swift +++ b/Application/Presentation/ProfileTab/Sources/Profile/ProfileView.swift @@ -78,13 +78,22 @@ public struct ProfileView: View { Text("프로필") .font(.largeTitle.bold()) Spacer() - Button { - path.append(.settings) - } label: { - Image(systemName: "gearshape") - .foregroundStyle(Color.textTertiary) + if #available(iOS 26.0, *) { + Button { + path.append(.settings) + } label: { + Image(systemName: "gearshape") + } + .topBarButtonStyle() + } else { + Button { + path.append(.settings) + } label: { + Image(systemName: "gearshape") + .foregroundStyle(Color.textTertiary) + } + .adaptiveButtonStyle() } - .topBarButtonStyle(glassEffect: .disabled) } Text("꾸준히 쌓아온 개발 기록을 확인하세요") .foregroundStyle(Color.textSecondary) From 3ee6d3efdc113291ab43c6de12e77a95d566267b Mon Sep 17 00:00:00 2001 From: opficdev Date: Tue, 22 Sep 2026 23:30:44 +0900 Subject: [PATCH 04/17] =?UTF-8?q?fix:=20=EA=B0=9C=EB=B0=9C=20=EB=AA=A9?= =?UTF-8?q?=ED=91=9C=20=EC=83=81=EC=84=B8=20=EB=82=B4=EB=B6=80=20=EB=82=B4?= =?UTF-8?q?=EB=B9=84=EA=B2=8C=EC=9D=B4=EC=85=98=20=EA=B5=AC=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Sources/Record/GoalDetail/GoalDetailView.swift | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/Application/Presentation/Development/Sources/Record/GoalDetail/GoalDetailView.swift b/Application/Presentation/Development/Sources/Record/GoalDetail/GoalDetailView.swift index 1e53bba3..16580367 100644 --- a/Application/Presentation/Development/Sources/Record/GoalDetail/GoalDetailView.swift +++ b/Application/Presentation/Development/Sources/Record/GoalDetail/GoalDetailView.swift @@ -22,12 +22,14 @@ public struct GoalDetailView: View { } public var body: some View { - presentedContent - .overlay { - if store.isTransitioning { - LoadingView() + NavigationStack { + presentedContent + .overlay { + if store.isTransitioning { + LoadingView() + } } - } + } } private var mainContent: some View { From 3864d8b1408888f0c98453c8691ff056e0d89f50 Mon Sep 17 00:00:00 2001 From: opficdev Date: Tue, 22 Sep 2026 23:30:54 +0900 Subject: [PATCH 05/17] =?UTF-8?q?refactor:=20=EA=B0=80=EB=8F=85=EC=84=B1?= =?UTF-8?q?=20=EA=B0=9C=EC=84=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Sources/Todo/Editor/TodoEditorView.swift | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Application/Presentation/PresentationShared/Sources/Todo/Editor/TodoEditorView.swift b/Application/Presentation/PresentationShared/Sources/Todo/Editor/TodoEditorView.swift index 8c3a8dcf..326c0d0b 100644 --- a/Application/Presentation/PresentationShared/Sources/Todo/Editor/TodoEditorView.swift +++ b/Application/Presentation/PresentationShared/Sources/Todo/Editor/TodoEditorView.swift @@ -62,8 +62,7 @@ public struct TodoEditorView: View { store: store, field: _field, minimumHeight: max( - 0, - geometry.size.height - store.editorHeaderHeight - 16 - safeAreaInsets.bottom + 0, geometry.size.height - store.editorHeaderHeight - 16 - safeAreaInsets.bottom ) ) .onTapGesture { From 9a11231ce306c6ae231ca7ae7b492e235cc6b41a Mon Sep 17 00:00:00 2001 From: opficdev Date: Tue, 22 Sep 2026 23:36:06 +0900 Subject: [PATCH 06/17] =?UTF-8?q?ui:=20=EC=83=81=EB=8B=A8=20=ED=8C=A8?= =?UTF-8?q?=EB=94=A9=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Development/Sources/Record/GoalDetail/GoalDetailView.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Application/Presentation/Development/Sources/Record/GoalDetail/GoalDetailView.swift b/Application/Presentation/Development/Sources/Record/GoalDetail/GoalDetailView.swift index 16580367..35050910 100644 --- a/Application/Presentation/Development/Sources/Record/GoalDetail/GoalDetailView.swift +++ b/Application/Presentation/Development/Sources/Record/GoalDetail/GoalDetailView.swift @@ -143,7 +143,7 @@ public struct GoalDetailView: View { } } .padding(.horizontal) - .padding(.bottom, 12) + .padding(.vertical, 12) .background(Color.appBackground, ignoresSafeAreaEdges: .top) } From b727997453b370c65bb9bb602123febe689ba614 Mon Sep 17 00:00:00 2001 From: opficdev Date: Tue, 22 Sep 2026 23:47:29 +0900 Subject: [PATCH 07/17] =?UTF-8?q?ui:=20=EA=B8=B0=EB=A1=9D=20=EC=83=81?= =?UTF-8?q?=EC=84=B8=20=ED=83=91=EB=B0=94=20=EC=88=98=EC=A7=81=20=EC=97=AC?= =?UTF-8?q?=EB=B0=B1=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Development/Sources/Record/Detail/RecordDetailView.swift | 1 + 1 file changed, 1 insertion(+) diff --git a/Application/Presentation/Development/Sources/Record/Detail/RecordDetailView.swift b/Application/Presentation/Development/Sources/Record/Detail/RecordDetailView.swift index 8c6d0da8..21052d09 100644 --- a/Application/Presentation/Development/Sources/Record/Detail/RecordDetailView.swift +++ b/Application/Presentation/Development/Sources/Record/Detail/RecordDetailView.swift @@ -100,6 +100,7 @@ public struct RecordDetailView: View { Spacer() } .padding(.horizontal) + .padding(.vertical, 12) .background(Color.appBackground, ignoresSafeAreaEdges: .top) } From baa3f100e4335d119ff5462d4e4bd6e57fb68fd9 Mon Sep 17 00:00:00 2001 From: opficdev Date: Wed, 23 Sep 2026 00:17:26 +0900 Subject: [PATCH 08/17] =?UTF-8?q?ui:=20=ED=83=91=EB=B0=94=20=EB=B2=84?= =?UTF-8?q?=ED=8A=BC=20Liquid=20Glass=20=EC=83=81=ED=98=B8=EC=9E=91?= =?UTF-8?q?=EC=9A=A9=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../PresentationShared/Sources/Extension/View+.swift | 10 +++++++--- .../Sources/Todo/Editor/TodoEditorView.swift | 2 +- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/Application/Presentation/PresentationShared/Sources/Extension/View+.swift b/Application/Presentation/PresentationShared/Sources/Extension/View+.swift index e11973e6..2eb8ee75 100644 --- a/Application/Presentation/PresentationShared/Sources/Extension/View+.swift +++ b/Application/Presentation/PresentationShared/Sources/Extension/View+.swift @@ -14,9 +14,12 @@ public enum AdaptiveButtonGlassEffect { public extension View { @ViewBuilder - func topBarButtonStyle(legacyColor: Color = .clear) -> some View { + func topBarButtonStyle( + legacyColor: Color = .clear, + isInteractive: Bool = true + ) -> some View { if #available(iOS 26.0, *) { - modifier(TopBarButtonStyleModifier()) + modifier(TopBarButtonStyleModifier(isInteractive: isInteractive)) } else { adaptiveButtonStyle(color: legacyColor, glassEffect: .enabled) } @@ -163,6 +166,7 @@ private struct TopBarButtonStyleModifier: ViewModifier { forTextStyle: .title2, compatibleWith: UITraitCollection(preferredContentSizeCategory: .large) ).lineHeight + let isInteractive: Bool func body(content: Content) -> some View { content @@ -170,6 +174,6 @@ private struct TopBarButtonStyleModifier: ViewModifier { .foregroundStyle(Color.primary) .frame(width: iconSize, height: iconSize) .padding(9) - .glassEffect(.regular, in: .circle) + .glassEffect(.regular.interactive(isInteractive), in: .circle) } } diff --git a/Application/Presentation/PresentationShared/Sources/Todo/Editor/TodoEditorView.swift b/Application/Presentation/PresentationShared/Sources/Todo/Editor/TodoEditorView.swift index 326c0d0b..c8613ad5 100644 --- a/Application/Presentation/PresentationShared/Sources/Todo/Editor/TodoEditorView.swift +++ b/Application/Presentation/PresentationShared/Sources/Todo/Editor/TodoEditorView.swift @@ -231,7 +231,7 @@ struct EditorToolbarActions: View { if store.isLoading { if #available(iOS 26.0, *) { ProgressView() - .topBarButtonStyle() + .topBarButtonStyle(isInteractive: false) } else { ProgressView() .frame(width: iconSize, height: iconSize) From 9e429c1c0737366bf96cdd14546718572cea90f7 Mon Sep 17 00:00:00 2001 From: opficdev Date: Wed, 23 Sep 2026 00:46:27 +0900 Subject: [PATCH 09/17] =?UTF-8?q?ui:=20iOS=20=EB=B2=84=EC=A0=84=EB=B3=84?= =?UTF-8?q?=20=ED=83=91=EB=B0=94=20=EB=B2=84=ED=8A=BC=20=EC=A0=95=EC=B1=85?= =?UTF-8?q?=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Sources/Goal/Create/GoalCreateView.swift | 2 +- .../GoalCreateTodoSelectionSheet.swift | 4 +- .../Record/Editor/RecordEditorView.swift | 4 +- .../Record/GoalDetail/GoalDetailView.swift | 9 ++-- .../Record/GoalDetail/GoalTodoLinkSheet.swift | 6 +-- .../HomeTab/Sources/Search/SearchView.swift | 9 ++-- .../Resources/Localizable.xcstrings | 17 ++++++ .../Sources/Extension/View+.swift | 54 ++++++++++++++----- .../Sources/Todo/Editor/TodoEditorView.swift | 6 +-- .../Todo/Editor/TodoPropertiesView.swift | 13 ++--- 10 files changed, 82 insertions(+), 42 deletions(-) diff --git a/Application/Presentation/Development/Sources/Goal/Create/GoalCreateView.swift b/Application/Presentation/Development/Sources/Goal/Create/GoalCreateView.swift index a2494530..64722690 100644 --- a/Application/Presentation/Development/Sources/Goal/Create/GoalCreateView.swift +++ b/Application/Presentation/Development/Sources/Goal/Create/GoalCreateView.swift @@ -87,7 +87,7 @@ private struct GoalCreateTopBar: View { Text(RecordPresentation.text("common_close")) } } - .topBarButtonStyle() + .topBarButtonStyle(tint: Color.accent) .disabled(isSaving) Spacer() diff --git a/Application/Presentation/Development/Sources/Goal/TodoSelection/GoalCreateTodoSelectionSheet.swift b/Application/Presentation/Development/Sources/Goal/TodoSelection/GoalCreateTodoSelectionSheet.swift index 87b8bab7..db6c79c3 100644 --- a/Application/Presentation/Development/Sources/Goal/TodoSelection/GoalCreateTodoSelectionSheet.swift +++ b/Application/Presentation/Development/Sources/Goal/TodoSelection/GoalCreateTodoSelectionSheet.swift @@ -94,7 +94,7 @@ struct GoalCreateTodoSelectionSheet: View { Text(RecordPresentation.text("common_close")) } } - .topBarButtonStyle(legacyColor: Color.surface) + .topBarButtonStyle(tint: Color.accent) Spacer() Button { store.send(.view(.save)) @@ -106,7 +106,7 @@ struct GoalCreateTodoSelectionSheet: View { .foregroundStyle(Color.accent) } } - .topBarButtonStyle(legacyColor: Color.surface) + .topBarButtonStyle() } } .padding(.horizontal, 16) diff --git a/Application/Presentation/Development/Sources/Record/Editor/RecordEditorView.swift b/Application/Presentation/Development/Sources/Record/Editor/RecordEditorView.swift index 3d693ed5..ab35a6a5 100644 --- a/Application/Presentation/Development/Sources/Record/Editor/RecordEditorView.swift +++ b/Application/Presentation/Development/Sources/Record/Editor/RecordEditorView.swift @@ -71,7 +71,7 @@ public struct RecordEditorView: View { Text(RecordPresentation.text("common_close")) } } - .topBarButtonStyle() + .topBarButtonStyle(tint: Color.accent) .disabled(store.isLoading) Spacer() Text(RecordPresentation.text( @@ -92,7 +92,7 @@ public struct RecordEditorView: View { .foregroundStyle(Color.accent) } } - .topBarButtonStyle(legacyColor: Color.surface) + .topBarButtonStyle() .disabled(!store.isReadyToSave) } .padding(.horizontal) diff --git a/Application/Presentation/Development/Sources/Record/GoalDetail/GoalDetailView.swift b/Application/Presentation/Development/Sources/Record/GoalDetail/GoalDetailView.swift index 35050910..3127c28b 100644 --- a/Application/Presentation/Development/Sources/Record/GoalDetail/GoalDetailView.swift +++ b/Application/Presentation/Development/Sources/Record/GoalDetail/GoalDetailView.swift @@ -107,11 +107,14 @@ public struct GoalDetailView: View { Button(action: dismiss.callAsFunction) { Image(systemName: "xmark") } - .topBarButtonStyle() + .topBarButtonStyle(tint: Color.accent) .disabled(store.isTransitioning) } else { - RecordBackButton(action: dismiss.callAsFunction) - .disabled(store.isTransitioning) + Button(action: dismiss.callAsFunction) { + Text(RecordPresentation.text("common_close")) + } + .topBarButtonStyle(tint: Color.accent) + .disabled(store.isTransitioning) } Spacer() if let status = store.goalStatus { diff --git a/Application/Presentation/Development/Sources/Record/GoalDetail/GoalTodoLinkSheet.swift b/Application/Presentation/Development/Sources/Record/GoalDetail/GoalTodoLinkSheet.swift index 03d065e4..d5ff0099 100644 --- a/Application/Presentation/Development/Sources/Record/GoalDetail/GoalTodoLinkSheet.swift +++ b/Application/Presentation/Development/Sources/Record/GoalDetail/GoalTodoLinkSheet.swift @@ -57,7 +57,7 @@ struct GoalTodoLinkSheet: View { Text(RecordPresentation.text("common_close")) } } - .topBarButtonStyle(legacyColor: Color.surface) + .topBarButtonStyle(tint: Color.accent) .disabled(store.isUpdating) Spacer() HStack(spacing: 8) { @@ -80,7 +80,7 @@ struct GoalTodoLinkSheet: View { ) { _ in store.send(.view(.clearSelection)) } - .topBarButtonStyle(legacyColor: Color.surface) + .topBarButtonStyle() } Button { store.send(.view(.save)) @@ -92,7 +92,7 @@ struct GoalTodoLinkSheet: View { .foregroundStyle(Color.accent) } } - .topBarButtonStyle(legacyColor: Color.surface) + .topBarButtonStyle() .disabled(!store.canSave) } } diff --git a/Application/Presentation/HomeTab/Sources/Search/SearchView.swift b/Application/Presentation/HomeTab/Sources/Search/SearchView.swift index ae0e6539..03b83ae5 100644 --- a/Application/Presentation/HomeTab/Sources/Search/SearchView.swift +++ b/Application/Presentation/HomeTab/Sources/Search/SearchView.swift @@ -62,18 +62,15 @@ struct SearchView: View { } label: { Image(systemName: "xmark") } - .topBarButtonStyle() + .topBarButtonStyle(tint: Color.accent) } else { Button { store.send(.binding(.set(\.isSearching, false))) dismiss() } label: { - Image(systemName: "chevron.left") - .foregroundStyle(Color.textSecondary) - .font(.title) - .padding(6) + Text(String(localized: "common_close", bundle: PresentationResources.bundle)) } - .adaptiveButtonStyle(shape: .circle, color: .border, glassEffect: .enabled) + .topBarButtonStyle(tint: Color.accent) } SearchField(store: store) } diff --git a/Application/Presentation/PresentationShared/Resources/Localizable.xcstrings b/Application/Presentation/PresentationShared/Resources/Localizable.xcstrings index e3ee8de6..52482774 100644 --- a/Application/Presentation/PresentationShared/Resources/Localizable.xcstrings +++ b/Application/Presentation/PresentationShared/Resources/Localizable.xcstrings @@ -298,6 +298,23 @@ } } }, + "common_done" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Done" + } + }, + "ko" : { + "stringUnit" : { + "state" : "translated", + "value" : "완료" + } + } + } + }, "common_copy" : { "extractionState" : "manual", "localizations" : { diff --git a/Application/Presentation/PresentationShared/Sources/Extension/View+.swift b/Application/Presentation/PresentationShared/Sources/Extension/View+.swift index 2eb8ee75..192bfcbd 100644 --- a/Application/Presentation/PresentationShared/Sources/Extension/View+.swift +++ b/Application/Presentation/PresentationShared/Sources/Extension/View+.swift @@ -14,17 +14,19 @@ public enum AdaptiveButtonGlassEffect { public extension View { @ViewBuilder - func topBarButtonStyle( - legacyColor: Color = .clear, - isInteractive: Bool = true - ) -> some View { + func topBarButtonStyle(tint: Color? = nil) -> some View { if #available(iOS 26.0, *) { - modifier(TopBarButtonStyleModifier(isInteractive: isInteractive)) + modifier(TopBarButtonStyleModifier(tint: tint, isInteractive: true)) } else { - adaptiveButtonStyle(color: legacyColor, glassEffect: .enabled) + modifier(LegacyTopBarButtonStyleModifier(tint: tint ?? .primary)) } } + @available(iOS 26.0, *) + func topBarProgressStyle() -> some View { + modifier(TopBarButtonStyleModifier(tint: nil, isInteractive: false)) + } + func toolbarBackground(_ color: Color) -> some View { overlay(alignment: .top) { GeometryReader { proxy in @@ -160,20 +162,48 @@ public extension View { } } +private struct LegacyTopBarButtonStyleModifier: ViewModifier { + let tint: Color + + func body(content: Content) -> some View { + content + .foregroundStyle(tint) + .padding(8) + .background { + Capsule() + .fill(Color.surface) + } + } +} + @available(iOS 26.0, *) private struct TopBarButtonStyleModifier: ViewModifier { @ScaledMetric(relativeTo: .title) private var iconSize = UIFont.preferredFont( forTextStyle: .title2, compatibleWith: UITraitCollection(preferredContentSizeCategory: .large) ).lineHeight + let tint: Color? let isInteractive: Bool + @ViewBuilder func body(content: Content) -> some View { - content - .font(.title2.weight(.semibold)) - .foregroundStyle(Color.primary) - .frame(width: iconSize, height: iconSize) - .padding(9) - .glassEffect(.regular.interactive(isInteractive), in: .circle) + if let tint { + content + .font(.title2.weight(.semibold)) + .foregroundStyle(Color.primary) + .frame(width: iconSize, height: iconSize) + .padding(9) + .glassEffect( + .regular.tint(tint).interactive(isInteractive), + in: .circle + ) + } else { + content + .font(.title2.weight(.semibold)) + .foregroundStyle(Color.primary) + .frame(width: iconSize, height: iconSize) + .padding(9) + .glassEffect(.regular.interactive(isInteractive), in: .circle) + } } } diff --git a/Application/Presentation/PresentationShared/Sources/Todo/Editor/TodoEditorView.swift b/Application/Presentation/PresentationShared/Sources/Todo/Editor/TodoEditorView.swift index c8613ad5..7fce097a 100644 --- a/Application/Presentation/PresentationShared/Sources/Todo/Editor/TodoEditorView.swift +++ b/Application/Presentation/PresentationShared/Sources/Todo/Editor/TodoEditorView.swift @@ -178,14 +178,14 @@ private struct ToolBar: View { } label: { Image(systemName: "xmark") } - .topBarButtonStyle() + .topBarButtonStyle(tint: Color.accent) } else { Button { onClose() } label: { Text(String(localized: "common_close", bundle: PresentationResources.bundle)) } - .adaptiveButtonStyle(shape: .circle, glassEffect: .enabled) + .topBarButtonStyle(tint: Color.accent) } Spacer() Text(store.navigationTitle) @@ -231,7 +231,7 @@ struct EditorToolbarActions: View { if store.isLoading { if #available(iOS 26.0, *) { ProgressView() - .topBarButtonStyle(isInteractive: false) + .topBarProgressStyle() } else { ProgressView() .frame(width: iconSize, height: iconSize) diff --git a/Application/Presentation/PresentationShared/Sources/Todo/Editor/TodoPropertiesView.swift b/Application/Presentation/PresentationShared/Sources/Todo/Editor/TodoPropertiesView.swift index b77404d5..989bcee1 100644 --- a/Application/Presentation/PresentationShared/Sources/Todo/Editor/TodoPropertiesView.swift +++ b/Application/Presentation/PresentationShared/Sources/Todo/Editor/TodoPropertiesView.swift @@ -10,10 +10,6 @@ import ComposableArchitecture import Core public struct TodoPropertiesView: View { - @ScaledMetric(relativeTo: .title) private var iconSize = UIFont.preferredFont( - forTextStyle: .title1, - compatibleWith: UITraitCollection(preferredContentSizeCategory: .large) - ).lineHeight @Bindable var store: StoreOf @FocusState private var isTagFieldFocused: Bool var showsEditorActions = false @@ -55,17 +51,14 @@ public struct TodoPropertiesView: View { } label: { Image(systemName: "xmark") } - .topBarButtonStyle() + .topBarButtonStyle(tint: Color.accent) } else { Button { onClose() } label: { - Image(systemName: "checkmark") - .frame(width: iconSize, height: iconSize) - .foregroundStyle(Color.primary) + Text(String(localized: "common_done", bundle: PresentationResources.bundle)) } - .font(.title) - .adaptiveButtonStyle(shape: .circle, color: Color.surface, glassEffect: .enabled) + .topBarButtonStyle(tint: Color.accent) } } } From 8c7980f93655d60d203507f94a3585e1a3fbf63e Mon Sep 17 00:00:00 2001 From: opficdev Date: Wed, 23 Sep 2026 00:47:34 +0900 Subject: [PATCH 10/17] =?UTF-8?q?ui:=20=EB=B2=84=EC=A0=84=20=EC=9D=B4?= =?UTF-8?q?=EB=A0=A5=20=ED=83=91=EB=B0=94=20=EC=88=98=EC=A7=81=20=EC=97=AC?= =?UTF-8?q?=EB=B0=B1=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Sources/Record/History/RecordVersionHistoryView.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Application/Presentation/Development/Sources/Record/History/RecordVersionHistoryView.swift b/Application/Presentation/Development/Sources/Record/History/RecordVersionHistoryView.swift index f013ad7c..e6dde50e 100644 --- a/Application/Presentation/Development/Sources/Record/History/RecordVersionHistoryView.swift +++ b/Application/Presentation/Development/Sources/Record/History/RecordVersionHistoryView.swift @@ -51,7 +51,7 @@ struct RecordVersionHistoryView: View { Spacer() } .padding(.horizontal) - .padding(.bottom, 12) + .padding(.vertical, 12) .background(Color.appBackground, ignoresSafeAreaEdges: .top) } From 9fa2b18dea577cc6e3edc00dc7e049e96a580dd5 Mon Sep 17 00:00:00 2001 From: opficdev Date: Wed, 23 Sep 2026 01:00:45 +0900 Subject: [PATCH 11/17] =?UTF-8?q?ui:=20=EB=A1=9C=EA=B7=B8=EC=9D=B8=20?= =?UTF-8?q?=EB=B2=84=ED=8A=BC=20=ED=85=8D=EC=8A=A4=ED=8A=B8=20=EC=83=89?= =?UTF-8?q?=EC=83=81=20=EC=A1=B0=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Entry/Sources/Common/Component/LoginButton.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Application/Presentation/Entry/Sources/Common/Component/LoginButton.swift b/Application/Presentation/Entry/Sources/Common/Component/LoginButton.swift index 3c063ae9..4a689aff 100644 --- a/Application/Presentation/Entry/Sources/Common/Component/LoginButton.swift +++ b/Application/Presentation/Entry/Sources/Common/Component/LoginButton.swift @@ -36,7 +36,7 @@ struct LoginButton: View { .tint(Color.accent) } else { Text(text) - .foregroundStyle(.primary) + .foregroundStyle(Color.textSecondary) } } .font(.system(.body)) From 833320892f5c1a8ff46b72695b781b6f29b51aa6 Mon Sep 17 00:00:00 2001 From: opficdev Date: Wed, 23 Sep 2026 01:01:02 +0900 Subject: [PATCH 12/17] =?UTF-8?q?ui:=20=EB=A1=9C=EA=B7=B8=EC=9D=B8=20?= =?UTF-8?q?=EB=B2=84=ED=8A=BC=20=ED=85=8C=EB=91=90=EB=A6=AC=20=EB=91=90?= =?UTF-8?q?=EA=BB=98=20=EC=A1=B0=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Entry/Sources/Common/Component/LoginButton.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Application/Presentation/Entry/Sources/Common/Component/LoginButton.swift b/Application/Presentation/Entry/Sources/Common/Component/LoginButton.swift index 4a689aff..227d3c6d 100644 --- a/Application/Presentation/Entry/Sources/Common/Component/LoginButton.swift +++ b/Application/Presentation/Entry/Sources/Common/Component/LoginButton.swift @@ -44,7 +44,7 @@ struct LoginButton: View { .frame(width: 300, height: height + 24) .background { RoundedRectangle(cornerRadius: 12) - .stroke(Color.border, lineWidth: 3) + .stroke(Color.border, lineWidth: 1) .fill(Color.surface) } .overlay(alignment: .leading) { From f3b5f122d52e32fb87f41d3af13aa7793e4f6c3c Mon Sep 17 00:00:00 2001 From: opficdev Date: Wed, 23 Sep 2026 01:01:22 +0900 Subject: [PATCH 13/17] =?UTF-8?q?ui:=20Todo=20=ED=8E=B8=EC=A7=91=20?= =?UTF-8?q?=EC=A0=9C=EC=B6=9C=20=EB=B2=84=ED=8A=BC=20=EA=B0=95=EC=A1=B0=20?= =?UTF-8?q?=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Sources/Todo/Editor/TodoEditorView.swift | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/Application/Presentation/PresentationShared/Sources/Todo/Editor/TodoEditorView.swift b/Application/Presentation/PresentationShared/Sources/Todo/Editor/TodoEditorView.swift index 7fce097a..d0a97120 100644 --- a/Application/Presentation/PresentationShared/Sources/Todo/Editor/TodoEditorView.swift +++ b/Application/Presentation/PresentationShared/Sources/Todo/Editor/TodoEditorView.swift @@ -244,16 +244,19 @@ struct EditorToolbarActions: View { } label: { Image(systemName: "checkmark") } - .topBarButtonStyle() + .topBarButtonStyle( + tint: store.isReadyToSubmit ? Color.accent : nil + ) .disabled(!store.isReadyToSubmit) } else { Button { onSubmit() } label: { Text(String(localized: "todo_manage_save", bundle: PresentationResources.bundle)) - .foregroundStyle(Color.primary) } - .adaptiveButtonStyle(shape: .circle, color: Color.surface, glassEffect: .enabled) + .topBarButtonStyle( + tint: store.isReadyToSubmit ? Color.accent : nil + ) .disabled(!store.isReadyToSubmit) } } From b60fceec315004b26a53b8401fea604e2a67e407 Mon Sep 17 00:00:00 2001 From: opficdev Date: Wed, 23 Sep 2026 01:01:33 +0900 Subject: [PATCH 14/17] =?UTF-8?q?ui:=20=ED=99=95=EC=9D=B8=20=ED=83=91?= =?UTF-8?q?=EB=B0=94=20=EB=8B=AB=EA=B8=B0=20=EB=B2=84=ED=8A=BC=20=EA=B0=95?= =?UTF-8?q?=EC=A1=B0=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Goal/TodoSelection/GoalCreateTodoSelectionSheet.swift | 2 +- .../Development/Sources/Record/Editor/RecordEditorView.swift | 2 +- .../Sources/Record/GoalDetail/GoalTodoLinkSheet.swift | 2 +- .../Sources/Todo/Editor/TodoEditorView.swift | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Application/Presentation/Development/Sources/Goal/TodoSelection/GoalCreateTodoSelectionSheet.swift b/Application/Presentation/Development/Sources/Goal/TodoSelection/GoalCreateTodoSelectionSheet.swift index db6c79c3..40fa205f 100644 --- a/Application/Presentation/Development/Sources/Goal/TodoSelection/GoalCreateTodoSelectionSheet.swift +++ b/Application/Presentation/Development/Sources/Goal/TodoSelection/GoalCreateTodoSelectionSheet.swift @@ -94,7 +94,7 @@ struct GoalCreateTodoSelectionSheet: View { Text(RecordPresentation.text("common_close")) } } - .topBarButtonStyle(tint: Color.accent) + .topBarButtonStyle() Spacer() Button { store.send(.view(.save)) diff --git a/Application/Presentation/Development/Sources/Record/Editor/RecordEditorView.swift b/Application/Presentation/Development/Sources/Record/Editor/RecordEditorView.swift index ab35a6a5..eaa4e369 100644 --- a/Application/Presentation/Development/Sources/Record/Editor/RecordEditorView.swift +++ b/Application/Presentation/Development/Sources/Record/Editor/RecordEditorView.swift @@ -71,7 +71,7 @@ public struct RecordEditorView: View { Text(RecordPresentation.text("common_close")) } } - .topBarButtonStyle(tint: Color.accent) + .topBarButtonStyle() .disabled(store.isLoading) Spacer() Text(RecordPresentation.text( diff --git a/Application/Presentation/Development/Sources/Record/GoalDetail/GoalTodoLinkSheet.swift b/Application/Presentation/Development/Sources/Record/GoalDetail/GoalTodoLinkSheet.swift index d5ff0099..5d373b7c 100644 --- a/Application/Presentation/Development/Sources/Record/GoalDetail/GoalTodoLinkSheet.swift +++ b/Application/Presentation/Development/Sources/Record/GoalDetail/GoalTodoLinkSheet.swift @@ -57,7 +57,7 @@ struct GoalTodoLinkSheet: View { Text(RecordPresentation.text("common_close")) } } - .topBarButtonStyle(tint: Color.accent) + .topBarButtonStyle() .disabled(store.isUpdating) Spacer() HStack(spacing: 8) { diff --git a/Application/Presentation/PresentationShared/Sources/Todo/Editor/TodoEditorView.swift b/Application/Presentation/PresentationShared/Sources/Todo/Editor/TodoEditorView.swift index d0a97120..051750e9 100644 --- a/Application/Presentation/PresentationShared/Sources/Todo/Editor/TodoEditorView.swift +++ b/Application/Presentation/PresentationShared/Sources/Todo/Editor/TodoEditorView.swift @@ -178,14 +178,14 @@ private struct ToolBar: View { } label: { Image(systemName: "xmark") } - .topBarButtonStyle(tint: Color.accent) + .topBarButtonStyle(tint: showsActions ? nil : Color.accent) } else { Button { onClose() } label: { Text(String(localized: "common_close", bundle: PresentationResources.bundle)) } - .topBarButtonStyle(tint: Color.accent) + .topBarButtonStyle(tint: showsActions ? nil : Color.accent) } Spacer() Text(store.navigationTitle) From b3951509163de009a75bf4df6f8b8183254b700c Mon Sep 17 00:00:00 2001 From: opficdev Date: Wed, 23 Sep 2026 09:32:40 +0900 Subject: [PATCH 15/17] =?UTF-8?q?ui:=20iOS=2026=EC=9D=BC=20=EB=95=8C=20?= =?UTF-8?q?=EC=8B=9C=EC=8A=A4=ED=85=9C=20=EB=B2=84=ED=8A=BC=20=EC=83=89=20?= =?UTF-8?q?=ED=86=B5=EC=9D=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../PresentationShared/Sources/Extension/View+.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Application/Presentation/PresentationShared/Sources/Extension/View+.swift b/Application/Presentation/PresentationShared/Sources/Extension/View+.swift index 192bfcbd..4115010b 100644 --- a/Application/Presentation/PresentationShared/Sources/Extension/View+.swift +++ b/Application/Presentation/PresentationShared/Sources/Extension/View+.swift @@ -190,7 +190,7 @@ private struct TopBarButtonStyleModifier: ViewModifier { if let tint { content .font(.title2.weight(.semibold)) - .foregroundStyle(Color.primary) + .foregroundStyle(Color.white) .frame(width: iconSize, height: iconSize) .padding(9) .glassEffect( From 5a0f4d0950ce503e8cda6c62d5f21f5a8818973c Mon Sep 17 00:00:00 2001 From: opficdev Date: Wed, 23 Sep 2026 09:34:38 +0900 Subject: [PATCH 16/17] =?UTF-8?q?fix:=20=EA=B3=A0=EC=A0=95=20=ED=83=91?= =?UTF-8?q?=EB=B0=94=20=EB=B0=B0=EA=B2=BD=20=EC=9C=84=EC=B9=98=20=EC=A1=B0?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Presentation/HomeTab/Sources/Home/HomeView.swift | 2 +- .../PresentationShared/Sources/Extension/View+.swift | 9 +++++---- .../Presentation/TodayTab/Sources/TodayView.swift | 2 +- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/Application/Presentation/HomeTab/Sources/Home/HomeView.swift b/Application/Presentation/HomeTab/Sources/Home/HomeView.swift index fadb6445..f4e7f6c1 100644 --- a/Application/Presentation/HomeTab/Sources/Home/HomeView.swift +++ b/Application/Presentation/HomeTab/Sources/Home/HomeView.swift @@ -58,6 +58,7 @@ public struct HomeView: View { todoSection } header: { topBar + .toolbarBackground(Color.appBackground) } DevelopmentGoalSection( items: store.developmentGoalItems, @@ -75,7 +76,6 @@ public struct HomeView: View { .toolbarVisibility(.hidden, for: .navigationBar) .navigationDestination(for: HomeRoute.self, destination: destinationView) } - .toolbarBackground(Color.appBackground) .onAppear { store.send(.view(.startObserving)) } .onChange(of: isSelected, initial: true) { _, isSelected in if isSelected { diff --git a/Application/Presentation/PresentationShared/Sources/Extension/View+.swift b/Application/Presentation/PresentationShared/Sources/Extension/View+.swift index 4115010b..624a2e8d 100644 --- a/Application/Presentation/PresentationShared/Sources/Extension/View+.swift +++ b/Application/Presentation/PresentationShared/Sources/Extension/View+.swift @@ -28,13 +28,14 @@ public extension View { } func toolbarBackground(_ color: Color) -> some View { - overlay(alignment: .top) { + background(alignment: .top) { GeometryReader { proxy in + let top = max(proxy.frame(in: .global).minY, 0) color - .frame(height: proxy.safeAreaInsets.top) - .offset(y: -proxy.safeAreaInsets.top) + .frame(height: top) + .offset(y: -top) + .allowsHitTesting(false) } - .allowsHitTesting(false) } } diff --git a/Application/Presentation/TodayTab/Sources/TodayView.swift b/Application/Presentation/TodayTab/Sources/TodayView.swift index 89b54d52..5d1b8ac5 100644 --- a/Application/Presentation/TodayTab/Sources/TodayView.swift +++ b/Application/Presentation/TodayTab/Sources/TodayView.swift @@ -58,6 +58,7 @@ public struct TodayView: View { } .padding(.bottom, 8) .background(Color.appBackground) + .toolbarBackground(Color.appBackground) } } .padding(.horizontal) @@ -70,7 +71,6 @@ public struct TodayView: View { CategoryFilterSheet(store: store) } } - .toolbarBackground(Color.appBackground) .inspector(isPresented: $store.isTodoInspectorPresented) { todoInspector } From 0fd578acfaa08a975d306100e6e55840dedecc6e Mon Sep 17 00:00:00 2001 From: opficdev Date: Wed, 23 Sep 2026 09:46:54 +0900 Subject: [PATCH 17/17] =?UTF-8?q?fix:=20Todo=20=EC=A0=9C=EC=B6=9C=20?= =?UTF-8?q?=EB=B2=84=ED=8A=BC=20=EB=B9=84=ED=99=9C=EC=84=B1=20=EC=83=81?= =?UTF-8?q?=ED=83=9C=20=ED=91=9C=EC=8B=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../PresentationShared/Sources/Todo/Editor/TodoEditorView.swift | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Application/Presentation/PresentationShared/Sources/Todo/Editor/TodoEditorView.swift b/Application/Presentation/PresentationShared/Sources/Todo/Editor/TodoEditorView.swift index 051750e9..384e6cff 100644 --- a/Application/Presentation/PresentationShared/Sources/Todo/Editor/TodoEditorView.swift +++ b/Application/Presentation/PresentationShared/Sources/Todo/Editor/TodoEditorView.swift @@ -248,6 +248,7 @@ struct EditorToolbarActions: View { tint: store.isReadyToSubmit ? Color.accent : nil ) .disabled(!store.isReadyToSubmit) + .opacity(store.isReadyToSubmit ? 1 : 0.4) } else { Button { onSubmit() @@ -258,6 +259,7 @@ struct EditorToolbarActions: View { tint: store.isReadyToSubmit ? Color.accent : nil ) .disabled(!store.isReadyToSubmit) + .opacity(store.isReadyToSubmit ? 1 : 0.4) } } }