fix: add tab button - #23
Conversation
|
Warning Review limit reached
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 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 configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (5)
📝 WalkthroughWalkthroughAdded persistent pane-local new-chat picker tabs. The change updates workspace state, app actions, tab navigation, picker rendering, styling, tests, and line-ending attributes. ChangesNew chat picker
Text attributes
Estimated code review effort: 3 (Moderate) | ~25 minutes Suggested reviewers: 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
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
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
newTabOpensupport 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
NewChatPickercomponent 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.
| const pane = state.panes.find((candidate) => candidate.id === paneId); | ||
| if (!pane) return; | ||
| clearSearch(); |
|
|
||
| function commit(chatId: string) { | ||
| void actions.selectChat(chatId); | ||
| void actions.selectChat(chatId, "", state.focusedPaneId, false); |
| .new-chat-picker-row:hover, | ||
| .new-chat-picker-row:focus-visible { | ||
| outline: 0; | ||
| background: var(--bg-hover); | ||
| } |
There was a problem hiding this comment.
Actionable comments posted: 3
🧹 Nitpick comments (1)
tauri/src/state/workspace.ts (1)
85-105: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueConsider extracting the picker-clearing clone.
selectTabrepeats theconst withoutNewTab = { ...pane }; delete withoutNewTab.newTabOpen;pattern three times, andcloseNewTabrepeats 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
📒 Files selected for processing (9)
.gitattributestauri/src/App.tsxtauri/src/components/ChatSwitcher.tsxtauri/src/components/NewChatPicker.tsxtauri/src/components/Tabs.tsxtauri/src/state/app.tstauri/src/state/workspace.tstauri/src/styles.csstauri/tests/workspace.test.ts
| .new-chat-picker-row:hover, | ||
| .new-chat-picker-row:focus-visible { | ||
| outline: 0; | ||
| background: var(--bg-hover); | ||
| } |
There was a problem hiding this comment.
📐 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 -120Repository: 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.
Summary by CodeRabbit
New Features
Bug Fixes
Tests