@moritzbrantner/diagrams - v0.1.1
    Preparing search index...

    @moritzbrantner/diagrams - v0.1.1

    @moritzbrantner/diagrams

    CI Pages npm version License: MIT

    Diagram primitives for React 19 applications. This package is for authored structural diagrams, UML diagrams, process and Gantt-style flows, org structures, relationship maps, dependency graphs, and other graph-based visualizations.

    Use @moritzbrantner/charts for line, bar, area, donut, histogram, sparkline, Recharts wrappers, density-aware data visualizations, analytical chart controls, and chart data processing.

    bun add @moritzbrantner/diagrams @moritzbrantner/ui react react-dom
    

    Import the shared UI stylesheet once in your app:

    import "@moritzbrantner/ui/atlas/styles.css";
    

    The package is published to public npm.

    Dependency Supported range Notes
    React ^19.0.0 Required for exported React diagram primitives.
    React DOM ^19.0.0 Required for examples and React rendering.
    @moritzbrantner/ui ^1.0.0 Provides the shared Atlas stylesheet and design tokens.
    TypeScript Repository compiler version Public types are checked from the generated package.

    The package is pre-1.0. Public APIs may change, but intentional changes are tracked through Changesets, changelog entries, and the committed API report in etc/diagrams.api.md. Breaking changes should include migration notes.

    Diagram components use the shared Atlas token classes from @moritzbrantner/ui. Import the stylesheet once in the consuming app before rendering diagrams:

    import "@moritzbrantner/ui/atlas/styles.css";
    

    The package does not inject global styles at runtime. If the stylesheet is omitted, diagrams still render structurally, but colors, spacing, borders, focus rings, and dark-mode tokens are not guaranteed to match the documented examples.

    Use case Component
    Service maps, boundaries, queues, data stores ArchitectureDiagram
    Branching decisions and outcomes DecisionTree
    Package, module, team, or service dependency DependencyGraph
    Tables, fields, keys, cardinality EntityRelationshipDiagram
    Scheduled work across dates GanttChart
    Phased user/customer journeys JourneyMap
    Radial or tree-like idea decomposition MindMap
    Hierarchical teams or ownership OrgChart
    Linear workflow status ProcessMap
    Stakeholder, ownership, risk, or control maps RelationshipMap
    Ordered participant interactions SequenceDiagram
    States, transitions, guards, terminal states StateMachineDiagram
    Work grouped by team, role, or system SwimlaneDiagram
    Milestones and events over time TimelineDiagram
    UML class, state, or general node-edge views UmlDiagram, UmlClassDiagram

    Choose the most specific component first. Use RelationshipMap, DependencyGraph, or UmlDiagram when the domain is genuinely a node-edge graph and none of the stricter structures fit.

    SVG-backed graph diagrams share optional interactive canvas props from DiagramInteractiveProps. Set interactiveFeatures to true for the full bundle, or pass an object to choose features:

    • viewport enables pan, wheel zoom, fit, reset, and controlled viewport callbacks.
    • pathHighlight highlights neighbors, incoming paths, outgoing paths, or connected paths.
    • search adds diagram search and focuses matching nodes or edges.
    • edgeInspector exposes hover/focus tooltips and click-open edge details.
    • controls controls whether the floating toolbar is automatic, always visible, or hidden.
    import * as React from "react";
    import {
    RelationshipMap,
    type DiagramElementRef,
    type DiagramViewport,
    } from "@moritzbrantner/diagrams";

    export function InteractiveServiceMap() {
    const [viewport, setViewport] = React.useState<DiagramViewport>();
    const [highlightedElement, setHighlightedElement] = React.useState<DiagramElementRef | null>(
    null,
    );
    const [searchQuery, setSearchQuery] = React.useState("");
    const [inspectedEdgeId, setInspectedEdgeId] = React.useState<string | null>(null);

    return (
    <RelationshipMap
    ariaLabel="Interactive service relationship map"
    interactiveFeatures={{
    controls: "always",
    edgeInspector: true,
    pathHighlight: { mode: "neighbors" },
    search: true,
    viewport: true,
    }}
    viewport={viewport}
    onViewportChange={setViewport}
    highlightedElement={highlightedElement}
    onHighlightedElementChange={setHighlightedElement}
    searchQuery={searchQuery}
    onSearchQueryChange={setSearchQuery}
    inspectedEdgeId={inspectedEdgeId}
    onInspectedEdgeIdChange={setInspectedEdgeId}
    renderEdgeInspector={(context) => (
    <div className="grid gap-1">
    <strong>{context.label ?? context.edgeId}</strong>
    <span>
    {context.sourceId} to {context.targetId}
    </span>
    </div>
    )}
    nodes={[
    { id: "web", label: "Web", x: 0, y: 0 },
    { id: "api", label: "API", x: 280, y: 0 },
    { id: "db", label: "Database", x: 560, y: 0 },
    ]}
    edges={[
    { id: "web-api", source: "web", target: "api", label: "requests" },
    { id: "api-db", source: "api", target: "db", label: "reads" },
    ]}
    />
    );
    }

    Run the local example page for experimentation:

    bun run dev
    

    Build the same page for GitHub Pages:

    bun run build:examples
    

    The deployed example is served from https://moritzbrantner.github.io/diagrams/. Generated API documentation is published under https://moritzbrantner.github.io/diagrams/api/.

    • ArchitectureDiagram for systems, boundaries, stores, queues, and external integrations.
    • DecisionTree for branching decisions, actions, and outcomes.
    • DependencyGraph for package, module, service, or team dependencies.
    • EntityRelationshipDiagram for entities, fields, keys, and cardinality relationships.
    • GanttChart for scheduled tasks, progress, earliest-start markers, and deadlines.
    • JourneyMap for phase-based journeys, touchpoints, sentiment, and ownership.
    • MindMap for radial or tree-like idea decomposition.
    • OrgChart, OrgChartNode, getVisibleOrgChartNodes, findOrgChartNode, insertOrgChartNode, updateOrgChartNode, and removeOrgChartNode for hierarchical org or ownership structures.
    • ProcessMap, ProcessMapStep, and ProcessMapConnector for horizontal and vertical workflow sequences.
    • RelationshipMap for node-and-edge dependency, stakeholder, ownership, or risk maps.
    • SequenceDiagram for ordered interactions between participants.
    • StateMachineDiagram for state machines with events, guards, actions, and terminal states.
    • SwimlaneDiagram for workflow steps grouped by team, role, or system.
    • TimelineDiagram for structural milestone and event timelines.
    • UmlDiagram, UmlClassDiagram, UmlStateDiagram, and getUmlDiagramBounds for generic UML, class, and state diagrams.

    Interactive diagrams keep their static role="img" surface until selection, actions, or keyboard props are supplied. Node-like diagrams use the same controlled shape:

    import { RelationshipMap } from "@moritzbrantner/diagrams";

    export function InteractiveMap() {
    const [selectedNodeId, setSelectedNodeId] = React.useState<string | null>("api");

    return (
    <RelationshipMap
    ariaLabel="Service relationships"
    selectedNodeId={selectedNodeId}
    onNodeSelect={(node) => setSelectedNodeId(node.id)}
    onNodeDeselect={() => setSelectedNodeId(null)}
    nodeActions={[
    {
    id: "inspect",
    label: "Inspect",
    onSelect: (node) => console.log(node.id),
    },
    ]}
    nodes={[
    { id: "api", label: "API", x: 0, y: 0 },
    { id: "db", label: "Database", x: 280, y: 0 },
    ]}
    edges={[{ id: "api-db", source: "api", target: "db", label: "reads" }]}
    />
    );
    }

    When interaction is enabled, arrow keys move focus between enabled items and Enter or Space activates the focused item.

    Hierarchical and grouped diagrams expose controlled collapse state. Expansion defaults to fully expanded when no state is supplied.

    import { ArchitectureDiagram, DecisionTree } from "@moritzbrantner/diagrams";

    export function CollapsibleDiagrams() {
    return (
    <>
    <DecisionTree
    expandedNodeIds={["root"]}
    root={{
    id: "root",
    label: "Launch?",
    children: [
    {
    id: "yes",
    label: "Yes",
    target: {
    id: "ship",
    label: "Ship",
    children: [
    { id: "announce", label: "Announce", target: { id: "done", label: "Done" } },
    ],
    },
    },
    ],
    }}
    />
    <ArchitectureDiagram
    collapsedBoundaryIds={["platform"]}
    boundaries={[{ id: "platform", label: "Platform" }]}
    nodes={[
    { id: "api", label: "API", boundaryId: "platform" },
    { id: "db", label: "Database", boundaryId: "platform" },
    { id: "user", label: "User", x: 560, y: 0 },
    ]}
    connections={[{ id: "user-api", source: "user", target: "api" }]}
    />
    </>
    );
    }
    import { RelationshipMap } from "@moritzbrantner/diagrams";

    export function Stakeholders() {
    return (
    <RelationshipMap
    ariaLabel="Stakeholder map"
    nodes={[
    { id: "product", label: "Product", x: 0, y: 80 },
    { id: "design", label: "Design", x: 280, y: 0, tone: "success" },
    { id: "engineering", label: "Engineering", x: 280, y: 160 },
    ]}
    edges={[
    {
    id: "product-design",
    source: "product",
    target: "design",
    label: "briefs",
    },
    {
    id: "product-eng",
    source: "product",
    target: "engineering",
    label: "prioritizes",
    },
    ]}
    />
    );
    }
    import { ProcessMap } from "@moritzbrantner/diagrams";

    export function ReleaseProcess() {
    return (
    <ProcessMap
    steps={[
    { id: "scope", label: "Scope", status: "done", tone: "success" },
    { id: "build", label: "Build", status: "active", tone: "accent" },
    { id: "ship", label: "Ship", status: "pending" },
    ]}
    />
    );
    }
    import { GanttChart } from "@moritzbrantner/diagrams";

    export function ReleasePlan() {
    return (
    <GanttChart
    ariaLabel="Release plan"
    startDate="2026-04-01"
    endDate="2026-04-24"
    tasks={[
    {
    id: "brief",
    label: "Release brief",
    startDate: "2026-04-01",
    endDate: "2026-04-04",
    earliestStartDate: "2026-04-01",
    deadlineDate: "2026-04-05",
    progress: 1,
    },
    {
    id: "components",
    label: "Component work",
    startDate: "2026-04-04",
    endDate: "2026-04-14",
    earliestStartDate: "2026-04-03",
    deadlineDate: "2026-04-16",
    progress: 0.68,
    },
    ]}
    />
    );
    }
    import { OrgChart } from "@moritzbrantner/diagrams";

    export function Team() {
    return (
    <OrgChart
    nodes={[
    {
    id: "owner",
    label: "Program owner",
    children: [
    { id: "design", label: "Design systems" },
    { id: "platform", label: "Frontend platform" },
    ],
    },
    ]}
    />
    );
    }
    import { UmlDiagram } from "@moritzbrantner/diagrams/uml-diagram";

    export function OrderFlow() {
    return (
    <UmlDiagram
    ariaLabel="Order service dependencies"
    nodes={[
    { id: "api", label: "API Gateway", x: 0, y: 0 },
    { id: "orders", label: "Orders Service", x: 280, y: 0 },
    ]}
    edges={[{ id: "api-orders", source: "api", target: "orders", label: "routes" }]}
    />
    );
    }

    Node-edge SVG diagrams are static by default. Pass interactiveFeatures={true} to enable built-in pan/zoom controls, connected-path highlighting, local search, and the edge inspector.

    <RelationshipMap
    interactiveFeatures={true}
    nodes={[
    { id: "product", label: "Product" },
    { id: "engineering", label: "Engineering" },
    ]}
    edges={[{ id: "handoff", source: "product", target: "engineering", label: "handoff" }]}
    />

    Viewport, search, highlight, and inspector state can be controlled by host applications.

    import * as React from "react";
    import { RelationshipMap, type DiagramViewport } from "@moritzbrantner/diagrams";

    export function ControlledCanvas() {
    const [viewport, setViewport] = React.useState<DiagramViewport>({
    x: -40,
    y: -40,
    width: 720,
    height: 420,
    });

    return (
    <RelationshipMap
    interactiveFeatures={{ viewport: true, controls: "always" }}
    viewport={viewport}
    onViewportChange={setViewport}
    nodes={[
    { id: "api", label: "API" },
    { id: "db", label: "DB" },
    ]}
    edges={[{ id: "api-db", source: "api", target: "db", label: "writes" }]}
    />
    );
    }
    import * as React from "react";
    import { DependencyGraph } from "@moritzbrantner/diagrams";

    export function SearchableGraph() {
    const [query, setQuery] = React.useState("orders");

    return (
    <DependencyGraph
    interactiveFeatures={{ search: true, pathHighlight: true }}
    searchQuery={query}
    onSearchQueryChange={setQuery}
    nodes={[
    { id: "orders", label: "Orders" },
    { id: "billing", label: "Billing" },
    ]}
    edges={[{ id: "orders-billing", source: "orders", target: "billing", label: "events" }]}
    />
    );
    }
    import { ArchitectureDiagram } from "@moritzbrantner/diagrams";

    <ArchitectureDiagram
    interactiveFeatures={{ edgeInspector: true }}
    nodes={[
    { id: "api", label: "API" },
    { id: "orders", label: "Orders" },
    ]}
    connections={[{ id: "api-orders", source: "api", target: "orders", protocol: "HTTP" }]}
    renderEdgeInspector={(context) => (
    <div>
    {context.edgeId}: {context.sourceId} to {context.targetId}
    </div>
    )}
    />;
    import {
    ArchitectureDiagram,
    DecisionTree,
    DependencyGraph,
    EntityRelationshipDiagram,
    JourneyMap,
    MindMap,
    SequenceDiagram,
    StateMachineDiagram,
    SwimlaneDiagram,
    TimelineDiagram,
    } from "@moritzbrantner/diagrams";

    <SequenceDiagram
    participants={[
    { id: "client", label: "Client" },
    { id: "api", label: "API" },
    ]}
    messages={[{ id: "request", from: "client", to: "api", label: "Request" }]}
    />;

    <SwimlaneDiagram
    lanes={[{ id: "team", label: "Team" }]}
    steps={[{ id: "build", laneId: "team", label: "Build" }]}
    />;

    <DependencyGraph
    nodes={[
    { id: "app", label: "App" },
    { id: "pkg", label: "Package" },
    ]}
    edges={[{ id: "app-pkg", source: "app", target: "pkg" }]}
    />;

    <DependencyGraph
    selectedNodeId={selectedNodeId}
    onNodeSelect={(node) => setSelectedNodeId(node.id)}
    onNodeDeselect={() => setSelectedNodeId(null)}
    nodeActions={[
    { id: "inspect", label: "Inspect" },
    { id: "remove", label: "Remove", destructive: true },
    ]}
    nodes={[
    { id: "app", label: "App" },
    { id: "pkg", label: "Package" },
    ]}
    edges={[{ id: "app-pkg", source: "app", target: "pkg" }]}
    />;

    <ArchitectureDiagram
    nodes={[
    { id: "api", label: "API" },
    { id: "db", label: "DB", kind: "database" },
    ]}
    connections={[{ id: "api-db", source: "api", target: "db", label: "writes" }]}
    />;

    <EntityRelationshipDiagram
    entities={[{ id: "orders", name: "orders", fields: [{ id: "id", name: "id", key: "primary" }] }]}
    />;

    <DecisionTree
    root={{
    id: "ready",
    label: "Ready?",
    children: [{ id: "yes", label: "Yes", target: { id: "ship", label: "Ship" } }],
    }}
    />;

    <StateMachineDiagram
    states={[
    { id: "draft", label: "Draft" },
    { id: "review", label: "Review" },
    ]}
    transitions={[{ id: "submit", source: "draft", target: "review", event: "submit" }]}
    />;

    <JourneyMap
    phases={[{ id: "discover", label: "Discover" }]}
    touchpoints={[{ id: "docs", phaseId: "discover", label: "Read docs" }]}
    />;

    <TimelineDiagram items={[{ id: "beta", date: "2026-04-10", label: "Beta" }]} />;

    <MindMap
    root={{ id: "diagrams", label: "Diagrams", children: [{ id: "workflow", label: "Workflow" }] }}
    />;

    @moritzbrantner/diagrams intentionally does not export analytical chart adapters. Keep time-series, categorical, statistical, and quantitative chart work in @moritzbrantner/charts; use this package for diagrams whose primary meaning comes from nodes, edges, hierarchy, sequence, state, dependency, scheduling, deadlines, or process structure.