LAWSOFUX · motion lab
Concept · law-of-uniform-connectedness

Law of Uniform Connectedness

Center-out radial pulse palette · cobalt / cream takeaways · 3

Definition

Elements joined by a visible connector — line, arrow, frame, ribbon — read as more strongly related than elements that are merely near or similar. Explicit connection beats implicit grouping. The connection itself does meaning work.

Why it matters for ShurIQ reports

Evidence trails (claim → evidence → source) and value-flow diagrams are exactly the surfaces where uniform connectedness earns its keep. A faint hairline from a stack-rank row to its supporting chart, or from a gap card to its source citation, makes the relationship undeniable. In a network viewport, edge styling carries as much meaning as node styling.

Takeaways

Visual motion language

Connectors animate in as a trail behind the connected elements — line draws from source to target with a 200ms ease. Parallel rays for sibling connections share timing for legibility.

Cavalry recreation seed. Within a 576×566 panel, draw 4 concentric circle outlines (stroke #f4f1d0 cream, 3px) at radii 281 / 206 / 133 / 59, centered at (283, 283). For each ring, place 3 small filled cream circles (radius 12) at fixed angular positions on or just off the ring's circumference (e.g. ring 1 at 12°/210°/305°; ring 2 at 80°/200°/350°; ring 3 at 60°/180°/300°; ring 4 at 30°/130°/240°). Animate ring + its 3 dots together, outer-to-inner, ~250ms per ring, total 1s. Hold 2.5s; loop. Background: deep cobalt #1A4373. NO radial spokes.

Origins

Gestalt psychology — added to the principles of grouping by later perceptual researchers.

Cavalry scene

The script below builds this concept's motion in Cavalry through the Stallion bridge. Pipe to cavalry_run_script via MCP, or paste into Cavalry's JavaScript Editor.

// Laws of UX · law-of-uniform-connectedness · Cavalry scene
// CORRECTED 2026-04-30 · verified from production page
// Motion family: nested concentric rings (NOT a starburst)
// 4 ring outlines, each carrying 3 small dots; outer-to-inner reveal
// Palette: deep cobalt + cream
// To run: pipe to cavalry_run_script tool, or paste into Cavalry's JavaScript Editor
// Built 2026-04-30 by ShurAI

(function () {
  var PREFIX = "claude_lawofux_law-of-uniform-connectedness_";

  var existing = api.getAllSceneLayers();
  for (var i = 0; i < existing.length; i++) {
    try {
      var nm = api.getNiceName(existing[i]);
      if (nm && nm.indexOf("claude_lawofux_") === 0) api.deleteLayer(existing[i]);
    } catch (e) {}
  }

  var BG    = "#1A4373";
  var CREAM = "#D6CDB0";

  var bg = api.primitive("rectangle", PREFIX + "bg");
  api.set(bg, { "generator.dimensions": [1080, 1080] });
  api.setFill(bg, true);
  api.set(bg, { "material.materialColor": BG });

  // 4 rings, outer-to-inner reveal. Radii proportional to verified 281/206/133/59 within 1080 canvas.
  // Scale factor ~1.5 -> radii 420/310/200/90
  var rings = [
    { radius: 420, angles: [12, 210, 305], beat: 0  },
    { radius: 310, angles: [80, 200, 350], beat: 8  },
    { radius: 200, angles: [60, 180, 300], beat: 16 },
    { radius:  90, angles: [30, 130, 240], beat: 24 }
  ];
  var STROKE_W = 4;

  for (var k = 0; k < rings.length; k++) {
    var ring = rings[k];

    // Ring as ellipse with stroke only
    var ringId = api.primitive("ellipse", PREFIX + "ring_" + k);
    api.set(ringId, {
      "generator.radius": [ring.radius, ring.radius],
      "position.x": 0, "position.y": 0,
      "opacity": 0
    });
    api.setFill(ringId, false);
    api.setStroke(ringId, true);
    api.set(ringId, {
      "stroke.strokeColor": CREAM,
      "stroke.width": STROKE_W
    });
    api.keyframe(ringId, ring.beat,      { "opacity": 0 });
    api.keyframe(ringId, ring.beat + 10, { "opacity": 100 });
    api.magicEasing(ringId, "opacity", ring.beat + 10, "EaseOut", "");

    // 3 dots placed on this ring
    for (var d = 0; d < 3; d++) {
      var rad = ring.angles[d] * Math.PI / 180;
      var dx = Math.cos(rad) * ring.radius;
      var dy = Math.sin(rad) * ring.radius; // Y positive=up: positive sin for upper-right? OK
      var dot = api.primitive("ellipse", PREFIX + "ring_" + k + "_dot_" + d);
      api.set(dot, {
        "generator.radius": [18, 18],
        "position.x": dx,
        "position.y": dy,
        "opacity": 0
      });
      api.setFill(dot, true);
      api.set(dot, { "material.materialColor": CREAM });
      api.keyframe(dot, ring.beat,      { "opacity": 0 });
      api.keyframe(dot, ring.beat + 10, { "opacity": 100 });
      api.magicEasing(dot, "opacity", ring.beat + 10, "EaseOut", "");
    }
  }

  var layerCount = api.getAllSceneLayers().length;
  console.log("scene built: law-of-uniform-connectedness (" + layerCount + " layers)");
})();