Skip to content
Merged
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@
"color-space" : "srgb",
"components" : {
"alpha" : "1.000",
"blue" : "0xEE",
"green" : "0xF0",
"red" : "0xEB"
"blue" : "0xE4",
"green" : "0xE6",
"red" : "0xE2"
}
},
"idiom" : "universal"
Expand All @@ -23,9 +23,9 @@
"color-space" : "srgb",
"components" : {
"alpha" : "1.000",
"blue" : "0xEE",
"green" : "0xF0",
"red" : "0xEB"
"blue" : "0xE4",
"green" : "0xE6",
"red" : "0xE2"
}
},
"idiom" : "universal"
Expand Down
16 changes: 8 additions & 8 deletions Projects/DVDesign/Sources/Components/DVCategory.swift
Original file line number Diff line number Diff line change
Expand Up @@ -64,21 +64,21 @@ extension DVCategory {

private var iconView: some View {
Image(systemName: systemImage)
.font(.system(size: 16, weight: .medium))
.foregroundStyle(isSelected ? Color.dv(.white) : Color.dv(.gray700))
.frame(width: 28, height: 28)
.dvFont(.headingLG)
.foregroundStyle(isSelected ? Color.dv(.white) : Color.dv(.gray800))
.frame(width: 24, height: 24)
}

private var titleLabel: some View {
Text(title)
.dvFont(.bodyLG)
.foregroundStyle(isSelected ? Color.dv(.white) : Color.dv(.gray800))
.foregroundStyle(isSelected ? Color.dv(.white) : Color.dv(.gray900))
}

private var countLabel: some View {
Text(count > 999 ? "999+" : "\(count)")
.dvFont(.bodyMD)
.foregroundStyle(isSelected ? Color.dv(.white).opacity(0.8) : Color.dv(.gray600))
.foregroundStyle(isSelected ? Color.dv(.white) : Color.dv(.gray600))
}
}

Expand All @@ -97,8 +97,8 @@ private struct DVCategoryButtonStyle: ButtonStyle {

private func backgroundColor(isPressed: Bool) -> Color {
if isSelected { return Color.dv(.vaultGreen) }
if isPressed { return Color.dv(.gray300) }
if isHovered { return Color.dv(.gray200) }
return Color.dv(.gray100)
if isPressed { return Color.dv(.gray400) }
if isHovered { return Color.dv(.gray300) }
return Color.dv(.gray200)
Comment thread
dlguszoo marked this conversation as resolved.
}
}
8 changes: 4 additions & 4 deletions Projects/DVDesign/Sources/Components/DVProjectContainer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ public struct DVProjectContainer: View {
Spacer(minLength: 8)
countLabel
}
.padding(6)
.padding(2)
.frame(minWidth: 120, alignment: .leading)
}
}
Expand All @@ -39,13 +39,13 @@ extension DVProjectContainer {
private var projectIcon: some View {
Image(systemName: "tray")
.dvFont(.captionLG)
.foregroundStyle(.primary)
.foregroundStyle(Color.dv(.gray900))
}

private var nameLabel: some View {
Text(name)
.dvFont(.bodyMD)
.foregroundStyle(.primary)
.foregroundStyle(Color.dv(.gray900))
.lineLimit(1)
.truncationMode(.tail)
.frame(minWidth: 40, alignment: .leading)
Expand All @@ -54,7 +54,7 @@ extension DVProjectContainer {
private var countLabel: some View {
Text(count > 999 ? "999+" : "\(count)")
.dvFont(.bodyMD)
.foregroundStyle(.secondary)
.foregroundStyle(Color.dv(.gray400))
.fixedSize()
}
}
38 changes: 38 additions & 0 deletions Projects/DVPresentation/Sources/Features/Main/MainFeature.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ public struct MainFeature {
@ObservableState
public struct State: Equatable {
public var columnVisibility: NavigationSplitViewVisibility = .all
var sidebar: SidebarFeature.State = .init()

public init() {}
}
Expand All @@ -27,6 +28,10 @@ public struct MainFeature {
case binding(BindingAction<State>)
case task

// MARK: - Child

case sidebar(SidebarFeature.Action)

// MARK: - Delegate

case delegate(Delegate)
Expand All @@ -42,6 +47,9 @@ public struct MainFeature {

public var body: some ReducerOf<Self> {
BindingReducer()
Scope(state: \.sidebar, action: \.sidebar) {
SidebarFeature()
}
Reduce { state, action in
switch action {
case .binding:
Expand All @@ -50,9 +58,39 @@ public struct MainFeature {
case .task:
return .none

case .sidebar(.delegate(let delegate)):
return handleSidebarDelegate(&state, delegate: delegate)

case .sidebar:
return .none

case .delegate:
return .none
}
}
}
}

// MARK: - Private

extension MainFeature {

private func handleSidebarDelegate(
_ state: inout State,
delegate: SidebarFeature.Action.Delegate
) -> Effect<Action> {
switch delegate {
case .selectionChanged:
return .none

case .addButtonTapped:
return .none

case .settingsButtonTapped:
return .none

case .addProjectTapped:
return .none
}
}
}
3 changes: 2 additions & 1 deletion Projects/DVPresentation/Sources/Features/Main/MainView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@ extension MainView {
}

private var sidebar: some View {
Text("Sidebar")
SidebarView(store: store.scope(state: \.sidebar, action: \.sidebar))
.navigationSplitViewColumnWidth(min: 200, ideal: 250, max: 270)
}

private var contentColumn: some View {
Expand Down
115 changes: 115 additions & 0 deletions Projects/DVPresentation/Sources/Features/Sidebar/SidebarFeature.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
// Copyright © 2026 Devault. All rights reserved

import Foundation

import ComposableArchitecture

// MARK: - SidebarFilter

public enum SidebarFilter: Equatable, CaseIterable, Hashable {
case all
case starred
case expired
case deleted

var title: String {
switch self {
case .all: "All"
case .starred: "Star"
case .expired: "Expired"
case .deleted: "Deleted"
}
Comment on lines +15 to +21

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

로컬라이제이션: "All", "Star", "Project", "Rename" 등 모든 사용자 노출 문자열이 하드코딩. 후속 이슈로 관리하고 있는지 확인

}

var icon: String {
switch self {
case .all: "square.grid.2x2.fill"
case .starred: "star.fill"
case .expired: "exclamationmark"
case .deleted: "trash"
}
Comment thread
dlguszoo marked this conversation as resolved.
}
}

// MARK: - SidebarSelection

public enum SidebarSelection: Equatable {
case filter(SidebarFilter)
case project(Int)
}

// MARK: - SidebarFeature

@Reducer
public struct SidebarFeature {

// MARK: - State

@ObservableState
public struct State: Equatable {
public internal(set) var selection: SidebarSelection = .filter(.all)
public internal(set) var isProjectSectionExpanded: Bool = true

public init() {}
}

// MARK: - Action

public enum Action: Equatable {

// MARK: - View

case task
case didSelect(SidebarSelection)
case didTapAddButton
case didTapSettingsButton
case didTapAddProject
case didToggleProjectSection

// MARK: - Delegate

case delegate(Delegate)

public enum Delegate: Equatable {
case selectionChanged(SidebarSelection)
case addButtonTapped
case settingsButtonTapped
case addProjectTapped
}
}

// MARK: - Init

public init() {}

// MARK: - Body

public var body: some ReducerOf<Self> {
Reduce { state, action in
switch action {
case .task:
return .none

case .didSelect(let selection):
state.selection = selection
return .send(.delegate(.selectionChanged(selection)))

case .didTapAddButton:
return .send(.delegate(.addButtonTapped))

case .didTapSettingsButton:
return .send(.delegate(.settingsButtonTapped))

case .didTapAddProject:
return .send(.delegate(.addProjectTapped))

case .didToggleProjectSection:
state.isProjectSectionExpanded.toggle()
return .none

case .delegate:
return .none
}
}
}
}
Loading