Skip to content

Conversation

@ComputelessComputer
Copy link
Collaborator

• Added turbo command to desktop2
• Implemented pre-defined colors
• Set left sidebar width to 280px
• Updated tab area UI
• Added forward/backward navigation buttons
• Improved search functionality

@coderabbitai
Copy link

coderabbitai bot commented Oct 14, 2025

📝 Walkthrough

Walkthrough

Adds Tauri npm scripts, new Tailwind color tokens, styling/layout tweaks across chat and sidebar, a refactored main body with a scrollable, reorderable tab strip and hotkey (mod+w), per-tab navigation history (goBack/goNext) in the Zustand store, and tests for tab history behavior.

Changes

Cohort / File(s) Summary
Build scripts
apps/desktop2/package.json
Adds npm scripts: tauri:dev, tauri:build.
Tailwind theme
apps/desktop2/tailwind.config.ts
Adds theme.extend.colors: color1, color2, color3, color4.
Chat UI styling
apps/desktop2/src/components/chat/body.tsx, apps/desktop2/src/components/chat/header.tsx, apps/desktop2/src/components/chat/input.tsx
Adjusts Tailwind classes for RightPanelOpen states, margins/padding/heights, and adds focus ring to header button; replaces some rounded-xl → rounded-md.
Main body: tabs, header, search
apps/desktop2/src/components/main/body/index.tsx, apps/desktop2/src/components/main/body/search.tsx, apps/desktop2/src/components/main/body/shared.tsx
Introduces scrollable/reorderable tab strip with per-tab refs and auto-scroll; adds navigation arrows, plus button, and mod+w hotkey to close tab or window; search gains focus state-driven width and bordered styling; shared tab styles switched to new color tokens.
Sidebar layout/styling
apps/desktop2/src/components/main/sidebar/index.tsx, apps/desktop2/src/components/main/sidebar/profile/index.tsx, .../sidebar/search/index.tsx, .../sidebar/timeline.tsx
Widens sidebar, restructures header/column layout, inserts ProfileSection, and standardizes backgrounds to bg-color1; adjusts profile button styling.
App layout
apps/desktop2/src/routes/app/main/_layout.index.tsx
Adds root padding/gap, sets autoSaveId="main-chat" on ResizablePanelGroup, inserts Body panel before Chat, and applies left padding to Chat panel.
Tab navigation store & tests
apps/desktop2/src/store/zustand/tabs.ts, apps/desktop2/src/store/zustand/tabs.test.ts
Adds per-tab navigation history (history map, push/update logic), exposes goBack() and goNext() in the store API, integrates history updates across tab actions (open/select/close/reorder), and adds tests covering back/forward/truncation/boundaries.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor User
  participant Body as Body (main/body/index)
  participant Hotkey as useTabCloseHotkey
  participant Tabs as TabsStore
  participant Win as AppWindow (Tauri)

  Note over Body,Hotkey: Register mod+w on mount
  User->>Body: Press mod+w
  Body->>Hotkey: onKey(mod+w)
  Hotkey->>Tabs: getTabCount()
  alt Multiple tabs
    Hotkey->>Tabs: closeActiveTab()
  else Single tab
    Hotkey->>Win: getCurrentWebviewWindow()
    Hotkey->>Win: close()
  end
Loading
sequenceDiagram
  autonumber
  actor User
  participant UI as Tab UI (main/body)
  participant Tabs as TabsStore
  participant History as TabHistory (store)

  User->>UI: Click "New Tab" (+)
  UI->>Tabs: openNew()
  Tabs->>History: pushHistory(newTabSlot, initialEntry)
  Tabs-->>UI: newTabId
  UI->>UI: scrollActiveTabIntoView()
Loading
sequenceDiagram
  autonumber
  actor User
  participant UI as Tab UI
  participant Tabs as TabsStore
  participant History as TabHistory

  User->>UI: Click Back (or call goBack)
  UI->>Tabs: goBack()
  Tabs->>History: decrement currentIndex, get previousEntry
  Tabs->>UI: select(previousEntry.tabId)
  UI->>UI: render selected tab state
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Title Check ✅ Passed The title succinctly highlights the key UI enhancements—addition of a command feature, sidebar resizing, and search improvements—which accurately reflect the main focus of the changeset without unnecessary detail.
Description Check ✅ Passed The description plainly lists the implemented features—command support, color tokens, sidebar width change, tab UI updates, navigation buttons, and enhanced search—which directly correspond to the actual changes and demonstrate relevance to 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 jj-branch-19

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

❤️ Share

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

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

🧹 Nitpick comments (1)
apps/desktop2/tailwind.config.ts (1)

13-18: Color tokens added for consistent theming.

The new color palette provides a foundation for consistent styling across components. These tokens are already in use throughout the codebase.

Consider using semantic names like backgroundPrimary, backgroundSecondary, textMuted, textSecondary instead of color1-4 for better self-documentation:

 colors: {
-  color1: "#FBFBFB",
-  color2: "#F4F4F4",
-  color3: "#8e8e8e",
-  color4: "#484848",
+  backgroundPrimary: "#FBFBFB",
+  backgroundSecondary: "#F4F4F4",
+  textMuted: "#8e8e8e",
+  textPrimary: "#484848",
 },

This would require updating all usages across the codebase.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 67c5c93 and 82b8d78.

📒 Files selected for processing (13)
  • apps/desktop2/package.json (1 hunks)
  • apps/desktop2/src/components/chat/body.tsx (1 hunks)
  • apps/desktop2/src/components/chat/header.tsx (2 hunks)
  • apps/desktop2/src/components/chat/input.tsx (1 hunks)
  • apps/desktop2/src/components/main/body/index.tsx (5 hunks)
  • apps/desktop2/src/components/main/body/search.tsx (4 hunks)
  • apps/desktop2/src/components/main/body/shared.tsx (2 hunks)
  • apps/desktop2/src/components/main/sidebar/index.tsx (1 hunks)
  • apps/desktop2/src/components/main/sidebar/profile/index.tsx (2 hunks)
  • apps/desktop2/src/components/main/sidebar/search/index.tsx (1 hunks)
  • apps/desktop2/src/components/main/sidebar/timeline.tsx (1 hunks)
  • apps/desktop2/src/routes/app/main/_layout.index.tsx (2 hunks)
  • apps/desktop2/tailwind.config.ts (1 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
**/*.{js,ts,tsx,rs}

⚙️ CodeRabbit configuration file

**/*.{js,ts,tsx,rs}: 1. Do not add any error handling. Keep the existing one.
2. No unused imports, variables, or functions.
3. For comments, keep it minimal. It should be about "Why", not "What".

Files:

  • apps/desktop2/tailwind.config.ts
  • apps/desktop2/src/components/chat/header.tsx
  • apps/desktop2/src/components/chat/input.tsx
  • apps/desktop2/src/components/main/sidebar/search/index.tsx
  • apps/desktop2/src/components/main/sidebar/index.tsx
  • apps/desktop2/src/components/main/body/shared.tsx
  • apps/desktop2/src/components/main/sidebar/profile/index.tsx
  • apps/desktop2/src/components/main/body/index.tsx
  • apps/desktop2/src/components/chat/body.tsx
  • apps/desktop2/src/components/main/body/search.tsx
  • apps/desktop2/src/components/main/sidebar/timeline.tsx
  • apps/desktop2/src/routes/app/main/_layout.index.tsx
apps/desktop2/**/*.{tsx,jsx}

📄 CodeRabbit inference engine (apps/desktop2/.cursor/rules/style.mdc)

apps/desktop2/**/*.{tsx,jsx}: When there are many Tailwind classNames with conditional logic, use the cn utility imported as import { cn } from "@hypr/ui/lib/utils"
Always pass an array to cn when composing Tailwind classNames
Split cn array entries by logical grouping when composing Tailwind classNames

Files:

  • apps/desktop2/src/components/chat/header.tsx
  • apps/desktop2/src/components/chat/input.tsx
  • apps/desktop2/src/components/main/sidebar/search/index.tsx
  • apps/desktop2/src/components/main/sidebar/index.tsx
  • apps/desktop2/src/components/main/body/shared.tsx
  • apps/desktop2/src/components/main/sidebar/profile/index.tsx
  • apps/desktop2/src/components/main/body/index.tsx
  • apps/desktop2/src/components/chat/body.tsx
  • apps/desktop2/src/components/main/body/search.tsx
  • apps/desktop2/src/components/main/sidebar/timeline.tsx
  • apps/desktop2/src/routes/app/main/_layout.index.tsx
🧬 Code graph analysis (4)
apps/desktop2/src/components/main/sidebar/search/index.tsx (1)
packages/ui/src/lib/utils.ts (1)
  • cn (4-6)
apps/desktop2/src/components/main/body/index.tsx (1)
packages/ui/src/lib/utils.ts (1)
  • cn (4-6)
apps/desktop2/src/components/main/body/search.tsx (1)
packages/ui/src/lib/utils.ts (1)
  • cn (4-6)
apps/desktop2/src/routes/app/main/_layout.index.tsx (1)
apps/desktop2/src/components/main/sidebar/index.tsx (1)
  • LeftSidebar (10-41)
⏰ 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). (2)
  • GitHub Check: ci (macos, macos-14)
  • GitHub Check: ci (windows, windows-latest)
🔇 Additional comments (19)
apps/desktop2/src/components/main/sidebar/search/index.tsx (1)

13-13: LGTM! Color token usage is consistent.

The change from bg-gray-50 to bg-color1 aligns with the new color palette defined in tailwind.config.ts.

apps/desktop2/src/components/main/sidebar/timeline.tsx (2)

20-20: LGTM! Consistent color token adoption.

The background color update to bg-color1 and the addition of rounded-lg align with the broader UI refresh.


23-23: Cleaner styling with background removed.

Removing the background from the sticky date header while preserving positioning is appropriate.

apps/desktop2/package.json (1)

13-14: Convenient Tauri shortcuts added.

The new scripts provide ergonomic aliases for common Tauri development and build workflows.

apps/desktop2/src/components/chat/input.tsx (1)

72-74: Refined input styling for better panel integration.

The border radius change to rounded-md and margin removal in RightPanelOpen mode create a cleaner visual connection with adjacent panels.

apps/desktop2/src/components/chat/body.tsx (1)

38-38: Consistent margin removal for panel alignment.

Removing mr-1 in RightPanelOpen mode aligns with the margin adjustments in input.tsx, ensuring proper panel spacing.

apps/desktop2/src/routes/app/main/_layout.index.tsx (3)

19-19: Improved outer container spacing.

Adding p-1 gap-1 creates consistent padding and gaps throughout the layout.


25-25: Panel size persistence enabled.

The autoSaveId="main-chat" prop allows the resizable panel to remember user's size preferences across sessions, improving UX.


33-33: Balanced chat panel spacing.

The pl-1 class on the chat panel creates visual balance with the overall layout spacing.

apps/desktop2/src/components/main/sidebar/profile/index.tsx (2)

67-67: Consistent background color token.

Updated to bg-color1 aligning with the new color palette.


105-105: Expanded state styling updated.

The color token usage in the expanded state maintains consistency with the overall color scheme.

apps/desktop2/src/components/chat/header.tsx (1)

27-29: LGTM! Layout adjustments align with PR objectives.

The padding and height changes improve the visual consistency of the header across different chat modes.

apps/desktop2/src/components/main/sidebar/index.tsx (1)

17-38: LGTM! Layout updates align with PR objectives.

The sidebar width increase to 280px and the addition of gap spacing improve the visual hierarchy and match the stated PR goal of setting the left sidebar width to 280px. The color token migration to bg-color1 ensures consistency with the new design system.

apps/desktop2/src/components/main/body/index.tsx (2)

29-29: LGTM! Layout adjustment improves spacing consistency.

Replacing p-1 with gap-1 provides better visual separation between child elements.


133-139: LGTM! Color token migration improves theming consistency.

The migration from text-gray-800 to text-color3 aligns with the new color token system introduced in the PR.

apps/desktop2/src/components/main/body/search.tsx (3)

11-11: LGTM! Focus state management correctly syncs local and context state.

The introduction of local isFocused state combined with handlers that call both setIsFocused and context callbacks ensures proper synchronization between component-level and app-level focus state.

Also applies to: 53-61


64-69: LGTM! Animated width expansion improves UX.

The dynamic width change from 200px to 240px with a 300ms transition provides smooth visual feedback when the search input receives focus.


84-87: LGTM! Border styling enhances focus visibility.

The border changes from border-0 to border border-transparent with focus:border-black provide clearer visual feedback on focus without breaking the unfocused appearance.

apps/desktop2/src/components/main/body/shared.tsx (1)

26-27: LGTM! Color token migration establishes consistent theming.

The migration from hardcoded colors to design tokens (color1, color3, color4) aligns with the broader theming system introduced in this PR. This provides a single source of truth for colors and facilitates future theme customization.

Also applies to: 44-45

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: 0

♻️ Duplicate comments (1)
apps/desktop2/src/components/main/body/index.tsx (1)

88-113: Add onClick handlers for navigation buttons.

The arrow navigation buttons render without functional onClick handlers, making them non-interactive placeholders. This issue was previously flagged.

Implement navigation logic or add TODO comments:

 <button
+  type="button"
+  onClick={() => {
+    // TODO: Implement backward navigation through tab history
+  }}
   className={cn([
     "flex items-center justify-center",
     "h-full",
     "px-1.5",
     "rounded-lg",
     "hover:bg-gray-50",
     "transition-colors",
     "group",
   ])}
 >
   <ArrowLeftIcon className="h-4 w-4 text-color3 cursor-pointer group-hover:text-black" />
 </button>

Apply similar changes to the right arrow button (lines 101-113).

Do you want me to help implement browser-style forward/backward navigation logic, or should this be tracked as a follow-up task?

🧹 Nitpick comments (1)
apps/desktop2/src/components/main/body/search.tsx (1)

20-51: Clarify purpose of console.log statements in keyboard handlers.

The down, up, and enter hotkey handlers contain only console.log statements without implementing navigation logic.

Are these debug statements that should be removed, or placeholders for pending functionality? If the latter, consider replacing them with TODO comments:

 useHotkeys(
   "down",
   (event) => {
     if (document.activeElement === inputRef.current) {
       event.preventDefault();
-      console.log("down");
+      // TODO: Navigate to next search result
     }
   },
   { enableOnFormTags: true },
 );

Do you want me to help implement the keyboard navigation logic for search results, or should this be tracked as a follow-up task?

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ba8fc62 and e33c487.

📒 Files selected for processing (2)
  • apps/desktop2/src/components/main/body/index.tsx (4 hunks)
  • apps/desktop2/src/components/main/body/search.tsx (4 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
apps/desktop2/**/*.{tsx,jsx}

📄 CodeRabbit inference engine (apps/desktop2/.cursor/rules/style.mdc)

apps/desktop2/**/*.{tsx,jsx}: When there are many Tailwind classNames with conditional logic, use the cn utility imported as import { cn } from "@hypr/ui/lib/utils"
Always pass an array to cn when composing Tailwind classNames
Split cn array entries by logical grouping when composing Tailwind classNames

Files:

  • apps/desktop2/src/components/main/body/index.tsx
  • apps/desktop2/src/components/main/body/search.tsx
**/*.{js,ts,tsx,rs}

⚙️ CodeRabbit configuration file

**/*.{js,ts,tsx,rs}: 1. Do not add any error handling. Keep the existing one.
2. No unused imports, variables, or functions.
3. For comments, keep it minimal. It should be about "Why", not "What".

Files:

  • apps/desktop2/src/components/main/body/index.tsx
  • apps/desktop2/src/components/main/body/search.tsx
🔇 Additional comments (4)
apps/desktop2/src/components/main/body/search.tsx (2)

53-61: Focus state management looks good.

The local isFocused state correctly synchronizes with context callbacks, enabling smooth UI transitions while maintaining proper focus event propagation.


64-87: Dynamic width transition enhances UX.

The wrapper's animated width change (200px → 240px on focus) provides visual feedback, and the updated input styling with border transitions follows modern design patterns.

apps/desktop2/src/components/main/body/index.tsx (2)

58-66: Auto-scroll to new tabs improves discoverability.

The setTimeout(() => {...}, 0) ensures the DOM updates before scrolling, and the smooth scroll behavior provides a polished user experience when creating tabs.


117-146: Scrollable tabs structure is well-organized.

The ref-based scrolling container integrates cleanly with the Reorder.Group, and the hidden scrollbar styling maintains a clean aesthetic while preserving horizontal scroll functionality.

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: 0

♻️ Duplicate comments (1)
apps/desktop2/src/components/main/body/index.tsx (1)

86-114: Navigation buttons still lack onClick handlers.

As previously noted in earlier reviews, these navigation buttons render without functional onClick handlers, making them non-interactive. The PR objectives mention "Added forward/backward navigation buttons," but the navigation logic remains unimplemented.

If navigation logic is deferred, add explicit TODO comments:

 <button
+  // TODO: Implement backward navigation logic
   className={cn([
     "flex items-center justify-center",
     "h-full",

Additionally, consider adding explicit type="button" to prevent unintended form submissions:

 <button
+  type="button"
   className={cn([
🧹 Nitpick comments (2)
apps/desktop2/src/components/main/body/index.tsx (2)

58-66: Consider requestAnimationFrame for more reliable timing.

The setTimeout(0) approach works but may occasionally fire before DOM updates complete. For more predictable behavior, consider using requestAnimationFrame:

-    setTimeout(() => {
+    requestAnimationFrame(() => {
       if (tabsScrollContainerRef.current) {
         tabsScrollContainerRef.current.scrollTo({
           left: tabsScrollContainerRef.current.scrollWidth,
           behavior: "smooth",
         });
       }
-    }, 0);
+    });

148-161: LGTM with minor accessibility suggestion.

The plus button is properly implemented with the correct onClick handler and styling.

For enhanced accessibility, consider adding explicit type="button":

 <button
+  type="button"
   onClick={handleNewNote}
   className={cn([
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e33c487 and a2ac5c8.

📒 Files selected for processing (2)
  • apps/desktop2/src/components/main/body/index.tsx (4 hunks)
  • apps/desktop2/src/components/main/body/search.tsx (4 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • apps/desktop2/src/components/main/body/search.tsx
🧰 Additional context used
📓 Path-based instructions (2)
apps/desktop2/**/*.{tsx,jsx}

📄 CodeRabbit inference engine (apps/desktop2/.cursor/rules/style.mdc)

apps/desktop2/**/*.{tsx,jsx}: When there are many Tailwind classNames with conditional logic, use the cn utility imported as import { cn } from "@hypr/ui/lib/utils"
Always pass an array to cn when composing Tailwind classNames
Split cn array entries by logical grouping when composing Tailwind classNames

Files:

  • apps/desktop2/src/components/main/body/index.tsx
**/*.{js,ts,tsx,rs}

⚙️ CodeRabbit configuration file

**/*.{js,ts,tsx,rs}: 1. Do not add any error handling. Keep the existing one.
2. No unused imports, variables, or functions.
3. For comments, keep it minimal. It should be about "Why", not "What".

Files:

  • apps/desktop2/src/components/main/body/index.tsx
🧬 Code graph analysis (1)
apps/desktop2/src/components/main/body/index.tsx (3)
packages/ui/src/lib/utils.ts (1)
  • cn (4-6)
apps/desktop2/src/store/zustand/tabs.ts (1)
  • uniqueIdfromTab (196-215)
apps/desktop2/src/components/main/body/search.tsx (1)
  • Search (8-107)
⏰ 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). (2)
  • GitHub Check: ci (macos, macos-14)
  • GitHub Check: ci (windows, windows-latest)
🔇 Additional comments (5)
apps/desktop2/src/components/main/body/index.tsx (5)

2-2: LGTM!

Import additions are correct and all used within the component.

Also applies to: 4-4


44-44: LGTM!

The ref is properly typed and used for controlling the scrollable tabs container.


76-84: LGTM!

The left sidebar toggle is properly structured with appropriate z-index layering and follows the coding guidelines for cn usage.


116-146: LGTM!

The scrollable tabs container is well-structured with proper ref assignment, hidden scrollbars, and correct Reorder.Group nesting. The cn usage follows coding guidelines.


163-164: LGTM!

The Search component is properly integrated into the header layout and includes focus states with animated width transitions.

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

♻️ Duplicate comments (1)
apps/desktop2/src/components/main/body/index.tsx (1)

106-131: Add onClick handlers for navigation buttons.

These buttons still lack click handlers, making them non-functional UI placeholders.

If navigation logic is not ready, add explicit TODO comments and ensure buttons have type="button":

       <button
+        type="button"
+        // TODO: Implement backward navigation through tab history
         className={cn([
           "flex items-center justify-center",
           "h-full",
           "px-1.5",
           "rounded-lg",
           "hover:bg-gray-50",
           "transition-colors",
           "group",
         ])}
       >
         <ArrowLeftIcon className="h-4 w-4 text-color3 cursor-pointer group-hover:text-black" />
       </button>
       <button
+        type="button"
+        // TODO: Implement forward navigation through tab history
         className={cn([

Do you want me to help design the navigation state management (e.g., maintaining a history stack per tab or a global navigation history)?

🧹 Nitpick comments (3)
apps/desktop2/tailwind.config.ts (1)

13-18: Consider semantic color token names for better maintainability.

The color tokens color1, color2, color3, and color4 are not semantically named. Using descriptive names like background-primary, background-secondary, text-muted, and text-dark would improve code readability and make future maintenance easier.

Apply this diff to use semantic naming:

       colors: {
-        color1: "#FBFBFB",
-        color2: "#F4F4F4",
-        color3: "#8e8e8e",
-        color4: "#484848",
+        "bg-primary": "#FBFBFB",
+        "bg-secondary": "#F4F4F4",
+        "text-muted": "#8e8e8e",
+        "text-dark": "#484848",
       },
apps/desktop2/src/components/main/body/index.tsx (2)

33-38: Remove explanatory comments.

These comments describe what the code does rather than why. The control flow is self-evident from reading the conditional logic.

Apply this diff to remove the comments:

-      if (tabs.length > 1) {
-        // If more than one tab, close the current tab
+      if (tabs.length > 1) {
         if (currentTab) {
           close(currentTab);
         }
-      } else if (tabs.length === 1) {
-        // If only one tab left, close the window
+      } else if (tabs.length === 1) {
         const appWindow = getCurrentWebviewWindow();
         await appWindow.close();
       }

74-87: Replace setTimeout with requestAnimationFrame in scrollTabsToEnd to ensure the scroll runs after the new tab has rendered.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7b88086 and 018f59e.

📒 Files selected for processing (14)
  • apps/desktop2/package.json (1 hunks)
  • apps/desktop2/src/components/chat/body.tsx (1 hunks)
  • apps/desktop2/src/components/chat/header.tsx (2 hunks)
  • apps/desktop2/src/components/chat/input.tsx (1 hunks)
  • apps/desktop2/src/components/main/body/index.tsx (4 hunks)
  • apps/desktop2/src/components/main/body/search.tsx (4 hunks)
  • apps/desktop2/src/components/main/body/shared.tsx (2 hunks)
  • apps/desktop2/src/components/main/sidebar/index.tsx (1 hunks)
  • apps/desktop2/src/components/main/sidebar/profile/index.tsx (5 hunks)
  • apps/desktop2/src/components/main/sidebar/search/index.tsx (1 hunks)
  • apps/desktop2/src/components/main/sidebar/timeline.tsx (1 hunks)
  • apps/desktop2/src/routes/app/main/_layout.index.tsx (2 hunks)
  • apps/desktop2/src/utils/tabs-scroll.ts (1 hunks)
  • apps/desktop2/tailwind.config.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (5)
  • apps/desktop2/src/components/main/sidebar/profile/index.tsx
  • apps/desktop2/src/components/chat/body.tsx
  • apps/desktop2/package.json
  • apps/desktop2/src/components/chat/header.tsx
  • apps/desktop2/src/components/main/sidebar/search/index.tsx
🧰 Additional context used
📓 Path-based instructions (2)
**/*.{js,ts,tsx,rs}

⚙️ CodeRabbit configuration file

**/*.{js,ts,tsx,rs}: 1. Do not add any error handling. Keep the existing one.
2. No unused imports, variables, or functions.
3. For comments, keep it minimal. It should be about "Why", not "What".

Files:

  • apps/desktop2/src/utils/tabs-scroll.ts
  • apps/desktop2/src/components/main/sidebar/index.tsx
  • apps/desktop2/src/components/main/sidebar/timeline.tsx
  • apps/desktop2/tailwind.config.ts
  • apps/desktop2/src/components/main/body/shared.tsx
  • apps/desktop2/src/components/chat/input.tsx
  • apps/desktop2/src/routes/app/main/_layout.index.tsx
  • apps/desktop2/src/components/main/body/search.tsx
  • apps/desktop2/src/components/main/body/index.tsx
apps/desktop2/**/*.{tsx,jsx}

📄 CodeRabbit inference engine (apps/desktop2/.cursor/rules/style.mdc)

apps/desktop2/**/*.{tsx,jsx}: When there are many Tailwind classNames with conditional logic, use the cn utility imported as import { cn } from "@hypr/ui/lib/utils"
Always pass an array to cn when composing Tailwind classNames
Split cn array entries by logical grouping when composing Tailwind classNames

Files:

  • apps/desktop2/src/components/main/sidebar/index.tsx
  • apps/desktop2/src/components/main/sidebar/timeline.tsx
  • apps/desktop2/src/components/main/body/shared.tsx
  • apps/desktop2/src/components/chat/input.tsx
  • apps/desktop2/src/routes/app/main/_layout.index.tsx
  • apps/desktop2/src/components/main/body/search.tsx
  • apps/desktop2/src/components/main/body/index.tsx
🧬 Code graph analysis (3)
apps/desktop2/src/routes/app/main/_layout.index.tsx (1)
apps/desktop2/src/components/main/sidebar/index.tsx (1)
  • LeftSidebar (10-41)
apps/desktop2/src/components/main/body/search.tsx (1)
packages/ui/src/lib/utils.ts (1)
  • cn (4-6)
apps/desktop2/src/components/main/body/index.tsx (2)
apps/desktop2/src/store/zustand/tabs.ts (2)
  • useTabs (31-121)
  • uniqueIdfromTab (196-215)
apps/desktop2/src/utils/tabs-scroll.ts (2)
  • setTabsScrollContainer (7-9)
  • scrollTabsToEnd (11-20)
⏰ 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). (2)
  • GitHub Check: ci (windows, windows-latest)
  • GitHub Check: ci (macos, macos-14)
🔇 Additional comments (10)
apps/desktop2/src/components/main/body/search.tsx (2)

53-61: LGTM!

The focus handlers correctly combine local state management with context callbacks, enabling the animated width transition while maintaining integration with the search context.


64-88: LGTM!

The animated width transition on focus provides good UX feedback, and the implementation correctly uses the cn utility with logical grouping of Tailwind classes.

apps/desktop2/src/components/main/sidebar/timeline.tsx (2)

20-20: LGTM!

The background color update to bg-color1 is consistent with the new color token system introduced in the Tailwind configuration.


23-23: LGTM!

Removing the background from the sticky header simplifies the styling while maintaining the sticky positioning behavior.

apps/desktop2/src/components/chat/input.tsx (1)

72-74: LGTM!

The border radius change to rounded-md and simplified RightPanelOpen styling align with the overall UI consistency improvements in this PR.

apps/desktop2/src/routes/app/main/_layout.index.tsx (2)

19-19: LGTM!

Adding padding and gap to the outer container improves visual spacing and consistency across the layout.


25-25: LGTM!

The autoSaveId prop enables persistence of the user's panel size preferences across sessions, improving UX.

apps/desktop2/src/components/main/sidebar/index.tsx (1)

17-17: LGTM!

The width increase to 280px and addition of gap-1 align with the PR objectives for sidebar layout improvements.

apps/desktop2/src/components/main/body/index.tsx (2)

27-45: LGTM! Window close behavior is well-implemented.

The hotkey handler correctly distinguishes between closing a tab (when multiple exist) and closing the entire window (when only one tab remains). The enableOnFormTags: true option is appropriate here since Cmd/Ctrl+W is a standard close action that users expect to work even in form fields.


143-143: Verify Reorder.Group key behavior.

The key {leftsidebar.expanded ? "expanded" : "collapsed"} forces React to remount the entire Reorder.Group and all its children whenever the sidebar expands or collapses. This will:

  • Reset internal animation state in Framer Motion
  • Lose any in-flight drag operations
  • Potentially cause a brief flicker

Confirm this remounting is intentional (e.g., to recalculate positions after sidebar width changes). If not, consider removing the key or using a stable identifier.

@yujonglee yujonglee merged commit ec593f5 into main Oct 14, 2025
5 of 6 checks passed
@yujonglee yujonglee deleted the jj-branch-19 branch October 14, 2025 11:01
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: 1

♻️ Duplicate comments (1)
apps/desktop2/src/components/main/body/index.tsx (1)

81-101: Nav buttons wired correctly; add small a11y tweaks

onClick handlers resolve the earlier “missing navigation logic” comment. Add aria-labels and type="button" to improve accessibility and avoid implicit submits.

Apply this diff:

-        <button
-          onClick={goBack}
+        <button
+          type="button"
+          aria-label="Go back"
+          onClick={goBack}
           disabled={!canGoBack}
           className={cn([
             "flex items-center justify-center",
             "h-full",
             "px-1.5",
             "rounded-lg",
             "transition-colors",
             canGoBack && ["hover:bg-gray-50", "group"],
             !canGoBack && "cursor-not-allowed",
           ])}
         >
@@
-        <button
-          onClick={goNext}
+        <button
+          type="button"
+          aria-label="Go forward"
+          onClick={goNext}
           disabled={!canGoNext}
           className={cn([
             "flex items-center justify-center",
             "h-full",
             "px-1.5",
             "rounded-lg",
             "transition-colors",
             canGoNext && ["hover:bg-gray-50", "group"],
             !canGoNext && "cursor-not-allowed",
           ])}
         >
@@
-      <button
-        onClick={handleNewNote}
+      <button
+        type="button"
+        aria-label="New note"
+        onClick={handleNewNote}
         className={cn([
           "flex items-center justify-center",
           "h-full",
           "px-1.5",
           "rounded-lg",
           "bg-white hover:bg-gray-50",
           "transition-colors",
           "shrink-0",
         ])}
       >

Nice use of cn([...]) and grouped class arrays.

Also applies to: 102-122, 157-171

🧹 Nitpick comments (3)
apps/desktop2/src/store/zustand/tabs.test.ts (1)

4-151: Good coverage for back/forward and forward-history truncation

Scenarios match the store semantics and validate flags well. Consider adding tests for:

  • select() switching tabs preserves active-slot history flags.
  • Closing the last tab resets flags/history to a clean state.
apps/desktop2/src/store/zustand/tabs.ts (2)

166-168: Clear history when the last tab closes

Leaving history populated when tabs become empty retains stale state and may confuse subsequent sessions.

Apply this diff:

-    if (remainingTabs.length === 0) {
-      return set({ tabs: [], currentTab: null, canGoBack: false, canGoNext: false });
-    }
+    if (remainingTabs.length === 0) {
+      return set({ tabs: [], currentTab: null, history: new Map(), canGoBack: false, canGoNext: false });
+    }

90-94: Add upper-bound guard when updating history current entry

Rare, but safer to ensure currentIndex is within stack bounds before assignment.

Apply this diff:

-  if (existing && existing.currentIndex >= 0) {
+  if (existing && existing.currentIndex >= 0 && existing.currentIndex < existing.stack.length) {
     const newStack = [...existing.stack];
     newStack[existing.currentIndex] = tab;
     newHistory.set(slotId, { ...existing, stack: newStack });
   }
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 36c2db7 and bbaf4e1.

📒 Files selected for processing (3)
  • apps/desktop2/src/components/main/body/index.tsx (5 hunks)
  • apps/desktop2/src/store/zustand/tabs.test.ts (1 hunks)
  • apps/desktop2/src/store/zustand/tabs.ts (5 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
**/*.{js,ts,tsx,rs}

⚙️ CodeRabbit configuration file

**/*.{js,ts,tsx,rs}: 1. Do not add any error handling. Keep the existing one.
2. No unused imports, variables, or functions.
3. For comments, keep it minimal. It should be about "Why", not "What".

Files:

  • apps/desktop2/src/store/zustand/tabs.ts
  • apps/desktop2/src/store/zustand/tabs.test.ts
  • apps/desktop2/src/components/main/body/index.tsx
apps/desktop2/**/*.{tsx,jsx}

📄 CodeRabbit inference engine (apps/desktop2/.cursor/rules/style.mdc)

apps/desktop2/**/*.{tsx,jsx}: When there are many Tailwind classNames with conditional logic, use the cn utility imported as import { cn } from "@hypr/ui/lib/utils"
Always pass an array to cn when composing Tailwind classNames
Split cn array entries by logical grouping when composing Tailwind classNames

Files:

  • apps/desktop2/src/components/main/body/index.tsx
🧬 Code graph analysis (2)
apps/desktop2/src/store/zustand/tabs.test.ts (1)
apps/desktop2/src/store/zustand/tabs.ts (2)
  • useTabs (99-271)
  • Tab (322-322)
apps/desktop2/src/components/main/body/index.tsx (1)
apps/desktop2/src/store/zustand/tabs.ts (3)
  • useTabs (99-271)
  • uniqueIdfromTab (346-365)
  • Tab (322-322)
⏰ 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). (2)
  • GitHub Check: ci (macos, macos-14)
  • GitHub Check: ci (windows, windows-latest)
🔇 Additional comments (3)
apps/desktop2/src/store/zustand/tabs.ts (1)

14-17: Note: Map in Zustand state isn’t serializable

If this store is ever persisted, Map won’t serialize by default. Ensure this slice is excluded from persistence or provide a (de)serialization transform.

Do you persist this store slice? If yes, I can draft a small transform to serialize history to arrays and back.

apps/desktop2/src/components/main/body/index.tsx (2)

125-133: Tauri drag-region may block tab clicks/drag-reorder

data-tauri-drag-region on the tabs scroll container can intercept clicks/drag within child controls (tab selection/reorder). Prefer restricting the drag region to non-interactive zones or marking interactive areas as no-drag.

Consider either:

  • Remove data-tauri-drag-region from the scroll container, or
  • Add data-tauri-drag-region="no-drag" to interactive wrappers (e.g., Reorder.Group/Reorder.Item or TabItem root) so clicks/drag reorder work reliably.

If desired, I can propose a concrete diff after you confirm desired drag behavior area.

Also applies to: 133-140


233-251: Hotkey behavior looks good

mod+w closes the active tab or the window when only one remains. No extra error handling added; deps array is correct.

Comment on lines 156 to 161
select: (tab) => {
const { tabs } = get();
const { tabs, history } = get();
const nextTabs = tabs.map((t) => ({ ...t, active: isSameTab(t, tab) }));
set({ tabs: nextTabs, currentTab: tab });
const flags = computeHistoryFlags(history, tab);
set({ tabs: nextTabs, currentTab: tab, ...flags });
},
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Bug: select() sets currentTab to a stale (inactive) object and computes flags on wrong slot

select() should set currentTab to the newly active tab instance and compute flags using that. Current code can leave canGoBack/canGoNext incorrect and break goBack/goNext lookups.

Apply this diff:

   select: (tab) => {
-    const { tabs, history } = get();
-    const nextTabs = tabs.map((t) => ({ ...t, active: isSameTab(t, tab) }));
-    const flags = computeHistoryFlags(history, tab);
-    set({ tabs: nextTabs, currentTab: tab, ...flags });
+    const { tabs, history } = get();
+    const nextTabs = tabs.map((t) => ({ ...t, active: isSameTab(t, tab) }));
+    const nextCurrentTab = nextTabs.find((t) => t.active) || null;
+    const flags = computeHistoryFlags(history, nextCurrentTab);
+    set({ tabs: nextTabs, currentTab: nextCurrentTab, ...flags });
   },
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
select: (tab) => {
const { tabs } = get();
const { tabs, history } = get();
const nextTabs = tabs.map((t) => ({ ...t, active: isSameTab(t, tab) }));
set({ tabs: nextTabs, currentTab: tab });
const flags = computeHistoryFlags(history, tab);
set({ tabs: nextTabs, currentTab: tab, ...flags });
},
select: (tab) => {
const { tabs, history } = get();
const nextTabs = tabs.map((t) => ({ ...t, active: isSameTab(t, tab) }));
const nextCurrentTab = nextTabs.find((t) => t.active) || null;
const flags = computeHistoryFlags(history, nextCurrentTab);
set({ tabs: nextTabs, currentTab: nextCurrentTab, ...flags });
},
🤖 Prompt for AI Agents
In apps/desktop2/src/store/zustand/tabs.ts around lines 156 to 161, select()
currently sets currentTab to the passed-in tab and computes history flags using
that stale object; instead, after mapping nextTabs, find the newly created
active tab instance (e.g. nextTabs.find(t => t.active)) and use that instance
when calling computeHistoryFlags and when setting currentTab so
canGoBack/canGoNext and subsequent goBack/goNext lookups use the fresh, active
object; fall back to the original tab if the find returns undefined.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants