feat(chat): add progress bar renderer for markdown code blocks#836
feat(chat): add progress bar renderer for markdown code blocks#836
Conversation
Add custom renderer for progress code blocks in chat messages. Users can now display progress bars using YAML-style syntax: ```progress value: 50 max: 100 description: Loading... color: success ``` Supports: - Determinate progress (LinearProgress) when value is provided - Indeterminate spinner (CircularProgress) when value is omitted - Customizable colors (primary, secondary, success, error, warning, info) - Display of value/max and percentage Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Document chat's markdown rendering capabilities (formatting, LaTeX, code blocks) - Add progress bar code block syntax documentation with parameters - Add test_chat_progress screenshot test for progress bar examples - Add light/dark mode screenshots for progress bar feature Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
📝 WalkthroughWalkthroughThe PR introduces progress indicator rendering support to the chat window. A new ProgressRenderer component parses and displays visual progress bars from Markdown code blocks labeled with the "progress" language identifier. Supporting types, utilities, documentation, and test coverage are added to enable this functionality across the chat interface. Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Poem
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
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: 1
🤖 Fix all issues with AI agents
In @app/src/components/ChatWindow.tsx:
- Around line 131-134: The percentage calculation in ChatWindow.tsx can divide
by zero when config.max === config.min; update the computation of percentage
(the const percentage using config.value, config.min, config.max) to first
compute the denominator and only calculate ((config.value - config.min) / denom)
* 100 when denom > 0, otherwise set percentage to null (or a safe fallback like
0) so NaN/Infinity cannot propagate into the later Math.min/Math.max clamping on
line 148.
🧹 Nitpick comments (1)
app/src/components/ChatWindow.tsx (1)
526-561: Consider extracting the duplicated code block rendering logic.The
codecomponent handler is duplicated nearly identically between fullscreen mode (lines 526-561) and normal mode (lines 801-836). This could be extracted to a shared function or custom component to improve maintainability.♻️ Example extraction
// Define outside ChatWindow component const createCodeComponent = (mode: "light" | "dark") => { return ({ node, className, children, ...props }: any) => { const match = /language-(\w+)/.exec(className || ""); const language = match?.[1]; const content = String(children).replace(/\n$/, ""); if (language === "progress") { return <ProgressRenderer content={content} />; } return match ? ( <SyntaxHighlighter style={mode === "dark" ? oneDark : oneLight} language={language} PreTag="div" {...props} > {content} </SyntaxHighlighter> ) : ( <code className={className} {...props}> {children} </code> ); }; };Also applies to: 801-836
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (2)
docs/source/_static/screenshots/darkmode/chat_progress.pngis excluded by!**/*.pngdocs/source/_static/screenshots/lightmode/chat_progress.pngis excluded by!**/*.png
📒 Files selected for processing (3)
app/src/components/ChatWindow.tsxdocs/source/python-api.rstmisc/test_screenshots.py
🧰 Additional context used
📓 Path-based instructions (2)
**/*.py
📄 CodeRabbit inference engine (AGENTS.md)
**/*.py: You MUST NEVER@pytest.mark.xfailor similar - all tests must pass!
All default values (e.g.,camera,particles) must be defined exclusively within the Pydantic model. Do not scatter fallback logic throughout the codebase.
Do not perform null checks combined with hardcoded literals for default values. Rely entirely on the schema to populate default values during initialization.
You can not use LUA scripts with Redis!
If sensible, implement collections.abc interfaces for your classes, such as MutableMapping or MutableSequence.
Use numpy style docstrings in Python code.
Docstrings must be concise and to the point.
Use type hints wherever possible in Python. Uselist[int|float] | Noneinstead oft.Optional[t.List[int|float]]!
Imports should always be at the top of the file in Python.
Files:
misc/test_screenshots.py
**/test_*.py
📄 CodeRabbit inference engine (AGENTS.md)
When designing new tests, read the old tests first to understand the existing patterns. Use
pytest.mark.parametrizeto avoid code duplication. Tests should be very specific and test only one thing. Avoid complex test setups. Each test must be a function, not a method of a class!
Files:
misc/test_screenshots.py
🧬 Code graph analysis (1)
misc/test_screenshots.py (2)
tests/conftest.py (1)
server(419-425)misc/conftest.py (7)
server(41-69)page(73-87)capture(91-120)bmim_bf4(124-132)light(102-107)toggle(116-118)dark(109-114)
⏰ 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). (3)
- GitHub Check: pytest (3.13, ubuntu-latest)
- GitHub Check: pytest (3.11, ubuntu-latest)
- GitHub Check: pytest (3.12, ubuntu-latest)
🔇 Additional comments (5)
docs/source/python-api.rst (1)
517-579: Documentation is well-structured and comprehensive.The new sections clearly document the Markdown rendering capabilities and progress bar syntax. The parameters (value, min, max, description, color) match the TypeScript implementation, and the example code is syntactically correct. The cross-reference to
progress_trackerfor real-time updates is a helpful addition.misc/test_screenshots.py (1)
764-797: Test follows established patterns and provides good coverage.The test correctly demonstrates both determinate (with
value: 75) and indeterminate (withoutvalue) progress bars. It follows the same structure as other screenshot tests in the file, using the standard fixtures and light/dark mode capture pattern.app/src/components/ChatWindow.tsx (3)
58-72: Type definitions are well-structured.The
ProgressColortype correctly maps to MUI's supported color variants, andProgressConfigproperly models the expected configuration with optionalvaluefor indeterminate progress support.
74-126: Parsing logic is robust and handles edge cases well.The function correctly uses
indexOf(':')instead ofsplit(':')to handle colons in description values. Number validation withNumber.isNaNand color validation against a whitelist are properly implemented. Case-insensitive key matching (toLowerCase()) is a good UX choice.
136-175: ProgressRenderer component implementation looks good.The component correctly handles both determinate (with value) and indeterminate (without value) progress states. The UI layout is clean with proper accessibility via semantic Typography components and appropriate color contrasts.
| const percentage = | ||
| config.value !== undefined | ||
| ? ((config.value - config.min) / (config.max - config.min)) * 100 | ||
| : null; |
There was a problem hiding this comment.
Potential division by zero when max === min.
If a user specifies max: 50 and min: 50, the percentage calculation will divide by zero, resulting in Infinity or NaN. While Math.min/Math.max clamping on line 148 handles Infinity, NaN would still propagate.
🔧 Suggested fix
const percentage =
config.value !== undefined
- ? ((config.value - config.min) / (config.max - config.min)) * 100
+ ? config.max !== config.min
+ ? ((config.value - config.min) / (config.max - config.min)) * 100
+ : 100
: null;📝 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.
| const percentage = | |
| config.value !== undefined | |
| ? ((config.value - config.min) / (config.max - config.min)) * 100 | |
| : null; | |
| const percentage = | |
| config.value !== undefined | |
| ? config.max !== config.min | |
| ? ((config.value - config.min) / (config.max - config.min)) * 100 | |
| : 100 | |
| : null; |
🤖 Prompt for AI Agents
In @app/src/components/ChatWindow.tsx around lines 131 - 134, The percentage
calculation in ChatWindow.tsx can divide by zero when config.max === config.min;
update the computation of percentage (the const percentage using config.value,
config.min, config.max) to first compute the denominator and only calculate
((config.value - config.min) / denom) * 100 when denom > 0, otherwise set
percentage to null (or a safe fallback like 0) so NaN/Infinity cannot propagate
into the later Math.min/Math.max clamping on line 148.
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #836 +/- ##
==========================================
+ Coverage 79.92% 79.93% +0.01%
==========================================
Files 161 161
Lines 19745 19745
==========================================
+ Hits 15781 15783 +2
+ Misses 3964 3962 -2 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
Add custom renderer for progress code blocks in chat messages. Users can now display progress bars using YAML-style syntax:
Supports:
Summary by CodeRabbit
New Features
Documentation
Tests
✏️ Tip: You can customize this high-level summary in your review settings.