Skip to content

feat(platform): mount canvas provider and render canvas pane#1385

Merged
larryro merged 3 commits into
mainfrom
feat/issue-1212-canvas-preview
Apr 11, 2026
Merged

feat(platform): mount canvas provider and render canvas pane#1385
larryro merged 3 commits into
mainfrom
feat/issue-1212-canvas-preview

Conversation

@yannickmonney
Copy link
Copy Markdown
Contributor

@yannickmonney yannickmonney commented Apr 11, 2026

Summary

  • Mounts CanvasProvider in the chat layout so canvas context is available to all chat components
  • Renders CanvasPane (via lazyComponent) as a sibling to the chat interface, appearing to the right when opened
  • Adds an "Open in Canvas" button to code blocks that detects content type (html/svg/mermaid/markdown/code) and opens the canvas pane
  • Uses useCanvasOptional() so the button only appears when CanvasProvider is in the tree, keeping code blocks reusable outside chat
  • Adds missing translation keys (copied, mermaidError, resizeHandle) to en.json
  • Adds full canvas translation block to de.json and Swiss German overrides to de-CH.json

Test plan

  • Tests verify "Open in Canvas" button renders only when CanvasProvider is present
  • Tests verify "Open in Canvas" button does not render when outside CanvasProvider
  • Tests verify canvas pane renders when opened and hides when closed
  • Tests verify toolbar buttons (copy, download, edit, close) and resize handle accessibility
  • Accessibility audits pass (axe) for code blocks with/without canvas and for canvas pane open/closed states
  • All 1868 client tests and 1955 server tests pass
  • Lint and typecheck pass

Closes #1212

Summary by CodeRabbit

  • New Features
    • Added a canvas panel for previewing and editing HTML, SVG, Mermaid, and Markdown code.
    • "Open in Canvas" button on code blocks enables quick preview of supported content types.
    • Canvas panel includes copy, download, and edit options with resizable interface.
    • Added Mermaid diagram rendering support.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 11, 2026

📝 Walkthrough

Walkthrough

The PR adds a Canvas feature to the chat interface for previewing and editing generated code outputs. It introduces a CanvasPane component with a resizable pane, toolbar buttons (copy, download, edit), and a resize handle. Code blocks now include an "Open in Canvas" button that maps language types (html, svg, mermaid, markdown) to canvas content types. The chat route is wrapped with CanvasProvider and includes a lazy-loaded CanvasPane component. Two new test files provide comprehensive coverage with accessibility audits. Translation keys are added for German and English languages. The mermaid dependency is added to package.json for diagram rendering support.

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)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main changes: mounting CanvasProvider and rendering CanvasPane in the chat layout.
Linked Issues check ✅ Passed All requirements from issue #1212 are met: canvas interface is implemented, integrated into chat UI, and uses optional hooks for reusability.
Out of Scope Changes check ✅ Passed All changes are directly scoped to implementing the canvas feature: provider mounting, pane rendering, button integration, translations, tests, and the mermaid dependency.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/issue-1212-canvas-preview

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@greptile-apps greptile-apps Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.
@larryro larryro force-pushed the feat/issue-1212-canvas-preview branch from 29ac969 to 18db44b Compare April 11, 2026 07:28
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 scope CanvasProvider to 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

📥 Commits

Reviewing files that changed from the base of the PR and between 2d1eeae and 18db44b.

⛔ Files ignored due to path filters (1)
  • bun.lock is excluded by !**/*.lock
📒 Files selected for processing (8)
  • services/platform/app/features/chat/components/canvas/__tests__/canvas-pane.test.tsx
  • services/platform/app/features/chat/components/message-bubble/__tests__/code-block.test.tsx
  • services/platform/app/features/chat/components/message-bubble/code-block.tsx
  • services/platform/app/routes/dashboard/$id/chat.tsx
  • services/platform/messages/de-CH.json
  • services/platform/messages/de.json
  • services/platform/messages/en.json
  • services/platform/package.json

Comment on lines +185 to +231
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--&gt;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();
});
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

“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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Preview/Canvas editing interface not present

2 participants