Skip to content

Conversation

@Shironex
Copy link
Collaborator

@Shironex Shironex commented Dec 21, 2025

  • Update Wiki with latest info
  • Refactor Sidebar from 2100+ lines to 378 lines
  • Remove pnpm-lock file since we are just using npm not pnpm seems to be added by accident from shared packages branch that got merged
  • Add unit test for claude-usage-service.ts
  • Fixed various lint issues went from 636 problems ( 517 errors, 119 warmings ) to 73 problems (0 errors, 73 warnings)

Summary by CodeRabbit

  • New Features

    • Richer sidebar UI: logo, collapse toggle, bug-report, project actions, project selector (search + drag reorder), trash & onboarding dialogs, theme preview, running agents indicator; onboarding/project creation improvements.
  • Refactor

    • Sidebar reorganized into modular components and hooks; many UI barrels consolidated.
    • Public API updates: expanded board component props and added collapsible accordion prop; a few minor API/type literal adjustments.
  • Style

    • Large-scale formatting/quote normalization across UI and tests.
  • Tests

    • New unit tests covering CLI/usage parsing and related behaviors.

✏️ Tip: You can customize this high-level summary in your review settings.

Shironex and others added 8 commits December 21, 2025 19:38
- Rename App.tsx to app.tsx (kebab-case naming convention)
- Add barrel exports (index.ts) for src/hooks/
- Add barrel exports (index.ts) for src/components/dialogs/
- Add barrel exports (index.ts) for src/components/layout/
- Update renderer.tsx import to use lowercase app.tsx

This is Phase 1 of folder-pattern.md compliance: establishing proper
file naming conventions and barrel export patterns.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Move dialogs to src/components/dialogs/ folder:
  - delete-session-dialog.tsx
  - delete-all-archived-sessions-dialog.tsx
  - new-project-modal.tsx
  - workspace-picker-modal.tsx
- Update all imports to reference new dialog locations
- Create barrel export (index.ts) for board-view/components/kanban-card/
- Create barrel exports (index.ts) for all 11 settings-view subfolders:
  - api-keys/, api-keys/hooks/, appearance/, audio/, cli-status/
  - components/, config/, danger-zone/, feature-defaults/
  - keyboard-shortcuts/, shared/

This is Phase 2 of folder-pattern.md compliance: organizing dialogs
and establishing consistent barrel export patterns across all view subfolders.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Extract inline components and organize sidebar structure:
- Create sidebar/ subfolder structure (components/, hooks/, dialogs/)
- Extract types.ts: NavSection, NavItem, component prop interfaces
- Extract constants.ts: theme options, feature flags
- Extract 3 inline components into separate files:
  - sortable-project-item.tsx (drag-and-drop project item)
  - theme-menu-item.tsx (memoized theme selector)
  - bug-report-button.tsx (reusable bug report button)
- Update sidebar.tsx to import from extracted modules
- Reduce sidebar.tsx from 2323 to 2187 lines (-136 lines)

This is Phase 3 (partial) of folder-pattern.md compliance: breaking down
the monolithic sidebar.tsx into maintainable, reusable components.

Further refactoring (hooks extraction, dialog extraction) can be done
incrementally to avoid disrupting functionality.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Extract 3 simple hooks with no UI dependencies:
- use-theme-preview.ts: Debounced theme preview on hover
- use-sidebar-auto-collapse.ts: Auto-collapse on small screens
- use-drag-and-drop.ts: Project reordering drag-and-drop

Benefits:
- Reduced sidebar.tsx by 88 lines (-4%)
- Improved testability (hooks can be tested in isolation)
- Removed unused imports (DragEndEvent, PointerSensor, useSensor, useSensors)
- Created hooks/ barrel export pattern

Next steps: Extract 10+ remaining hooks and 10+ UI sections to reach
target of 200-300 lines (current: 2099 lines, need to reduce ~1800 more)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Introduced new hooks: useRunningAgents, useTrashOperations, useProjectPicker, useSpecRegeneration, and useNavigation for improved state management and functionality.
- Created CollapseToggleButton component for sidebar collapse functionality, enhancing UI responsiveness.
- Refactored sidebar.tsx to utilize the new hooks and components, improving code organization and maintainability.
- Updated sidebar structure to streamline project selection and navigation processes.

This refactor aims to enhance user experience and maintainability by modularizing functionality and improving the sidebar's responsiveness.
…ility

Extract logo, header, actions, and navigation into separate components:
- AutomakerLogo: SVG logo with collapsed/expanded states
- SidebarHeader: Logo section with bug report button
- ProjectActions: New/Open/Trash action buttons
- SidebarNavigation: Navigation items with active states

Reduces sidebar.tsx from 1551 to 1442 lines (-109 lines)
Improves code organization and component reusability

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
…ionality

- Extracted new components: ProjectSelectorWithOptions, SidebarFooter, TrashDialog, and OnboardingDialog to improve code organization and reusability.
- Introduced new hooks: useProjectCreation, useSetupDialog, and useTrashDialog for better state management and modularity.
- Updated sidebar.tsx to utilize the new components and hooks, reducing complexity and improving maintainability.
- Enhanced project creation and setup processes with dedicated dialogs and streamlined user interactions.

This refactor aims to enhance the user experience and maintainability of the sidebar by modularizing functionality and improving the overall structure.
…nd documentation

- Updated type imports for `icon` and `content` in the `WikiSection` interface to use `ElementType` and `ReactNode` for better clarity and type safety.
- Expanded the content description in the WikiView to include shared libraries and updated technology stack details.
- Revised the directory structure representation for clarity and completeness, reflecting the current organization of the codebase.
- Adjusted file paths in the feature list for better accuracy and organization.

These changes aim to improve the documentation and type safety within the WikiView component, enhancing developer experience and understanding of the project structure.
@Shironex Shironex self-assigned this Dec 21, 2025
@Shironex Shironex added Work-In-Progress Currently being addressed. Refactor A complete logic rewrite is requested or being performed for an issue. Do Not Merge Use this label if something should not be merged. labels Dec 21, 2025
@coderabbitai
Copy link

coderabbitai bot commented Dec 21, 2025

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

Walkthrough

Adds extensive server unit tests for ClaudeUsageService and a large UI refactor: Sidebar decomposed into many new components, hooks, dialogs, and barrels; several component props/signatures expanded; widespread string-quote normalization and small API signature tweaks across UI libraries and tests.

Changes

Cohort / File(s) Summary
Server tests
apps/server/tests/unit/services/claude-usage-service.test.ts
New comprehensive unit tests for ClaudeUsageService: availability checks (macOS/Windows), ANSI stripping, reset-time parsing, section/usage parsing, mac expect flow, Windows node-pty flow, auth/error/timeout handling, and related edge cases with mocks and fake timers.
Sidebar refactor (core + barrel)
apps/ui/src/components/layout/sidebar.tsx, apps/ui/src/components/layout/index.ts
Major refactor: Sidebar decomposed to compose new components/hooks; introduced SIDEBAR_FEATURE_FLAGS and exported Sidebar via layout barrel.
Sidebar components & barrel
apps/ui/src/components/layout/sidebar/components/*, apps/ui/src/components/layout/sidebar/components/index.ts
Added many UI components (AutomakerLogo, BugReportButton, CollapseToggleButton, ProjectActions, ProjectSelectorWithOptions, SidebarHeader, SidebarNavigation, SidebarFooter, SortableProjectItem, ThemeMenuItem) and a components barrel re-exporting them.
Sidebar hooks & barrel
apps/ui/src/components/layout/sidebar/hooks/*, apps/ui/src/components/layout/sidebar/hooks/index.ts
Added hooks for sidebar behavior (use-drag-and-drop, use-navigation, use-project-creation, use-project-picker, use-project-theme, use-running-agents, use-setup-dialog, use-sidebar-auto-collapse, use-spec-regeneration, use-theme-preview, use-trash-dialog, use-trash-operations) and a hooks barrel.
Sidebar dialogs, constants, types
apps/ui/src/components/layout/sidebar/dialogs/*, apps/ui/src/components/layout/sidebar/constants.ts, apps/ui/src/components/layout/sidebar/types.ts
New OnboardingDialog and TrashDialog, new theme lists and SIDEBAR_FEATURE_FLAGS, and several sidebar TypeScript interfaces (NavSection, NavItem, SortableProjectItemProps, ThemeMenuItemProps).
Kanban card & KanbanBoard API
apps/ui/src/components/views/board-view/components/kanban-card/index.ts, apps/ui/src/components/views/board-view/kanban-board.tsx
Added barrel for kanban-card subcomponents; expanded KanbanBoard props with many new handlers/props (drag callbacks, actions, shortcuts, suggestions API surface).
Dialog barrels & UI dialogs
apps/ui/src/components/dialogs/*, apps/ui/src/components/dialogs/index.ts
Minor formatting on several dialog files and added a dialogs barrel re-exporting dialog components.
Numerous barrel exports (settings, hooks, views)
apps/ui/src/components/views/settings-view/**/index.ts, apps/ui/src/hooks/index.ts, apps/ui/src/components/views/board-view/components/kanban-card/index.ts, ...
Added many index barrel files to re-export components/hooks/types across settings, hooks, and views.
UI components & hooks changes
apps/ui/src/components/ui/accordion.tsx, apps/ui/src/components/layout/sidebar/..., apps/ui/src/components/ui/*
Public API change: AccordionProps gains optional collapsible?: boolean; many new components/hooks added under sidebar.
Lib/API signature tweaks
apps/ui/src/lib/api-providers.ts, apps/ui/src/lib/utils.ts, apps/ui/src/lib/http-api-client.ts
Minor signature/typing/name normalizations (ProviderKey literal formatting, removed google param from buildProviderConfigs destructure, renamed model param to _model, HttpApiClient.openFile param renamed).
Vite env types
apps/ui/src/vite-env.d.ts
Added ImportMetaEnv and ImportMeta augmentation for typed Vite env vars.
Formatting & test updates
many apps/ui/src/** files and apps/ui/tests/**
Widespread stylistic changes: double → single quotes, minor JSX/text reflows; tests updated/normalized, feature-lifecycle spec now uses per-test git repo lifecycle hooks; Playwright helpers and test utilities reformatted.

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant Sidebar as Sidebar UI
  participant Hooks as Sidebar Hooks
  participant Store as App Store
  participant Electron as Electron API

  Note over User,Sidebar: user interacts with sidebar (clicks, drag, create)
  User->>Sidebar: click "New Project" / reorder project / open item
  Sidebar->>Hooks: delegate (useProjectCreation / useDragAndDrop / useNavigation)
  Hooks->>Electron: invoke FS/clone/spec-regeneration/open-folder
  Electron-->>Hooks: result (success / error / events)
  Hooks->>Store: update state (projects, modal flags, theme preview)
  Store-->>Sidebar: new state
  Sidebar-->>User: render updated UI / show toast
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

  • Focus areas:
    • apps/server/tests/unit/services/claude-usage-service.test.ts — verify platform mocks, timers, and coverage correctness.
    • apps/ui/src/components/layout/sidebar.tsx and the new sidebar components/hooks — check prop contracts, event wiring, and feature-flag gating.
    • use-project-creation, use-trash-operations, use-spec-regeneration — review Electron API usage, IO side effects, error handling, and toast/reporting logic.
    • KanbanBoard prop expansion — ensure all consumers/types updated and no breaking call sites.
    • Barrel exports — verify no circular imports or incorrect paths.

Possibly related PRs

Suggested labels

Tests

Poem

🐰 I hopped through diff with tiny paws,

Tests for Claude and many laws;
Sidebar bits in tidy rows,
Hooks and barrels, petals close;
Single quotes snug beneath my claws. ✨

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 51.35% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'refactor: sidebar' is concise and directly references the main change—a comprehensive sidebar refactor reducing code from 2,100+ to 378 lines. However, it omits other significant changes (Wiki updates, unit tests, lint fixes, pnpm-lock removal) that constitute material parts of the changeset.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch refactor/folder-pattern-compliance

📜 Recent review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 26236d3 and 0c59add.

📒 Files selected for processing (2)
  • apps/server/tests/unit/services/claude-usage-service.test.ts (1 hunks)
  • apps/ui/src/components/layout/sidebar/hooks/use-sidebar-auto-collapse.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • apps/server/tests/unit/services/claude-usage-service.test.ts
  • apps/ui/src/components/layout/sidebar/hooks/use-sidebar-auto-collapse.ts
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: e2e

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

@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @Shironex, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request introduces a significant refactoring of the UI application's folder structure, aiming to enhance code organization and maintainability. It involves relocating various components, particularly dialogs and sidebar-related logic, into more granular and semantically grouped subdirectories. This restructuring simplifies navigation, reduces cognitive load for developers, and sets a foundation for future feature development by promoting a cleaner, more modular codebase.

Highlights

  • Folder Structure Refactoring: Key UI components and dialogs have been moved into dedicated subdirectories (e.g., components/dialogs, components/layout/sidebar/components) to improve organization and modularity.
  • Consistent Naming Conventions: File names like App.tsx have been renamed to app.tsx to ensure compliance with lowercase naming patterns.
  • Sidebar Modularization: The sidebar.tsx component underwent a significant refactor, extracting its complex logic into separate hooks, components, constants, and types files within a new sidebar/ subdirectory for better maintainability.
  • Import Path Updates: All affected files, including session-manager.tsx, welcome-view.tsx, and renderer.tsx, have had their import paths updated to reflect the new file locations.
  • Code Style Consistency: Numerous string literals were updated from double quotes to single quotes across the codebase, aligning with a consistent code style.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This is a significant and well-executed refactoring that greatly improves the structure of the Sidebar component by breaking it down into smaller, more manageable components and hooks. It also reorganizes component files into a more logical folder structure. While the refactoring is a huge improvement, I've found a critical regression in the project creation logic that was extracted into the new useProjectCreation hook. Additionally, this has led to duplicated and inconsistent project creation logic between the Sidebar and the WelcomeView. My review focuses on these two key issues to ensure the refactoring doesn't negatively impact core functionality.

- Updated the project creation logic to write a detailed app_spec.txt file in XML format, including project name, overview, technology stack, core capabilities, and implemented features.
- Improved handling for projects created from templates and custom repositories, ensuring relevant information is captured in the app_spec.txt.
- Enhanced user feedback with success messages upon project creation, improving overall user experience.

These changes aim to provide a clearer project structure and facilitate better integration with AI analysis tools.
- Deleted the pnpm-lock.yaml file as part of project cleanup.
- Introduced comprehensive unit tests for the ClaudeUsageService, covering methods for checking CLI availability, parsing reset times, and handling usage output.
- Enhanced test coverage for both macOS and Windows environments, ensuring robust functionality across platforms.

These changes aim to streamline project dependencies and improve the reliability of the Claude usage tracking service through thorough testing.
@Shironex Shironex marked this pull request as ready for review December 21, 2025 21:41
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
apps/ui/src/components/layout/sidebar.tsx (1)

168-226: Missing dependencies in handleOpenFolder callback.

The callback uses setSetupProjectPath (line 205) and setShowSetupDialog (line 206) from useSetupDialog, but these are not included in the dependency array. While React state setters are typically stable, these come from a custom hook's return value. If the hook ever returns new setter references, this could cause stale closure bugs.

🔎 Suggested fix
  }, [trashedProjects, upsertAndSetCurrentProject, currentProject, globalTheme]);
+ }, [trashedProjects, upsertAndSetCurrentProject, currentProject, globalTheme, setSetupProjectPath, setShowSetupDialog]);
♻️ Duplicate comments (1)
apps/ui/src/components/views/welcome-view.tsx (1)

227-525: Project creation logic remains duplicated.

As noted in the previous review, the project creation handlers (handleCreateBlankProject, handleCreateFromTemplate, handleCreateFromCustomUrl) in this component duplicate logic that should be centralized in the useProjectCreation hook. The previous reviewer noted that this implementation is actually more correct than the hook version.

Consider consolidating this logic into the useProjectCreation hook to ensure consistent behavior across the application and reduce maintenance burden.

Based on previous review comments.

🧹 Nitpick comments (15)
apps/ui/src/components/views/wiki-view.tsx (1)

139-567: LGTM! Consistent string normalization and content improvements.

The section data has been updated with:

  • Consistent single-quote string literals throughout
  • Improved wiki content for clarity
  • Updated file paths and descriptions

The changes maintain functionality while improving code style consistency.

Optional: Verify linter/formatter configuration.

To prevent future inconsistencies with quote styles, consider verifying that your ESLint or Prettier configuration enforces single quotes:

Example ESLint/Prettier configuration

ESLint (.eslintrc.json):

{
  "rules": {
    "quotes": ["error", "single", { "avoidEscape": true }]
  }
}

Prettier (.prettierrc):

{
  "singleQuote": true
}
apps/server/tests/unit/services/claude-usage-service.test.ts (1)

109-127: Consider reusing the service instance from beforeEach.

These tests create new ClaudeUsageService() instances, but there's already a service variable initialized in beforeEach (line 18). This pattern is repeated throughout many test blocks (lines 140, 149, 160, 172, 183, 195, 208, 218, 228, 250, 259, 273, 296, 305, 315, 326, 354, 369, 390).

🔎 Example fix
   describe('stripAnsiCodes', () => {
     it('should strip ANSI color codes from text', () => {
-      const service = new ClaudeUsageService();
       const input = '\x1B[31mRed text\x1B[0m Normal text';
       // @ts-expect-error - accessing private method for testing
       const result = service.stripAnsiCodes(input);

       expect(result).toBe('Red text Normal text');
     });

     it('should handle text without ANSI codes', () => {
-      const service = new ClaudeUsageService();
       const input = 'Plain text';
       // @ts-expect-error - accessing private method for testing
       const result = service.stripAnsiCodes(input);

       expect(result).toBe('Plain text');
     });
   });
apps/ui/src/components/layout/sidebar/components/collapse-toggle-button.tsx (1)

17-30: Refactor the z-index to use a more reasonable value.

The z-9999 on line 20 is an extremely high z-index that suggests z-index management issues. This can lead to stacking context problems and makes it difficult to layer UI elements predictably.

Consider using a more reasonable z-index value (e.g., 50, 100, or 1000) or defining z-index levels in a centralized CSS/design tokens file.

💡 Suggested approach

Define z-index constants in your theme or design tokens:

// In a central location like lib/z-index.ts or theme config
export const Z_INDEX = {
  SIDEBAR_TOGGLE: 50,
  MODAL: 100,
  TOOLTIP: 1000,
} as const;

Then use it:

-        'hidden lg:flex absolute top-[68px] -right-3 z-9999',
+        'hidden lg:flex absolute top-[68px] -right-3 z-50',
apps/ui/src/components/layout/sidebar/components/sortable-project-item.tsx (1)

46-51: Add keyboard accessibility to the project selection area.

The clickable div on line 47 is not keyboard accessible. Users navigating with keyboard cannot select projects since the div is not focusable and has no keyboard event handlers.

Consider making this interactive element keyboard accessible to comply with accessibility best practices.

💡 Suggested fix
-      <div className="flex items-center gap-2.5 flex-1 min-w-0" onClick={() => onSelect(project)}>
+      <div 
+        role="button"
+        tabIndex={0}
+        className="flex items-center gap-2.5 flex-1 min-w-0" 
+        onClick={() => onSelect(project)}
+        onKeyDown={(e) => {
+          if (e.key === 'Enter' || e.key === ' ') {
+            e.preventDefault();
+            onSelect(project);
+          }
+        }}
+      >

Alternatively, wrap the content in a <button> element styled to match the current div appearance.

apps/ui/src/components/layout/sidebar/components/automaker-logo.tsx (1)

29-49: Consider unique SVG gradient IDs to avoid potential conflicts.

The gradient and filter IDs (bg-collapsed, bg-expanded, iconShadow-collapsed, iconShadow-expanded) are hardcoded. If multiple instances of this component are rendered on the same page, these IDs could conflict, causing incorrect rendering.

Since this is a logo component likely rendered once, this is probably not an issue in practice, but for maximum safety you could generate unique IDs using React's useId() hook.

🔎 Example refactor using useId()
+import { useId } from 'react';
 import type { NavigateOptions } from '@tanstack/react-router';
 import { cn } from '@/lib/utils';

 export function AutomakerLogo({ sidebarOpen, navigate }: AutomakerLogoProps) {
+  const id = useId();
+  const bgCollapsedId = `bg-collapsed-${id}`;
+  const bgExpandedId = `bg-expanded-${id}`;
+  const shadowCollapsedId = `iconShadow-collapsed-${id}`;
+  const shadowExpandedId = `iconShadow-expanded-${id}`;
+
   return (
     // ... then use these IDs in the SVG elements:
-    <linearGradient id="bg-collapsed" ...>
+    <linearGradient id={bgCollapsedId} ...>
     // ... and in fill/filter references:
-    fill="url(#bg-collapsed)"
+    fill={`url(#${bgCollapsedId})`}
   );
 }

Also applies to: 74-95

apps/ui/src/components/layout/sidebar/hooks/use-trash-operations.ts (2)

31-64: Consider replacing window.confirm with a proper dialog component.

The window.confirm calls (lines 33 and 71) provide functional confirmation but have UX limitations:

  • Blocks the UI thread
  • Uses native browser styling (inconsistent with app design)
  • Limited accessibility support

Consider creating a dedicated confirmation dialog component for better user experience and consistency with the rest of the application's design system.

That said, the defensive check for api.trashItem availability (lines 41-43) is excellent and prevents runtime errors in environments where the API might not be available.


66-83: Consider replacing window.confirm with a proper dialog component.

Similar to handleDeleteProjectFromDisk, the window.confirm call (lines 71-73) would benefit from being replaced with a custom confirmation dialog for better UX and design consistency.

apps/ui/src/components/layout/sidebar/dialogs/trash-dialog.tsx (1)

58-60: Consider defensive date parsing.

If project.trashedAt contains an invalid date string, new Date(project.trashedAt).toLocaleString() will display "Invalid Date". Consider adding a fallback or validation if the data source isn't fully trusted.

🔎 Example defensive approach
-                  <p className="text-[11px] text-muted-foreground/80">
-                    Trashed {new Date(project.trashedAt).toLocaleString()}
-                  </p>
+                  <p className="text-[11px] text-muted-foreground/80">
+                    Trashed {(() => {
+                      const date = new Date(project.trashedAt);
+                      return isNaN(date.getTime()) ? 'Unknown date' : date.toLocaleString();
+                    })()}
+                  </p>
apps/ui/src/components/layout/sidebar/components/sidebar-navigation.tsx (1)

121-121: Potential fragile data-testid generation.

Using item.label.toLowerCase() directly may produce inconsistent test IDs if labels contain spaces or special characters (e.g., "Running Agents" → "running agents"). Consider using a slug or the existing item.id for consistency.

🔎 Suggested fix
-                      data-testid={`sidebar-tooltip-${item.label.toLowerCase()}`}
+                      data-testid={`sidebar-tooltip-${item.id}`}
apps/ui/src/components/layout/sidebar/components/project-selector-with-options.tsx (2)

256-271: Review theme selection side effects.

When selecting "Use Global" (value === ''), setTheme(globalTheme) is called, which may trigger unnecessary re-renders if the theme is already the global theme. Consider checking if a theme change is actually needed.

🔎 Suggested optimization
                 onValueChange={(value) => {
                   if (currentProject) {
                     setPreviewTheme(null);
-                    if (value !== '') {
-                      setTheme(value as ThemeMode);
-                    } else {
-                      setTheme(globalTheme);
-                    }
+                    // Only update theme if it's actually changing
+                    const newTheme = value === '' ? globalTheme : (value as ThemeMode);
+                    setTheme(newTheme);
                     setProjectTheme(
                       currentProject.id,
                       value === '' ? null : (value as ThemeMode)
                     );
                   }
                 }}

146-160: Add aria-label for accessibility.

The search input has a placeholder but lacks an accessible label for screen readers. Adding aria-label="Search projects" would improve accessibility.

🔎 Suggested fix
              <input
                ref={projectSearchInputRef}
                type="text"
                placeholder="Search projects..."
+               aria-label="Search projects"
                value={projectSearchQuery}
apps/ui/src/components/layout/sidebar/hooks/use-setup-dialog.ts (1)

87-101: Consider resetting generateFeatures, analyzeProject, and featureCount on skip.

When the user skips setup, projectOverview and setupProjectPath are reset, but the toggle/select states (generateFeatures, analyzeProject, featureCount) are preserved. If a user skips, then later opens the dialog for a different project, these stale values may not be appropriate defaults.

🔎 Suggested improvement
  const handleSkipSetup = useCallback(() => {
    setShowSetupDialog(false);
    setProjectOverview('');
    setSetupProjectPath('');
+   setGenerateFeatures(true);
+   setAnalyzeProject(true);
+   setFeatureCount(50);

    // Clear onboarding state if we came from onboarding
    if (newProjectPath) {
      setNewProjectName('');
      setNewProjectPath('');
    }

    toast.info('Setup skipped', {
      description: 'You can set up your app_spec.txt later from the Spec view.',
    });
- }, [newProjectPath, setNewProjectName, setNewProjectPath]);
+ }, [newProjectPath, setNewProjectName, setNewProjectPath, setGenerateFeatures, setAnalyzeProject, setFeatureCount]);
apps/ui/src/components/layout/sidebar/hooks/use-project-creation.ts (3)

67-73: Consider extracting duplicated theme resolution logic.

The theme resolution pattern is duplicated in three places:

  • finalizeProjectCreation (lines 68-72)
  • handleCreateFromTemplate (lines 164-168)
  • handleCreateFromCustomUrl (lines 233-237)
🔎 Suggested helper function
// Add inside the hook, before the handlers
const resolveEffectiveTheme = useCallback(
  (projectPath: string): ThemeMode => {
    const trashedProject = trashedProjects.find((p) => p.path === projectPath);
    return (
      (trashedProject?.theme as ThemeMode | undefined) ||
      (currentProject?.theme as ThemeMode | undefined) ||
      globalTheme
    );
  },
  [trashedProjects, currentProject, globalTheme]
);

// Then use it in handlers:
const effectiveTheme = resolveEffectiveTheme(projectPath);

Also applies to: 163-169, 232-238


125-189: handleCreateFromTemplate duplicates finalization logic instead of using finalizeProjectCreation.

This handler performs the same post-creation steps (initialize project, write app_spec, resolve theme, update state, show onboarding, toast) that finalizeProjectCreation handles. The only difference is the template-specific app_spec.txt content.

Consider refactoring finalizeProjectCreation to accept an optional appSpecContent parameter, allowing template/custom URL flows to reuse it while providing custom content.


191-258: Same duplication issue in handleCreateFromCustomUrl.

This handler also duplicates the finalization logic. The same refactoring approach would reduce maintenance burden and ensure consistent behavior across all creation paths.

📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ee9ccd0 and 43c93fe.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (55)
  • apps/server/tests/unit/services/claude-usage-service.test.ts (1 hunks)
  • apps/ui/src/app.tsx (2 hunks)
  • apps/ui/src/components/dialogs/delete-all-archived-sessions-dialog.tsx (2 hunks)
  • apps/ui/src/components/dialogs/delete-session-dialog.tsx (2 hunks)
  • apps/ui/src/components/dialogs/index.ts (1 hunks)
  • apps/ui/src/components/dialogs/new-project-modal.tsx (21 hunks)
  • apps/ui/src/components/dialogs/workspace-picker-modal.tsx (5 hunks)
  • apps/ui/src/components/layout/index.ts (1 hunks)
  • apps/ui/src/components/layout/sidebar.tsx (6 hunks)
  • apps/ui/src/components/layout/sidebar/components/automaker-logo.tsx (1 hunks)
  • apps/ui/src/components/layout/sidebar/components/bug-report-button.tsx (1 hunks)
  • apps/ui/src/components/layout/sidebar/components/collapse-toggle-button.tsx (1 hunks)
  • apps/ui/src/components/layout/sidebar/components/index.ts (1 hunks)
  • apps/ui/src/components/layout/sidebar/components/project-actions.tsx (1 hunks)
  • apps/ui/src/components/layout/sidebar/components/project-selector-with-options.tsx (1 hunks)
  • apps/ui/src/components/layout/sidebar/components/sidebar-footer.tsx (1 hunks)
  • apps/ui/src/components/layout/sidebar/components/sidebar-header.tsx (1 hunks)
  • apps/ui/src/components/layout/sidebar/components/sidebar-navigation.tsx (1 hunks)
  • apps/ui/src/components/layout/sidebar/components/sortable-project-item.tsx (1 hunks)
  • apps/ui/src/components/layout/sidebar/components/theme-menu-item.tsx (1 hunks)
  • apps/ui/src/components/layout/sidebar/constants.ts (1 hunks)
  • apps/ui/src/components/layout/sidebar/dialogs/index.ts (1 hunks)
  • apps/ui/src/components/layout/sidebar/dialogs/onboarding-dialog.tsx (1 hunks)
  • apps/ui/src/components/layout/sidebar/dialogs/trash-dialog.tsx (1 hunks)
  • apps/ui/src/components/layout/sidebar/hooks/index.ts (1 hunks)
  • apps/ui/src/components/layout/sidebar/hooks/use-drag-and-drop.ts (1 hunks)
  • apps/ui/src/components/layout/sidebar/hooks/use-navigation.ts (1 hunks)
  • apps/ui/src/components/layout/sidebar/hooks/use-project-creation.ts (1 hunks)
  • apps/ui/src/components/layout/sidebar/hooks/use-project-picker.ts (1 hunks)
  • apps/ui/src/components/layout/sidebar/hooks/use-project-theme.ts (1 hunks)
  • apps/ui/src/components/layout/sidebar/hooks/use-running-agents.ts (1 hunks)
  • apps/ui/src/components/layout/sidebar/hooks/use-setup-dialog.ts (1 hunks)
  • apps/ui/src/components/layout/sidebar/hooks/use-sidebar-auto-collapse.ts (1 hunks)
  • apps/ui/src/components/layout/sidebar/hooks/use-spec-regeneration.ts (1 hunks)
  • apps/ui/src/components/layout/sidebar/hooks/use-theme-preview.ts (1 hunks)
  • apps/ui/src/components/layout/sidebar/hooks/use-trash-dialog.ts (1 hunks)
  • apps/ui/src/components/layout/sidebar/hooks/use-trash-operations.ts (1 hunks)
  • apps/ui/src/components/layout/sidebar/types.ts (1 hunks)
  • apps/ui/src/components/session-manager.tsx (24 hunks)
  • apps/ui/src/components/views/board-view/components/kanban-card/index.ts (1 hunks)
  • apps/ui/src/components/views/settings-view/api-keys/hooks/index.ts (1 hunks)
  • apps/ui/src/components/views/settings-view/api-keys/index.ts (1 hunks)
  • apps/ui/src/components/views/settings-view/appearance/index.ts (1 hunks)
  • apps/ui/src/components/views/settings-view/audio/index.ts (1 hunks)
  • apps/ui/src/components/views/settings-view/cli-status/index.ts (1 hunks)
  • apps/ui/src/components/views/settings-view/components/index.ts (1 hunks)
  • apps/ui/src/components/views/settings-view/config/index.ts (1 hunks)
  • apps/ui/src/components/views/settings-view/danger-zone/index.ts (1 hunks)
  • apps/ui/src/components/views/settings-view/feature-defaults/index.ts (1 hunks)
  • apps/ui/src/components/views/settings-view/keyboard-shortcuts/index.ts (1 hunks)
  • apps/ui/src/components/views/settings-view/shared/index.ts (1 hunks)
  • apps/ui/src/components/views/welcome-view.tsx (32 hunks)
  • apps/ui/src/components/views/wiki-view.tsx (14 hunks)
  • apps/ui/src/hooks/index.ts (1 hunks)
  • apps/ui/src/renderer.tsx (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (22)
apps/ui/src/components/layout/sidebar/hooks/use-running-agents.ts (2)
apps/ui/src/components/layout/sidebar/hooks/index.ts (1)
  • useRunningAgents (4-4)
apps/ui/src/lib/electron.ts (1)
  • getElectronAPI (568-577)
apps/ui/src/components/layout/sidebar/hooks/use-project-picker.ts (2)
apps/ui/src/components/layout/sidebar/hooks/index.ts (1)
  • useProjectPicker (6-6)
apps/ui/src/lib/electron.ts (1)
  • setCurrentProject (2713-2719)
apps/ui/src/components/layout/sidebar/components/theme-menu-item.tsx (2)
apps/ui/src/components/layout/sidebar/components/index.ts (1)
  • ThemeMenuItem (2-2)
apps/ui/src/components/layout/sidebar/types.ts (1)
  • ThemeMenuItemProps (22-31)
apps/ui/src/components/layout/sidebar/components/sortable-project-item.tsx (2)
apps/ui/src/components/layout/sidebar/components/index.ts (1)
  • SortableProjectItem (1-1)
apps/ui/src/components/layout/sidebar/types.ts (1)
  • SortableProjectItemProps (15-20)
apps/ui/src/components/layout/sidebar/hooks/use-sidebar-auto-collapse.ts (1)
apps/ui/src/components/layout/sidebar/hooks/index.ts (1)
  • useSidebarAutoCollapse (2-2)
apps/ui/src/components/layout/sidebar/hooks/use-drag-and-drop.ts (1)
apps/ui/src/components/layout/sidebar/hooks/index.ts (1)
  • useDragAndDrop (3-3)
apps/ui/src/components/layout/sidebar/components/automaker-logo.tsx (1)
apps/ui/src/components/layout/sidebar/components/index.ts (1)
  • AutomakerLogo (5-5)
apps/ui/src/components/layout/sidebar/components/collapse-toggle-button.tsx (2)
apps/ui/src/components/layout/sidebar/components/index.ts (1)
  • CollapseToggleButton (4-4)
apps/ui/src/store/app-store.ts (1)
  • formatShortcut (77-122)
apps/ui/src/components/dialogs/workspace-picker-modal.tsx (1)
apps/ui/src/components/dialogs/index.ts (1)
  • WorkspacePickerModal (6-6)
apps/ui/src/components/layout/sidebar/components/bug-report-button.tsx (2)
apps/ui/src/components/layout/sidebar/components/index.ts (1)
  • BugReportButton (3-3)
apps/ui/src/components/layout/sidebar/types.ts (1)
  • BugReportButtonProps (33-36)
apps/ui/src/components/layout/sidebar/hooks/use-navigation.ts (2)
apps/ui/src/components/layout/sidebar/hooks/index.ts (1)
  • useNavigation (8-8)
apps/ui/src/components/layout/sidebar/types.ts (2)
  • NavSection (3-6)
  • NavItem (8-13)
apps/ui/src/components/layout/sidebar/constants.ts (1)
apps/ui/src/config/theme-options.ts (2)
  • darkThemes (340-340)
  • lightThemes (343-343)
apps/ui/src/components/layout/sidebar/components/project-selector-with-options.tsx (5)
apps/ui/src/components/layout/sidebar/components/index.ts (2)
  • ProjectSelectorWithOptions (9-9)
  • ThemeMenuItem (2-2)
apps/ui/src/store/app-store.ts (2)
  • useAppStore (838-2265)
  • formatShortcut (77-122)
apps/ui/src/components/layout/sidebar/hooks/index.ts (3)
  • useProjectPicker (6-6)
  • useDragAndDrop (3-3)
  • useProjectTheme (12-12)
apps/ui/src/components/layout/sidebar/hooks/use-project-theme.ts (1)
  • useProjectTheme (7-25)
apps/ui/src/components/layout/sidebar/constants.ts (2)
  • PROJECT_DARK_THEMES (3-8)
  • PROJECT_LIGHT_THEMES (10-15)
apps/ui/src/components/layout/sidebar/components/sidebar-header.tsx (2)
apps/ui/src/components/layout/sidebar/components/index.ts (3)
  • SidebarHeader (6-6)
  • AutomakerLogo (5-5)
  • BugReportButton (3-3)
apps/ui/src/components/layout/sidebar/components/automaker-logo.tsx (1)
  • AutomakerLogo (9-117)
apps/server/tests/unit/services/claude-usage-service.test.ts (2)
apps/server/src/services/claude-usage-service.ts (1)
  • ClaudeUsageService (17-452)
init.mjs (1)
  • lines (83-83)
apps/ui/src/components/layout/sidebar/hooks/use-project-creation.ts (2)
apps/ui/src/lib/electron.ts (2)
  • TrashedProject (2696-2699)
  • getElectronAPI (568-577)
apps/ui/src/lib/project-init.ts (1)
  • initializeProject (43-143)
apps/ui/src/components/layout/sidebar/hooks/use-setup-dialog.ts (2)
apps/ui/src/components/views/spec-view/types.ts (1)
  • FeatureCount (2-2)
apps/ui/src/lib/electron.ts (1)
  • getElectronAPI (568-577)
apps/ui/src/components/layout/sidebar/dialogs/trash-dialog.tsx (1)
apps/ui/src/lib/electron.ts (1)
  • TrashedProject (2696-2699)
apps/ui/src/components/layout/sidebar/hooks/use-spec-regeneration.ts (1)
apps/ui/src/lib/electron.ts (1)
  • getElectronAPI (568-577)
apps/ui/src/components/layout/sidebar/dialogs/onboarding-dialog.tsx (1)
apps/ui/src/components/layout/sidebar/dialogs/index.ts (1)
  • OnboardingDialog (2-2)
apps/ui/src/components/views/welcome-view.tsx (2)
apps/server/src/services/auto-mode-service.ts (1)
  • analyzeProject (1107-1190)
apps/ui/src/lib/electron.ts (1)
  • getElectronAPI (568-577)
apps/ui/src/components/session-manager.tsx (1)
apps/ui/src/lib/electron.ts (1)
  • getElectronAPI (568-577)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: e2e
🔇 Additional comments (62)
apps/ui/src/components/views/settings-view/config/index.ts (1)

1-2: LGTM! Clean barrel export pattern.

The re-exports follow TypeScript best practices and align with the PR's folder pattern compliance objectives. This centralized entry point will make imports cleaner for consumers of the config module.

apps/ui/src/components/views/settings-view/keyboard-shortcuts/index.ts (1)

1-1: LGTM! Barrel export improves module organization.

This barrel export simplifies imports for consumers and aligns with the refactoring goal of improving code organization and maintainability.

apps/ui/src/components/views/settings-view/components/index.ts (1)

1-4: LGTM! Barrel exports support modularization effort.

These barrel exports consolidate component imports into a single entry point, directly supporting the refactoring goal of breaking down the 2,100+ line sidebar into modular, maintainable components. The consistent export pattern improves code organization.

apps/ui/src/components/views/settings-view/cli-status/index.ts (1)

1-1: LGTM! Clean barrel export pattern.

This barrel export follows standard TypeScript conventions and aligns with the PR's modularization goals. The single re-export keeps the module focused and provides a clean public API surface.

apps/ui/src/components/views/settings-view/danger-zone/index.ts (1)

1-1: LGTM! Clean barrel export implementation.

The barrel export follows standard TypeScript/React patterns and aligns perfectly with the PR's folder pattern compliance objective. This simplifies imports by allowing consumers to import from the danger-zone folder rather than the specific file.

apps/ui/src/components/views/settings-view/feature-defaults/index.ts (1)

1-1: LGTM! Clean barrel export pattern.

This re-export correctly establishes a public API for the FeatureDefaultsSection component, aligning with the PR's modularization objectives and the project's barrel export conventions.

apps/ui/src/components/views/board-view/components/kanban-card/index.ts (1)

1-7: LGTM! Clean barrel export pattern.

The barrel export file follows best practices by consolidating the public API of the Kanban card package. The named exports are well-organized and enable consumers to import these components from a single entry point, which aligns with the folder pattern compliance objectives of this refactoring.

apps/ui/src/components/views/settings-view/shared/index.ts (1)

1-2: LGTM! Clean barrel export pattern.

The barrel export approach is appropriate for organizing shared types and simplifies imports for consumers. Using export type syntax is the correct best practice for type-only exports. All exported types exist in their source files and the exports are complete with no missing shared types.

apps/ui/src/components/views/wiki-view.tsx (4)

1-1: LGTM! Modern type import pattern.

The import statement correctly uses TypeScript's type modifier for type-only imports of ReactNode and ElementType. This aligns with React 19 best practices and improves tree-shaking.


29-30: LGTM! Type references correctly updated.

The interface properties now use the imported ElementType and ReactNode types directly, which is cleaner and consistent with the updated imports.


89-89: LGTM! Consistent type usage.

The props type correctly uses ElementType to match the updated import pattern.


115-115: LGTM! Consistent string literal style.

The state initialization now uses single quotes, aligning with the string literal normalization throughout the file.

apps/ui/src/components/views/settings-view/api-keys/hooks/index.ts (1)

1-1: Barrel export is correctly structured.

The export properly references the target file, and the useApiKeyManagement hook is correctly exported from use-api-key-management.ts.

apps/ui/src/components/views/settings-view/api-keys/index.ts (1)

1-4: Component barrel exports are well-structured.

All four component re-exports follow consistent naming conventions and properly reference existing components that export the expected named exports.

apps/ui/src/components/views/settings-view/appearance/index.ts (1)

1-1: LGTM! Clean barrel export pattern.

The barrel export correctly centralizes the public export for AppearanceSection. The underlying file exists and properly exports the component.

apps/ui/src/components/views/settings-view/audio/index.ts (1)

1-1: LGTM! Consistent barrel export pattern.

The barrel export is consistent with the pattern established in other settings-view sections. The referenced ./audio-section file exists and exports AudioSection correctly.

apps/server/tests/unit/services/claude-usage-service.test.ts (8)

16-42: LGTM!

The test setup is well-structured with proper mock initialization for both child_process.spawn and node-pty processes, and correctly clears mocks between tests.


44-107: LGTM!

The isAvailable tests comprehensively cover success, failure, error, and cross-platform scenarios. The Windows test correctly instantiates a new service after mocking os.platform() to ensure isWindows is set appropriately at construction time.


129-237: LGTM!

Comprehensive test coverage for parseResetTime including duration formats (hours/minutes), AM/PM time formats, date formats with month/day, 12am/12pm edge cases, and fallback behavior for unparseable text.


239-269: LGTM!

The getDefaultResetTime tests correctly verify both session (5 hours from now) and weekly (next Monday) default behaviors using a controlled timestamp.


271-322: LGTM!

Good coverage for parseSection including percentage conversion (left vs used), missing sections, timezone stripping, and case-insensitive matching.


324-404: LGTM!

Thorough test coverage for parseUsageOutput including complete output parsing, ANSI code handling, alternative section names (Opus), and graceful defaults for missing sections.


406-509: LGTM!

Good test coverage for macOS/Linux command execution including successful output handling, authentication error detection, and timeout behavior.


590-636: LGTM!

The Windows authentication error and timeout tests are well-structured, correctly simulating the respective error conditions and verifying expected behavior.

apps/ui/src/app.tsx (1)

1-35: LGTM! Quote normalization aligns with coding style.

The changes consistently normalize string literals and import statements to use single quotes throughout the file, with no functional modifications.

apps/ui/src/components/dialogs/delete-all-archived-sessions-dialog.tsx (1)

1-55: LGTM! Consistent quote style and improved readability.

The import statement updates and dialog description consolidation maintain functionality while improving code consistency.

apps/ui/src/components/dialogs/delete-session-dialog.tsx (1)

1-48: LGTM! Style normalization with no functional impact.

Import and JSX formatting changes align with project conventions while preserving all behavior and styling.

apps/ui/src/components/layout/sidebar/constants.ts (1)

1-24: LGTM! Well-structured constants with good type safety.

The theme transformations and feature flags are clearly defined:

  • Consistent Icon→icon property normalization for API surface
  • Proper use of as const for type-level guarantees on feature flags
  • Clean separation of dark/light theme data
apps/ui/src/components/layout/sidebar/hooks/use-theme-preview.ts (1)

1-53: LGTM! Well-implemented debounced theme preview.

The hook properly handles:

  • Debouncing with a one-frame delay to prevent excessive re-renders
  • Cleanup of pending timeouts on unmount
  • Smart prevention of preview clearing when moving between theme items (line 29)

The use of relatedTarget and the CSS attribute selector ensures smooth hover transitions without flickering.

apps/ui/src/components/layout/sidebar/components/bug-report-button.tsx (1)

1-23: LGTM! Clean button component with proper accessibility.

The component correctly handles conditional positioning and test IDs based on sidebar state, with good hover states and a descriptive title attribute for accessibility.

apps/ui/src/components/layout/sidebar/hooks/use-drag-and-drop.ts (1)

10-41: LGTM!

The drag-and-drop logic is well-implemented with appropriate guards:

  • Checks that over exists before proceeding
  • Ensures the dragged item moved to a different position
  • Validates both indices before calling reorderProjects
  • Properly memoized with correct dependencies
apps/ui/src/hooks/index.ts (1)

1-9: LGTM!

Clean barrel export pattern for centralized hook imports.

apps/ui/src/components/layout/sidebar/types.ts (1)

1-36: LGTM!

Well-structured type definitions with:

  • Clear interface naming
  • Appropriate use of optional properties
  • Proper typing for React components (React.ComponentType)
  • Good separation of concerns
apps/ui/src/components/layout/sidebar/hooks/use-navigation.ts (1)

38-211: LGTM!

Well-structured navigation hook with:

  • Proper conditional rendering logic for nav items based on visibility flags
  • Appropriate guards for keyboard shortcuts (only enabled when conditions are met)
  • Correct memoization with comprehensive dependency arrays
  • Clean separation between nav sections and keyboard shortcuts

The cascading memoization (navSections computed first, then used in navigationShortcuts) is correctly implemented.

apps/ui/src/components/layout/index.ts (1)

1-1: LGTM!

Clean barrel export for the Sidebar component.

apps/ui/src/components/layout/sidebar/hooks/use-trash-dialog.ts (1)

12-40: LGTM!

Clean composition pattern that:

  • Adds dialog state management to existing trash operations
  • Properly delegates to useTrashOperations
  • Returns a unified interface for dialog + operations

This is a good example of hook composition.

apps/ui/src/components/layout/sidebar/dialogs/index.ts (1)

1-2: LGTM!

Clean barrel export pattern for dialog components.

apps/ui/src/components/dialogs/workspace-picker-modal.tsx (1)

1-141: LGTM!

Formatting and style consistency changes only. The functional behavior remains unchanged.

apps/ui/src/components/layout/sidebar/hooks/use-project-theme.ts (1)

1-25: LGTM! Clean hook composition.

The hook effectively composes theme state management from the app store with preview handlers from useThemePreview, providing a unified interface for theme-related functionality.

apps/ui/src/components/layout/sidebar/components/theme-menu-item.tsx (1)

1-27: LGTM! Clean component implementation.

The memoized ThemeMenuItem component is well-structured with proper event handlers for theme preview functionality. The use of memo is appropriate for this presentational component that receives stable props.

apps/ui/src/components/session-manager.tsx (1)

1-577: LGTM!

Formatting and style consistency changes only. The functional behavior of the session manager remains unchanged.

apps/ui/src/components/layout/sidebar/hooks/use-running-agents.ts (1)

23-48: LGTM! Robust event subscription pattern.

The hook properly handles the case when autoMode is unavailable, subscribes to relevant auto-mode events for real-time updates, and correctly cleans up the subscription on unmount. The event filtering logic appropriately refreshes the count on feature lifecycle events.

apps/ui/src/renderer.tsx (1)

3-3: The import path is correct.

The actual file is named app.tsx (lowercase), so the import from './app' matches the actual filename and is necessary for the code to work on case-sensitive file systems.

Likely an incorrect or invalid review comment.

apps/ui/src/components/dialogs/new-project-modal.tsx (1)

1-459: LGTM! Formatting changes only.

The changes in this file are purely formatting adjustments (quote normalization and consistent string literals) with no behavioral modifications. The logic, event handlers, and data flow remain unchanged.

apps/ui/src/components/layout/sidebar/components/sidebar-header.tsx (1)

1-40: LGTM! Clean component separation.

The SidebarHeader component is well-structured with clear props and conditional rendering based on sidebar state. The dual rendering of BugReportButton for expanded/collapsed states is intentional for different layout contexts.

apps/ui/src/components/layout/sidebar/dialogs/onboarding-dialog.tsx (1)

28-36: Verify the onSkip behavior on dialog close.

The onOpenChange handler calls onSkip() whenever the dialog is closed (Line 32), regardless of how it was closed (backdrop click, ESC key, X button, etc.). This means users who simply want to dismiss the dialog temporarily will trigger the skip action.

Verify this is the intended behavior. If users should be able to close the dialog without skipping (e.g., to think about it), consider adding a separate close handler or tracking whether the user explicitly clicked "Skip for now" vs. other close methods.

apps/ui/src/components/layout/sidebar/hooks/use-spec-regeneration.ts (1)

17-78: LGTM! Proper event subscription handling.

The hook correctly subscribes to spec regeneration events, filters by project path, handles both success and error cases, and properly cleans up the subscription. The comprehensive dependency array (lines 68-77) is necessary since the setters are passed as props and ensures the effect stays synchronized with the latest callbacks.

apps/ui/src/components/layout/sidebar/hooks/use-project-picker.ts (1)

1-105: LGTM! Well-structured project picker hook.

The hook provides comprehensive project picker functionality with search filtering, keyboard navigation, and proper focus management. The setTimeout(0) pattern (line 47) for focusing the input is a common and acceptable approach for ensuring the DOM is ready. The keyboard handling properly prevents conflicts between search input and global shortcuts (lines 77-83).

apps/ui/src/components/layout/sidebar/components/project-actions.tsx (1)

1-91: LGTM! Clean action button component.

The component provides a clear interface for project actions with appropriate visual feedback. The trash count badge (lines 83-87) correctly displays the count with a "9+" overflow indicator, and the conditional rendering ensures it only appears when there are trashed projects.

apps/ui/src/components/dialogs/index.ts (1)

1-6: LGTM! Clean barrel export structure.

The barrel export file provides a centralized access point for dialog components, improving import organization and maintainability.

apps/ui/src/components/layout/sidebar/components/sidebar-footer.tsx (1)

1-269: Well-structured modular component with good separation of concerns.

The component cleanly encapsulates the footer navigation logic with appropriate props for configuration and callbacks. The badge count capping at 99 is a good UX pattern, and the conditional rendering for Wiki/Running Agents is implemented correctly.

A few observations:

  1. The button styling pattern is heavily repeated across the three navigation items. Consider extracting a shared FooterNavButton component if this pattern grows or needs maintenance.
  2. The custom tooltip implementation using absolute-positioned spans works but may have accessibility gaps compared to using a proper tooltip component with ARIA attributes.
apps/ui/src/components/layout/sidebar/hooks/index.ts (1)

1-12: Clean barrel export structure.

The barrel file correctly consolidates all sidebar hooks for streamlined imports. The consistent naming convention and alphabetical-ish grouping aids discoverability.

apps/ui/src/components/layout/sidebar/dialogs/trash-dialog.tsx (1)

98-111: Review DialogFooter layout with justify-between.

When trashedProjects.length === 0, only the Close button renders, and justify-between has no effect on a single child. However, when both buttons render, they'll be pushed to opposite ends as intended. This is likely fine, but verify the visual alignment matches the design intent for the empty state.

apps/ui/src/components/layout/sidebar/components/sidebar-navigation.tsx (1)

1-140: Clean implementation of navigation rendering.

The component properly handles all states (no project, project selected, expanded/collapsed) with appropriate visual feedback. The section-based organization and shortcut display integration are well done.

apps/ui/src/components/layout/sidebar/components/project-selector-with-options.tsx (1)

44-92: Good use of composition and early returns.

The component properly delegates logic to specialized hooks (useProjectPicker, useDragAndDrop, useProjectTheme) and exits early when rendering is unnecessary. This keeps the component focused on presentation while maintaining clean separation of concerns.

apps/ui/src/components/layout/sidebar/hooks/use-setup-dialog.ts (2)

1-27: Well-structured hook with clear state management.

The hook properly encapsulates setup dialog state and exposes a clean API. State initialization and type imports are correct.


32-82: Solid async handler with optimistic UI and proper error recovery.

The handleCreateInitialSpec handler follows good patterns:

  • Optimistic state update before async operation
  • Defensive check for API availability
  • Proper error handling with state rollback
  • Conditional parameter passing for featureCount
apps/ui/src/components/layout/sidebar/hooks/use-project-creation.ts (1)

40-65: Previous issue resolved: app_spec.txt path is now correct.

The path ${projectPath}/.automaker/app_spec.txt and the <project_specification> XML root tag are both correct, addressing the regression flagged in the previous review.

apps/ui/src/components/layout/sidebar/components/index.ts (1)

1-10: Clean barrel exports enabling modular imports.

This consolidates the sidebar component exports, supporting the PR's refactoring goal of reducing sidebar.tsx from 2,100+ lines.

apps/ui/src/components/layout/sidebar.tsx (3)

13-33: Clean modular imports supporting the refactoring goal.

The sidebar now composes from well-organized local imports: components, dialogs, constants, and hooks. This structure supports maintainability and testability.


70-118: Good separation of concerns with dedicated hooks.

The sidebar now delegates state and logic to useProjectCreation and useSetupDialog hooks, significantly reducing component complexity. The hook composition and prop passing looks correct.


255-375: Well-composed JSX with clear component boundaries.

The sidebar render tree is now clean and readable. Each child component receives focused props, and dialogs are properly positioned at the end of the component. The refactoring achieves the stated goal of reducing complexity.

- Updated ESLint configuration to include support for `.mjs` and `.cjs` file types, adding necessary global variables for Node.js and browser environments.
- Introduced a new `vite-env.d.ts` file to define environment variables for Vite, improving type safety.
- Refactored error handling in `file-browser-dialog.tsx`, `description-image-dropzone.tsx`, and `feature-image-upload.tsx` to omit error parameters, simplifying the catch blocks.
- Removed unused bug report button functionality from the sidebar, streamlining the component structure.
- Adjusted various components to improve code readability and maintainability, including updates to type imports and component props.

These changes aim to enhance the development experience by improving linting support and simplifying error handling across components.
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (3)
apps/ui/src/components/views/board-view/dialogs/edit-feature-dialog.tsx (1)

189-196: Add nullish coalescing for thinking level default.

When a model supports thinking but editingFeature.thinkingLevel is undefined, line 194 will assign undefined instead of defaulting to 'none'. For consistency with the logic in handleUpdate (lines 151-153), consider:

🔎 Proposed fix
   setEditingFeature({
     ...editingFeature,
     model,
-    thinkingLevel: modelSupportsThinking(model) ? editingFeature.thinkingLevel : 'none',
+    thinkingLevel: modelSupportsThinking(model) ? (editingFeature.thinkingLevel ?? 'none') : 'none',
   });
apps/ui/src/components/ui/description-image-dropzone.tsx (2)

126-199: Missing setPreviewImages in dependency array.

The processFiles callback uses setPreviewImages at line 184 but doesn't include it in the dependency array (lines 189-198). This violates the rules of hooks and could cause the function to close over a stale version of setPreviewImages, leading to incorrect state updates.

🔎 Suggested fix
    [
      disabled,
      isProcessing,
      images,
      maxFiles,
      maxFileSize,
      onImagesChange,
      previewImages,
      saveImageToTemp,
+     setPreviewImages,
    ]

254-264: Missing setPreviewImages in dependency array.

The removeImage callback uses setPreviewImages at line 257 but doesn't include it in the dependency array (line 263). This could cause stale closures.

🔎 Suggested fix
    },
-   [images, onImagesChange]
+   [images, onImagesChange, setPreviewImages]
  );
♻️ Duplicate comments (2)
apps/ui/src/components/views/welcome-view.tsx (1)

227-525: Centralize project creation logic to eliminate duplication.

This component contains substantial project creation logic across three functions (handleCreateBlankProject, handleCreateFromTemplate, handleCreateFromCustomUrl) totaling nearly 300 lines. A previous review noted that a useProjectCreation hook was introduced to centralize this logic, but this component still maintains its own implementation.

Having duplicate implementations across multiple components creates maintenance overhead and increases the risk of inconsistent behavior. All project creation logic should be consolidated into the useProjectCreation hook, and this component should consume that hook instead.

Based on learnings, this duplication concern was previously raised and remains unaddressed.

apps/ui/src/components/layout/sidebar.tsx (1)

74-92: Critical: Project creation regression already flagged.

A previous review identified a critical regression in the useProjectCreation hook:

  1. Incorrect app_spec.txt path (should be in .automaker/ subdirectory)
  2. Simplified XML content loses template-specific details
  3. Root XML tag changed from <project_specification> to <project>

This issue breaks project creation functionality and must be resolved before merge.

🧹 Nitpick comments (17)
apps/ui/src/components/views/board-view/kanban-board.tsx (2)

14-17: Consider using proper types from @dnd-kit/core instead of any.

Using any for sensors, collisionDetectionStrategy, and the drag event handlers loses type safety. The @dnd-kit/core library exports appropriate types:

  • SensorDescriptor<any>[] for sensors
  • CollisionDetection for collision strategy
  • DragStartEvent / DragEndEvent for handlers
🔎 Suggested type improvements
+import { DndContext, DragOverlay, CollisionDetection, DragStartEvent, DragEndEvent, SensorDescriptor } from '@dnd-kit/core';

 interface KanbanBoardProps {
-  sensors: any;
-  collisionDetectionStrategy: (args: any) => any;
-  onDragStart: (event: any) => void;
-  onDragEnd: (event: any) => void;
+  sensors: SensorDescriptor<any>[];
+  collisionDetectionStrategy: CollisionDetection;
+  onDragStart: (event: DragStartEvent) => void;
+  onDragEnd: (event: DragEndEvent) => void;

13-51: Large prop surface area — consider grouping related callbacks.

The component accepts 38 props, many of which are feature action callbacks (onEdit, onDelete, onVerify, etc.). This prop drilling can become unwieldy as the component evolves.

A potential improvement would be to group related callbacks into a single featureActions object prop or leverage React Context for feature operations if these callbacks are used across multiple descendant components.

apps/ui/src/config/api-providers.ts (2)

44-58: Interface requires unused google parameter.

ProviderConfigParams mandates a google property, but buildProviderConfigs ignores it. Callers must still construct and pass a full google object that is never used.

Consider making google optional or removing it from the interface until Google provider support is re-enabled.

🔎 Proposed fix
 export interface ProviderConfigParams {
   apiKeys: ApiKeys;
   anthropic: {
     value: string;
     setValue: Dispatch<SetStateAction<string>>;
     show: boolean;
     setShow: Dispatch<SetStateAction<boolean>>;
     testing: boolean;
     onTest: () => Promise<void>;
     result: { success: boolean; message: string } | null;
   };
-  google: {
+  google?: {
     value: string;
     setValue: Dispatch<SetStateAction<string>>;
     show: boolean;
     setShow: Dispatch<SetStateAction<boolean>>;
     testing: boolean;
     onTest: () => Promise<void>;
     result: { success: boolean; message: string } | null;
   };
 }

85-110: Consider removing or tracking commented-out Google provider code.

This 25-line commented block adds maintenance burden. If Google provider support is planned, consider tracking it in an issue and removing the commented code. If it's not planned, removing it keeps the codebase clean—it can always be retrieved from version control.

apps/ui/src/lib/utils.ts (1)

12-15: Consider simplifying or documenting the unused parameter.

The function unconditionally returns true and never uses the _model parameter. While the underscore prefix correctly signals it's unused, consider either:

  • Removing the parameter entirely if all models will always support thinking, or
  • Adding a comment explaining why the parameter is retained (e.g., for API compatibility or future use)
apps/ui/src/components/views/board-view/dialogs/agent-output-modal.tsx (1)

1-399: Quote standardization looks good.

The conversion from double quotes to single quotes is applied consistently throughout the file with no functional changes. All imports, type literals, and string literals are correctly updated.

Since this is part of a project-wide style standardization, consider adding or updating ESLint rules (e.g., quotes: ['error', 'single']) to automatically enforce single quotes and prevent inconsistencies in future commits.

Optional: Verify consistency across the codebase
#!/bin/bash
# Check if there are other files in the UI app that still use double quotes inconsistently

# Search for remaining double-quoted imports in TypeScript/TSX files
echo "=== Files with double-quoted imports ==="
rg --type=ts --type-add 'tsx:*.tsx' -g '*.{ts,tsx}' -g '!node_modules' "^import .* from \"" apps/ui/src/ | head -20

# Search for type literals with double quotes
echo -e "\n=== Type literals with double quotes ==="
rg --type=ts --type-add 'tsx:*.tsx' -g '*.{ts,tsx}' -g '!node_modules' "type \w+ = \"" apps/ui/src/ | head -20
apps/ui/src/components/views/setup-view/steps/welcome-step.tsx (1)

18-19: Optional: Polish the user-facing text.

While the reflow itself is fine, consider improving the text quality:

  • The "either...or" construction is grammatically awkward. Consider: "To get started, we'll need to verify that either the Claude Code CLI is installed or you have Anthropic API keys."
  • Capitalize product names: "Claude Code CLI" instead of "claude code cli"
  • Capitalize acronyms: "API keys" instead of "api keys"
apps/ui/tests/utils/views/board.ts (1)

193-219: Consider escaping branch names in RegExp (optional improvement).

The static analysis tool correctly identifies that constructing RegExp from variables can theoretically lead to ReDoS issues. While the risk is minimal in test utilities with controlled input, you could eliminate the warning by escaping special regex characters.

🔎 Optional refactor to escape special characters
 export async function selectWorktreeBranch(page: Page, branchName: string): Promise<void> {
-  const branchButton = page.getByRole('button', {
-    name: new RegExp(branchName, 'i'),
-  });
+  const escapedBranch = branchName.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
+  const branchButton = page.getByRole('button', {
+    name: new RegExp(escapedBranch, 'i'),
+  });
   await branchButton.click();
   await page.waitForTimeout(500); // Wait for UI to update
 }

Apply the same pattern to isWorktreeBranchVisible:

 export async function isWorktreeBranchVisible(page: Page, branchName: string): Promise<boolean> {
-  const branchButton = page.getByRole('button', {
-    name: new RegExp(branchName, 'i'),
-  });
+  const escapedBranch = branchName.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
+  const branchButton = page.getByRole('button', {
+    name: new RegExp(escapedBranch, 'i'),
+  });
   return await branchButton.isVisible().catch(() => false);
 }
apps/ui/src/components/views/board-view/components/kanban-card/agent-info-panel.tsx (1)

119-119: Optional: Explicit cast may be redundant.

The explicit as ThinkingLevel cast appears unnecessary due to TypeScript's control flow narrowing after the condition on line 115. However, it's defensive and doesn't cause any issues.

apps/ui/src/components/views/settings-view/api-keys/authentication-status-display.tsx (1)

48-58: Quote normalization applied successfully.

The string literals now consistently use single quotes throughout the authentication method display logic.

Optional: Consider refactoring the nested ternary for readability.

The 6-level nested ternary, while logically correct, can be challenging to parse. A future refactor could use a lookup map or helper function to improve maintainability.

💡 Optional refactor to improve readability
+const AUTH_METHOD_LABELS: Record<string, string> = {
+  oauth_token: 'Using stored OAuth token (subscription)',
+  api_key_env: 'Using ANTHROPIC_API_KEY',
+  api_key: 'Using stored API key',
+  credentials_file: 'Using credentials file',
+  cli_authenticated: 'Using Claude CLI authentication',
+};
+
 <span>
-  {claudeAuthStatus.method === 'oauth_token'
-    ? 'Using stored OAuth token (subscription)'
-    : claudeAuthStatus.method === 'api_key_env'
-      ? 'Using ANTHROPIC_API_KEY'
-      : claudeAuthStatus.method === 'api_key'
-        ? 'Using stored API key'
-        : claudeAuthStatus.method === 'credentials_file'
-          ? 'Using credentials file'
-          : claudeAuthStatus.method === 'cli_authenticated'
-            ? 'Using Claude CLI authentication'
-            : `Using ${claudeAuthStatus.method || 'detected'} authentication`}
+  {AUTH_METHOD_LABELS[claudeAuthStatus.method] || 
+    `Using ${claudeAuthStatus.method || 'detected'} authentication`}
 </span>
apps/ui/eslint.config.mjs (1)

28-91: Consider using the globals package for better maintainability.

The manual declaration of 60+ globals is verbose and harder to maintain. Modern ESLint flat configs typically leverage the globals package, which provides predefined sets like globals.browser, globals.node, etc.

🔎 Refactor to use the globals package

First, ensure the globals package is installed:

npm install -D globals

Then refactor the config:

+import globals from "globals";
 import { defineConfig, globalIgnores } from "eslint/config";
 import js from "@eslint/js";
 import ts from "@typescript-eslint/eslint-plugin";
 import tsParser from "@typescript-eslint/parser";

 const eslintConfig = defineConfig([
   js.configs.recommended,
   {
     files: ["**/*.mjs", "**/*.cjs"],
     languageOptions: {
-      globals: {
-        console: "readonly",
-        process: "readonly",
-        require: "readonly",
-        __dirname: "readonly",
-        __filename: "readonly",
-      },
+      globals: globals.node,
     },
   },
   {
     files: ["**/*.ts", "**/*.tsx"],
     languageOptions: {
       parser: tsParser,
       parserOptions: {
         ecmaVersion: "latest",
         sourceType: "module",
       },
-      globals: {
-        // Browser/DOM APIs
-        window: "readonly",
-        document: "readonly",
-        navigator: "readonly",
-        Navigator: "readonly",
-        localStorage: "readonly",
-        sessionStorage: "readonly",
-        fetch: "readonly",
-        WebSocket: "readonly",
-        File: "readonly",
-        FileList: "readonly",
-        FileReader: "readonly",
-        Blob: "readonly",
-        atob: "readonly",
-        crypto: "readonly",
-        prompt: "readonly",
-        confirm: "readonly",
-        getComputedStyle: "readonly",
-        requestAnimationFrame: "readonly",
-        // DOM Element Types
-        HTMLElement: "readonly",
-        HTMLInputElement: "readonly",
-        HTMLDivElement: "readonly",
-        HTMLButtonElement: "readonly",
-        HTMLSpanElement: "readonly",
-        HTMLTextAreaElement: "readonly",
-        HTMLHeadingElement: "readonly",
-        HTMLParagraphElement: "readonly",
-        HTMLImageElement: "readonly",
-        Element: "readonly",
-        // Event Types
-        Event: "readonly",
-        KeyboardEvent: "readonly",
-        DragEvent: "readonly",
-        PointerEvent: "readonly",
-        CustomEvent: "readonly",
-        ClipboardEvent: "readonly",
-        WheelEvent: "readonly",
-        DataTransfer: "readonly",
-        // Web APIs
-        ResizeObserver: "readonly",
-        AbortSignal: "readonly",
-        Audio: "readonly",
-        ScrollBehavior: "readonly",
-        // Timers
-        setTimeout: "readonly",
-        setInterval: "readonly",
-        clearTimeout: "readonly",
-        clearInterval: "readonly",
-        // Node.js (for scripts and Electron)
-        process: "readonly",
-        require: "readonly",
-        __dirname: "readonly",
-        __filename: "readonly",
-        NodeJS: "readonly",
-        // React
-        React: "readonly",
-        JSX: "readonly",
-        // Electron
-        Electron: "readonly",
-        // Console
-        console: "readonly",
-      },
+      globals: {
+        ...globals.browser,
+        ...globals.node,
+      },
     },
     plugins: {
       "@typescript-eslint": ts,
     },

This approach:

  • Reduces config size and complexity
  • Provides comprehensive, battle-tested global definitions
  • Makes it easier to adjust environments in the future
  • Reduces the risk of missing or incorrectly defining globals
apps/ui/src/components/ui/sheet.tsx (1)

1-150: Consider using automated tooling for quote style enforcement.

This file demonstrates consistent quote style normalization (double to single quotes). To ensure this style is maintained project-wide and prevent future inconsistencies, consider configuring ESLint or Prettier with quote style rules.

Example ESLint configuration:

{
  "rules": {
    "quotes": ["error", "single", { "avoidEscape": true }],
    "@typescript-eslint/quotes": ["error", "single"]
  }
}
apps/ui/src/components/views/agent-view.tsx (1)

196-196: Replace deprecated substr with substring or slice.

String.prototype.substr() is deprecated. Use substring() or slice() instead.

🔎 Proposed fix
-            id: `img-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,
+            id: `img-${Date.now()}-${Math.random().toString(36).slice(2, 11)}`,
apps/ui/src/lib/file-picker.ts (1)

68-73: Consider gating verbose logging behind a debug flag.

The [FilePicker] logs are helpful for debugging but may be noisy in production. Consider using a debug flag or removing them before release.

Example approach
const DEBUG = process.env.NODE_ENV === 'development';

function log(...args: unknown[]) {
  if (DEBUG) console.log('[FilePicker]', ...args);
}

// Usage:
log('Change event fired');
apps/ui/src/components/ui/accordion.tsx (2)

7-7: Consider using the AccordionType alias in AccordionProps.

The AccordionType alias is defined but the type prop in AccordionProps repeats the literal union. Using the alias improves maintainability.

🔎 Proposed fix
 interface AccordionProps extends React.HTMLAttributes<HTMLDivElement> {
-  type?: 'single' | 'multiple';
+  type?: AccordionType;
   value?: string | string[];

Also applies to: 19-19


1-1: Use type aliases to eliminate the need for eslint-disable.

The empty interfaces on lines 142 and 180 require the eslint-disable directive. Using type aliases achieves the same result without suppressing the linter.

🔎 Proposed fix

Remove line 1:

-/* eslint-disable @typescript-eslint/no-empty-object-type */

Replace the empty interfaces with type aliases:

-interface AccordionTriggerProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {}
+type AccordionTriggerProps = React.ButtonHTMLAttributes<HTMLButtonElement>;
-interface AccordionContentProps extends React.HTMLAttributes<HTMLDivElement> {}
+type AccordionContentProps = React.HTMLAttributes<HTMLDivElement>;

Also applies to: 142-142, 180-180

apps/ui/src/components/ui/description-image-dropzone.tsx (1)

55-69: Consider removing localPreviewImages from the dependency array.

Including localPreviewImages (a state variable) in the dependency array causes this callback to be recreated on every state update, which undermines the purpose of useCallback. The callback should remain stable across renders. The current implementation will work correctly but may cause unnecessary re-renders of child components.

🔎 Suggested improvement
  const setPreviewImages = useCallback(
    (updater: Map<string, string> | ((prev: Map<string, string>) => Map<string, string>)) => {
      if (onPreviewMapChange) {
-       const currentMap = previewMap !== undefined ? previewMap : localPreviewImages;
+       const currentMap = previewMap !== undefined ? previewMap : new Map();
        const newMap = typeof updater === 'function' ? updater(currentMap) : updater;
        onPreviewMapChange(newMap);
      } else {
        setLocalPreviewImages((prev) => {
          const newMap = typeof updater === 'function' ? updater(prev) : updater;
          return newMap;
        });
      }
    },
-   [onPreviewMapChange, previewMap, localPreviewImages]
+   [onPreviewMapChange, previewMap]
  );

Note: If parent provides previewMap, use it; otherwise setLocalPreviewImages receives prev directly from React, so localPreviewImages isn't needed in the closure.

📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 43c93fe and 26236d3.

📒 Files selected for processing (40)
  • apps/ui/eslint.config.mjs (2 hunks)
  • apps/ui/src/components/dialogs/file-browser-dialog.tsx (16 hunks)
  • apps/ui/src/components/layout/sidebar.tsx (6 hunks)
  • apps/ui/src/components/layout/sidebar/components/bug-report-button.tsx (1 hunks)
  • apps/ui/src/components/layout/sidebar/components/project-selector-with-options.tsx (1 hunks)
  • apps/ui/src/components/layout/sidebar/components/sidebar-header.tsx (1 hunks)
  • apps/ui/src/components/layout/sidebar/types.ts (1 hunks)
  • apps/ui/src/components/ui/accordion.tsx (9 hunks)
  • apps/ui/src/components/ui/description-image-dropzone.tsx (13 hunks)
  • apps/ui/src/components/ui/feature-image-upload.tsx (12 hunks)
  • apps/ui/src/components/ui/image-drop-zone.tsx (6 hunks)
  • apps/ui/src/components/ui/sheet.tsx (6 hunks)
  • apps/ui/src/components/views/agent-view.tsx (37 hunks)
  • apps/ui/src/components/views/analysis-view.tsx (32 hunks)
  • apps/ui/src/components/views/board-view/board-header.tsx (3 hunks)
  • apps/ui/src/components/views/board-view/components/kanban-card/agent-info-panel.tsx (8 hunks)
  • apps/ui/src/components/views/board-view/dialogs/agent-output-modal.tsx (11 hunks)
  • apps/ui/src/components/views/board-view/dialogs/edit-feature-dialog.tsx (15 hunks)
  • apps/ui/src/components/views/board-view/kanban-board.tsx (7 hunks)
  • apps/ui/src/components/views/context-view.tsx (31 hunks)
  • apps/ui/src/components/views/settings-view/api-keys/authentication-status-display.tsx (2 hunks)
  • apps/ui/src/components/views/settings-view/components/delete-project-dialog.tsx (2 hunks)
  • apps/ui/src/components/views/setup-view/steps/claude-setup-step.tsx (22 hunks)
  • apps/ui/src/components/views/setup-view/steps/complete-step.tsx (1 hunks)
  • apps/ui/src/components/views/setup-view/steps/welcome-step.tsx (2 hunks)
  • apps/ui/src/components/views/terminal-view.tsx (29 hunks)
  • apps/ui/src/components/views/welcome-view.tsx (35 hunks)
  • apps/ui/src/config/api-providers.ts (2 hunks)
  • apps/ui/src/lib/file-picker.ts (10 hunks)
  • apps/ui/src/lib/http-api-client.ts (38 hunks)
  • apps/ui/src/lib/utils.ts (3 hunks)
  • apps/ui/src/lib/workspace-config.ts (3 hunks)
  • apps/ui/src/routes/__root.tsx (1 hunks)
  • apps/ui/src/vite-env.d.ts (1 hunks)
  • apps/ui/tests/feature-lifecycle.spec.ts (16 hunks)
  • apps/ui/tests/spec-editor-persistence.spec.ts (13 hunks)
  • apps/ui/tests/utils/components/toasts.ts (5 hunks)
  • apps/ui/tests/utils/git/worktree.ts (17 hunks)
  • apps/ui/tests/utils/views/board.ts (11 hunks)
  • apps/ui/tests/utils/views/setup.ts (1 hunks)
✅ Files skipped from review due to trivial changes (9)
  • apps/ui/src/components/views/setup-view/steps/claude-setup-step.tsx
  • apps/ui/src/components/views/board-view/board-header.tsx
  • apps/ui/src/components/dialogs/file-browser-dialog.tsx
  • apps/ui/src/components/views/analysis-view.tsx
  • apps/ui/src/components/ui/image-drop-zone.tsx
  • apps/ui/tests/utils/views/setup.ts
  • apps/ui/src/lib/http-api-client.ts
  • apps/ui/src/components/views/context-view.tsx
  • apps/ui/tests/utils/git/worktree.ts
🧰 Additional context used
🧬 Code graph analysis (12)
apps/ui/src/components/views/board-view/components/kanban-card/agent-info-panel.tsx (3)
apps/ui/src/lib/electron.ts (1)
  • getElectronAPI (568-577)
apps/ui/src/lib/agent-context-parser.ts (2)
  • formatModelName (35-40)
  • DEFAULT_MODEL (30-30)
apps/ui/src/lib/utils.ts (1)
  • cn (5-7)
apps/ui/src/components/views/terminal-view.tsx (2)
apps/ui/src/lib/utils.ts (1)
  • cn (5-7)
apps/ui/src/store/app-store.ts (1)
  • TerminalPanelContent (282-289)
apps/ui/src/components/views/board-view/dialogs/edit-feature-dialog.tsx (3)
apps/ui/src/components/ui/description-image-dropzone.tsx (1)
  • ImagePreviewMap (9-9)
apps/ui/src/store/app-store.ts (3)
  • PlanningMode (216-216)
  • AgentModel (216-216)
  • ThinkingLevel (216-216)
apps/ui/src/lib/utils.ts (1)
  • modelSupportsThinking (12-15)
apps/ui/tests/feature-lifecycle.spec.ts (2)
apps/ui/tests/utils/git/worktree.ts (2)
  • createTempDirPath (52-55)
  • TestRepo (19-22)
apps/ui/tests/utils/views/board.ts (1)
  • confirmAddFeature (158-164)
apps/ui/src/components/layout/sidebar/components/sidebar-header.tsx (4)
apps/ui/src/components/layout/sidebar/components/index.ts (3)
  • SidebarHeader (6-6)
  • AutomakerLogo (5-5)
  • BugReportButton (3-3)
apps/ui/src/lib/utils.ts (1)
  • cn (5-7)
apps/ui/src/components/layout/sidebar/components/automaker-logo.tsx (1)
  • AutomakerLogo (9-117)
apps/ui/src/components/layout/sidebar/components/bug-report-button.tsx (1)
  • BugReportButton (10-33)
apps/ui/src/components/layout/sidebar/components/bug-report-button.tsx (3)
apps/ui/src/components/layout/sidebar/components/index.ts (1)
  • BugReportButton (3-3)
apps/ui/src/lib/electron.ts (1)
  • getElectronAPI (568-577)
apps/ui/src/lib/utils.ts (1)
  • cn (5-7)
apps/ui/src/components/ui/accordion.tsx (1)
apps/ui/src/lib/utils.ts (1)
  • cn (5-7)
apps/ui/src/components/ui/feature-image-upload.tsx (1)
apps/ui/src/lib/utils.ts (1)
  • cn (5-7)
apps/ui/src/components/ui/description-image-dropzone.tsx (3)
apps/ui/src/lib/http-api-client.ts (1)
  • saveImageToTemp (306-318)
apps/ui/src/lib/electron.ts (1)
  • getElectronAPI (568-577)
apps/ui/src/lib/utils.ts (1)
  • cn (5-7)
apps/ui/src/components/ui/sheet.tsx (1)
apps/ui/src/lib/utils.ts (1)
  • cn (5-7)
apps/ui/src/components/layout/sidebar.tsx (12)
apps/ui/src/components/layout/sidebar/constants.ts (1)
  • SIDEBAR_FEATURE_FLAGS (17-24)
apps/ui/src/components/layout/sidebar/hooks/use-setup-dialog.ts (1)
  • useSetupDialog (14-147)
apps/ui/src/components/layout/sidebar/hooks/use-sidebar-auto-collapse.ts (1)
  • useSidebarAutoCollapse (8-30)
apps/ui/src/components/layout/sidebar/hooks/use-running-agents.ts (1)
  • useRunningAgents (4-53)
apps/ui/src/components/layout/sidebar/hooks/use-spec-regeneration.ts (1)
  • useSpecRegeneration (17-78)
apps/ui/src/components/layout/sidebar/hooks/use-navigation.ts (1)
  • useNavigation (38-211)
apps/ui/src/components/layout/sidebar/components/collapse-toggle-button.tsx (1)
  • CollapseToggleButton (11-60)
apps/ui/src/components/layout/sidebar/components/sidebar-header.tsx (1)
  • SidebarHeader (11-39)
apps/ui/src/components/layout/sidebar/components/project-actions.tsx (1)
  • ProjectActions (16-91)
apps/ui/src/components/layout/sidebar/components/sidebar-footer.tsx (1)
  • SidebarFooter (18-269)
apps/ui/src/components/layout/sidebar/dialogs/trash-dialog.tsx (1)
  • TrashDialog (25-116)
apps/ui/src/components/layout/sidebar/dialogs/onboarding-dialog.tsx (1)
  • OnboardingDialog (20-122)
apps/ui/src/components/views/welcome-view.tsx (1)
apps/ui/src/lib/electron.ts (1)
  • getElectronAPI (568-577)
🪛 ast-grep (0.40.0)
apps/ui/tests/utils/views/board.ts

[warning] 194-194: Regular expression constructed from variable input detected. This can lead to Regular Expression Denial of Service (ReDoS) attacks if the variable contains malicious patterns. Use libraries like 'recheck' to validate regex safety or use static patterns.
Context: new RegExp(branchName, 'i')
Note: [CWE-1333] Inefficient Regular Expression Complexity [REFERENCES]
- https://owasp.org/www-community/attacks/Regular_expression_Denial_of_Service_-_ReDoS
- https://cwe.mitre.org/data/definitions/1333.html

(regexp-from-variable)


[warning] 217-217: Regular expression constructed from variable input detected. This can lead to Regular Expression Denial of Service (ReDoS) attacks if the variable contains malicious patterns. Use libraries like 'recheck' to validate regex safety or use static patterns.
Context: new RegExp(branchName, 'i')
Note: [CWE-1333] Inefficient Regular Expression Complexity [REFERENCES]
- https://owasp.org/www-community/attacks/Regular_expression_Denial_of_Service_-_ReDoS
- https://cwe.mitre.org/data/definitions/1333.html

(regexp-from-variable)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: e2e
🔇 Additional comments (56)
apps/ui/src/lib/workspace-config.ts (1)

6-9: LGTM! Formatting standardization applied correctly.

All changes are purely stylistic—normalizing string literals to single quotes across imports, constants, and error messages. No functional impact.

Also applies to: 11-11, 20-21, 23-24, 84-85

apps/ui/src/components/views/settings-view/components/delete-project-dialog.tsx (2)

1-3: LGTM! Import improvements follow best practices.

The quote style normalization to single quotes and the use of import type for the Project type are excellent improvements. Type-only imports enable better tree-shaking and make the distinction between runtime and type-only dependencies clearer.


42-43: LGTM! Clean JSX formatting.

Collapsing the multi-line JSX to single-line improves readability and maintains consistency across the codebase.

apps/ui/src/routes/__root.tsx (1)

17-17: LGTM! Clean refactor of unused destructured properties.

Removing theme and previewTheme from the destructuring is appropriate since the file obtains the theme via the getEffectiveTheme() method call at line 61. This aligns with the PR's goal of centralizing theme logic in dedicated hooks elsewhere in the UI.

apps/ui/src/components/views/board-view/kanban-board.tsx (3)

1-11: Formatting updates look good.

The quote normalization (double → single) and inline expression consolidation are consistent with the PR's standardization goals. No behavioral changes introduced.

Also applies to: 88-88, 110-110, 121-121, 166-167, 180-180, 187-187, 190-192, 205-205


163-168: Shortcut key assignment logic is correct.

The logic correctly assigns keys 19 for indices 0–8 and 0 for index 9, covering the first 10 in-progress cards as intended.


202-223: Drag overlay implementation is clean.

The DragOverlay with custom drop animation and preview card rendering follows @dnd-kit best practices. The visual feedback (rotation, shadow, blur) provides good UX during drag operations.

apps/ui/src/config/api-providers.ts (2)

1-4: LGTM!

Import statements and type definition are clean. Single-quote standardization is consistent with the broader formatting changes in this PR.


59-84: LGTM!

Anthropic provider configuration is well-structured with clear test IDs and descriptive labels. Single-quote standardization is consistent.

apps/ui/src/lib/utils.ts (3)

1-7: LGTM! Formatting standardization looks good.

The quote normalization and semicolon additions are consistent with the PR's project-wide style cleanup.


20-27: LGTM! Quote normalization applied consistently.

String literal formatting updated to match project style.


43-45: LGTM! Quote normalization with correct escape handling.

The regex escape sequence remains properly handled after the quote style change.

apps/ui/src/components/ui/feature-image-upload.tsx (1)

1-282: LGTM! Consistent quote normalization across the file.

All changes are purely stylistic, converting double-quoted strings to single quotes throughout imports, string literals, error messages, and template literals. The logic and functionality remain unchanged. The removal of the unused error parameter in the catch block (line 90) is also a nice cleanup.

apps/ui/src/components/views/setup-view/steps/welcome-step.tsx (2)

1-2: LGTM! Consistent formatting applied.

The import statements have been updated to use single quotes, aligning with the project-wide formatting standardization mentioned in the PR objectives.


16-16: LGTM! Formatting cleanup.

The h2 element has been reformatted to a single line without any functional changes.

apps/ui/src/components/views/terminal-view.tsx (1)

1-707: LGTM! Clean formatting normalization.

All changes in this file are purely stylistic—normalizing double-quoted strings to single quotes across imports, literals, JSX attributes, and object properties. No functional logic or behavior has been altered. This is consistent with the PR's refactoring objectives.

apps/ui/tests/utils/components/toasts.ts (1)

1-85: LGTM! Formatting consistency applied.

The string literal normalization (double quotes → single quotes) is consistent with the PR's stated objectives and improves code style uniformity across the test utilities.

apps/ui/tests/spec-editor-persistence.spec.ts (1)

1-361: LGTM! Consistent formatting normalization applied.

The comprehensive string literal normalization (double quotes → single quotes) aligns with the project-wide refactoring goals. The simplified catch clause on line 100 is valid modern syntax and improves code clarity when the error object is unused.

apps/ui/tests/feature-lifecycle.spec.ts (1)

1-459: LGTM! Formatting consistency and improved test isolation.

The string literal normalization is consistent with project-wide refactoring goals. The addition of per-test lifecycle hooks (lines 60-70) that create and cleanup a fresh test repository for each test is a valuable improvement—this prevents test interference and enhances reliability by ensuring each test runs in complete isolation.

apps/ui/tests/utils/views/board.ts (2)

1-89: LGTM! Formatting improvements enhance consistency.

The string-quote normalization and inline comment formatting align well with the PR's refactoring objectives and improve code consistency across the test utilities.


114-164: LGTM! Test logic preserved with improved formatting.

The formatting updates maintain the existing test behavior while improving readability through consistent quote usage and inline expressions.

apps/ui/src/components/views/board-view/components/kanban-card/agent-info-panel.tsx (1)

1-259: LGTM! Clean and consistent formatting refactor.

The string quote normalization from double to single quotes is applied consistently throughout the file. All imports, string literals, and conditional comparisons have been updated without altering any logic or component behavior.

apps/ui/src/components/views/settings-view/api-keys/authentication-status-display.tsx (2)

1-2: LGTM! Import formatting normalized.

The import statements now consistently use single quotes, aligning with the PR's string-quote normalization objective.


36-36: LGTM! UI text formatting improved.

The status header and authentication text have been collapsed to single-line spans, improving code readability without affecting the displayed content.

Also applies to: 43-43

apps/ui/eslint.config.mjs (1)

8-19: LGTM!

The Node.js globals for .mjs and .cjs files are appropriate and correctly configured.

apps/ui/src/components/ui/sheet.tsx (3)

1-7: LGTM: Quote style normalization in imports.

The import statements have been updated to use single quotes consistently. This aligns with the broader quote style normalization across the file.


31-31: LGTM: Type annotation quote normalization.

The 'data-slot' type annotations have been consistently updated from double to single quotes across SheetOverlay, SheetContent, SheetTitle, and SheetDescription components.

Also applies to: 55-55, 115-115, 130-130


46-46: LGTM: String literal union type quote normalization.

The side property type has been updated to use single quotes, making it consistent with the default value on line 53.

apps/ui/src/components/views/agent-view.tsx (1)

1-873: Formatting normalization changes look good.

This file contains primarily quote style normalization (double → single quotes) and minor formatting adjustments with no runtime behavior changes, aligning with the PR's broader code style standardization effort. The core functionality for session management, message rendering, image handling, and drag-and-drop remains intact.

apps/ui/src/lib/file-picker.ts (4)

1-29: Documentation and interface definition look good.

The formatting adjustments are consistent with the project-wide standardization, and the documentation accurately describes browser security constraints around file path access.


30-141: Formatting changes applied correctly to directory picker logic.

The core logic for extracting directory information from file inputs remains intact. The dual-method approach (checking file.path first, then falling back to webkitRelativePath) handles cross-browser compatibility well.


142-189: Cancellation detection logic formatted consistently.

The focus/blur event pattern for detecting dialog cancellation is a reasonable workaround given browser limitations. The { once: true } option prevents listener accumulation, and the extended timeout accommodates Windows file dialog processing delays.


192-277: File picker function formatting updated consistently.

The multi-line function signature format (lines 197-200) improves readability. The path extraction logic correctly handles both the non-standard file.path property and the fallback to file.name.

apps/ui/src/components/views/setup-view/steps/complete-step.tsx (3)

1-2: LGTM! Nice UI enhancement with the Sparkles icon.

The Sparkles icon addition to the "Start Building" button is a good visual touch that reinforces the AI-powered theme. The import is properly added and the icon is correctly sized and positioned.

Also applies to: 29-30


16-16: LGTM! Text content is clear and properly formatted.

The heading and description text are well-written and user-friendly. The use of &apos; for the apostrophe is the correct JSX approach.

Also applies to: 18-19


11-11: No action needed. The bg-linear-to-br and bg-linear-to-r classes are standard Tailwind CSS v4 utilities and are correctly used with the from-* and to-* color stop utilities. No custom class definitions are required.

Likely an incorrect or invalid review comment.

apps/ui/src/components/ui/accordion.tsx (3)

26-98: LGTM!

The Accordion component is well-implemented with proper controlled/uncontrolled pattern, correct memoization dependencies, and clean handling of single/multiple modes with collapsible behavior.


111-140: LGTM!

The AccordionItem component correctly calculates isOpen state for both single and multiple accordion modes, with proper context validation and memoization.


182-225: LGTM!

The AccordionContent component uses ResizeObserver effectively for smooth height animations with proper cleanup. The animation logic correctly handles both open and closed states.

apps/ui/src/components/views/board-view/dialogs/edit-feature-dialog.tsx (2)

1-56: LGTM! Clean formatting normalization.

The import statement formatting changes (switching to single quotes) are consistent and improve code style uniformity.


262-528: LGTM! Consistent quote style normalization.

The JSX formatting changes throughout this section maintain functional equivalence while standardizing on single quotes. The logic for default values, status checks, and conditional rendering remains correct.

apps/ui/src/vite-env.d.ts (1)

8-11: The ImportMeta interface redeclaration in this file is necessary and not redundant. Vite's recommended pattern requires declaring both ImportMetaEnv (for custom env variables) and ImportMeta with the env property, as omitting the ImportMeta declaration causes TypeScript errors.

apps/ui/src/components/views/welcome-view.tsx (6)

1-35: LGTM: Import reorganization aligns with refactoring.

The quote normalization and updated import paths for dialog components are consistent with the broader UI reorganization described in the PR objectives.


68-68: LGTM: Consistent quote normalization.

String literals normalized from double quotes to single quotes throughout the file. This is consistent with the project-wide string-quote normalization mentioned in the PR summary.

Also applies to: 74-74, 78-79, 82-82, 85-85, 102-103, 128-129, 134-136, 140-140, 142-144, 177-177, 182-182, 189-189, 221-221, 236-238, 245-247, 254-256, 264-266, 307-309, 320-323, 350-352, 362-364, 405-407, 421-424, 447-449, 459-461, 502-504, 518-521


573-576: LGTM: Minor UI text refinements.

Text formatting and wording adjustments are minor and improve consistency. The changes maintain the same semantic meaning while being more concise.

Also applies to: 620-623, 645-646, 689-692, 719-725, 729-730, 756-762, 794-794


115-115: LGTM: Store action usage appears correct.

Calling upsertAndSetCurrentProject without capturing the return value is appropriate, as the function is a store action that handles state updates internally.


541-541: No changes needed. The bg-linear-to-* classes are standard Tailwind CSS utilities in v4.0+ (released January 2025), where bg-gradient-* was officially renamed to bg-linear-* for linear gradients. The project uses Tailwind v4.1.18, and this code correctly implements the current syntax.

Likely an incorrect or invalid review comment.


244-244: The API structure change is correctly implemented. Both stat() usages in the codebase consistently access the nested stats.isDirectory property according to the StatResult interface definition. No inconsistencies or missing updates found.

apps/ui/src/components/layout/sidebar/types.ts (1)

1-32: LGTM! Well-structured type definitions.

The new interfaces provide clear, type-safe contracts for the modularized sidebar components. The type definitions are appropriately scoped and use proper React types for component props.

apps/ui/src/components/layout/sidebar/components/bug-report-button.tsx (1)

1-33: LGTM! Clean component implementation.

The BugReportButton component correctly handles both expanded and collapsed sidebar states with appropriate styling transitions and test identifiers. The use of useCallback with an empty dependency array is correct since the click handler has no external dependencies.

apps/ui/src/components/layout/sidebar/components/sidebar-header.tsx (1)

1-39: LGTM! Clear component composition.

The header component cleanly composes the logo and bug report button with appropriate conditional layout logic for expanded/collapsed states. The dual placement strategy ensures optimal positioning in both sidebar modes.

apps/ui/src/components/layout/sidebar/components/project-selector-with-options.tsx (2)

44-374: Well-architected component with rich interactions.

This component effectively consolidates project selection, theming, history navigation, and trash operations into a cohesive UI. The integration of drag-and-drop reordering, type-ahead search, and keyboard navigation provides excellent UX.


247-254: Remove redundant pointer leave handlers on submenu wrapper.

The submenu has two unconditional onPointerLeave handlers (lines 250 and 275) that both call setPreviewTheme(null). However, handlePreviewLeave in the hook already contains the necessary logic to check if the pointer remains within theme elements using relatedTarget.closest(). The direct handlers bypass this check and are redundant—keep only the smart handler passed to ThemeMenuItem components.

apps/ui/src/components/layout/sidebar.tsx (3)

14-33: Excellent modularization of sidebar architecture.

The refactor successfully decomposes a 2100+ line monolithic sidebar into well-organized components, dialogs, hooks, and constants. This improves maintainability, testability, and reusability across the codebase.


58-59: Good practice: centralized feature flags.

Using SIDEBAR_FEATURE_FLAGS object instead of direct environment variable reads improves discoverability and creates a single source of truth for configuration.


249-366: Clean component composition maintains functionality.

The sidebar rendering successfully composes the new modular components while maintaining the original feature set. Each component receives well-defined props, and dialogs are properly wired with their respective state handlers.

@Shironex Shironex changed the title refactor: folder pattern compliance refactor: sidebar Dec 21, 2025
… callback

- Added an `afterEach` hook to clean up after tests in `claude-usage-service.test.ts`.
- Updated the mock for `onExit` to include an exit callback, ensuring proper handling of process termination.
- Modified the `fetchUsageData` test to await the promise resolution, preventing unhandled promise rejections.

These changes improve the reliability and robustness of the unit tests for the ClaudeUsageService.
@Shironex Shironex added Ready-To-Merge A feature or bug has been improved/fixed and a final review is requested before merging. and removed Work-In-Progress Currently being addressed. Do Not Merge Use this label if something should not be merged. labels Dec 21, 2025
@webdevcody webdevcody merged commit 4ce1636 into main Dec 22, 2025
4 of 5 checks passed
@webdevcody webdevcody deleted the refactor/folder-pattern-compliance branch December 22, 2025 00:47
@coderabbitai coderabbitai bot mentioned this pull request Dec 22, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Ready-To-Merge A feature or bug has been improved/fixed and a final review is requested before merging. Refactor A complete logic rewrite is requested or being performed for an issue.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants