Skip to content

Design/#38 - Sidebar UI 및 SidebarFeature 구현 - #40

Merged
dlguszoo merged 10 commits into
developfrom
design/#38
Jul 19, 2026
Merged

Design/#38 - Sidebar UI 및 SidebarFeature 구현#40
dlguszoo merged 10 commits into
developfrom
design/#38

Conversation

@dlguszoo

@dlguszoo dlguszoo commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

✨ What’s this PR?

📌 관련 이슈 (Related Issue)


🧶 주요 변경 내용 (Summary)

  • SidebarFilter, SidebarSelection enum 정의 및 SidebarFeature 구현
  • DVCategory, DVProjectContainer를 활용한 SidebarView 구현
    • 해당 컴포넌트 자잘 UI 수정
  • MainFeature에 SidebarFeature를 Scope으로 연결, MainView에 SidebarView 주입

📸 스크린샷 (Optional)

스크린샷 2026-07-16 오전 5 23 38

🧪 테스트 / 검증 내역

  • UI 정상 동작 확인
  • 필터(All / Star / Expired / Deleted) 탭 시 선택 상태 전환 확인
  • 프로젝트 행 선택 시 filter 선택 해제되는 것 확인
  • 프로젝트 섹션 접기/펼치기 동작 확인
  • 하단 설정/추가 버튼 탭 확인
  • My Mac, macOS 14.0 환경에서 정상 동작

💬 기타 공유 사항

SidebarSelection enum 도입
filter 선택과 project 선택은 동시에 존재할 수 없는 상호 배타적 상태.
selectedFilter + selectedProjectIndex 두 프로퍼티로 분리하면 둘이 동시에 값을 갖는 잘못된 상태가 모델링 가능하므로, SidebarSelection enum 하나로 통합해 타입 시스템에서 불가능하게 만들었습니다.

List selection Binding 처리
List(selection:)Binding<Int?>를 요구하지만 store의 selection은 SidebarSelection(enum)이라 타입 불일치로 $store 직접 바인딩이 불가합니다.
가이드라인(8.4)를 벗어나지만, 의도적 예외이므로 주석으로 이유를 명시했습니다.

List selection 컬러
macOS List .sidebar 스타일의 selection 하이라이트 색상은 .tint()로 변경 불가 — 시스템 Accent Color를 강제 사용합니다. NSAccentColorName asset 방식도 시도했으나 동작하지 않아 시스템 컬러로 유지합니다.

List 가로 패딩
사이드바 전체에 .padding(.horizontal, 12)를 적용하되, List만 .padding(.horizontal, -12)로 상쇄해 List가 사이드바 전체 너비를 사용하도록 처리했습니다.

아무래도... 다크모드 대응이 필수일 듯 합니다..

🙇🏻‍♀️ 리뷰 가이드 (선택)

추후 예정 작업

  • 실제 프로젝트 데이터 연결 (현재 더미 데이터)
  • contextMenu Action 구현 (Rename, New Secret, Delete Project)
  • MainFeature.handleSidebarDelegate 실제 구현 (현재 모두 .none)
  • SidebarFeature TestStore 기반 단위 테스트 작성

Summary by CodeRabbit

  • 새 기능
    • 메인 화면에 사이드바를 연결하고, 전체/즐겨찾기/만료/삭제 필터와 프로젝트 목록을 추가했습니다.
    • 프로젝트 섹션을 펼치거나 접고, 프로젝트 추가 및 선택 전환을 지원합니다.
    • 프로젝트 항목 컨텍스트 메뉴(이름 변경/새 시크릿/삭제)를 제공합니다.
  • 스타일 개선
    • 카테고리 아이콘·텍스트 크기/색과 선택 상태 표시를 정돈했습니다.
    • 프로젝트 항목의 패딩과 전경색 톤을 개선하고, 사이드바 너비 범위를 조정했습니다.
  • 기타
    • 그레이 톤을 미세 조정했습니다.

@dlguszoo dlguszoo linked an issue Jul 15, 2026 that may be closed by this pull request
5 tasks
@dlguszoo dlguszoo self-assigned this Jul 15, 2026
@dlguszoo dlguszoo added the 🎨 Design UI 디자인 작업 label Jul 15, 2026
@coderabbitai

coderabbitai Bot commented Jul 15, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@dlguszoo, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 53 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 15d3cabd-c14e-4148-92c2-16bc7853232f

📥 Commits

Reviewing files that changed from the base of the PR and between 82d13e7 and 58ff27f.

📒 Files selected for processing (1)
  • Projects/DVDesign/Sources/Components/DVCategory.swift

Walkthrough

사이드바 필터·프로젝트 선택 기능을 TCA로 구현하고 MainFeature 및 NavigationSplitView에 연결했습니다. 사이드바 UI와 프로젝트 목록을 추가했으며, 카테고리와 프로젝트 컨테이너의 디자인 토큰 및 레이아웃을 조정했습니다.

Changes

메인 및 사이드바 UI

Layer / File(s) Summary
사이드바 상태와 이벤트 리듀서
Projects/DVPresentation/Sources/Features/Sidebar/SidebarFeature.swift
필터·프로젝트 선택 모델, 확장 상태, 사용자 액션과 델리게이트를 정의하고 리듀서에서 상태 변경 및 이벤트 전달을 처리합니다.
사이드바 레이아웃과 디자인 시스템 적용
Projects/DVPresentation/Sources/Features/Sidebar/SidebarView.swift, Projects/DVDesign/Sources/Components/DVCategory.swift, Projects/DVDesign/Sources/Components/DVProjectContainer.swift, Projects/DVDesign/Resources/Assets.xcassets/color/gray300.colorset/Contents.json
필터 그리드, 프로젝트 섹션, 하단 버튼과 미리보기를 추가하고 관련 컴포넌트의 색상·크기·패딩 및 gray300 색상 값을 조정합니다.
메인 기능과 앱 화면 연결
Projects/DVPresentation/Sources/Features/Main/MainFeature.swift, Projects/DVPresentation/Sources/Features/Main/MainView.swift
MainFeature가 SidebarFeature를 스코프하고, MainView가 SidebarView와 사이드바 컬럼 너비를 NavigationSplitView에 연결합니다.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant SidebarView
  participant SidebarFeature
  participant MainFeature
  User->>SidebarView: 필터 또는 프로젝트 선택
  SidebarView->>SidebarFeature: didSelect 전송
  SidebarFeature->>SidebarFeature: selection 갱신
  SidebarFeature->>MainFeature: selectionChanged delegate 전송
  MainFeature-->>SidebarView: 스코프된 상태로 화면 갱신
Loading

Possibly related PRs

Suggested labels: ✨ Feature

Suggested reviewers: yeseonglee

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed 제목이 사이드바 UI와 SidebarFeature 구현이라는 변경 핵심을 정확히 요약합니다.
Linked Issues check ✅ Passed 사이드바 뷰, 필터 그리드, 프로젝트 섹션, 하단 버튼, MainView/MainFeature 연결이 요구사항과 맞습니다.
Out of Scope Changes check ✅ Passed 사이드바 구현에 필요한 연동과 스타일 조정만 보이며, 명백한 무관 변경은 없습니다.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch design/#38

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
Projects/DVDesign/Sources/Components/DVCategory.swift (1)

98-103: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

불필요한 isHovered 분기 제거

isHovered 조건이 참일 때의 반환값과 조건문을 통과한 기본 반환값이 모두 gray200으로 동일합니다. 중복되는 조건 분기를 제거하여 코드를 더 간결하게 유지하는 것을 제안합니다.

💡 제안하는 수정안
     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(.gray200)
     }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@Projects/DVDesign/Sources/Components/DVCategory.swift` around lines 98 - 103,
Remove the redundant isHovered branch from backgroundColor(isPressed:), since it
returns the same gray200 color as the default path; preserve the isSelected and
isPressed priority and keep gray200 as the fallback.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@Projects/DVDesign/Sources/Components/DVCategory.swift`:
- Around line 98-103: Remove the redundant isHovered branch from
backgroundColor(isPressed:), since it returns the same gray200 color as the
default path; preserve the isSelected and isPressed priority and keep gray200 as
the fallback.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: cc94e1fd-89d4-4aa9-ba86-7e3f75a636d8

📥 Commits

Reviewing files that changed from the base of the PR and between 9171222 and d673266.

📒 Files selected for processing (11)
  • Projects/DVDesign/Sources/Components/DVCategory.swift
  • Projects/DVDesign/Sources/Components/DVProjectContainer.swift
  • Projects/DVPresentation/Sources/Features/AppFeature.swift
  • Projects/DVPresentation/Sources/Features/AppView.swift
  • Projects/DVPresentation/Sources/Features/Main/MainFeature.swift
  • Projects/DVPresentation/Sources/Features/Main/MainView.swift
  • Projects/DVPresentation/Sources/Features/Sidebar/SidebarFeature.swift
  • Projects/DVPresentation/Sources/Features/Sidebar/SidebarView.swift
  • Projects/DVPresentation/Sources/ProjectSecretRelationDemoView.swift
  • Projects/DVPresentation/Sources/SecretUseCaseDemoView.swift
  • Projects/Devault/Sources/ContentView.swift
💤 Files with no reviewable changes (3)
  • Projects/Devault/Sources/ContentView.swift
  • Projects/DVPresentation/Sources/SecretUseCaseDemoView.swift
  • Projects/DVPresentation/Sources/ProjectSecretRelationDemoView.swift

dlguszoo added 5 commits July 16, 2026 10:25
SidebarFilter, SidebarSelection enum 정의 및 SidebarFeature 구현.
SidebarSelection으로 filter/project 선택을 단일 상태로 표현해 상호 배타성 보장.
Scope으로 SidebarFeature를 MainFeature에 연결하고
SidebarView를 MainView sidebar 컬럼에 주입.
DVCategory, DVProjectContainer 컴포넌트를 활용한 사이드바 UI 구현.
filterGrid, projectSection, bottomBar로 구성.
Comment thread Projects/DVPresentation/Sources/Features/Sidebar/SidebarView.swift Outdated
Comment thread Projects/DVDesign/Sources/Components/DVCategory.swift
Comment thread Projects/DVPresentation/Sources/Features/Sidebar/SidebarFeature.swift Outdated
Comment thread Projects/DVPresentation/Sources/Features/Sidebar/SidebarView.swift
Comment thread Projects/DVPresentation/Sources/Features/Sidebar/SidebarView.swift Outdated
Comment on lines +15 to +21
var title: String {
switch self {
case .all: "All"
case .starred: "Star"
case .expired: "Expired"
case .deleted: "Deleted"
}

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" 등 모든 사용자 노출 문자열이 하드코딩. 후속 이슈로 관리하고 있는지 확인

dlguszoo added 4 commits July 19, 2026 18:37
외부 모듈에서 State를 관찰해야 하는 시점을 대비해 selection, isProjectSectionExpanded를
public internal(set)으로 변경. getter는 외부 공개, setter는 모듈 내부(reducer)만 접근 가능.
- List maxHeight 제한 제거
- 접근성 레이블 추가: Add Project, Collapse/Expand Projects, Settings, Add Secret
- 프리뷰를 Group으로 통합, 너비 200/250/270pt 대응
- collapsed 시 Spacer(minLength: 0) 추가로 bottomBar 하단 고정 버그 수정
- List deselect nil 처리 TODO 주석 추가
@dlguszoo

Copy link
Copy Markdown
Contributor Author

TODO 목록

Localization

  • SidebarFilter.title — "All", "Star", "Expired", "Deleted" 하드코딩
  • Text("Project") — projectSectionHeader
  • 접근성 레이블 전체 ("Add Project", "Settings" 등) — String(localized:) 또는 LocalizedStringKey 적용
  • contextMenu 항목 — "Rename", "New Secret", "Delete Project"

접근성 (Accessibility)

  • DVCategory — isSelected 상태를 VoiceOver에 전달 (.accessibilityAddTraits(.isSelected))
  • DVCategory — 아이콘+타이틀+카운트를 하나의 레이블로 통합 (e.g. "All, 5 items")
  • DVProjectContainer — 리스트 아이템 accessibilityLabel 없음

기능 구현

  • projectList 더미 데이터 → 실제 데이터 연결
  • List deselect(nil) 처리 — content 컬럼 연결 시 결정
  • contextMenu 액션 구현 (Rename, New Secret, Delete Project)
  • didTapAddProject → 알럿으로 프로젝트 생성
  • MainFeature.handleSidebarDelegate 실제 구현 (현재 전부 .none)

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
Projects/DVDesign/Sources/Components/DVCategory.swift (1)

92-102: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

버튼 눌림(Pressed) 상태에 대한 시각적 피드백을 추가하세요.

현재 makeBody에서 configuration.isPressed에 대한 처리가 누락되어 클릭 시 반응이 없습니다. macOS 환경에서는 마우스 상호작용이 주가 되므로 클릭 피드백이 필수적입니다.
또한, SwiftUI 뷰 구조 가이드라인에 따라 파라미터가 있는 하위 뷰/로직은 private func로 정의해야 합니다.

💡 제안하는 수정안
    func makeBody(configuration: Configuration) -> some View {
        configuration.label
-           .background(backgroundColor)
+           .background(backgroundColor(isPressed: configuration.isPressed))
            .clipShape(RoundedRectangle(cornerRadius: 16))
    }

-   private var backgroundColor: Color {
+   private func backgroundColor(isPressed: Bool) -> Color {
+       if isPressed { return Color.dv(.gray400) } // 적절한 Pressed 색상으로 변경
        if isSelected { return Color.dv(.vaultGreen) }
        if isHovered  { return Color.dv(.gray300) }
        return Color.dv(.gray200)
    }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@Projects/DVDesign/Sources/Components/DVCategory.swift` around lines 92 - 102,
Update makeBody(configuration:) to provide visual feedback when
configuration.isPressed is true, while preserving the selected, hovered, and
default background behavior. Move the parameter-dependent background selection
logic out of the parameterless backgroundColor property into a private function
that accepts the button configuration or pressed state, and use it from
makeBody.

Source: Path instructions

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@Projects/DVDesign/Sources/Components/DVCategory.swift`:
- Around line 92-102: Update makeBody(configuration:) to provide visual feedback
when configuration.isPressed is true, while preserving the selected, hovered,
and default background behavior. Move the parameter-dependent background
selection logic out of the parameterless backgroundColor property into a private
function that accepts the button configuration or pressed state, and use it from
makeBody.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 015f101e-4dba-4ea5-94e6-e4df2c0a4b04

📥 Commits

Reviewing files that changed from the base of the PR and between 9b5f61e and 82d13e7.

📒 Files selected for processing (5)
  • Projects/DVDesign/Resources/Assets.xcassets/color/gray300.colorset/Contents.json
  • Projects/DVDesign/Sources/Components/DVCategory.swift
  • Projects/DVPresentation/Sources/Features/Main/MainView.swift
  • Projects/DVPresentation/Sources/Features/Sidebar/SidebarFeature.swift
  • Projects/DVPresentation/Sources/Features/Sidebar/SidebarView.swift
🚧 Files skipped from review as they are similar to previous changes (3)
  • Projects/DVPresentation/Sources/Features/Main/MainView.swift
  • Projects/DVPresentation/Sources/Features/Sidebar/SidebarView.swift
  • Projects/DVPresentation/Sources/Features/Sidebar/SidebarFeature.swift

@doyeonk429 doyeonk429 left a comment

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.

👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

🎨 Design UI 디자인 작업

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Design: 사이드바 뷰 구현

2 participants