✨(sources) add source panel#480
Conversation
add sources panel
WalkthroughChat sources are refactored from inline message rendering to a right-side panel using React portals. A preferences store manages panel visibility, context-based anchor propagation enables portal rendering, and layout adjustments accommodate the new sidebar. Message action buttons now use dedicated SVG icons. ChangesSources Panel Refactor
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Suggested labels
Suggested reviewers
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
⚔️ Resolve merge conflicts
Warning There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure. 🔧 ESLint
ESLint skipped: no ESLint configuration detected in root package.json. To enable, add 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: 3
🤖 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
`@src/frontend/apps/conversations/src/features/chat/components/MessageItem.tsx`:
- Around line 457-461: The toggle button currently shows a state label
("Hidden") instead of an action; update the JSX in MessageItem (the expression
using isSourceOpen, message.id and sourceParts) so when the panel is open
(isSourceOpen === message.id) it renders the imperative label t('Hide') instead
of t('Hidden'), and when closed it remains t('Show'); keep the count and
pluralization logic (sourceParts.length and t('source'/'sources')) unchanged.
In
`@src/frontend/apps/conversations/src/features/chat/stores/useChatPreferencesStore.ts`:
- Around line 51-57: The partialize function in useChatPreferencesStore
currently omits isSourcesPanelOpen so that preference isn't persisted; update
the partialize return to include isSourcesPanelOpen alongside
themeModePreference, selectedModelHrid, forceWebSearch, isDarkModePreference,
and isPanelOpen so the sources panel open/closed state is stored and restored
across reloads.
In `@src/frontend/apps/conversations/src/layouts/MainLayout.tsx`:
- Around line 86-90: The closed-panel right offset uses a hardcoded '-300px'
while the panel width constant is SOURCES_PANEL_WIDTH_PX (360); update the
ternary in the styled/template string that uses isSourcesPanelOpen so the closed
position uses `-${SOURCES_PANEL_WIDTH_PX}px` instead of '-300px' (i.e., replace
the hardcoded value with the SOURCES_PANEL_WIDTH_PX-based expression) to ensure
the slide distance matches the panel width.
🪄 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: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: 1855b4c3-9f37-4e25-8775-858f8cf95ec3
⛔ Files ignored due to path filters (5)
src/frontend/apps/conversations/src/assets/icons/uikit-custom/book-filled.svgis excluded by!**/*.svgsrc/frontend/apps/conversations/src/assets/icons/uikit-custom/book.svgis excluded by!**/*.svgsrc/frontend/apps/conversations/src/assets/icons/uikit-custom/checkmark.svgis excluded by!**/*.svgsrc/frontend/apps/conversations/src/assets/icons/uikit-custom/clipboard.svgis excluded by!**/*.svgsrc/frontend/apps/conversations/src/assets/icons/uikit-custom/sources.svgis excluded by!**/*.svg
📒 Files selected for processing (10)
CHANGELOG.mdsrc/frontend/apps/conversations/src/features/chat/components/Chat.tsxsrc/frontend/apps/conversations/src/features/chat/components/MessageItem.tsxsrc/frontend/apps/conversations/src/features/chat/components/SourceItem.tsxsrc/frontend/apps/conversations/src/features/chat/components/SourceItemList.tsxsrc/frontend/apps/conversations/src/features/chat/stores/useChatPreferencesStore.tssrc/frontend/apps/conversations/src/features/sources-panel/SourcePanel.tsxsrc/frontend/apps/conversations/src/features/sources-panel/index.tssrc/frontend/apps/conversations/src/layouts/MainLayout.tsxsrc/frontend/apps/conversations/src/pages/globals.css
| {isSourceOpen !== message.id ? t('Show') : t('Hidden')}{' '} | ||
| {isSourceOpen !== message.id | ||
| ? `${sourceParts.length} ` | ||
| : ''} | ||
| {sourceParts.length !== 1 ? t('sources') : t('source')} |
There was a problem hiding this comment.
Use an action label instead of state text for the toggle button.
On Line 457, Hidden reads like a status, not a button action. Prefer an imperative label (Hide) when the panel is open.
🧰 Tools
🪛 GitHub Check: SonarCloud Code Analysis
[warning] 458-458: Unexpected negated condition.
[warning] 457-457: Unexpected negated condition.
🤖 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 `@src/frontend/apps/conversations/src/features/chat/components/MessageItem.tsx`
around lines 457 - 461, The toggle button currently shows a state label
("Hidden") instead of an action; update the JSX in MessageItem (the expression
using isSourceOpen, message.id and sourceParts) so when the panel is open
(isSourceOpen === message.id) it renders the imperative label t('Hide') instead
of t('Hidden'), and when closed it remains t('Show'); keep the count and
pluralization logic (sourceParts.length and t('source'/'sources')) unchanged.
| partialize: (state) => ({ | ||
| themeModePreference: state.themeModePreference, | ||
| selectedModelHrid: state.selectedModelHrid, | ||
| forceWebSearch: state.forceWebSearch, | ||
| isDarkModePreference: state.isDarkModePreference, | ||
| isPanelOpen: state.isPanelOpen, | ||
| }), |
There was a problem hiding this comment.
Persist isSourcesPanelOpen in chat preferences.
On Line 51, partialize excludes isSourcesPanelOpen, so this preference resets after reload while other panel preferences are restored.
Proposed fix
partialize: (state) => ({
themeModePreference: state.themeModePreference,
selectedModelHrid: state.selectedModelHrid,
forceWebSearch: state.forceWebSearch,
isDarkModePreference: state.isDarkModePreference,
isPanelOpen: state.isPanelOpen,
+ isSourcesPanelOpen: state.isSourcesPanelOpen,
}),📝 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.
| partialize: (state) => ({ | |
| themeModePreference: state.themeModePreference, | |
| selectedModelHrid: state.selectedModelHrid, | |
| forceWebSearch: state.forceWebSearch, | |
| isDarkModePreference: state.isDarkModePreference, | |
| isPanelOpen: state.isPanelOpen, | |
| }), | |
| partialize: (state) => ({ | |
| themeModePreference: state.themeModePreference, | |
| selectedModelHrid: state.selectedModelHrid, | |
| forceWebSearch: state.forceWebSearch, | |
| isDarkModePreference: state.isDarkModePreference, | |
| isPanelOpen: state.isPanelOpen, | |
| isSourcesPanelOpen: state.isSourcesPanelOpen, | |
| }), |
🤖 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
`@src/frontend/apps/conversations/src/features/chat/stores/useChatPreferencesStore.ts`
around lines 51 - 57, The partialize function in useChatPreferencesStore
currently omits isSourcesPanelOpen so that preference isn't persisted; update
the partialize return to include isSourcesPanelOpen alongside
themeModePreference, selectedModelHrid, forceWebSearch, isDarkModePreference,
and isPanelOpen so the sources panel open/closed state is stored and restored
across reloads.
| right: ${isSourcesPanelOpen ? '0px' : '-300px'}; | ||
| bottom: 0; | ||
| z-index: 1001; | ||
| width: ${SOURCES_PANEL_WIDTH_PX}px; | ||
| ` |
There was a problem hiding this comment.
Use the same offset constant for closed panel position.
On Line 86, the closed position uses -300px while the panel width is 360px. This creates an inconsistent slide distance.
Proposed fix
- right: ${isSourcesPanelOpen ? '0px' : '-300px'};
+ right: ${isSourcesPanelOpen
+ ? '0px'
+ : `-${SOURCES_PANEL_WIDTH_PX}px`};📝 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.
| right: ${isSourcesPanelOpen ? '0px' : '-300px'}; | |
| bottom: 0; | |
| z-index: 1001; | |
| width: ${SOURCES_PANEL_WIDTH_PX}px; | |
| ` | |
| right: ${isSourcesPanelOpen | |
| ? '0px' | |
| : `-${SOURCES_PANEL_WIDTH_PX}px`}; | |
| bottom: 0; | |
| z-index: 1001; | |
| width: ${SOURCES_PANEL_WIDTH_PX}px; | |
| ` |
🧰 Tools
🪛 GitHub Check: SonarCloud Code Analysis
[warning] 86-86: Extract this nested ternary operation into an independent statement.
🤖 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 `@src/frontend/apps/conversations/src/layouts/MainLayout.tsx` around lines 86 -
90, The closed-panel right offset uses a hardcoded '-300px' while the panel
width constant is SOURCES_PANEL_WIDTH_PX (360); update the ternary in the
styled/template string that uses isSourcesPanelOpen so the closed position uses
`-${SOURCES_PANEL_WIDTH_PX}px` instead of '-300px' (i.e., replace the hardcoded
value with the SOURCES_PANEL_WIDTH_PX-based expression) to ensure the slide
distance matches the panel width.



add sources panel
Summary by CodeRabbit
New Features
Documentation