Skip to content

Variable: graphAttributes ​

ts
const graphAttributes: ObjectNode<{
  arc: ObjectNode<{
     groupsep: Attr<number, {
        description: "With `order: 'group'`: extra space where the group changes.";
        dflt: 0;
        editType: "calc";
        min: 0;
     }>;
     loopsize: Attr<number, {
        description: "How far the loop of a link from a node to itself rises beyond the node's edge.";
        dflt: 12;
        editType: "calc";
        min: 0;
     }>;
     maxheight: Attr<number, {
        description: "How far an arc may rise from the line, in layout units: longer arcs are flattened to this height. Default: no limit (half circles).";
        editType: "calc";
        min: 0;
     }>;
     nodesep: Attr<number, {
        description: "Space between two neighbours on the line, in layout units.";
        dflt: 20;
        editType: "calc";
        min: 0;
     }>;
     order: Attr<"input" | "group" | "degree" | "barycenter", {
        description: "The order of the nodes along the line, which is what an arc diagram shows. `'input'`: as given. `'group'`: by `node.group`. `'degree'`: most links first. `'barycenter'`: the given order improved so that linked nodes are close and the arcs short. Default: `'group'` when the nodes have groups, else `'input'`.";
        editType: "calc";
        values: readonly ["input", "group", "degree", "barycenter"];
     }>;
     orientation: Attr<"h" | "v", {
        description: "The direction of the line the nodes sit on: horizontal (`'h'`, first node on the left) or vertical (`'v'`, first node at the top).";
        dflt: "h";
        editType: "calc";
        values: readonly ["h", "v"];
     }>;
     sides: Attr<"above" | "below" | "direction", {
        description: "The side of the line the arcs are on: `'above'` (to the right of a vertical line), `'below'`, or `'direction'`: above for a link that points forward along the line and below for one that points back.";
        dflt: "above";
        editType: "calc";
        values: readonly ["above", "below", "direction"];
     }>;
  }>;
  arrangement: Attr<
     | "radial"
     | "preset"
     | "force"
     | "layered"
     | "tree"
     | "dendrogram"
     | "circular"
     | "grid"
     | "arc"
     | "hive"
     | "custom", {
     description: "The layout that places the nodes. `'preset'`: at `node.x` / `node.y`, which are data on the trace's axes. `'force'`: a force-directed layout, linked nodes pulled together and all nodes pushed apart (options: `force`). `'layered'`: a layered drawing of a directed graph, every link pointing the same way (pipelines, dependencies, state machines; options: `layered`). `'tree'`: a tidy tree; `'radial'`: the same tree on rings around its root; `'dendrogram'`: a tree with its leaves on one line and every other node at the height `node.value` gives it (options of the three: `tree`). `'circular'`: evenly on a circle, the nodes of a group next to each other. `'grid'`: in rows. `'arc'`: an arc diagram, the nodes on a line and the links as arcs over it (options: `arc`). `'hive'`: a hive plot, the nodes on a few axes around a center (options: `hive`). `'custom'`: the layout named by `custom.name`. Every arrangement but `'preset'` hides the axes and gives them one scale, with two exceptions: a dendrogram with `node.value` shows the axis of its heights, and a `'force'` graph whose nodes all have an `x` and no `y` (or the reverse) keeps them at those values on a visible axis and moves them along the other one only (a timeline). Default: `'preset'` when every node has an `x` and a `y`, else `'force'`.";
     editType: "calc";
     values: readonly ["preset", "force", "layered", "tree", "radial", "dendrogram", "circular", "grid", "arc", "hive", "custom"];
  }>;
  custom: ObjectNode<{
     name: Attr<string, {
        description: "With `arrangement: 'custom'`: the name of a layout registered with `registerGraphLayout(name, layout)`.";
        editType: "calc";
        noBlank: true;
        strict: true;
     }>;
     options: AttrSpec<unknown, unknown>;
  }>;
  force: ObjectNode<{
     algorithm: Attr<"spring" | "forceatlas2", {
        description: "The model of the simulation. `'spring'`: links are springs with a rest length and every two nodes repel (the d3-force model); even link lengths, the usual choice. `'forceatlas2'`: links pull in proportion to their length and nodes repel in proportion to their degrees (ForceAtlas2); it pulls communities apart better in graphs with hubs.";
        dflt: "spring";
        editType: "calc";
        values: readonly ["spring", "forceatlas2"];
     }>;
     charge: Attr<number, {
        description: "`'spring'`: the strength of the force between every two nodes: negative values push them apart (the more negative, the larger and more open the layout), positive ones pull them together.";
        dflt: -60;
        editType: "calc";
     }>;
     collide: Attr<boolean, {
        description: "Keep nodes from overlapping, each taken as a circle around its marker or box.";
        dflt: true;
        editType: "calc";
     }>;
     collidepadding: Attr<number, {
        description: "With `collide`: the room left between two nodes, in layout units.";
        dflt: 2;
        editType: "calc";
        min: 0;
     }>;
     gravity: Attr<number, {
        description: "The pull toward the center, which keeps the parts of a graph that are not linked from drifting apart. `'spring'`: each connected part is pulled as a whole (default 0.05). `'forceatlas2'`: every node is pulled, the more links it has the harder (default 1).";
        editType: "calc";
        min: 0;
     }>;
     groupstrength: Attr<number, {
        description: "The pull of every node toward the middle of its group (`node.group`), which keeps the nodes of a group together even where the links do not. 0.05 to 0.3 are usual values.";
        dflt: 0;
        editType: "calc";
        min: 0;
     }>;
     linkdistance: Attr<number, {
        description: "`'spring'`: the rest length of a link, in layout units (CSS px before the graph is fitted to the plot area). Links end up longer where the repulsion of their nodes stretches them.";
        dflt: 30;
        editType: "calc";
        min: 0;
     }>;
     linkstrength: Attr<number, {
        description: "`'spring'`: how hard a link pulls its nodes to its rest length, 0 to 1. Default: per link, 1 / the smaller degree of its two nodes, so that the links of a hub do not crush its neighbours onto it.";
        editType: "calc";
        max: 1;
        min: 0;
     }>;
     linkweight: Attr<"none" | "strength" | "distance", {
        description: "What `link.value` does to a link: `'strength'`: a larger value pulls harder; `'distance'`: a larger value makes the link shorter (`'spring'` only; as `'strength'` for `'forceatlas2'`); `'none'`: nothing.";
        dflt: "strength";
        editType: "calc";
        values: readonly ["strength", "distance", "none"];
     }>;
     linlog: Attr<boolean, {
        description: "`'forceatlas2'`: links pull with the logarithm of their length instead of the length: tighter and better separated clusters.";
        dflt: false;
        editType: "calc";
     }>;
     scalingratio: Attr<number, {
        description: "`'forceatlas2'`: the repulsion between nodes; a larger value gives a larger, more open layout. Default: 10, or 1 with `linlog`.";
        editType: "calc";
        min: 0;
     }>;
     seed: Attr<number, {
        description: "Seed of the generator that separates nodes at the same place. The layout is deterministic: the same figure gives the same positions everywhere; another seed gives another, equally valid, layout of graphs that have such nodes.";
        dflt: 1;
        editType: "calc";
        min: 0;
     }>;
     simulate: Attr<boolean, {
        description: "Show the layout settling: the nodes start in a spiral and the chart draws the simulation as it cools, a few steps per frame, ending on the same picture as without it. The axes are sized for the settled layout from the start. It runs again when something the layout reads changes (the nodes, the links, their sizes, these options), not on a change of style. Without motion (`prefers-reduced-motion`, `config.a11y.reducedMotion`), on a static plot (an image export) and for graphs of more than 2,000 nodes or 10,000 links the settled layout is drawn at once. When the layout runs off the main thread (`worker`), the positions the worker reports are what is shown, as fast as they come: nothing is replayed afterwards, and `simulate` then only says whether a dragged node pushes the others aside.";
        dflt: false;
        editType: "plot";
     }>;
     start: ObjectNode<{
        alpha: Attr<number, {
           description: "How warm the layout still is at these positions. 0: at rest: the positions are the layout, and nothing is simulated. Above 0 the simulation goes on from them, cooling from this value at the rate of a full run, so 0.3 moves the nodes about a little and 1 is a full run.";
           dflt: 1;
           editType: "calc";
           max: 1;
           min: 0;
        }>;
        x: AttrSpec<DataArray, DataArray | undefined>;
        y: AttrSpec<DataArray, DataArray | undefined>;
     }>;
     ticks: Attr<number, {
        description: "Steps of the simulation from its start to rest; the cooling is spread over them. More steps untangle a graph better and take longer. Default: 600 up to 500 nodes, fewer for larger graphs (300 from 1,000 to 3,000 nodes, 90 at 10,000).";
        editType: "calc";
        min: 1;
     }>;
  }>;
  highlight: ObjectNode<{
     color: Attr<string, {
        description: "Color of the highlighted links. Default: each link's own color, made opaque.";
        editType: "style";
     }>;
     dim: Attr<number, {
        description: "Opacity factor of the nodes, links and labels that are not highlighted while something is.";
        dflt: 0.15;
        editType: "style";
        max: 1;
        min: 0;
     }>;
     direction: Attr<"both" | "out" | "in", {
        description: "With `'neighbors'`: which links are followed from the hovered node, and from each node reached. `'both'`: all of them. `'out'`: only from a link's source to its target, which gives what the node leads to (its descendants). `'in'`: only from target to source: what leads to it (its ancestors).";
        dflt: "both";
        editType: "style";
        values: readonly ["both", "out", "in"];
     }>;
     hops: Attr<number, {
        description: "With `'neighbors'`: how many links away from the hovered node the highlight reaches. 1: its neighbours; 2: their neighbours too; 0: the node alone. The links between two nodes that are both at the last hop are not part of it.";
        dflt: 1;
        editType: "style";
        min: 0;
     }>;
     mode: Attr<
        | "none"
        | "neighbors"
        | "path"
        | `neighbors+${string}`
        | `path+${string}`, {
        description: "What is emphasized, the rest of the graph being dimmed (`highlight.dim`). `'neighbors'`: while the pointer is over a node, the node, the links that lead from it and the nodes they lead to (`highlight.hops`, `highlight.direction`); over a link, the link and its two ends. `'path'`: while exactly two nodes are selected, a shortest path between them. `'none'`: neither. Hover highlighting is skipped for a graph of more than 50,000 nodes and links together.";
        dflt: "neighbors+path";
        editType: "style";
        extras: readonly ["none"];
        flags: readonly ["neighbors", "path"];
     }>;
     nodes: AttrSpec<DataArray, DataArray | undefined>;
     path: AttrSpec<[number, number], [number, number] | undefined>;
     pathdirected: Attr<boolean, {
        description: "Whether a path follows every link from its source to its target only. Default: `true` when the links have arrowheads at their targets (`link.arrow.end`), else `false`: a path may run along a link either way.";
        editType: "style";
     }>;
     pathweight: Attr<"value" | "hops", {
        description: "What makes a path short. `'hops'`: the number of its links. `'value'`: the sum of its links' `link.value`, each taken as a cost or a distance (a link without a positive value costs 1).";
        dflt: "hops";
        editType: "style";
        values: readonly ["hops", "value"];
     }>;
  }>;
  hive: ObjectNode<{
     assign: Attr<"degree" | "direction", {
        description: "How nodes without groups get their axis. `'degree'`: sorted by their number of links and cut into `axes` equal parts. `'direction'`: three axes, for the nodes that only have outgoing links, those in between, and those that only have incoming links.";
        dflt: "degree";
        editType: "calc";
        values: readonly ["degree", "direction"];
     }>;
     axes: Attr<number, {
        description: "Number of axes when the nodes have no groups (with `node.group` there is one axis per group, with the group's name at its end) and `assign` is `'degree'`.";
        dflt: 3;
        editType: "calc";
        max: 360;
        min: 1;
     }>;
     innerradius: Attr<number, {
        description: "Distance from the center to the first node of an axis, in layout units.";
        dflt: 40;
        editType: "calc";
        min: 0;
     }>;
     outerradius: Attr<number, {
        description: "Distance from the center to the last node of an axis, in layout units.";
        dflt: 300;
        editType: "calc";
        min: 0;
     }>;
     position: Attr<"value" | "degree", {
        description: "What places a node along its axis: its rank by number of links among the nodes of the axis (`'degree'`, the least linked nearest the center) or `node.value`, on one scale for all axes.";
        dflt: "degree";
        editType: "calc";
        values: readonly ["degree", "value"];
     }>;
     startangle: Attr<number, {
        description: "Angle of the first axis in degrees, counter-clockwise from 3 o'clock. The others follow counter-clockwise, evenly spaced.";
        dflt: 90;
        editType: "calc";
     }>;
  }>;
  hoverinfo: Attr<"all" | "none" | "skip", {
     description: "Hover of nodes and links: labels (`'all'`), events without labels (`'none'`) or no hover at all (`'skip'`). The default of `node.hoverinfo` and `link.hoverinfo`.";
     dflt: "all";
     editType: "none";
     extras: readonly ["all", "none", "skip"];
     flags: readonly [];
  }>;
  labels: AttrSpec<DataArray, DataArray | undefined>;
  layered: ObjectNode<{
     aspect: Attr<number, {
        description: "Width over height that the parts of a graph that are not linked to each other are packed into. Default: the proportions of the plot area.";
        editType: "calc";
        min: 0.05;
     }>;
     clusterpadding: Attr<number, {
        description: "With `clusters`: the space between a frame and its nodes, in layout units.";
        dflt: 12;
        editType: "calc";
        min: 0;
     }>;
     clusters: Attr<boolean, {
        description: "Keep the nodes of a group (`node.group`) together and draw a frame around each group, tinted in its color, with its name at the top.";
        dflt: false;
        editType: "calc";
     }>;
     edgesep: Attr<number, {
        description: "Free space between two long links that cross a layer side by side, in layout units.";
        dflt: 12;
        editType: "calc";
        min: 0;
     }>;
     nodesep: Attr<number, {
        description: "Free space between two nodes of a layer, in layout units.";
        dflt: 30;
        editType: "calc";
        min: 0;
     }>;
     rankdir: Attr<"TB" | "BT" | "LR" | "RL", {
        description: "The direction the links point in: top to bottom (`'TB'`), bottom to top (`'BT'`), left to right (`'LR'`) or right to left (`'RL'`).";
        dflt: "TB";
        editType: "calc";
        values: readonly ["TB", "BT", "LR", "RL"];
     }>;
     ranker: Attr<"network-simplex" | "tight-tree" | "longest-path", {
        description: "How nodes get their layer. `'network-simplex'`: the layers that make the links shortest in total. `'tight-tree'`: its starting point, faster and nearly as short. `'longest-path'`: every node as early as its links allow, the fastest, with longer links.";
        dflt: "network-simplex";
        editType: "calc";
        values: readonly ["network-simplex", "tight-tree", "longest-path"];
     }>;
     ranksep: Attr<number, {
        description: "Free space between two layers, in layout units.";
        dflt: 50;
        editType: "calc";
        min: 0;
     }>;
     routing: Attr<"spline" | "polyline" | "orthogonal", {
        description: "The shape of the links: smooth curves (`'spline'`), straight segments through the same points (`'polyline'`) or horizontal and vertical segments (`'orthogonal'`).";
        dflt: "spline";
        editType: "calc";
        values: readonly ["spline", "polyline", "orthogonal"];
     }>;
  }>;
  link: ObjectNode<{
     arrow: ObjectNode<{
        end: Attr<boolean, {
           description: "Draw an arrowhead at the target end of every link (a directed graph). Default: `true` with `arrangement: 'layered'`, whose links all point one way, else `false`.";
           dflt: false;
           editType: "plot";
        }>;
        size: Attr<number, {
           description: "Length of the arrowheads in CSS px; a wide link gets a head at least three times its width.";
           dflt: 8;
           editType: "plot";
           min: 0;
        }>;
        start: Attr<boolean, {
           description: "Draw an arrowhead at the source end of every link.";
           dflt: false;
           editType: "plot";
        }>;
     }>;
     bundle: ObjectNode<{
        compatibility: Attr<number, {
           description: "With force-directed bundling: how alike two links must be to attract each other (their directions, lengths and positions), 0 to 1. Lower values bundle more links, also ones that do not belong together.";
           dflt: 0.6;
           editType: "calc";
           max: 1;
           min: 0;
        }>;
        method: Attr<"none" | "auto" | "force" | "hierarchical", {
           description: "Draw links that run the same way together, as bundles, so that a dense graph shows its main streams. The nodes stay where they are. `'hierarchical'`: a link follows the path between its two ends in the hierarchy of the nodes, their groups (`node.group`) or, under a tree arrangement, the tree: links between the same two groups share their middle. Cheap, and at its best on `'circular'` and `'radial'`. `'force'`: links that lie alongside each other attract each other, for graphs without groups; costly, and refused above 20,000 links (the links are then drawn straight, with a warning). `'auto'`: `'hierarchical'` when the nodes have groups or the arrangement is a tree, else `'force'`. Links the arrangement routed itself (`'layered'`, `'arc'`, `'hive'`, the edges of a tree) keep their routes. The bundles are computed after the layout and arrive a moment after the nodes (see `worker`); while a node is dragged, hierarchical bundles follow it and force-directed ones are drawn straight until it is dropped.";
           dflt: "none";
           editType: "calc";
           values: readonly ["none", "auto", "hierarchical", "force"];
        }>;
        strength: Attr<number, {
           description: "How tightly the links are bundled: 0 leaves them straight, 1 pulls them all the way together.";
           dflt: 0.85;
           editType: "calc";
           max: 1;
           min: 0;
        }>;
     }>;
     color: Attr<string | readonly string[], {
        arrayOk: true;
        description: "Link color, or one per link. Default: a translucent gray that reads on the plot background, light or dark.";
        editType: "style";
     }>;
     curve: Attr<
        | number
        | TypedArray
        | readonly number[], {
        arrayOk: true;
        description: "How far a link bows out, as a fraction of its length: 0 is straight, positive bows to the left of its direction, negative to the right. One value, or one per link. Default: straight, except that the links between the same two nodes are fanned out so that each can be seen. A value replaces that fan: one value for all links draws the links between the same two nodes on top of each other (give one value per link to keep them apart), and in an array a link without a number keeps its place in the fan. A link the layout routed keeps its route.";
        editType: "plot";
        max: 2;
        min: -2;
     }>;
     customdata: AttrSpec<DataArray, DataArray | undefined>;
     dash: Attr<string, {
        description: "Dash style of every link: `'solid'`, `'dot'`, `'dash'`, `'longdash'`, `'dashdot'`, `'longdashdot'`, or a dash list such as `'5px,10px,2px'`.";
        dflt: "solid";
        editType: "style";
     }>;
     hoverinfo: Attr<"all" | "none" | "skip", {
        description: `Hover of ${string}: labels (`'all'`), events without labels (`'none'`) or no hover and no events (`'skip'`). Default: the trace `hoverinfo`.`;
        dflt: "all";
        editType: "none";
        values: readonly ["all", "none", "skip"];
     }>;
     hovertemplate: Attr<string, {
        description: "Template of the link hover labels: `%{label}`, `%{value}`, `%{source.label}`, `%{target.label}`, `%{source.index}`, `%{target.index}`, `%{customdata}`. `<extra>…</extra>` replaces the trace name.";
        editType: "none";
     }>;
     label: AttrSpec<DataArray, DataArray | undefined>;
     opacity: Attr<number, {
        description: "Link opacity (multiplied by the trace `opacity` and the color alpha).";
        dflt: 1;
        editType: "style";
        max: 1;
        min: 0;
     }>;
     secondary: ObjectNode<{
        color: Attr<string, {
           description: "Color of the secondary links. Default: each link's own color.";
           editType: "style";
        }>;
        dash: Attr<string, {
           description: "Dash style of the secondary links (see `link.dash`).";
           dflt: "dash";
           editType: "style";
        }>;
        opacity: Attr<number, {
           description: "Opacity of the secondary links, multiplied by `link.opacity`.";
           dflt: 0.7;
           editType: "style";
           max: 1;
           min: 0;
        }>;
     }>;
     source: AttrSpec<DataArray, DataArray | undefined>;
     target: AttrSpec<DataArray, DataArray | undefined>;
     value: AttrSpec<DataArray, DataArray | undefined>;
     width: Attr<
        | number
        | TypedArray
        | readonly number[], {
        arrayOk: true;
        description: "Link width in CSS px, or one per link. Ignored with `link.widthby`.";
        dflt: 1;
        editType: "plot";
        min: 0;
     }>;
     widthby: Attr<"none" | "value", {
        description: "`'value'`: widths from `link.value`, proportional to it, between the two widths of `link.widthrange` (the largest value gets the second).";
        dflt: "none";
        editType: "plot";
        values: readonly ["none", "value"];
     }>;
     widthrange: AttrSpec<[number, number], [number, number]>;
  }>;
  lod: Attr<boolean | "auto", {
     description: "Level of detail: what a large graph leaves out while it is drawn small. `'auto'`: for a graph of more than 3,000 nodes or 5,000 links; `true`: for any graph; `false`: never. With it, node labels are drawn once the nodes are 24 px apart on average, and arrowheads once the links are 24 px long on average (they go again below 18 px, so a zoom at the threshold does not make them flicker); neither is built before. Nodes are drawn smaller where they are closer together than one and a half times their size, down to dots of 1.5 px, and lose their outlines below 4 px. Links fade as they cover more of the plot, so that a dense graph stays a texture instead of a block of one color, and come back to `link.opacity` on a zoom into it. What a hover or a selection highlights is drawn in full.";
     dflt: "auto";
     editType: "plot";
     values: readonly ["auto", true, false];
  }>;
  node: ObjectNode<{
     autocolorscale: AttrSpec<boolean, boolean | undefined>;
     cauto: AttrSpec<boolean, boolean | undefined>;
     cmax: AttrSpec<number, number | undefined>;
     cmid: AttrSpec<number, number | undefined>;
     cmin: AttrSpec<number, number | undefined>;
     color: Attr<string | readonly string[], {
        arrayOk: true;
        description: "Node color, one CSS color per node, or numbers mapped through `colorscale` (with a colorbar when `showscale` is on). Default: the group's color when `node.group` is given (the colorway, one color per group), else the trace's colorway color.";
        editType: "style";
     }>;
     coloraxis: AttrSpec<string, string | undefined>;
     colorbar: ObjectNode<{
        bgcolor: Attr<string, {
           description: "Background of the box.";
           dflt: "rgba(0,0,0,0)";
        }>;
        bordercolor: Attr<string, {
           description: "Border color of the colorbar box.";
           dflt: "#444";
        }>;
        borderwidth: Attr<number, {
           description: "Border width of the box, px.";
           dflt: 0;
           min: 0;
        }>;
        dtick: AttrSpec<unknown, unknown>;
        exponentformat: Attr<"none" | "e" | "E" | "power" | "SI" | "B", {
           description: "How large and small numbers are written: `none` (1000000), `e` (1e+6), `E` (1E+6), `power` (1×10⁶), `SI` (1M), `B` (like SI but 1B for 10⁹).";
           dflt: "B";
           editType: readonly (
              | "none"
              | "legend"
              | "calc"
              | "calcIfAutorange"
              | "crossTraceCalc"
              | "layout"
              | "ticks"
              | "plot"
              | "style"
              | "colorbars"
              | "modebar"
             | "camera")[];
           values: readonly ["none", "e", "E", "power", "SI", "B"];
        }>;
        len: Attr<number, {
           description: "Length of the colorbar along its axis, padding included (`ypad` / `xpad`).";
           dflt: 1;
           min: 0;
        }>;
        lenmode: Attr<"fraction" | "pixels", {
           description: "Unit of `len`: px, or a fraction of the plot height (`v`) / width (`h`).";
           dflt: "fraction";
           values: readonly ["fraction", "pixels"];
        }>;
        minexponent: Attr<number, {
           description: "Smallest decimal exponent written in exponent form (`SI`/`B` and exponent formats); smaller magnitudes are written out in full.";
           dflt: 3;
           editType: readonly (
              | "none"
              | "legend"
              | "calc"
              | "calcIfAutorange"
              | "crossTraceCalc"
              | "layout"
              | "ticks"
              | "plot"
              | "style"
              | "colorbars"
              | "modebar"
             | "camera")[];
           min: 0;
        }>;
        nticks: Attr<number, {
           description: "Maximum number of ticks for `tickmode: auto` (the actual number may be lower so steps stay round). 0 picks it from the axis length.";
           dflt: 0;
           editType: "ticks";
           min: 0;
        }>;
        orientation: Attr<"h" | "v", {
           description: "Vertical bar (`v`, beside the plot) or horizontal bar (`h`, above or below).";
           dflt: "v";
           values: readonly ["h", "v"];
        }>;
        outlinecolor: Attr<string, {
           description: "Color of the outline around the bar.";
           dflt: "#444";
        }>;
        outlinewidth: Attr<number, {
           description: "Outline width, px.";
           dflt: 1;
           min: 0;
        }>;
        separatethousands: Attr<boolean, {
           description: "Always separate thousands (1,000). By default only numbers with 5 or more integer digits are separated.";
           dflt: false;
           editType: readonly (
              | "none"
              | "legend"
              | "calc"
              | "calcIfAutorange"
              | "crossTraceCalc"
              | "layout"
              | "ticks"
              | "plot"
              | "style"
              | "colorbars"
              | "modebar"
             | "camera")[];
        }>;
        showexponent: Attr<"all" | "none" | "first" | "last", {
           description: "Which tick labels show the exponent.";
           dflt: "all";
           editType: readonly (
              | "none"
              | "legend"
              | "calc"
              | "calcIfAutorange"
              | "crossTraceCalc"
              | "layout"
              | "ticks"
              | "plot"
              | "style"
              | "colorbars"
              | "modebar"
             | "camera")[];
           values: readonly ["all", "first", "last", "none"];
        }>;
        showticklabels: Attr<boolean, {
           description: "Show tick labels.";
           dflt: true;
           editType: readonly (
              | "none"
              | "legend"
              | "calc"
              | "calcIfAutorange"
              | "crossTraceCalc"
              | "layout"
              | "ticks"
              | "plot"
              | "style"
              | "colorbars"
              | "modebar"
             | "camera")[];
        }>;
        showtickprefix: Attr<"all" | "none" | "first" | "last", {
           description: "Which tick labels get `tickprefix`.";
           dflt: "all";
           editType: readonly (
              | "none"
              | "legend"
              | "calc"
              | "calcIfAutorange"
              | "crossTraceCalc"
              | "layout"
              | "ticks"
              | "plot"
              | "style"
              | "colorbars"
              | "modebar"
             | "camera")[];
           values: readonly ["all", "first", "last", "none"];
        }>;
        showticksuffix: Attr<"all" | "none" | "first" | "last", {
           description: "Which tick labels get `ticksuffix`.";
           dflt: "all";
           editType: readonly (
              | "none"
              | "legend"
              | "calc"
              | "calcIfAutorange"
              | "crossTraceCalc"
              | "layout"
              | "ticks"
              | "plot"
              | "style"
              | "colorbars"
              | "modebar"
             | "camera")[];
           values: readonly ["all", "first", "last", "none"];
        }>;
        thickness: Attr<number, {
           description: "Thickness of the color bar.";
           dflt: 30;
           min: 0;
        }>;
        thicknessmode: Attr<"fraction" | "pixels", {
           description: "Unit of `thickness`: px, or a fraction of the plot width (`v`) / height (`h`).";
           dflt: "pixels";
           values: readonly ["fraction", "pixels"];
        }>;
        tick0: AttrSpec<unknown, unknown>;
        tickangle: Attr<number | "auto", {
           description: "Tick-label rotation in degrees. `auto` rotates x-axis labels by the first `autotickangles` entry that avoids overlap.";
           dflt: "auto";
           editType: readonly (
              | "none"
              | "legend"
              | "calc"
              | "calcIfAutorange"
              | "crossTraceCalc"
              | "layout"
              | "ticks"
              | "plot"
              | "style"
              | "colorbars"
              | "modebar"
             | "camera")[];
           extras: readonly ["auto"];
        }>;
        tickcolor: Attr<string, {
           description: "Tick color. Defaults to `color`.";
           editType: "ticks";
        }>;
        tickfont: ObjectNode<{
           color: Attr<string, {
              description: "Text color.";
              editType: "style";
           }>;
           family: Attr<string, {
              description: "CSS font-family list. The renderer uses the first family it can load and falls back through the list.";
              noBlank: true;
              strict: true;
           }>;
           lineposition: Attr<
              | "none"
              | "under"
              | "over"
              | "through"
              | `under+${(...)}`
              | `over+${(...)}`
              | `through+${(...)}`, {
              description: "Text decoration: `under`, `over` and/or `through` joined with `+` (e.g. `under+over`), or `none`.";
              extras: readonly [...];
              flags: readonly [..., ..., ...];
           }>;
           shadow: Attr<string, {
              description: "CSS `text-shadow` behind the text (`2px 2px 3px black`; only the first shadow is drawn), `none`, or `auto` for a thin halo in the contrast color of the text.";
           }>;
           size: Attr<number, {
              description: "Font size in CSS pixels.";
              min: 1;
           }>;
           style: Attr<"normal" | "italic", {
              description: "Font style.";
              values: readonly [..., ...];
           }>;
           textcase: Attr<"normal" | "word caps" | "upper" | "lower", {
              description: "Letter case transform: `upper`, `lower`, `word caps` (first letter of each word), or `normal`.";
              values: readonly [..., ..., ..., ...];
           }>;
           variant: Attr<
              | "normal"
              | "small-caps"
              | "all-small-caps"
              | "all-petite-caps"
              | "petite-caps"
              | "unicase", {
              description: "Capitals variant (CSS `font-variant-caps`). The SDF text renderer approximates small and petite caps with uppercase letters at a reduced size.";
              values: readonly [..., ..., ..., ..., ..., ...];
           }>;
           weight: Attr<number | "normal" | "bold", {
              description: "Font weight: a CSS numeric weight (1–1000), `normal` or `bold`.";
              extras: readonly [..., ...];
              max: 1000;
              min: 1;
           }>;
        }>;
        tickformat: Attr<string, {
           description: "Tick-label format: a d3-format specifier for numbers (`.2f`, `~s`, `$,`) or a d3-time-format specifier for dates (`%b %Y`), plus `%{n}f` for `n` digits of fractional seconds and `%h` for the half year. Empty picks a format automatically.";
           dflt: "";
           editType: readonly (
              | "none"
              | "legend"
              | "calc"
              | "calcIfAutorange"
              | "crossTraceCalc"
              | "layout"
              | "ticks"
              | "plot"
              | "style"
              | "colorbars"
              | "modebar"
             | "camera")[];
        }>;
        ticklabeloverflow: Attr<"allow" | "hide past div" | "hide past domain", {
           description: "Hide labels past the figure or past the bar. Defaults to `hide past domain` for inside labels, else `hide past div`.";
           values: readonly ["allow", "hide past div", "hide past domain"];
        }>;
        ticklabelposition: Attr<
           | "outside"
           | "inside"
           | "outside top"
           | "inside top"
           | "outside left"
           | "inside left"
           | "outside right"
           | "inside right"
           | "outside bottom"
           | "inside bottom", {
           description: "Tick labels outside the bar (away from it) or inside (over it); `top`/`bottom` (`v`) or `left`/`right` (`h`) move them beside their tick.";
           dflt: "outside";
           values: readonly ["outside", "inside", "outside top", "inside top", "outside bottom", "inside bottom", "outside left", "inside left", "outside right", "inside right"];
        }>;
        ticklabelstep: Attr<number, {
           description: "Label every n-th tick only (`tickmode` `auto` and `linear`).";
           dflt: 1;
           editType: "ticks";
           min: 1;
        }>;
        ticklen: Attr<number, {
           description: "Tick length in px.";
           dflt: 5;
           editType: readonly (
              | "none"
              | "legend"
              | "calc"
              | "calcIfAutorange"
              | "crossTraceCalc"
              | "layout"
              | "ticks"
              | "plot"
              | "style"
              | "colorbars"
              | "modebar"
             | "camera")[];
           min: 0;
        }>;
        tickmode: Attr<"auto" | "linear" | "array" | "sync", {
           description: "`auto` picks up to `nticks` round ticks; `linear` places ticks from `tick0` every `dtick`; `array` uses `tickvals`/`ticktext`; `sync` aligns with the overlaid axis (reserved; behaves as `auto`). Defaults to `array` when `tickvals` is set, `linear` when `dtick` is set, else `auto`.";
           editType: "ticks";
           values: readonly ["auto", "linear", "array", "sync"];
        }>;
        tickprefix: Attr<string, {
           description: "Text before each tick label.";
           dflt: "";
           editType: readonly (
              | "none"
              | "legend"
              | "calc"
              | "calcIfAutorange"
              | "crossTraceCalc"
              | "layout"
              | "ticks"
              | "plot"
              | "style"
              | "colorbars"
              | "modebar"
             | "camera")[];
        }>;
        ticks: Attr<"" | "outside" | "inside", {
           description: "Draw tick marks outside or inside the plot area, or not at all (`''`).";
           dflt: "";
           editType: EditType;
           values: readonly ["outside", "inside", ""];
        }>;
        ticksuffix: Attr<string, {
           description: "Text after each tick label.";
           dflt: "";
           editType: readonly (
              | "none"
              | "legend"
              | "calc"
              | "calcIfAutorange"
              | "crossTraceCalc"
              | "layout"
              | "ticks"
              | "plot"
              | "style"
              | "colorbars"
              | "modebar"
             | "camera")[];
        }>;
        ticktext: AttrSpec<DataArray, DataArray | undefined>;
        tickvals: AttrSpec<DataArray, DataArray | undefined>;
        tickwidth: Attr<number, {
           description: "Tick width in px.";
           dflt: 1;
           editType: "ticks";
           min: 0;
        }>;
        title: ObjectNode<{
           font: ObjectNode<{
              color: Attr<..., ...>;
              family: Attr<..., ...>;
              lineposition: Attr<..., ...>;
              shadow: Attr<..., ...>;
              size: Attr<..., ...>;
              style: Attr<..., ...>;
              textcase: Attr<..., ...>;
              variant: Attr<..., ...>;
              weight: Attr<..., ...>;
           }>;
           side: Attr<"right" | "top" | "bottom", {
              description: "Where the title goes relative to the bar. Defaults to `top` (`v`) or `right` (`h`).";
              values: readonly [..., ..., ...];
           }>;
           text: Attr<string, {
              description: "Colorbar title.";
              dflt: "";
           }>;
        }>;
        x: Attr<number, {
           description: "Horizontal position (`xref` fraction). Defaults to 1.02 (`v`, paper), 1 (`v`, container) or 0.5 (`h`).";
        }>;
        xanchor: Attr<"left" | "center" | "right", {
           description: "Which side of the colorbar sits at `x`. Defaults to `left` (`v`, paper), `right` (`v`, container) or `center` (`h`).";
           values: readonly ["left", "center", "right"];
        }>;
        xpad: Attr<number, {
           description: "Horizontal padding, px.";
           dflt: 10;
           min: 0;
        }>;
        xref: Attr<"container" | "paper", {
           description: "Reference of `x`: the plot area (`paper`) or the whole figure.";
           dflt: "paper";
           values: readonly ["container", "paper"];
        }>;
        y: Attr<number, {
           description: "Vertical position (`yref` fraction). Defaults to 0.5 (`v`), 1.02 (`h`, paper) or 1 (`h`, container).";
        }>;
        yanchor: Attr<"middle" | "top" | "bottom", {
           description: "Which side of the colorbar sits at `y`. Defaults to `middle` (`v`), `bottom` (`h`, paper) or `top` (`h`, container).";
           values: readonly ["top", "middle", "bottom"];
        }>;
        ypad: Attr<number, {
           description: "Vertical padding, px.";
           dflt: 10;
           min: 0;
        }>;
        yref: Attr<"container" | "paper", {
           description: "Reference of `y`: the plot area (`paper`) or the whole figure.";
           dflt: "paper";
           values: readonly ["container", "paper"];
        }>;
     }>;
     colorscale: AttrSpec<ColorScale, ColorScale | undefined>;
     customdata: AttrSpec<DataArray, DataArray | undefined>;
     draggable: Attr<boolean, {
        description: "Whether a press on a node drags it. `'preset'`: the release restyles `node.x` and `node.y` with the node's new position as data (a date on a date axis, the nearest category on a category axis). `'force'`: the release pins the node, restyling its `node.x` and `node.y` and, with the picture on screen, `force.start`, so nothing else moves; with `force.simulate` the other nodes give way while it is dragged. A pinned node has a ring, and a double click releases it. A press that does not move is a click; a press on empty space is the chart's own drag (`dragmode`). Default: `true` for `'preset'` and `'force'` (not on a timeline), `false` for `'custom'`, whose layout gets the position as `graph.x` / `graph.y`. The nodes of the other arrangements do not drag.";
        editType: "plot";
     }>;
     group: AttrSpec<DataArray, DataArray | undefined>;
     hoverinfo: Attr<"all" | "none" | "skip", {
        description: `Hover of ${string}: labels (`'all'`), events without labels (`'none'`) or no hover and no events (`'skip'`). Default: the trace `hoverinfo`.`;
        dflt: "all";
        editType: "none";
        values: readonly ["all", "none", "skip"];
     }>;
     hovertemplate: Attr<string, {
        description: "Template of the node hover labels: `%{label}`, `%{degree}`, `%{indegree}`, `%{outdegree}`, `%{neighbors}` (the number of nodes it is linked to), `%{group}`, `%{value}`, `%{size}`, `%{color}`, `%{x}`, `%{y}`, `%{customdata}`. `<extra>…</extra>` replaces the trace name.";
        editType: "none";
     }>;
     label: AttrSpec<DataArray, DataArray | undefined>;
     line: ObjectNode<{
        color: Attr<string | readonly string[], {
           arrayOk: true;
           description: "Outline color of the nodes, or one per node. Default: the plot background, so that nodes stand out from the links and from each other.";
           editType: "style";
        }>;
        width: Attr<
           | number
           | TypedArray
           | readonly number[], {
           arrayOk: true;
           description: "Outline width of the nodes in CSS px, or one per node.";
           dflt: 1;
           editType: "style";
           min: 0;
        }>;
     }>;
     opacity: Attr<
        | number
        | TypedArray
        | readonly number[], {
        arrayOk: true;
        description: "Node opacity (multiplied by the trace `opacity`), or one per node.";
        dflt: 1;
        editType: "style";
        max: 1;
        min: 0;
     }>;
     reversescale: AttrSpec<boolean, boolean>;
     shape: Attr<"marker" | "box", {
        description: "How nodes are drawn: a marker (`node.symbol`, `node.size`) with the label next to it, or a box as large as the label with the text inside (`'box'`; diagrams such as pipelines and state machines). Default: `'box'` with `arrangement: 'layered'` when the nodes have labels, else `'marker'`.";
        dflt: "marker";
        editType: "calc";
        values: readonly ["marker", "box"];
     }>;
     showscale: AttrSpec<boolean, boolean>;
     size: Attr<
        | number
        | TypedArray
        | readonly number[], {
        arrayOk: true;
        description: "Node diameter in CSS px, or one per node. Ignored with `node.sizeby` and for box nodes. Default: 10, and 6 in a `'dendrogram'`, whose nodes are points on a scale.";
        dflt: 10;
        editType: "calc";
        min: 0;
     }>;
     sizeby: Attr<"none" | "degree" | "indegree" | "outdegree", {
        description: "Size nodes by their links instead of `node.size`: `'degree'` (all links at the node), `'indegree'` (links that end at it) or `'outdegree'` (links that start at it). The area grows with the count, between the two diameters of `node.sizerange`.";
        dflt: "none";
        editType: "calc";
        values: readonly ["none", "degree", "indegree", "outdegree"];
     }>;
     sizerange: AttrSpec<[number, number], [number, number]>;
     symbol: Attr<
        | PrimitiveValue
        | readonly PrimitiveValue[], {
        accepts: (value) => boolean;
        arrayOk: true;
        description: "Marker symbol: a name (`'diamond-open'`), a Plotly numeric code, a custom symbol registered with `symbols.register` (with the same `-open` / `-dot` variants), a `'text:…'` glyph such as `'text:🚀'`, or one per point.";
        dflt: "circle";
        editType: "style";
        values: readonly PrimitiveValue[];
     }>;
     textfont: ObjectNode<{
        color: Attr<string, {
           description: "Text color. Default: `layout.font.color`; inside a box node, black or white, whichever reads better on the box.";
           editType: "plot";
        }>;
        family: Attr<string, {
           description: "CSS font-family list. Default: `layout.font.family`.";
           editType: "calc";
           noBlank: true;
           strict: true;
        }>;
        shadow: Attr<string, {
           description: "CSS `text-shadow` (first shadow only), `'none'`, or `'auto'` (the default): a thin halo in the text's contrast color, so labels read over the links.";
           editType: "plot";
        }>;
        size: Attr<number, {
           description: "Font size in CSS px. Default: `layout.font.size`.";
           editType: "calc";
           min: 1;
        }>;
        style: Attr<"normal" | "italic", {
           description: "Font style.";
           editType: "calc";
           values: readonly ["normal", "italic"];
        }>;
        weight: Attr<number | "normal" | "bold", {
           description: "Font weight: a CSS numeric weight (1–1000), `normal` or `bold`.";
           editType: "calc";
           extras: readonly ["normal", "bold"];
           max: 1000;
           min: 1;
        }>;
     }>;
     textposition: Attr<
        | "none"
        | "auto"
        | "top left"
        | "top center"
        | "top right"
        | "middle left"
        | "middle center"
        | "middle right"
        | "bottom left"
        | "bottom center"
        | "bottom right", {
        description: "Where the label sits relative to its marker. `'auto'`: where the arrangement leaves room. To the right of the node in general; pointing away from the center around a `'circular'` arrangement; in a tree, beyond a leaf and before a node with children (turned upright under the leaves of a tree that grows downwards or upwards, and along the radius in a `'radial'` tree, never upside down); under the line of an `'arc'` diagram, upright; beside the axes of a `'hive'` plot. `'none'` draws no labels (they still show in hover labels). Box nodes have their label inside.";
        dflt: "auto";
        editType: "calc";
        values: readonly ["auto", "top left", "top center", "top right", "middle left", "middle center", "middle right", "bottom left", "bottom center", "bottom right", "none"];
     }>;
     value: AttrSpec<DataArray, DataArray | undefined>;
     x: AttrSpec<DataArray, DataArray | undefined>;
     y: AttrSpec<DataArray, DataArray | undefined>;
  }>;
  parents: AttrSpec<DataArray, DataArray | undefined>;
  selected: ObjectNode<{
     node: ObjectNode<{
        color: Attr<string, {
           description: "Color of selected nodes." | "Color of unselected nodes.";
           editType: "style";
        }>;
        opacity: Attr<number, {
           description:   | "Opacity of selected nodes."
              | "Opacity of selected nodes. Default: 0.2 × the node opacity when no selected or unselected opacity is set."
              | "Opacity of unselected nodes."
              | "Opacity of unselected nodes. Default: 0.2 × the node opacity when no selected or unselected opacity is set.";
           editType: "style";
           max: 1;
           min: 0;
        }>;
     }>;
  }>;
  tree: ObjectNode<{
     collapsed: AttrSpec<DataArray, DataArray | undefined>;
     collapsible: Attr<boolean, {
        description: "A click on a node that has children folds its subtree away, and a second click unfolds it. The chart then updates `tree.collapsed` itself and emits `restyle`, as for any change made on the chart, and the tree moves to its new shape (at once without motion: `prefers-reduced-motion`, `config.a11y.reducedMotion`).";
        dflt: true;
        editType: "plot";
     }>;
     links: Attr<"straight" | "curved" | "elbow", {
        description: "The shape of the tree's links: straight lines, S-shaped curves (`'curved'`) or right angles (`'elbow'`; in a `'radial'` tree, along the rings). Default: `'curved'`, and `'elbow'` for a dendrogram, which has no curves.";
        editType: "calc";
        values: readonly ["straight", "curved", "elbow"];
     }>;
     nodesep: Attr<number, {
        description: "Room between two neighbours on a level (on a ring for `'radial'`; between two leaves for `'dendrogram'`), on top of their sizes and of their labels, in layout units. Default: 10, or 20 for box nodes.";
        editType: "calc";
        min: 0;
     }>;
     orientation: Attr<"TB" | "BT" | "LR" | "RL", {
        description: "`'tree'` and `'dendrogram'`: where the root is and which way the tree grows: `'TB'` (root at the top), `'BT'`, `'LR'` (root on the left) or `'RL'`. Default: `'LR'` for a tree, whose labels then read along the levels, and `'TB'` for a dendrogram, whose heights are then on the y axis.";
        editType: "calc";
        values: readonly ["TB", "BT", "LR", "RL"];
     }>;
     ranksep: Attr<number, {
        description: "Room between two levels (two rings for `'radial'`), in layout units; a dendrogram without `node.value` has levels this far apart. Default: 50, plus room for the labels that are drawn between the levels.";
        editType: "calc";
        min: 0;
     }>;
     sector: ObjectNode<{
        span: Attr<number, {
           description: "How far around the tree goes, in degrees; negative values run clockwise. 180 is a half circle.";
           dflt: 360;
           editType: "calc";
           max: 360;
           min: -360;
        }>;
        start: Attr<number, {
           description: "Angle at which the tree begins, in degrees counter-clockwise from 3 o'clock.";
           dflt: 0;
           editType: "calc";
        }>;
     }>;
     sort: Attr<"input" | "value" | "size", {
        description: "The order of the children of a node: as given (`'input'`), by the number of nodes below them (`'size'`) or by `node.value`.";
        dflt: "input";
        editType: "calc";
        values: readonly ["input", "size", "value"];
     }>;
     sortorder: Attr<"descending" | "ascending", {
        description: "Which way `sort: 'size'` and `'value'` order: largest first, or smallest first.";
        dflt: "descending";
        editType: "calc";
        values: readonly ["descending", "ascending"];
     }>;
     subtreesep: Attr<number, {
        description: "`'tree'` and `'radial'`: room between two neighbours that have different parents. Default: `nodesep`.";
        editType: "calc";
        min: 0;
     }>;
  }>;
  unselected: ObjectNode<{
     node: ObjectNode<{
        color: Attr<string, {
           description: "Color of selected nodes." | "Color of unselected nodes.";
           editType: "style";
        }>;
        opacity: Attr<number, {
           description:   | "Opacity of selected nodes."
              | "Opacity of selected nodes. Default: 0.2 × the node opacity when no selected or unselected opacity is set."
              | "Opacity of unselected nodes."
              | "Opacity of unselected nodes. Default: 0.2 × the node opacity when no selected or unselected opacity is set.";
           editType: "style";
           max: 1;
           min: 0;
        }>;
     }>;
  }>;
  worker: Attr<boolean | "auto", {
     description: "Where the layout is computed. `false`: with the rest of the figure, on the main thread; the chart is drawn once, laid out, and the page waits until then (a `'force'` layout of 10,000 nodes takes a second or more). `true`: off the main thread, in the package's layout worker. The chart is drawn at once, a `'force'` layout with the nodes moving to their places as the worker reports them, any other with its nodes on a circle until the layout arrives; the axes are fitted to the result when it is there, `chart.ready` and the promise of the update resolve then, and an image export waits for it. The result is the same picture as with `false`. `'auto'`: off the main thread where the wait would be felt: a `'force'` layout of at least 1,000 nodes or 5,000 links, a `'layered'` one of at least 3,000 nodes or 6,000 links, and force-directed link bundling (`link.bundle`) of at least 1,000 links. Never in the worker: `'preset'`, `'circular'`, `'grid'` and `'custom'` (a registered layout is a function of the page), a timeline or a dendrogram with a real axis, and `force.start` at rest. Hover and selection answer for what is on screen while the nodes move; nodes are dragged once the layout is there. Where no worker can be started (no `Worker`, a Content Security Policy, a bundler that left the file out) the same code runs on the main thread in slices of a few milliseconds, with one warning. Default: `config.worker`, which is `false`.";
     dflt: false;
     editType: "calc";
     values: readonly ["auto", true, false];
  }>;
  zorder: Attr<number, {
     description: "Stacking order among the traces of a subplot: higher is drawn on top. At equal `zorder`, scatter traces draw above bars (Plotly’s layer order), then in trace order.";
     dflt: 0;
     editType: "plot";
  }>;
}>;

Experimental

The graph schema.

Released under the MIT License.