Problem Statement
When Streamdown is embedded inside a desktop webview or an iframe sidebar panel, the Mermaid download and fullscreen actions are confined to the web context:
- Download is sandboxed to the browser/webview and cannot invoke host-native save dialogs or write files to user-selected locations.
- Fullscreen is limited to the iframe/panel container, not a true host-level expanded view.
This blocks good UX for desktop integrations where the host application needs to handle these actions natively.
Proposed Solution
Add optional callback hooks to the Mermaid controls configuration:
onMermaidDownload(payload) — called before the default download. Receives the generated Blob, suggested filename, mimeType, chart source, and config. If the callback returns { handled: true }, the default browser download is skipped.
onMermaidFullscreen(payload) — called before the default fullscreen. Receives chart source and config. If the callback returns { handled: true }, the default fullscreen behavior is skipped.
If no callbacks are provided, existing behavior is unchanged.
Alternatives Considered
- Custom renderer plugin: Using the existing
customRenderer API to replace the entire Mermaid block. This is too heavy-handed — it requires reimplementing the full Mermaid UI just to intercept two actions.
Use Case
import { Streamdown } from "streamdown";
<Streamdown
mermaid={{
config: { theme: "dark" },
onDownload: async ({ blob, filename, mimeType, chart, config }) => {
// Forward blob to desktop host via postMessage / bridge API
window.parent.postMessage(
{ type: "save-file", blob, filename, mimeType },
"*"
);
return { handled: true }; // skip default browser download
},
onFullscreen: ({ chart, config }) => {
// Ask host to open chart in a dedicated large window
window.parent.postMessage(
{ type: "open-fullscreen", chart, config },
"*"
);
return { handled: true }; // skip default in-panel fullscreen
},
}}
>
{markdown}
</Streamdown>;
Priority
Important
Contribution
Additional Context
No response
Problem Statement
When Streamdown is embedded inside a desktop webview or an iframe sidebar panel, the Mermaid download and fullscreen actions are confined to the web context:
This blocks good UX for desktop integrations where the host application needs to handle these actions natively.
Proposed Solution
Add optional callback hooks to the Mermaid controls configuration:
onMermaidDownload(payload)— called before the default download. Receives the generatedBlob, suggested filename, mimeType, chart source, and config. If the callback returns{ handled: true }, the default browser download is skipped.onMermaidFullscreen(payload)— called before the default fullscreen. Receives chart source and config. If the callback returns{ handled: true }, the default fullscreen behavior is skipped.If no callbacks are provided, existing behavior is unchanged.
Alternatives Considered
customRendererAPI to replace the entire Mermaid block. This is too heavy-handed — it requires reimplementing the full Mermaid UI just to intercept two actions.Use Case
Priority
Important
Contribution
Additional Context
No response