Diagrams
DiagramExportMenu
Taking the figure off the page: PNG, JPEG, WebP, SVG and a 1200×630 share card.
Ships from@misoto22/design/diagrams
When to reach for it
Examples
default
2 elements and 1 relationships.
- CloudFront (cloud) — CDN
- API (backend) — FastAPI
- CloudFront → API: HTTPS
Notes
Taking the figure off the page: five files, one menu.
WHY THE MENU DOES THE WORK rather than handing back a format: every one of these exports is the same six steps — find the <svg>, walk it with getComputedStyle to bake the custom properties into real colours, serialise, rasterise, name the file, hand it to the browser — and only the last two differ between them. A menu that emitted 'png' and left the caller to do the rest would be a menu that every consumer reimplements, badly, and the interesting half (a serialised SVG resolves var(--ink) to nothing and comes out invisible) is exactly the half a caller would not know to write.
onExport is still there for a page with its own pipeline — a server-side renderer, a different frame size — and taking it turns everything below into a no-op.
What each format actually is, stated rather than implied.
SVG is the artwork with resolved colours. It is editable and it is the only lossless one, but it carries no web fonts: a machine without the family renders it in a fallback, so type metrics will differ.
PNG, JPEG and WebP are the browser's own rasteriser re-drawing that SVG at 2×. Not a screenshot — antialiasing and any effect a page stylesheet applied from OUTSIDE the <svg> are not in it. JPEG has no alpha, so it is flattened onto the resolved paper colour rather than onto black, which is what a transparent PNG becomes when a format with no transparency is asked to hold it.
The share card is a 1200 × 630 frame with the title on it and the whole diagram letterboxed inside — never cropped. A card that cropped to fill the frame would be a picture of a different diagram.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
| targetRefrequired | RefObject<HTMLElement | SVGSVGElement | null> | The `<svg>` to export, or an element containing exactly one. A ref rather than a selector, because a page can hold several figures and a selector would export whichever the document happened to reach first. | |
| titlerequired | string | Names the file, and is printed on the share card. | |
| className | string | — | |
| onExport | (format: ExportFormat) => void | Promise<void> | Runs instead of the built-in export — for a caller with its own pipeline. | |
| onResult | (result: ExportResult) => void | Told what happened, so a page can raise a toast. | |
| trigger | ReactNode | Replaces the trigger. |
Parts
Composed at the call site rather than configured through props, so a layout this component did not anticipate is still expressible.
exportFigure
One figure, one format, one file.
Exported so a page can wire a keyboard shortcut or its own button to exactly what the menu does, without reimplementing the six steps.
Takes no props of its own.
Types
export type ExportFormat = 'png' | 'jpeg' | 'webp' | 'svg' | 'share-card'Accessibility
- A failed export is reported through onResult rather than swallowed: a click that quietly does nothing is indistinguishable from a broken button.