Skip to content

Visual Action Types

Visual actions are the rendering instructions embedded in each step. They tell the rendering engine what to display when a step is active. Every visual action has a type field (camelCase string) and action-specific parameters.

Visual actions use an open vocabulary — the type field is a plain string, not a closed enum. Renderers silently ignore action types they do not recognize. This allows new action types to be defined in generators before renderer support exists.

interface VisualAction {
readonly type: string;
readonly [key: string]: unknown;
}

All parameter values must be JSON-serializable.


These are the fundamental actions used by classical algorithm visualizations (sorting, searching).

TypeParametersDescriptionUsed By
highlightElementindex: number, color?: stringHighlight a single element (array cell, graph node). Default color: "highlight".Binary search, bubble sort, quicksort, merge sort
movePointerid: string, to: numberMove a named pointer to a new position. id identifies the pointer (e.g., "left", "right", "mid").Binary search, quicksort
highlightRangefrom: number, to: number, color?: stringHighlight a contiguous range of elements (inclusive on both ends). Constraint: from <= to.Binary search, merge sort, quicksort
dimRangefrom: number, to: numberVisually de-emphasize a contiguous range. Constraint: from <= to.Binary search
swapElementsi: number, j: numberSwap two elements. Both indices are 0-based.Bubble sort, quicksort
compareElementsi: number, j: number, result: "less" | "greater" | "equal"Visually compare two elements and show the comparison result.Bubble sort, binary search, merge sort
markFoundindex: numberMark an element as the found/target element.Binary search
markNotFound(none)Indicate that the target was not found. No specific index.Binary search
showMessagetext: string, messageType: "info" | "success" | "warning" | "error"Display a transient text message on the visualization.All algorithms
interface HighlightElementAction extends VisualAction {
readonly type: "highlightElement";
readonly index: number; // 0-based element index
readonly color?: string; // Semantic color: "highlight", "compare", "found", "active", "inactive"
}
interface MovePointerAction extends VisualAction {
readonly type: "movePointer";
readonly id: string; // Pointer name (e.g., "left", "right", "mid")
readonly to: number; // 0-based target index
}
interface HighlightRangeAction extends VisualAction {
readonly type: "highlightRange";
readonly from: number; // 0-based start index (inclusive)
readonly to: number; // 0-based end index (inclusive). Must satisfy: from <= to
readonly color?: string;
}
interface DimRangeAction extends VisualAction {
readonly type: "dimRange";
readonly from: number; // 0-based start index (inclusive)
readonly to: number; // 0-based end index (inclusive). Must satisfy: from <= to
}
interface SwapElementsAction extends VisualAction {
readonly type: "swapElements";
readonly i: number; // 0-based index of first element
readonly j: number; // 0-based index of second element
}
interface CompareElementsAction extends VisualAction {
readonly type: "compareElements";
readonly i: number;
readonly j: number;
readonly result: "less" | "greater" | "equal";
}
interface MarkFoundAction extends VisualAction {
readonly type: "markFound";
readonly index: number; // 0-based index of the found element
}
interface MarkNotFoundAction extends VisualAction {
readonly type: "markNotFound";
// No additional parameters
}
interface ShowMessageAction extends VisualAction {
readonly type: "showMessage";
readonly text: string;
readonly messageType: "info" | "success" | "warning" | "error";
}

Actions for graph-based algorithm visualizations (BFS, DFS, Dijkstra).

TypeParametersDescriptionUsed By
visitNodenodeId: string, color?: stringMark a graph node as visited. Default color: "visited".BFS, DFS, Dijkstra
highlightEdgefrom: string, to: string, color?: stringHighlight an edge between two nodes. Default color: "highlight".BFS, DFS, Dijkstra
updateNodeValuenodeId: string, value: number | string | nullUpdate the displayed value of a node (e.g., distance in Dijkstra). null clears the value.Dijkstra
interface VisitNodeAction extends VisualAction {
readonly type: "visitNode";
readonly nodeId: string; // Unique node identifier within the graph
readonly color?: string; // Default: "visited"
}
interface HighlightEdgeAction extends VisualAction {
readonly type: "highlightEdge";
readonly from: string; // Source node ID
readonly to: string; // Target node ID
readonly color?: string; // Default: "highlight"
}
interface UpdateNodeValueAction extends VisualAction {
readonly type: "updateNodeValue";
readonly nodeId: string;
readonly value: number | string | null; // null clears the display value
}

Actions for neural network visualizations (forward propagation, backpropagation, training).

TypeParametersDescriptionUsed By
activateNeuronlayer: number, index: number, value: numberActivate (light up) a neuron in a network layer.Forward propagation
propagateSignalfromLayer: number, toLayer: numberShow signal propagating between layers.Forward propagation
showGradientlayer: number, values: number[]Display gradient values for a layer (one per neuron).Backpropagation
showWeightsfromLayer: number, toLayer: number, weights: number[][]Show weight values on connections. Shape: [toLayerSize, fromLayerSize].Forward propagation, training
showWeightGradientsfromLayer: number, toLayer: number, gradients: number[][]Show weight gradient values. Shape: [toLayerSize, fromLayerSize]. gradients[j][i] = dLoss/dw_ji.Backpropagation
showBiasGradientslayer: number, biasGradients: number[]Show bias gradient values. biasGradients[j] = dLoss/db_j.Backpropagation
updateWeightsfromLayer: number, toLayer: number, oldWeights: number[][], newWeights: number[][], learningRate: numberShow weight update after gradient descent.Training
showPreActivationlayer: number, index: number, z: number, weightedInputs: number[], bias: numberShow pre-activation value: z = sum(w_i * x_i) + b.Forward propagation
showActivationFunctionlayer: number, index: number, functionName: string, input: number, output: numberShow activation function being applied: a = f(z).Forward propagation
showLossloss: number, lossFunction: string, predictions: number[], targets: number[]Show the computed loss value.Training
interface ActivateNeuronAction extends VisualAction {
readonly type: "activateNeuron";
readonly layer: number; // 0-based layer index
readonly index: number; // 0-based neuron index within the layer
readonly value: number; // Activation value (typically 0-1, but not constrained)
}
interface PropagateSignalAction extends VisualAction {
readonly type: "propagateSignal";
readonly fromLayer: number; // 0-based source layer index
readonly toLayer: number; // 0-based target layer index
}
interface ShowGradientAction extends VisualAction {
readonly type: "showGradient";
readonly layer: number;
readonly values: readonly number[]; // One gradient value per neuron
}
interface ShowWeightsAction extends VisualAction {
readonly type: "showWeights";
readonly fromLayer: number;
readonly toLayer: number;
readonly weights: readonly (readonly number[])[]; // Shape: [toLayerSize, fromLayerSize]
// weights[j][i] = weight from neuron i in fromLayer to neuron j in toLayer
}
interface ShowWeightGradientsAction extends VisualAction {
readonly type: "showWeightGradients";
readonly fromLayer: number;
readonly toLayer: number;
readonly gradients: readonly (readonly number[])[]; // Shape: [toLayerSize, fromLayerSize]
// gradients[j][i] = dLoss/dw_ji = delta_j * a_i
}
interface ShowBiasGradientsAction extends VisualAction {
readonly type: "showBiasGradients";
readonly layer: number;
readonly biasGradients: readonly number[]; // biasGradients[j] = dLoss/db_j = delta_j
}
interface UpdateWeightsAction extends VisualAction {
readonly type: "updateWeights";
readonly fromLayer: number;
readonly toLayer: number;
readonly oldWeights: readonly (readonly number[])[]; // Before update
readonly newWeights: readonly (readonly number[])[]; // After update
readonly learningRate: number;
// newWeights[j][i] = oldWeights[j][i] - learningRate * dLoss/dw_ji
}
interface ShowPreActivationAction extends VisualAction {
readonly type: "showPreActivation";
readonly layer: number;
readonly index: number;
readonly z: number; // Pre-activation: z = sum(w_i * x_i) + b
readonly weightedInputs: readonly number[]; // Individual terms: w_i * x_i
readonly bias: number; // Bias term
}
interface ShowActivationFunctionAction extends VisualAction {
readonly type: "showActivationFunction";
readonly layer: number;
readonly index: number;
readonly functionName: "sigmoid" | "relu" | "tanh" | "step";
readonly input: number; // z (pre-activation)
readonly output: number; // a = activation_fn(z)
}
interface ShowLossAction extends VisualAction {
readonly type: "showLoss";
readonly loss: number;
readonly lossFunction: "mse" | "binary-cross-entropy";
readonly predictions: readonly number[];
readonly targets: readonly number[];
}

Actions for convolution operation visualizations.

TypeParametersDescriptionUsed By
highlightKernelPositionrow: number, col: number, kernelHeight: number, kernelWidth: numberHighlight the current position of the convolution kernel on the input grid.2D Convolution
showConvolutionProductsrow: number, col: number, products: number[][], sum: numberShow element-wise products between kernel and input patch at the current position.2D Convolution
writeOutputCellrow: number, col: number, value: numberWrite a computed value into the output feature map.2D Convolution
interface HighlightKernelPositionAction extends VisualAction {
readonly type: "highlightKernelPosition";
readonly row: number; // Top-left row of kernel window on input
readonly col: number; // Top-left column of kernel window on input
readonly kernelHeight: number; // Kernel height
readonly kernelWidth: number; // Kernel width
}
interface ShowConvolutionProductsAction extends VisualAction {
readonly type: "showConvolutionProducts";
readonly row: number;
readonly col: number;
readonly products: readonly (readonly number[])[];
// products[kr][kc] = input[row + kr][col + kc] * kernel[kr][kc]
readonly sum: number; // Sum of all products -- becomes the output value
}
interface WriteOutputCellAction extends VisualAction {
readonly type: "writeOutputCell";
readonly row: number; // Row in the output feature map
readonly col: number; // Column in the output feature map
readonly value: number; // Computed value to write
}

Actions for gradient descent and optimizer visualizations.

TypeParametersDescriptionUsed By
showLandscapePositionparameters: number[], loss: number, gradient: number[]Show the current position on the loss landscape.Gradient descent
showDescentStepfromParameters: number[], toParameters: number[], fromLoss: number, toLoss: number, optimizer: string, learningRate: numberShow a gradient descent step from current to new position.Gradient descent
showTrajectorytrajectory: {parameters: number[], loss: number}[], optimizer: stringShow the trajectory of all visited positions.Gradient descent
showMomentumvelocity: number[], secondMoment?: number[]Show momentum/velocity vector. secondMoment is for Adam only.Gradient descent
interface ShowLandscapePositionAction extends VisualAction {
readonly type: "showLandscapePosition";
readonly parameters: readonly number[]; // Current parameter values
readonly loss: number; // Loss at this position
readonly gradient: readonly number[]; // Gradient vector at this position
}
interface ShowDescentStepAction extends VisualAction {
readonly type: "showDescentStep";
readonly fromParameters: readonly number[];
readonly toParameters: readonly number[];
readonly fromLoss: number;
readonly toLoss: number;
readonly optimizer: "sgd" | "momentum" | "adam";
readonly learningRate: number;
}
interface ShowTrajectoryAction extends VisualAction {
readonly type: "showTrajectory";
readonly trajectory: readonly {
readonly parameters: readonly number[];
readonly loss: number;
}[];
readonly optimizer: "sgd" | "momentum" | "adam";
}
interface ShowMomentumAction extends VisualAction {
readonly type: "showMomentum";
readonly velocity: readonly number[];
readonly secondMoment?: readonly number[]; // Adam only; omit for plain momentum
}

Actions for generative AI visualizations (tokenization, embeddings, attention mechanisms, transformer blocks).

TypeParametersDescriptionUsed By
showAttentionWeightsqueryIdx: number, weights: number[]Show attention weights from a query token to all keys. Weights must sum to 1.0 (within 1e-6).Self-attention, multi-head attention
highlightTokenindex: number, color?: stringHighlight a token in a sequence.Tokenization, embeddings, attention
updateBarChartvalues: number[], labels?: string[]Update a bar chart (e.g., probability distributions). If labels provided, labels.length must equal values.length.Tokenization
highlightTextSpanstart: number, end: number, color?: stringHighlight characters in source text. start inclusive, end exclusive.BPE tokenization
mergeTokensleftIndex: number, rightIndex: number, result: stringShow a BPE merge of two adjacent tokens.BPE tokenization
showEmbeddingtokenIndex: number, values: number[]Display an embedding vector for a token.Token embeddings
showSimilaritytokenA: number, tokenB: number, score: numberShow cosine similarity between two embeddings. Score in [-1, 1].Token embeddings
showProjectionMatrixprojectionType: "Q" | "K" | "V", matrix: number[][]Show Q, K, or V projection matrix. Shape: [seqLen, d_k].Self-attention
showAttentionScoresscores: number[][]Show raw (pre-softmax) attention scores. Shape: [seqLen, seqLen]. scores[i][j] = Q[i] . K[j]^T / sqrt(d_k).Self-attention
showFullAttentionMatrixweights: number[][]Show full attention matrix after softmax. Each row sums to 1.0.Self-attention
showWeightedValuesqueryIdx: number, contextVector: number[]Show weighted value vectors (attention output) for a query.Self-attention
activateHeadheadIndex: number, totalHeads: numberActivate a specific attention head.Multi-head attention
showConcatenatedHeadsmatrix: number[][]Show concatenated multi-head output. Shape: [seqLen, numHeads * d_v].Multi-head attention
activateSublayersublayerId: string, label: stringShow data flowing through a transformer sublayer.Transformer block
showResidualConnectioninput: number[], sublayerOutput: number[], result: number[]Show residual connection: result = input + sublayerOutput.Transformer block
showLayerNorminput: number[], output: number[]Show layer normalization. Output has mean ~0, variance ~1.Transformer block
interface ShowAttentionWeightsAction extends VisualAction {
readonly type: "showAttentionWeights";
readonly queryIdx: number;
readonly weights: readonly number[];
// Invariant: Math.abs(weights.reduce((a, b) => a + b, 0) - 1.0) <= 1e-6
// Each weight must be in [0, 1]
}
interface HighlightTokenAction extends VisualAction {
readonly type: "highlightToken";
readonly index: number; // 0-based token index
readonly color?: string; // Default: "highlight"
}
interface UpdateBarChartAction extends VisualAction {
readonly type: "updateBarChart";
readonly values: readonly number[];
readonly labels?: readonly string[]; // Must match values.length if provided
}
interface HighlightTextSpanAction extends VisualAction {
readonly type: "highlightTextSpan";
readonly start: number; // 0-based start character index (inclusive)
readonly end: number; // 0-based end character index (exclusive)
readonly color?: string;
}
interface MergeTokensAction extends VisualAction {
readonly type: "mergeTokens";
readonly leftIndex: number; // 0-based index of left token
readonly rightIndex: number; // 0-based index of right token
readonly result: string; // The resulting merged token string
}
interface ShowEmbeddingAction extends VisualAction {
readonly type: "showEmbedding";
readonly tokenIndex: number;
readonly values: readonly number[]; // Length equals d_model
}
interface ShowSimilarityAction extends VisualAction {
readonly type: "showSimilarity";
readonly tokenA: number;
readonly tokenB: number;
readonly score: number; // Cosine similarity in [-1, 1]
// score = (A . B) / (||A|| * ||B||)
}
interface ShowProjectionMatrixAction extends VisualAction {
readonly type: "showProjectionMatrix";
readonly projectionType: "Q" | "K" | "V";
readonly matrix: readonly (readonly number[])[]; // Shape: [seqLen, d_k]
}
interface ShowAttentionScoresAction extends VisualAction {
readonly type: "showAttentionScores";
readonly scores: readonly (readonly number[])[]; // Shape: [seqLen, seqLen]
// scores[i][j] = (Q[i] . K[j]) / sqrt(d_k)
}
interface ShowFullAttentionMatrixAction extends VisualAction {
readonly type: "showFullAttentionMatrix";
readonly weights: readonly (readonly number[])[]; // Shape: [seqLen, seqLen]
// Invariant: each row sums to 1.0 (within 1e-6)
}
interface ShowWeightedValuesAction extends VisualAction {
readonly type: "showWeightedValues";
readonly queryIdx: number;
readonly contextVector: readonly number[]; // Length: d_v
}
interface ActivateHeadAction extends VisualAction {
readonly type: "activateHead";
readonly headIndex: number; // 0-based head index
readonly totalHeads: number; // Total number of heads (for UI layout)
}
interface ShowConcatenatedHeadsAction extends VisualAction {
readonly type: "showConcatenatedHeads";
readonly matrix: readonly (readonly number[])[]; // Shape: [seqLen, numHeads * d_v]
}
interface ActivateSublayerAction extends VisualAction {
readonly type: "activateSublayer";
readonly sublayerId: string; // e.g., "self-attention", "add-norm-1", "ffn", "add-norm-2"
readonly label: string; // Human-readable label
}
interface ShowResidualConnectionAction extends VisualAction {
readonly type: "showResidualConnection";
readonly input: readonly number[]; // Input vector (d_model)
readonly sublayerOutput: readonly number[]; // Sublayer output (d_model)
readonly result: readonly number[]; // input + sublayerOutput (d_model)
// Invariant: Math.abs(result[j] - (input[j] + sublayerOutput[j])) <= 1e-9
}
interface ShowLayerNormAction extends VisualAction {
readonly type: "showLayerNorm";
readonly input: readonly number[]; // Before normalization (d_model)
readonly output: readonly number[]; // After normalization (d_model)
// Invariant (without learnable gamma/beta):
// Math.abs(mean(output)) <= 1e-6
// Math.abs(variance(output) - 1.0) <= 1e-4
}

For exhaustive switch statements in renderers, the KnownVisualAction type is a discriminated union of all known action interfaces:

type KnownVisualAction =
| HighlightElementAction
| MovePointerAction
| HighlightRangeAction
| DimRangeAction
| SwapElementsAction
| CompareElementsAction
| MarkFoundAction
| MarkNotFoundAction
| ShowMessageAction
| VisitNodeAction
| HighlightEdgeAction
| UpdateNodeValueAction
| ActivateNeuronAction
| PropagateSignalAction
| ShowGradientAction
| ShowWeightsAction
| ShowWeightGradientsAction
| ShowBiasGradientsAction
| UpdateWeightsAction
| ShowPreActivationAction
| ShowActivationFunctionAction
| ShowLossAction
| HighlightKernelPositionAction
| ShowConvolutionProductsAction
| WriteOutputCellAction
| ShowLandscapePositionAction
| ShowDescentStepAction
| ShowTrajectoryAction
| ShowMomentumAction
| ShowAttentionWeightsAction
| HighlightTokenAction
| UpdateBarChartAction
| HighlightTextSpanAction
| MergeTokensAction
| ShowEmbeddingAction
| ShowSimilarityAction
| ShowProjectionMatrixAction
| ShowAttentionScoresAction
| ShowFullAttentionMatrixAction
| ShowWeightedValuesAction
| ActivateHeadAction
| ShowConcatenatedHeadsAction
| ActivateSublayerAction
| ShowResidualConnectionAction
| ShowLayerNormAction;

Renderers must also handle unknown types gracefully (no-op) because the vocabulary is open.


To add a new visual action type:

  1. Define the interface in shared/types/step.ts, extending VisualAction.
  2. Add it to the KnownVisualAction union for type safety.
  3. Use it in a generator — no changes to the runner are needed (the runner does not inspect action types, except for validated types like highlightRange and showAttentionWeights).
  4. Implement renderer support — add a case to the renderer’s action handler. Until renderer support exists, the action is silently ignored.

No version bump is required for new action types because the open vocabulary design ensures backward compatibility. Renderers that do not recognize a new action type will simply skip it.

The generator runner validates the following action types at runtime:

Action TypeValidation Rule
highlightRangefrom <= to
dimRangefrom <= to
compareElementsresult is one of "less", "greater", "equal"
showAttentionWeightsEach weight in [0, 1]; weights sum to 1.0 within 1e-6 (Kahan summation)
updateBarChartIf labels present, labels.length === values.length

All other action types are passed through without validation. If you need validation for a custom action type, add it to the validateVisualActions function in GeneratorRunner.ts.