vercel / vercel/streamdown

Host-integrated Mermaid download and fullscreen hooks

Open
#490 0 comments 1 reaction 0 assignees View on GitHub

Nobody has claimed this yet.

enhancement
Dominant language
TypeScript
Stars
5.6k
Forks
302
Avg merge
3d 19h
Merged PRs (30d)
14

Description

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
  • I am willing to help implement this feature
Additional Context

No response

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by locating the Mermaid controls configuration and the existing download and fullscreen handlers. Trace their payloads and default behavior, then add the optional callbacks so a handled result skips the corresponding default action while no callback preserves current behavior; verify the callback payloads and unchanged defaults with the relevant Mermaid tests.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
frontend
Issue type
Feature
Difficulty
3/5
Estimated time
1-2 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
65/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.