Repository navigation
Conversation
|
Capy auto-review is paused for this organization because the monthly auto-review limit has been reached. Increase the limit or turn it off in billing settings to resume automatic reviews. |
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (2)
🚧 Files skipped from review as they are similar to previous changes (1)
📝 WalkthroughWalkthroughAdds project color support to desktop sidebars: shared color utilities, persisted per-project color in local meta store, hook integration exposing color and setter, UI wiring through sidebar components and context menu, and color-aware thumbnail rendering in dashboard and workspace sidebars. ChangesProject Color Support
sequenceDiagram
participant User
participant DashboardSidebar
participant DashboardSidebarProjectContextMenu
participant useV2ProjectLocalMetaStore
participant ProjectThumbnail
User->>DashboardSidebar: open sidebar / right-click project
DashboardSidebar->>DashboardSidebarProjectContextMenu: open menu (projectColor)
DashboardSidebarProjectContextMenu->>useV2ProjectLocalMetaStore: call setProjectColor via handleSetColor
DashboardSidebar->>ProjectThumbnail: pass updated color prop
ProjectThumbnail->>useV2ProjectLocalMetaStore: (reads color via hook for rendering)
🎯 3 (Moderate) | ⏱️ ~20 minutes
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
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. Comment |
|
Ready to review this PR? Stage has broken it down into 5 individual chapters for you: Chapters generated by Stage for commit 56cc7bc on Jun 2, 2026 9:25am UTC. |
Greptile SummaryThis PR ports the project color customization feature from the v1 sidebar to the v2 dashboard sidebar. Users can right-click a project in the v2 sidebar, pick a color from a "Set Color" submenu, and the thumbnail border/background/text tint accordingly; the color is stored in the existing
Confidence Score: 3/5The color-setting flow works correctly, but once a color is chosen it cannot be cleared — the Default reset option is absent from the context menu. The store, hook, and thumbnail rendering are all wired correctly, and the shared-helper extraction is clean. The blocking gap is in ColorSelector's menu variant: it iterates only the 12 palette colors and never emits PROJECT_COLOR_DEFAULT, so users who set a color have no way to revert to the default gray border. The PR's own test plan flags this scenario as unverified, and the current implementation will not satisfy it. apps/desktop/src/renderer/components/ColorSelector/ColorSelector.tsx — the menu variant needs a Default item prepended to allow color resets.
|
| Filename | Overview |
|---|---|
| apps/desktop/src/renderer/components/ColorSelector/ColorSelector.tsx | Menu variant omits the PROJECT_COLOR_DEFAULT option, making it impossible to clear a color once set — breaks the PR's own test-plan item. |
| apps/desktop/src/renderer/stores/v2-project-local-meta.ts | Additive schema change (color: string |
| apps/desktop/src/shared/constants/project-colors.ts | Correctly extracts hexToRgba and isCustomProjectColor from v1 thumbnail into a shared helper; isCustomProjectColor signature improved to be a type guard (color is string). |
| apps/desktop/src/renderer/routes/_authenticated/components/ProjectThumbnail/ProjectThumbnail.tsx | New v2 thumbnail correctly applies border/background/text tint using shared helpers; fallback letter rendering with custom color looks correct. |
| apps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/ProjectSection/ProjectThumbnail/ProjectThumbnail.tsx | Cleaned up local hexToRgba/isCustomColor duplicates and replaced with shared helpers; logic unchanged. |
| apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarProjectSection/hooks/useDashboardSidebarProjectSectionActions/useDashboardSidebarProjectSectionActions.ts | Correctly reads projectColor from the zustand store and exposes handleSetColor; signature narrowing (string instead of string |
| apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarProjectSection/components/DashboardSidebarProjectContextMenu/DashboardSidebarProjectContextMenu.tsx | Correctly wires the Set Color submenu using ContextMenuSub with ColorSelector in menu variant; passes projectColor for checked-state display. |
Flowchart
%%{init: {'theme': 'neutral'}}%%
flowchart TD
Store["v2-project-local-meta\n(zustand persist)"]
Hook["useDashboardSidebarProjectSectionActions\nprojectColor / handleSetColor"]
Section["DashboardSidebarProjectSection"]
CtxMenu["DashboardSidebarProjectContextMenu\nonSetColor / projectColor"]
ColorSel["ColorSelector\nvariant='menu'"]
Row["DashboardSidebarProjectRow\nprojectColor"]
Collapsed["DashboardSidebarCollapsedProjectContent\nprojectColor"]
ThumbV2["ProjectThumbnail (v2)\nborder + bg + text tint"]
ThumbV1["ProjectThumbnail (v1)\nborder + bg + text tint"]
SharedHelpers["shared/constants/project-colors.ts\nhexToRgba · isCustomProjectColor"]
Store -->|"color ?? null"| Hook
Hook -->|"projectColor, handleSetColor"| Section
Section --> CtxMenu
Section --> Row
Section --> Collapsed
CtxMenu --> ColorSel
ColorSel -->|"onSelectColor(hex)"| Hook
Hook -->|"setProjectColor(id, color)"| Store
Row --> ThumbV2
Collapsed --> ThumbV2
ThumbV2 --> SharedHelpers
ThumbV1 --> SharedHelpers
Prompt To Fix All With AI
Fix the following 2 code review issues. Work through them one at a time, proposing concise fixes.
---
### Issue 1 of 2
apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarProjectSection/hooks/useDashboardSidebarProjectSectionActions/useDashboardSidebarProjectSectionActions.ts:58-60
**`handleSetColor` signature prevents clearing to `null`**
`setProjectColor` accepts `string | null`, but `handleSetColor` (and therefore `onSetColor` on the context menu) only accepts `string`. When a "Default"/"clear" option is eventually added to the `ColorSelector` menu variant, the handler will need to forward `null` (or the `PROJECT_COLOR_DEFAULT` sentinel) to the store. The current narrow signature will silently store `"default"` as a string instead of `null`, which still works for `isCustomProjectColor`, but is an inconsistency that could cause confusion.
### Issue 2 of 2
apps/desktop/src/shared/constants/project-colors.ts:33-38
**`hexToRgba` silently produces `rgba(NaN, NaN, NaN, alpha)` for invalid hex**
The function slices the input without any length/format validation. A 3-character shorthand (`#RGB`), a hex-with-alpha string (`#RRGGBBAA`), or any non-`#RRGGBB` string produces `NaN` components. Since callers guard with `isCustomProjectColor` (which checks `startsWith("#")`), arbitrary strings are already blocked, but a mismatched-length hex like `#abc` would still pass through and produce a broken rgba value. Given that colors are currently constrained to the predefined palette this is low risk, but the shared helper doesn't document or enforce the expected format.
Reviews (1): Last reviewed commit: "feat(desktop): add project color customi..." | Re-trigger Greptile
|
Actionable comments posted: 0 |
There was a problem hiding this comment.
3 issues found across 9 files
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarProjectSection/components/DashboardSidebarProjectContextMenu/DashboardSidebarProjectContextMenu.tsx">
<violation number="1" location="apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarProjectSection/components/DashboardSidebarProjectContextMenu/DashboardSidebarProjectContextMenu.tsx:65">
P2: This submenu has no way to clear a project color back to default, so custom colors can be added but not removed.</violation>
</file>
<file name="apps/desktop/src/shared/constants/project-colors.ts">
<violation number="1" location="apps/desktop/src/shared/constants/project-colors.ts:29">
P3: Validate the full hex format here instead of only checking `startsWith("#")`; values like `#abc` pass this guard and can produce invalid `rgba(...)` output downstream.</violation>
</file>
Architecture diagram
sequenceDiagram
participant User
participant V2Sidebar as V2 Dashboard Sidebar
participant ContextMenu as Project Context Menu
participant ColorSelector as ColorSelector (menu variant)
participant V2Store as v2-project-local-meta (zustand + persist)
participant Thumbnail as ProjectThumbnail (v2)
participant SharedHelpers as shared/constants/project-colors.ts
Note over User,SharedHelpers: Project Color Customization — Client-Side Only
User->>V2Sidebar: Right-click project in sidebar
V2Sidebar->>ContextMenu: Open context menu (projectColor, onSetColor)
ContextMenu->>ContextMenu: Render "Set Color" submenu with LuPalette icon
ContextMenu->>ColorSelector: Pass selectedColor={projectColor}, onSelectColor={handleSetColor}
User->>ColorSelector: Click a color swatch (or default)
ColorSelector->>ContextMenu: onSelectColor(color)
ContextMenu->>V2Store: setProjectColor(project.id, color)
alt Color is hex value (not default)
V2Store->>V2Store: Update projects[id].color = "#RRGGBB"
else Color is null (cleared/default)
V2Store->>V2Store: Update projects[id].color = null
end
Note over V2Store: Zustand persist middleware saves to localStorage automatically
V2Store->>V2Sidebar: Re-render with updated projectColor
V2Sidebar->>Thumbnail: Pass color={projectColor}
Note over Thumbnail,SharedHelpers: Thumbnail rendering
alt Sidebar is collapsed
V2Sidebar->>DashboardSidebarCollapsedProjectContent: pass projectColor
DashboardSidebarCollapsedProjectContent->>Thumbnail: render with color
else Sidebar is expanded
V2Sidebar->>DashboardSidebarProjectRow: pass projectColor
DashboardSidebarProjectRow->>Thumbnail: render with color
end
Thumbnail->>SharedHelpers: isCustomProjectColor(color)
SharedHelpers-->>Thumbnail: boolean (true if hex and not default)
alt hasCustomColor == true
Thumbnail->>SharedHelpers: hexToRgba(color, 0.6) for border
Thumbnail->>Thumbnail: Apply border color (rgba with 0.6 alpha)
opt Icon fails to load
Thumbnail->>SharedHelpers: hexToRgba(color, 0.15) for background
Thumbnail->>Thumbnail: Set background and text color to custom color
end
else hasCustomColor == false
Thumbnail->>Thumbnail: Use default border-foreground/10 and bg-muted
end
Thumbnail-->>V2Sidebar: Render thumbnail with applied color style
V2Sidebar-->>User: Display updated project thumbnail
Reply with feedback, questions, or to request a fix.
Re-trigger cubic
| export function isCustomProjectColor( | ||
| color: string | null | undefined, | ||
| ): color is string { | ||
| return !!color && color !== PROJECT_COLOR_DEFAULT && color.startsWith("#"); |
There was a problem hiding this comment.
P3: Validate the full hex format here instead of only checking startsWith("#"); values like #abc pass this guard and can produce invalid rgba(...) output downstream.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At apps/desktop/src/shared/constants/project-colors.ts, line 29:
<comment>Validate the full hex format here instead of only checking `startsWith("#")`; values like `#abc` pass this guard and can produce invalid `rgba(...)` output downstream.</comment>
<file context>
@@ -21,3 +21,18 @@ export const PROJECT_CUSTOM_COLORS = PROJECT_COLORS;
+export function isCustomProjectColor(
+ color: string | null | undefined,
+): color is string {
+ return !!color && color !== PROJECT_COLOR_DEFAULT && color.startsWith("#");
+}
+
</file context>
| return !!color && color !== PROJECT_COLOR_DEFAULT && color.startsWith("#"); | |
| return !!color && color !== PROJECT_COLOR_DEFAULT && /^#[0-9A-Fa-f]{6}$/.test(color); |
| interface ProjectMeta { | ||
| isCollapsed: boolean; | ||
| tabOrder: number; | ||
| color: string | null; |
There was a problem hiding this comment.
shouldnt we have a default value instead of null for the color string value?
| getProjectMeta: (id: string) => ProjectMeta; | ||
| toggleProjectCollapsed: (id: string) => void; | ||
| setProjectTabOrder: (id: string, order: number) => void; | ||
| setProjectColor: (id: string, color: string | null) => void; |
| const DEFAULT_PROJECT_META: ProjectMeta = { | ||
| isCollapsed: false, | ||
| tabOrder: 0, | ||
| color: null, |
There was a problem hiding this comment.
default string instead of null maybe, we already have the default gray we use
| interface ProjectThumbnailProps { | ||
| projectName: string; | ||
| iconUrl?: string | null; | ||
| color?: string | null; |
|
Actionable comments posted: 0 |
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (1)
apps/desktop/src/renderer/stores/v2-project-local-meta.ts (1)
5-9: ⚡ Quick winBackfill missing
ProjectMeta.colorongetProjectMeta(zustand persist has no migration)
apps/desktop/src/renderer/stores/v2-project-local-meta.tsusespersistwithname: "v2-project-local-meta", version: 1and no migration/merge logic, so older persistedprojects[id]entries can lackcolor. A repo search forgetProjectMeta(in*.tsdidn’t find any consumers reading.colordirectly, but returning an object withcolor: undefinedstill breaks theProjectMetainvariant.🛠️ Proposed fix to backfill missing fields
getProjectMeta: (id) => { - return get().projects[id] ?? DEFAULT_PROJECT_META; + return { ...DEFAULT_PROJECT_META, ...get().projects[id] }; },🤖 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 `@apps/desktop/src/renderer/stores/v2-project-local-meta.ts` around lines 5 - 9, Persisted project entries may lack the ProjectMeta.color field because the zustand persist store ("v2-project-local-meta", version: 1) has no migration; update the persist usage and getProjectMeta to backfill defaults: add a migration/merge handler in the persist config for "v2-project-local-meta" that assigns a sane default color when loading older state, and in the getProjectMeta function ensure any returned ProjectMeta always contains a non-undefined color (e.g., set color = color ?? '<default-color>' or compute fallback) so the ProjectMeta invariant is preserved; reference the ProjectMeta interface, getProjectMeta, and the persist config name when making changes.
🤖 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 `@apps/desktop/src/renderer/stores/v2-project-local-meta.ts`:
- Around line 5-9: Persisted project entries may lack the ProjectMeta.color
field because the zustand persist store ("v2-project-local-meta", version: 1)
has no migration; update the persist usage and getProjectMeta to backfill
defaults: add a migration/merge handler in the persist config for
"v2-project-local-meta" that assigns a sane default color when loading older
state, and in the getProjectMeta function ensure any returned ProjectMeta always
contains a non-undefined color (e.g., set color = color ?? '<default-color>' or
compute fallback) so the ProjectMeta invariant is preserved; reference the
ProjectMeta interface, getProjectMeta, and the persist config name when making
changes.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: f4fb9654-004e-4138-a124-e8a7288b301d
📒 Files selected for processing (5)
apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarProjectSection/components/DashboardSidebarCollapsedProjectContent/DashboardSidebarCollapsedProjectContent.tsxapps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarProjectSection/components/DashboardSidebarProjectContextMenu/DashboardSidebarProjectContextMenu.tsxapps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarProjectSection/components/DashboardSidebarProjectRow/DashboardSidebarProjectRow.tsxapps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarProjectSection/hooks/useDashboardSidebarProjectSectionActions/useDashboardSidebarProjectSectionActions.tsapps/desktop/src/renderer/stores/v2-project-local-meta.ts
🚧 Files skipped from review as they are similar to previous changes (3)
- apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarProjectSection/components/DashboardSidebarCollapsedProjectContent/DashboardSidebarCollapsedProjectContent.tsx
- apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarProjectSection/components/DashboardSidebarProjectRow/DashboardSidebarProjectRow.tsx
- apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarProjectSection/components/DashboardSidebarProjectContextMenu/DashboardSidebarProjectContextMenu.tsx
Summary
Ports the project-color feature from the v1 sidebar to the v2 dashboard sidebar (inspired by the
project-color-sidebarbranch). Users can right-click a project in the v2 sidebar and pick a color from a Set Color submenu; the chosen color tints the project thumbnail's border (and background/text for the letter fallback).Color is stored client-side only in the existing
v2-project-local-metazustand store (persisted locally) — no server/DB changes, matching the v1 behavior.Changes
v2-project-local-metastore: addcolortoProjectMeta+setProjectColoraction.ColorSelector, menu variant) in the project context menu; threadprojectColorthrough the section → row / collapsed content →ProjectThumbnail.ProjectThumbnail(v2): render custom hex color on border + letter fallback.hexToRgba/isCustomProjectColorhelpers intoshared/constants/project-colors.tsand refactored both the v1 and v2 thumbnails to consume them (removes a pre-existing copy).Test Plan
bun run lintclean,typecheckpasses, existing colors + v1 thumbnail tests pass.Summary by cubic
Adds project color customization to the v2 dashboard sidebar. Right‑click a project to Set Color (includes Default to reset); thumbnails tint accordingly and choices persist locally with no server changes.
New Features
ColorSelector(menu variant) withincludeDefault.projectColorthrough collapsed and expanded views toProjectThumbnail; apply color to border and letter fallback.v2-project-local-metaviasetProjectColor(clearing setsPROJECT_COLOR_DEFAULT).Refactors
v2-project-local-meta, defaulting toPROJECT_COLOR_DEFAULT.hexToRgbaandisCustomProjectColortoshared/constants/project-colors.ts; v1 and v2 thumbnails use them.Written for commit 56cc7bc. Summary will update on new commits.
Summary by CodeRabbit