All guides

Diagrams and density

The TSX component library draws static figures. It packs a page of facts into a frame by default, and it renders larger when you are presenting.

Two engines, one package#

Films use the stage engine, which is vector animation from TypeScript functions. Figures use the component library, which lays out TSX elements and renders PNG, SVG, and GIF.

Use a figure when the reader studies the picture. Use a film when the change over time is the point.

npx vizmatic ./architecture.tsx --out ./figures --theme dark,light --format both

The component explorer shows every component with live controls, and the diagram builder arranges them on a canvas.

Titles are optional#

A scene takes a title and a subtitle, and both are optional. Leave them out when the surrounding page already names the figure, and add a title when the visual needs them.

A rich node#

Graph nodes can carry more than a title. A node can have key and value rows, metrics with small trend lines, tags, an owner, and a footer. A reader then gets the facts from the figure without a second document.

import { getThemeColors, GraphDiagram, Scene, type GraphDiagramEdge, type GraphDiagramNode, type ThemeMode } from 'vizmatic'

const nodes: GraphDiagramNode[] = [
    {
        id: 'api', label: 'Checkout API', detail: 'Go, 3 regions', icon: 'server', tone: 'blue', status: 'ok',
        rows: [{ key: 'replicas', value: '48' }, { key: 'deploy', value: 'blue/green' }],
        metrics: [{ label: 'p95', value: '184 ms' }, { label: 'errors', value: '0.02%' }],
    },
    { id: 'db', label: 'Orders', detail: 'Postgres 16', icon: 'database', tone: 'green' },
]
const edges: GraphDiagramEdge[] = [{ from: 'api', to: 'db', label: 'SQL, 2.1k/s' }]

export const width = 960
export const height = 420

export function create(theme: ThemeMode = 'dark') {
    const c = getThemeColors(theme)
    return (
        <Scene c={c} title="Checkout">
            <GraphDiagram c={c} nodes={nodes} edges={edges} width={900} height={320} />
        </Scene>
    )
}

Database schemas#

EntityRelationshipDiagram draws entity tables with attribute types, primary and foreign keys, uniqueness, nullability, and crow-foot endpoints. Each endpoint states how many records of that entity can match one record at the opposite end: one, zero-or-one, one-or-many, or zero-or-many.

import { EntityRelationshipDiagram, getThemeColors, type ThemeMode } from 'vizmatic'

export const width = 960
export const height = 420

export function create(theme: ThemeMode = 'dark') {
    return <EntityRelationshipDiagram c={getThemeColors(theme)} width={960} height={420}
        title="Customer orders"
        entities={[
            { id: 'customers', attributes: [
                { name: 'id', type: 'uuid', primaryKey: true },
                { name: 'email', type: 'text', unique: true },
            ] },
            { id: 'orders', attributes: [
                { name: 'id', type: 'uuid', primaryKey: true },
                { name: 'customer_id', type: 'uuid', foreignKey: true },
            ] },
        ]}
        relationships={[{
            id: 'customer-orders', label: 'places',
            from: { entity: 'customers', attribute: 'id', cardinality: 'one' },
            to: { entity: 'orders', attribute: 'customer_id', cardinality: 'zero-or-many' },
        }]} />
}

This relationship gives each order exactly one customer; a customer may have no orders or many orders. For guest orders, mark customer_id nullable and use zero-or-one at the customer endpoint. Mark each primary-key attribute for a composite key, and pass an ordered attribute array at each relationship endpoint to show a composite relationship. Set identifying when the parent key forms part of the child primary key; the relationship then uses a solid line.

The component checks duplicate names, endpoint references, composite arity, nullable primary keys, and canvas dimensions. Tables expand for long names instead of reducing text size. Exported SVGs retain an accessible schema summary, entity constraints, and relationship cardinalities. The checkout example includes guest orders and a composite line-item key.

Accessible chart exports#

Charts keep their titles and data summaries in exported SVGs. Use title to name the chart and description to explain its takeaway or context. The generated summary also retains category values, series, coordinates, or intervals. A labeled sparkline can provide the same metadata; an unlabeled sparkline stays decorative beside its surrounding metric.

Density#

Every component reads its type, spacing, strokes, and corner radius from one set of tokens. One source can render as a dense engineering figure or as a slide.

DensityUse
denseThe default. Small type at 10 to 12 px, hairlines, and tight gutters.
compactA little more air, for docs and dashboards.
comfortableThe sizes the components were first designed at.
presentationLarge type and strokes, for a room.
a numberA direct scale. 0.9 is slightly dense, and 1.25 is large.

Set it on a scene.

import { CalloutCard, getThemeColors, Scene, type ThemeMode } from 'vizmatic'

export function create(theme: ThemeMode = 'dark') {
    const c = getThemeColors(theme)
    return (
        <Scene c={c} title="Same content, larger" density="presentation">
            <CalloutCard c={c} title="Density is one prop" detail="Nothing else in the source changes." />
        </Scene>
    )
}

Or set it for a whole render.

import { renderToPng } from 'vizmatic'
import type { ReactElement } from 'react'

export async function renderBoth(figure: ReactElement): Promise<void> {
    await renderToPng(figure, { width: 1400, height: 800, outputPath: 'figure.png', density: 'dense' })
    await renderToPng(figure, { width: 1400, height: 800, outputPath: 'slide.png', density: 'presentation' })
}

Check before you publish#

vizmatic check reports overflow, contrast, small text, overlapping labels, and connector congestion. It works in both themes and can write JSON.

npx vizmatic check ./architecture.tsx --theme dark,light --json

Keep the source#

A figure is a TSX file. Keep it beside the document it illustrates, review it in a pull request, and render it in CI. Dark and light come from the same file.

Search

↑ ↓ to navigateEnter to openEsc to close
Editable TSX

Example source

Open in the builder

Open the builder to edit this scene, preview animations, and export your visual.

Example preview