feat(platform): mount canvas provider and render canvas pane#1385
Conversation
📝 WalkthroughWalkthroughThe PR adds a Canvas feature to the chat interface for previewing and editing generated code outputs. It introduces a Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes The changes span multiple files with moderate complexity: test files introduce mocking patterns and accessibility checks; source modifications add canvas type resolution logic and UI integration across the route and component layers; i18n updates are straightforward JSON additions. The interconnected nature of the changes (provider setup, button integration, pane rendering, type mapping) requires understanding how the pieces fit together, though individual logic units remain relatively straightforward. Possibly related PRs
🚥 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)
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.
Your free trial has ended. If you'd like to continue receiving code reviews, you can add a payment method here.
Wire up the existing canvas components into the chat UI: - Mount CanvasProvider in the chat layout above ChatLayoutContent - Render CanvasPane as a sibling to the chat interface via lazyComponent - Add "Open in Canvas" button to code blocks using useCanvasOptional - Detect content type from language (html/svg/mermaid/markdown/code) - Add missing en.json keys: copied, mermaidError, resizeHandle - Add full canvas translation block to de.json and de-CH.json overrides - Add tests for code block canvas button and canvas pane visibility Closes #1212
The mermaid package was dynamically imported in canvas-mermaid-renderer but missing from package.json, causing the Vite build to fail.
29ac969 to
18db44b
Compare
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
services/platform/app/routes/dashboard/$id/chat.tsx (1)
188-211:⚠️ Potential issue | 🟠 Major"Open in Canvas" button appears in shared chat view but the pane is not mounted.
SharedChatView is wrapped by CanvasProvider (at ChatLayout level, line 268), and CodeBlock uses
useCanvasOptional()to conditionally render the "Open in Canvas" button. Since CanvasProvider always creates a non-null context, the button will appear in shared messages. However, CanvasPane is only mounted in the non-shared branch (line 256), so clicking the button updates canvas state with no visible effect.Either mount
<CanvasPane />in the shared branch (lines 188–211) or scopeCanvasProviderto non-shared paths only.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@services/platform/app/routes/dashboard/`$id/chat.tsx around lines 188 - 211, The shared chat branch renders SharedChatView while CanvasPane is only mounted in the non-shared branch, so CodeBlock's useCanvasOptional/CanvasProvider causes an "Open in Canvas" button that does nothing; fix by either mounting <CanvasPane /> alongside <SharedChatView /> in the shared branch (so canvas UI is present when shareToken exists) or move/scope CanvasProvider out of ChatLayout so it's only provided for non-shared paths—update the code around SharedChatView/CanvasPane/CanvasProvider (and ensure CodeBlock/useCanvasOptional behavior remains consistent) to make the button operate against a mounted CanvasPane.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In
`@services/platform/app/features/chat/components/message-bubble/__tests__/code-block.test.tsx`:
- Around line 185-231: Replace the no-op assertions in the three tests that
click the "Open in Canvas" button by spying/mocking the openCanvas function
provided by the WithCanvas test provider (or the canvas context used by
CodeBlock) and assert it was called once with the correct payload/type for each
language case: for CodeBlock lang="html" expect openCanvas called with type
"html" (and the HTML code/content), for lang="mermaid" expect type "mermaid"
(and the mermaid source), and for other languages (e.g., "python") expect type
"code" (and the code content); update the tests referencing CodeBlock,
WithCanvas and the "Open in Canvas" button to verify the exact openCanvas call
arguments instead of only checking button presence.
---
Outside diff comments:
In `@services/platform/app/routes/dashboard/`$id/chat.tsx:
- Around line 188-211: The shared chat branch renders SharedChatView while
CanvasPane is only mounted in the non-shared branch, so CodeBlock's
useCanvasOptional/CanvasProvider causes an "Open in Canvas" button that does
nothing; fix by either mounting <CanvasPane /> alongside <SharedChatView /> in
the shared branch (so canvas UI is present when shareToken exists) or move/scope
CanvasProvider out of ChatLayout so it's only provided for non-shared
paths—update the code around SharedChatView/CanvasPane/CanvasProvider (and
ensure CodeBlock/useCanvasOptional behavior remains consistent) to make the
button operate against a mounted CanvasPane.
🪄 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: ASSERTIVE
Plan: Pro
Run ID: 9b443287-cb23-46f1-8adb-31c25a650880
⛔ Files ignored due to path filters (1)
bun.lockis excluded by!**/*.lock
📒 Files selected for processing (8)
services/platform/app/features/chat/components/canvas/__tests__/canvas-pane.test.tsxservices/platform/app/features/chat/components/message-bubble/__tests__/code-block.test.tsxservices/platform/app/features/chat/components/message-bubble/code-block.tsxservices/platform/app/routes/dashboard/$id/chat.tsxservices/platform/messages/de-CH.jsonservices/platform/messages/de.jsonservices/platform/messages/en.jsonservices/platform/package.json
| it('calls openCanvas with type "html" for html language', async () => { | ||
| const user = userEvent.setup(); | ||
| render( | ||
| <WithCanvas> | ||
| <CodeBlock lang="html"> | ||
| <code>{'<div>Hello</div>'}</code> | ||
| </CodeBlock> | ||
| </WithCanvas>, | ||
| ); | ||
|
|
||
| const button = screen.getByRole('button', { name: 'Open in Canvas' }); | ||
| await user.click(button); | ||
|
|
||
| // The canvas should now be open — verify by checking that the context updated | ||
| // (CanvasPane would render, but we don't render it here; we trust the context call) | ||
| expect(button).toBeInTheDocument(); | ||
| }); | ||
|
|
||
| it('calls openCanvas with type "mermaid" for mermaid language', async () => { | ||
| const user = userEvent.setup(); | ||
| render( | ||
| <WithCanvas> | ||
| <CodeBlock lang="mermaid"> | ||
| <code>graph TD; A-->B;</code> | ||
| </CodeBlock> | ||
| </WithCanvas>, | ||
| ); | ||
|
|
||
| const button = screen.getByRole('button', { name: 'Open in Canvas' }); | ||
| await user.click(button); | ||
| expect(button).toBeInTheDocument(); | ||
| }); | ||
|
|
||
| it('calls openCanvas with type "code" for other languages', async () => { | ||
| const user = userEvent.setup(); | ||
| render( | ||
| <WithCanvas> | ||
| <CodeBlock lang="python"> | ||
| <code>print("hello")</code> | ||
| </CodeBlock> | ||
| </WithCanvas>, | ||
| ); | ||
|
|
||
| const button = screen.getByRole('button', { name: 'Open in Canvas' }); | ||
| await user.click(button); | ||
| expect(button).toBeInTheDocument(); | ||
| }); |
There was a problem hiding this comment.
“calls openCanvas …” tests don’t currently assert the call contract.
These cases only click and re-check button presence, so they won’t catch regressions in language→canvas type mapping or openCanvas arguments.
As per coding guidelines, “ALWAYS write tests for new features and bug fixes” and cover behavior meaningfully (happy paths/edge cases/error conditions).
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In
`@services/platform/app/features/chat/components/message-bubble/__tests__/code-block.test.tsx`
around lines 185 - 231, Replace the no-op assertions in the three tests that
click the "Open in Canvas" button by spying/mocking the openCanvas function
provided by the WithCanvas test provider (or the canvas context used by
CodeBlock) and assert it was called once with the correct payload/type for each
language case: for CodeBlock lang="html" expect openCanvas called with type
"html" (and the HTML code/content), for lang="mermaid" expect type "mermaid"
(and the mermaid source), and for other languages (e.g., "python") expect type
"code" (and the code content); update the tests referencing CodeBlock,
WithCanvas and the "Open in Canvas" button to verify the exact openCanvas call
arguments instead of only checking button presence.
- Add INLINE OUTPUT PREFERENCE instruction to create_agent_config when file generation tools are available, guiding LLMs to output content as fenced code blocks (HTML, Mermaid, SVG, Markdown) rendered by the Canvas preview pane instead of generating downloadable files - Update pptx tool description to direct LLMs to output HTML slide decks inline; only call generate when user explicitly asks to export - Simplify chat-agent and file-assistant system instructions by removing tool-specific details already covered by tool descriptions - Fix code block overflow: remove redundant max-w on <pre>, add min-w-0 to assistant message bubble to prevent flex child overflow
Summary
CanvasProviderin the chat layout so canvas context is available to all chat componentsCanvasPane(vialazyComponent) as a sibling to the chat interface, appearing to the right when openeduseCanvasOptional()so the button only appears whenCanvasProvideris in the tree, keeping code blocks reusable outside chatcopied,mermaidError,resizeHandle) toen.jsonde.jsonand Swiss German overrides tode-CH.jsonTest plan
CanvasProvideris presentCanvasProviderCloses #1212
Summary by CodeRabbit