Improve AllChats UI: grouping, URL tabs, avatar fix#21
Conversation
… colors - AllChatsList: collapsible user groups (collapsed by default) - Sidebar: controlled activeTab/onTabChange props for URL routing - useBichatRouter: /all-chats URL prefix, sidebarTab, onSidebarTabChange - UserAvatar: inline styles for colors (fixes portal rendering in shadow DOM) - Export ActiveTab type
|
Warning Rate limit exceeded
Your organization is not enrolled in usage-based pricing. Contact your admin to enable usage-based pricing to continue reviews beyond the rate limit, or try again in 7 minutes and 3 seconds. ⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (3)
WalkthroughThe PR restructures chat list rendering with collapsible owner-based grouping (when no user is selected), adds controlled/uncontrolled tab state management to Sidebar, introduces all-chats view routing support, and converts avatar colors from Tailwind classes to inline hex values for shadow DOM compatibility. Changes
Sequence Diagram(s)sequenceDiagram
actor User
participant Sidebar
participant Router as useBichatRouter
participant AllChatsList
User->>Sidebar: Click "All Chats" tab
Sidebar->>Sidebar: handleTabChange('all-chats')
Sidebar->>Router: onSidebarTabChange('all-chats')
Router->>Router: navigate to /all-chats
Router->>Sidebar: sidebarTab = 'all-chats'
Sidebar->>AllChatsList: selectedUser = null
AllChatsList->>AllChatsList: Compute groupedChats<br/>(group by owner.id)
AllChatsList->>AllChatsList: Render group headers<br/>with AnimatePresence
User->>AllChatsList: Click group caret
AllChatsList->>AllChatsList: toggleGroup(ownerId)<br/>update expandedGroups
AllChatsList->>AllChatsList: AnimatePresence triggers<br/>height/opacity transition
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ 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.
Actionable comments posted: 4
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@ui/src/bichat/components/AllChatsList.tsx`:
- Around line 143-156: expandedGroups only updates on manual toggles and can
become stale across route/filter changes; add a useEffect that watches
activeSessionId and selectedUser and reseeds setExpandedGroups accordingly: when
activeSessionId is present, derive its ownerId (from the sessions/props state
used in this component) and call setExpandedGroups(new Set([ownerId])) so the
owner group is expanded to reveal the selected session, otherwise call
setExpandedGroups(new Set()) to return to the default collapsed view; keep
toggleGroup unchanged.
- Around line 165-170: The owner fallback in AllChatsList.tsx currently
hardcodes "Unknown", "User", and "Unknown User" when chat.owner is missing;
replace those hardcoded strings with calls to the app's localization function
(the same translation keys used by the sidebar) — import/use the existing i18n
hook/function (e.g., useTranslation or t) in AllChatsList, and substitute the
fallback values in the owner = chat.owner ?? { ... } object with localized
strings (e.g., t('sidebar.unknown'), t('sidebar.user'),
t('sidebar.unknownUser')); apply the same change for the other occurrence
mentioned (the fallback at the second location).
In `@ui/src/bichat/components/Sidebar.tsx`:
- Around line 218-227: handleTabChange currently only updates internalActiveTab
when onTabChange is absent, causing the uncontrolled mode to stay stuck when a
callback is passed; change handleTabChange (and its dependencies) so it always
calls onTabChange if provided, and updates internalActiveTab only when
controlledActiveTab is undefined (e.g. if (!controlledActiveTab)
setInternalActiveTab(tab)); reference handleTabChange, internalActiveTab,
controlledActiveTab, onTabChange, and setInternalActiveTab when making the
change.
In `@ui/src/bichat/components/UserAvatar.tsx`:
- Around line 41-50: The palette in UserAvatar (the array of { bg, text }
objects) uses '#ffffff' for every entry which yields poor contrast on lighter
backgrounds (amber, lime, cyan, green); update those entries so their text color
is a dark value (e.g. '#000000' or a dark gray like '#111827') or implement a
small luminance check inside the UserAvatar component to pick dark vs light text
dynamically based on the bg value so initials are readable (adjust the objects
for bg '#22c55e', '#06b6d4', '#f59e0b', '#84cc16' (and any other light hues) to
use dark text, or add a helper used by the UserAvatar render logic to choose
'#ffffff' vs '#111827' by calculating background luminance).
🪄 Autofix (Beta)
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: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 08e452a7-4f63-43bf-aee1-0335c680b957
📒 Files selected for processing (5)
ui/src/bichat/components/AllChatsList.tsxui/src/bichat/components/Sidebar.tsxui/src/bichat/components/UserAvatar.tsxui/src/bichat/hooks/useBichatRouter.tsui/src/bichat/index.ts
| // Expanded state for user groups (tracks expanded owner IDs; collapsed by default) | ||
| const [expandedGroups, setExpandedGroups] = useState<Set<string>>(new Set()); | ||
|
|
||
| const toggleGroup = useCallback((ownerId: string) => { | ||
| setExpandedGroups((prev) => { | ||
| const next = new Set(prev); | ||
| if (next.has(ownerId)) { | ||
| next.delete(ownerId); | ||
| } else { | ||
| next.add(ownerId); | ||
| } | ||
| return next; | ||
| }); | ||
| }, []); |
There was a problem hiding this comment.
Reconcile group expansion with route/filter changes.
expandedGroups only changes on manual toggles right now. After a refresh on /all-chats/session/:id, the selected session can stay hidden inside a collapsed owner group, and clearing selectedUser reuses stale expansion state instead of returning to the default collapsed view. Please seed/reset this set when activeSessionId or selectedUser changes.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@ui/src/bichat/components/AllChatsList.tsx` around lines 143 - 156,
expandedGroups only updates on manual toggles and can become stale across
route/filter changes; add a useEffect that watches activeSessionId and
selectedUser and reseeds setExpandedGroups accordingly: when activeSessionId is
present, derive its ownerId (from the sessions/props state used in this
component) and call setExpandedGroups(new Set([ownerId])) so the owner group is
expanded to reveal the selected session, otherwise call setExpandedGroups(new
Set()) to return to the default collapsed view; keep toggleGroup unchanged.
…ol, contrast
- Auto-expand owner group when activeSessionId is present (deep-link fix)
- Localize "Unknown User" fallback with t('BiChat.Common.Untitled')
- Fix handleTabChange to work in both controlled and uncontrolled modes
- Use dark text on light avatar backgrounds for accessibility
Summary
activeTab/onTabChangeprops for URL-driven tab state/all-chatsURL prefix support,sidebarTab,onSidebarTabChangeActiveTabtypeTest plan
/all-chats, persists on refresh/all-chats/session/:id/activeTab/onTabChange(backward compat)Summary by CodeRabbit
Release Notes
New Features
Bug Fixes