Skip to content

fix: add tab button - #23

Open
AdityaVKochar wants to merge 2 commits into
thinkter:mainfrom
AdityaVKochar:main
Open

fix: add tab button#23
AdityaVKochar wants to merge 2 commits into
thinkter:mainfrom
AdityaVKochar:main

Conversation

@AdityaVKochar

@AdityaVKochar AdityaVKochar commented Aug 4, 2026

Copy link
Copy Markdown

Summary by CodeRabbit

  • New Features

    • Added persistent “New chat” tabs for each conversation pane.
    • Search for and start chats with people or groups directly from the new-chat picker.
    • Added keyboard navigation, loading and error states, empty results, avatars, and accessible labels.
    • New-chat tabs remain available across workspace sessions and integrate with tab selection and closing.
  • Bug Fixes

    • Improved focus restoration and pane behavior when opening, closing, or switching chats.
  • Tests

    • Added coverage for new-chat tabs, picker restoration, tab closing, and workspace persistence.

Copilot AI lite review requested due to automatic review settings August 4, 2026 16:54
@coderabbitai

coderabbitai Bot commented Aug 4, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

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

Next review available in: 37 minutes

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

How can I continue?

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

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

How do review limits work?

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

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

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: a7243631-211f-4486-b3cd-11f5f3d27dd1

📥 Commits

Reviewing files that changed from the base of the PR and between a59433a and beca186.

📒 Files selected for processing (5)
  • tauri/src/App.tsx
  • tauri/src/components/SpotlightSearch.tsx
  • tauri/src/components/Tabs.tsx
  • tauri/src/components/TitleBar.tsx
  • tauri/src/state/app.ts
📝 Walkthrough

Walkthrough

Added persistent pane-local new-chat picker tabs. The change updates workspace state, app actions, tab navigation, picker rendering, styling, tests, and line-ending attributes.

Changes

New chat picker

Layer / File(s) Summary
Workspace picker state
tauri/src/state/workspace.ts, tauri/tests/workspace.test.ts
Panes now persist picker-tab state. Workspace operations handle picker selection, closure, restoration, normalization, and pane removal. Tests cover these behaviors.
App picker actions
tauri/src/state/app.ts
App actions open and close picker tabs, persist state, target panes, reset UI state, and select contacts or chats.
Picker interface
tauri/src/App.tsx, tauri/src/components/NewChatPicker.tsx, tauri/src/styles.css
Panes with an open picker render NewChatPicker. The picker supports local and remote results, keyboard navigation, loading and error states, guarded selection, and dedicated styling.
Tab navigation integration
tauri/src/components/Tabs.tsx, tauri/src/components/ChatSwitcher.tsx
The new-chat tab supports selection, focus, keyboard navigation, deletion, closing, accessibility labels, and direct opening from the add button.

Text attributes

Layer / File(s) Summary
Line-ending rules
.gitattributes
Text files use LF normalization. .bat and .cmd files use CRLF endings.

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

Suggested reviewers: copilot, thinkter

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant Tabs
  participant AppModel
  participant NewChatPicker
  participant Workspace
  User->>Tabs: Open new-chat tab
  Tabs->>AppModel: openNewTab(paneId)
  AppModel->>Workspace: Persist picker state
  Workspace-->>NewChatPicker: Activate picker pane
  User->>NewChatPicker: Select contact or group
  NewChatPicker->>AppModel: openContact(result, paneId)
  AppModel->>Workspace: selectChat(chatId, paneId, replaceNewTab)
  Workspace-->>Tabs: Activate regular chat tab
Loading
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately identifies the add-tab button change, which is a real part of the broader new-chat tab implementation.
Docstring Coverage ✅ Passed Docstring coverage is 87.50% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

This PR introduces a “New chat” picker as a pane-local, browser-style tab, along with UI/keyboard support for opening/closing it and persisting/restoring it via workspace snapshots.

Changes:

  • Adds newTabOpen support to pane/workspace state, including snapshot normalization and new close/open helpers.
  • Updates the tab strip UI to render a “New chat” tab plus a “+” button that opens it, and renders the picker surface when active.
  • Adds the NewChatPicker component plus corresponding styling and workspace-level tests.

Reviewed changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
tauri/tests/workspace.test.ts Adds coverage for new-tab picker open/close/selection and workspace normalization behavior.
tauri/src/styles.css Introduces styling for the new-chat picker surface and result rows.
tauri/src/state/workspace.ts Extends Pane with newTabOpen, adds open/close helpers, updates close behavior, and restores picker state from snapshots.
tauri/src/state/app.ts Wires picker open/close into the app model, persists picker state, and updates tab-selection plumbing.
tauri/src/components/Tabs.tsx Adds “New chat” tab rendering, keyboard navigation integration, and “+” button behavior.
tauri/src/components/NewChatPicker.tsx New picker UI for selecting people/groups into the active tab.
tauri/src/components/ChatSwitcher.tsx Adjusts click-commit behavior for the Ctrl+Tab overlay.
tauri/src/App.tsx Renders NewChatPicker when the picker tab is active.
.gitattributes Establishes consistent line ending rules across platforms.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread tauri/src/state/app.ts Outdated
Comment on lines +1115 to +1117
const pane = state.panes.find((candidate) => candidate.id === paneId);
if (!pane) return;
clearSearch();
Comment thread tauri/src/components/ChatSwitcher.tsx Outdated

function commit(chatId: string) {
void actions.selectChat(chatId);
void actions.selectChat(chatId, "", state.focusedPaneId, false);
Comment thread tauri/src/styles.css Outdated
Comment on lines +1111 to +1115
.new-chat-picker-row:hover,
.new-chat-picker-row:focus-visible {
outline: 0;
background: var(--bg-hover);
}

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🧹 Nitpick comments (1)
tauri/src/state/workspace.ts (1)

85-105: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Consider extracting the picker-clearing clone.

selectTab repeats the const withoutNewTab = { ...pane }; delete withoutNewTab.newTabOpen; pattern three times, and closeNewTab repeats it once. A small helper reduces the duplication and keeps the three return paths readable.

♻️ Proposed helper
+/** Drop the picker marker while keeping the rest of the pane intact. */
+function withoutPicker(pane: Pane): Pane {
+  if (!pane.newTabOpen) return pane;
+  const next = { ...pane };
+  delete next.newTabOpen;
+  return next;
+}
+
 export function selectTab(pane: Pane, chatId: string): Pane {
   const replacesNewTab = pane.newTabOpen && !pane.activeChatId;
+  const base = replacesNewTab ? withoutPicker(pane) : pane;
   if (pane.tabChatIds.includes(chatId)) {
-    if (!replacesNewTab) return { ...pane, activeChatId: chatId };
-    const withoutNewTab = { ...pane };
-    delete withoutNewTab.newTabOpen;
-    return { ...withoutNewTab, activeChatId: chatId };
+    return { ...base, activeChatId: chatId };
   }
   const activeIndex = pane.tabChatIds.indexOf(pane.activeChatId);
   if (activeIndex < 0) {
-    if (!replacesNewTab) {
-      return { ...pane, tabChatIds: [...pane.tabChatIds, chatId], activeChatId: chatId };
-    }
-    const withoutNewTab = { ...pane };
-    delete withoutNewTab.newTabOpen;
-    return { ...withoutNewTab, tabChatIds: [...pane.tabChatIds, chatId], activeChatId: chatId };
+    return { ...base, tabChatIds: [...pane.tabChatIds, chatId], activeChatId: chatId };
   }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tauri/src/state/workspace.ts` around lines 85 - 105, Extract the repeated
pane-cloning and newTabOpen-removal logic from selectTab into a small helper,
then reuse it across all three selectTab paths and the corresponding closeNewTab
path. Preserve each function’s existing tabChatIds and activeChatId updates
while keeping the helper focused solely on clearing newTabOpen.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@tauri/src/components/NewChatPicker.tsx`:
- Around line 127-136: Update the global handleGlobalKeyDown logic in App.tsx to
skip its Escape-key handling when the event target is the NewChatPicker search
input, allowing that input’s onKeyDown handler to clear the query without also
closing the picker tab. Preserve existing global Escape behavior for all other
targets.

In `@tauri/src/state/app.ts`:
- Around line 1114-1128: In the openNewTab function, replace the unconditional
clearSearch() call with a conditional that checks whether the picker is already
open and selected before clearing. Only invoke clearSearch() when the picker is
not currently focused or active, so that users who re-open the tab picker (via
the new-chat button or moveSelection) preserve their typed search query. Keep
the rest of the function's batch state updates and persistWorkspace call
unchanged.

In `@tauri/src/styles.css`:
- Around line 1111-1115: Update the .new-chat-picker-row states so :hover
retains only the hover background, while :focus-visible uses the stylesheet’s
existing focus-ring convention with a visible outline and no hover-only styling.

---

Nitpick comments:
In `@tauri/src/state/workspace.ts`:
- Around line 85-105: Extract the repeated pane-cloning and newTabOpen-removal
logic from selectTab into a small helper, then reuse it across all three
selectTab paths and the corresponding closeNewTab path. Preserve each function’s
existing tabChatIds and activeChatId updates while keeping the helper focused
solely on clearing newTabOpen.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: f19a6398-3ace-477d-be46-87d9b735e546

📥 Commits

Reviewing files that changed from the base of the PR and between a8ed092 and a59433a.

📒 Files selected for processing (9)
  • .gitattributes
  • tauri/src/App.tsx
  • tauri/src/components/ChatSwitcher.tsx
  • tauri/src/components/NewChatPicker.tsx
  • tauri/src/components/Tabs.tsx
  • tauri/src/state/app.ts
  • tauri/src/state/workspace.ts
  • tauri/src/styles.css
  • tauri/tests/workspace.test.ts

Comment thread tauri/src/components/NewChatPicker.tsx Outdated
Comment thread tauri/src/state/app.ts Outdated
Comment thread tauri/src/styles.css Outdated
Comment on lines +1111 to +1115
.new-chat-picker-row:hover,
.new-chat-picker-row:focus-visible {
outline: 0;
background: var(--bg-hover);
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Description: Inspect existing focus-visible conventions and available focus tokens.
fd --glob 'styles.css' --exec rg -n -C2 'focus-visible|--focus|outline'

Repository: thinkter/rust-meow

Length of output: 1912


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== styles.css focus/outline context =="
sed -n '55,85p;1105,1118p;2820,2828p;4072,4085p' tauri/src/styles.css | cat -n

echo "== variable usage references =="
rg -n '(--border-focus|--accent|--bg-hover|--bg-(primary|secondary|tertiary)?)' tauri/src/styles.css | head -120

Repository: thinkter/rust-meow

Length of output: 7268


Keep a distinct focus indicator on picker rows.

.new-chat-picker-row:focus-visible currently deletes the outline and uses var(--bg-hover), so keyboard focus is identical to hover with no ring. Split the state: keep only hover on the background and add a visible focus outline in :focus-visible, using the stylesheet’s existing focus-ring convention.

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

In `@tauri/src/styles.css` around lines 1111 - 1115, Update the
.new-chat-picker-row states so :hover retains only the hover background, while
:focus-visible uses the stylesheet’s existing focus-ring convention with a
visible outline and no hover-only styling.

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.

2 participants