LAWSOFUX · motion lab
Concept · parkinsons-law

Parkinson's Law

Square / diamond inflate palette · warm tan / cream takeaways · 3

Definition

Any task expands to fill the time the user expects to spend on it. If a form is laid out to look like a 10-minute task, it will take 10 minutes — even if the underlying data could be entered in two. Users calibrate effort to perceived duration, not actual duration.

Why it matters for ShurIQ reports

A brief that signals "long read" will be skimmed in long-read posture; a brief that signals "five-minute briefing" will get five focused minutes. The reading surface must telegraph its expected duration honestly: a viz hub with five viewports tells the executive to budget five short engagements, not one long one. Likewise, autofill on filter rails and saved viewport states cut perceived effort and convert dropoff into completion.

Takeaways

Visual motion language

Form fields and filter rails count-up populated values from cached state with a 200ms reveal; the visible auto-completion communicates "this will be fast."

Cavalry recreation seed. Center diamond 320×320 (rotated square, 12px cream stroke). Center dot ø36 dark-olive. From each diamond corner project a chevron-arrow head that points outward, ~60px long, 12px stroke cream. Animate the 4 arrows scaling 0.7→1 with stagger=0 (sync) over 800ms, then scale back 1→0.7 over 800ms. Loop. Diamond and center remain static throughout.

Origins

Cyril Northcote Parkinson, 1955 — essay published in The Economist.

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 · parkinsons-law · Cavalry scene
// Motion family: single-form (diamond + 4 outward-pulsing arrows)
// Palette: olive-mustard + 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_parkinsons-law_";

  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    = "#8C7C45";
  var DARK  = "#6E5F2F";
  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 });

  // Diamond = rotated square outline
  var dia = api.primitive("rectangle", PREFIX + "diamond");
  api.set(dia, {
    "generator.dimensions": [320, 320],
    "position.x": 0, "position.y": 0,
    "rotation.z": 45,
    "opacity": 0
  });
  api.setFill(dia, false);
  api.setStroke(dia, true);
  api.set(dia, { "stroke.strokeColor": CREAM, "stroke.width": 12 });
  api.keyframe(dia, 0,  { "opacity": 0   });
  api.keyframe(dia, 18, { "opacity": 100 });

  // Center dot
  var cd = api.primitive("ellipse", PREFIX + "center");
  api.set(cd, {
    "generator.radius": [18, 18],
    "position.x": 0, "position.y": 0,
    "opacity": 0
  });
  api.setFill(cd, true);
  api.set(cd, { "material.materialColor": DARK });
  api.keyframe(cd, 6,  { "opacity": 0   });
  api.keyframe(cd, 22, { "opacity": 100 });

  // 4 corner arrows projecting outward (use triangles)
  // Diamond corners (after rotation 45°): top, right, bottom, left
  // distances ≈ half-diagonal of 320 square = ~226
  var d = 290;
  var arrows = [
    { x:  0, y:  d, rot:    0 },  // top → up
    { x:  d, y:  0, rot:   90 },  // right
    { x:  0, y: -d, rot:  180 },  // bottom
    { x: -d, y:  0, rot:  -90 }   // left
  ];

  for (var i = 0; i < arrows.length; i++) {
    var a = arrows[i];
    var arr = api.primitive("polygon", PREFIX + "arrow_" + i);
    api.set(arr, {
      "generator.sides": 3,
      "generator.radius": 36,
      "position.x": a.x, "position.y": a.y,
      "rotation.z": a.rot,
      "opacity": 0,
      "scale.x": 0.7, "scale.y": 0.7
    });
    api.setFill(arr, true);
    api.set(arr, { "material.materialColor": CREAM });

    api.keyframe(arr, 18, { "opacity": 0,   "scale.x": 0.7, "scale.y": 0.7 });
    api.keyframe(arr, 36, { "opacity": 100, "scale.x": 1.0, "scale.y": 1.0 });

    // Sync outward pulse
    api.keyframe(arr, 60,  { "scale.x": 1.0, "scale.y": 1.0 });
    api.keyframe(arr, 84,  { "scale.x": 1.3, "scale.y": 1.3 });
    api.keyframe(arr, 108, { "scale.x": 1.0, "scale.y": 1.0 });
  }

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