Skip to content

Layout Configuration

The <xcode-graph> component uses a two-phase hierarchical layout:

  1. Macro layout (ELK) — positions clusters (groups of related nodes) using the ELK layered algorithm
  2. Micro layout (D3-force) — positions nodes within each cluster using force-directed simulation

You can customize both phases via the layoutOptions property.

LayoutOptions

ts
interface LayoutOptions {
  configOverrides?: Partial<LayoutConfig>;
  hooks?: LayoutHooks;
}
FieldTypeDescription
configOverridesPartial<LayoutConfig>Override any layout configuration parameter
hooksLayoutHooksLifecycle hooks for observing or reacting to layout stages

Usage

js
const app = document.querySelector('xcode-graph');

app.layoutOptions = {
  configOverrides: {
    elkDirection: 'RIGHT',
    elkNodeSpacing: 300,
    elkLayerSpacing: 400,
    iterations: 500,
  },
  hooks: {
    onLayoutComplete: (result) => {
      console.log('Layout done:', result.clusters.length, 'clusters');
    },
  },
};

LayoutConfig

All available configuration parameters with their default values. Pass any subset of these as configOverrides.

ELK Macro Layout

These parameters control the cluster-level layout computed by ELK.js.

ParameterTypeDefaultDescription
elkDirection'DOWN' | 'RIGHT''DOWN'Direction of flow. 'DOWN' = top-to-bottom, 'RIGHT' = left-to-right.
elkAlgorithmstring'layered'ELK layout algorithm. 'layered' is best for dependency graphs.
elkEdgeRouting'ORTHOGONAL' | 'SPLINES''ORTHOGONAL'Edge routing style. 'ORTHOGONAL' = rectilinear, 'SPLINES' = curved.
elkNodeSpacingnumber200Spacing between nodes in the same layer (pixels).
elkLayerSpacingnumber300Spacing between layers/ranks (pixels).
elkPaddingnumber100Padding around clusters (pixels).
elkMergeEdgesbooleantrueSimplify edge routing by merging ports.
elkMaxWidthnumber2000Maximum width target for wrapping.
elkMaxHeightnumber2000Maximum height target for wrapping.
elkHierarchyHandling'INHERIT' | 'INCLUDE_CHILDREN' | 'SEPARATE_CHILDREN''SEPARATE_CHILDREN'How ELK handles hierarchy within clusters.

D3-Force Micro Layout

These parameters control the per-cluster interior node positioning using D3 force simulation.

ParameterTypeDefaultDescription
nodeRadiusnumber6Base node radius (pixels).
nodeCollisionPaddingnumber20Extra padding around nodes to prevent overlap.
linkDistancenumber45Desired distance between linked nodes.
linkStrengthnumber0.35Strength of link forces (0–1).
nodeChargenumber-35Repulsion force between nodes. Negative = repel.
ParameterTypeDefaultDescription
crossClusterDistanceMulnumber3.5Multiplier for cross-cluster link distance.
crossClusterStrengthMulnumber0.02Multiplier for cross-cluster link strength.

Cluster Forces

ParameterTypeDefaultDescription
clusterStrengthnumber0.3Attraction strength toward cluster center.
clusterDistanceMinnumber20Minimum distance before cluster force activates.
clusterRepulsionStrengthnumber8000Repulsion strength between clusters.
clusterPaddingnumber120Padding inside cluster boundaries.
clusterAttractionStrengthnumber0.2Attraction strength between related clusters.
clusterAttractionActivationDistnumber500Distance threshold for cluster attraction.
clusterRepulsionYScalenumber0.2Y-axis scaling for cluster repulsion.

Cluster Strata

ParameterTypeDefaultDescription
clusterStrataSpacingnumber800Vertical spacing between cluster strata.
clusterHorizontalSpacingnumber120Horizontal spacing between clusters in a row.
clusterMaxRowWidthnumber900Maximum width before wrapping to next row.
clusterStrataAnchorStrengthnumber0.8Anchor strength pulling clusters to strata positions.

Layer/Stratum

ParameterTypeDefaultDescription
layerSpacingnumber120Vertical spacing between node layers.
layerStrengthnumber0.35Force strength pushing nodes to their assigned layer.

Dependency Hang Force

ParameterTypeDefaultDescription
hangGapnumber72Vertical gap for dependency hang positioning.
hangStrengthnumber0.08Strength of the dependency hang force.

Radial Force

ParameterTypeDefaultDescription
radialStrengthnumber0.25Strength of radial force pushing nodes toward cluster interior.

Simulation

ParameterTypeDefaultDescription
iterationsnumber300Number of force simulation iterations. Higher = more stable but slower.

Cluster Sizing

ParameterTypeDefaultDescription
minClusterSizenumber60Minimum cluster size (pixels).
clusterNodeSpacingnumber12Spacing between nodes within a cluster.

Edge Bundling

ParameterTypeDefaultDescription
bundlingCyclesnumber5Number of edge bundling cycles.
bundlingIterationsnumber80Iterations per bundling cycle.
compatibilityThresholdnumber0.65Edge compatibility threshold for bundling (0–1). Higher = fewer bundles.
bundlingBudgetnumber40000Maximum edge pairs to consider for bundling.

Drift Prevention

ParameterTypeDefaultDescription
clusterCenteringStrengthnumber0.75Strength of force centering clusters.
clusterBoundingRadiusnumber1200Maximum bounding radius for cluster positions.
clusterBoundingStrengthnumber0.5Strength of bounding force.
clusterStrataAlignmentStrengthnumber0.45Strength of strata alignment force.

Port Routing

ParameterTypeDefaultDescription
portRoutingEnabledbooleantrueEnable port-based edge routing for cross-cluster edges.
portSpacingnumber20Minimum spacing between ports on a cluster boundary.
portMarginnumber30Margin from cluster corners for port placement.
maxPortsPerSidenumber8Maximum number of ports per side to prevent overcrowding.

LayoutHooks

Lifecycle hooks for observing or reacting to layout computation stages.

ts
interface LayoutHooks {
  onBeforeLayout?: (nodes: GraphNode[], edges: GraphEdge[]) => void;
  onAfterMicroLayout?: (clusters: Cluster[]) => void;
  onLayoutComplete?: (result: HierarchicalLayoutResult) => void;
}
HookParametersDescription
onBeforeLayoutnodes: GraphNode[], edges: GraphEdge[]Called before layout computation starts. Useful for logging or pre-processing.
onAfterMicroLayoutclusters: Cluster[]Called after per-cluster interior layout completes.
onLayoutCompleteresult: HierarchicalLayoutResultCalled when layout is fully complete. The result contains all node/cluster positions, routed edges, and cycle detection data.

Example: Logging Layout Performance

js
const start = performance.now();

app.layoutOptions = {
  hooks: {
    onBeforeLayout: (nodes, edges) => {
      console.log(`Starting layout: ${nodes.length} nodes, ${edges.length} edges`);
    },
    onLayoutComplete: (result) => {
      const elapsed = performance.now() - start;
      console.log(`Layout complete in ${elapsed.toFixed(0)}ms`);
      console.log(`Clusters: ${result.clusters.length}`);
      if (result.cycleNodes?.size) {
        console.warn(`Circular dependencies: ${result.cycleNodes.size} nodes in cycles`);
      }
    },
  },
};