Definition
The time required to make a decision grows logarithmically with the number of options. Add complexity to each option and the curve steepens further. The takeaway is not "fewer choices always" — the takeaway is that decision time is a designable quantity.
Why it matters for ShurIQ reports
Viewport selectors, filter rails, and stack-rank toggles are decision surfaces; every additional option pays a measurable cost in time-to-insight. A viz hub that surfaces 18 filters at once buries the executive; a hub that surfaces 4 with a "more" expansion respects the law. The framing carries forward to gap card design — never ask the reader to choose among undifferentiated cards.
Takeaways
- Design decision surfaces with the median reader's attention budget in mind, not the power user's.
- Decompose any 5+ option control into a primary set and a secondary set behind disclosure.
- Visually pre-rank options — recommended first, default selected, rest equal-weighted.
- Use progressive onboarding so first-time readers see fewer choices than returning ones.
- Watch for the simplification trap: removing options is good; removing labels is not.
Visual motion language
Non-default options collapse to a compact secondary tier on first paint, expanding only on user request. The default option zoom-focuses with a 1.05× scale to signal the recommended path.
Origins
William Edmund Hick and Ray Hyman, 1952 — formalized reaction time as a function of number of stimuli.
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 · hicks-law · Cavalry scene
// Motion family: grid-stagger
// Palette: 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_hicks-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 = "#1E5C8C";
var DARK = "#163E5C";
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 });
// 7 cols x 6 rows of small dark dots
var COLS = 7, ROWS = 6, SPACE = 70, R = 14;
var startX = -((COLS - 1) * SPACE) / 2;
var startY = ((ROWS - 1) * SPACE) / 2;
for (var r = 0; r < ROWS; r++) {
for (var c = 0; c < COLS; c++) {
var d = api.primitive("ellipse", PREFIX + "dot_" + r + "_" + c);
api.set(d, {
"generator.radius": [R, R],
"position.x": startX + c * SPACE,
"position.y": startY - r * SPACE,
"opacity": 0
});
api.setFill(d, true);
api.set(d, { "material.materialColor": DARK });
api.keyframe(d, r * 4, { "opacity": 0 });
api.keyframe(d, r * 4 + 12, { "opacity": 70 });
}
}
// CPU-chip motif at center: outer square outline + inner square + 4 stub legs
var chipOuter = api.primitive("rectangle", PREFIX + "chip_outer");
api.set(chipOuter, {
"generator.dimensions": [140, 140],
"position.x": 0, "position.y": 0,
"opacity": 0,
"scale.x": 0.4, "scale.y": 0.4
});
api.setFill(chipOuter, false);
api.setStroke(chipOuter, true);
api.set(chipOuter, { "stroke.strokeColor": CREAM, "stroke.width": 8 });
var chipInner = api.primitive("rectangle", PREFIX + "chip_inner");
api.set(chipInner, {
"generator.dimensions": [60, 60],
"position.x": 0, "position.y": 0,
"opacity": 0,
"scale.x": 0.4, "scale.y": 0.4
});
api.setFill(chipInner, false);
api.setStroke(chipInner, true);
api.set(chipInner, { "stroke.strokeColor": CREAM, "stroke.width": 6 });
// 4 stub legs
var legs = [
{ x: 0, y: 90, w: 16, h: 30 },
{ x: 0, y: -90, w: 16, h: 30 },
{ x: 90, y: 0, w: 30, h: 16 },
{ x: -90, y: 0, w: 30, h: 16 }
];
var legIds = [];
for (var li = 0; li < legs.length; li++) {
var lg = legs[li];
var L = api.primitive("rectangle", PREFIX + "leg_" + li);
api.set(L, {
"generator.dimensions": [lg.w, lg.h],
"position.x": lg.x, "position.y": lg.y,
"opacity": 0,
"scale.x": 0.4, "scale.y": 0.4
});
api.setFill(L, true);
api.set(L, { "material.materialColor": CREAM });
legIds.push(L);
}
var chipParts = [chipOuter, chipInner].concat(legIds);
for (var ci = 0; ci < chipParts.length; ci++) {
var p = chipParts[ci];
api.keyframe(p, 30, { "opacity": 0, "scale.x": 0.4, "scale.y": 0.4 });
api.keyframe(p, 48, { "opacity": 100, "scale.x": 1.0, "scale.y": 1.0 });
api.magicEasing(p, "scale.x", 48, "EaseOut", "");
api.magicEasing(p, "scale.y", 48, "EaseOut", "");
// Breathing
api.keyframe(p, 90, { "scale.x": 1.0, "scale.y": 1.0 });
api.keyframe(p, 120, { "scale.x": 1.05, "scale.y": 1.05 });
api.keyframe(p, 150, { "scale.x": 1.0, "scale.y": 1.0 });
}
var layerCount = api.getAllSceneLayers().length;
console.log("scene built: hicks-law (" + layerCount + " layers)");
})();