Open decisions
Design decisions
Eight directions, all plump, all oval-cornered, all filled — built in real code with the real typeface, real shadows and working hover, press and focus states. Hover them. Press them. Tab through them. Direction A · Full capsule was chosen and is now the product's only button. The rest are kept here as the record of what was rejected.
Build progress
Chosen and shipping. Progress here is not a percentage — it is seven named steps, one of which can be blocked by a finding, so the fraction is the headline and the ticks let you count what is left. Drive the state below; the agent drives it the same way.
Drive the state
Step 3 of 7 · blocked
Advance the build the way the agent does when verify_current_step passes, and inject a finding the way inspect_build does. Both changes animate.
Collapsed
The default. Click it — the full step list opens beneath, and picking a step jumps the build there. Escape or an outside click closes it.
Compact, in the workbench topbar
At 64px the card cannot fit, so the same control collapses to one line: a small fraction, the ticks, and an amber dot when a step is blocked. It opens the same list.
Kit checklist control
This is not a consent box or a settings toggle — it is an inventory mark on a list the user runs down once before starting. Nothing is blocked by leaving one unticked, so it should feel like counting stock rather than agreeing to terms. Five readings, all interactive.
CB1Round, filled
The square becomes a circle so it matches the capsules everywhere else, and the tick scales in rather than appearing. Closest to today, just in the product's own shape language.
CB2Round, outline
The same circle, but ticking it draws a blue ring and a blue tick instead of flooding the box. A checked list stays quiet, which suits a list where most items end up ticked.
CB3Inventory row
The whole row is the control. Unticked reads as a slot to fill (dashed outline, plus sign, “Add”); ticked turns green and says “Have it”. Largest target, and the only one that looks like stock-taking rather than consent.
CB4Soft square, raised
Keeps the square but rounds it to 7px and puts it on the same plate as the buttons — ticked, it becomes a small blue button. Consistent with the controls, but heavier down a long list.
CB5Capsule action
No box at all. Each part carries a small capsule that says what it is for: “Add” before, “Have it” after. Reads as an action rather than a checkbox, and the label states the meaning outright.
Surrounding layer
A filled pad sitting around the capsule, offset a few pixels from the fill on every side — so the button reads as an object resting on something rather than a shape painted on the page.
F1Neutral pad6/6/6
One pale grey pad behind every role, 6px on all sides. The layer is a surface the controls sit on, not a property of each button — so a row of four reads as one assembly.
F2Colour-matched pad6/6/6
Each pad is a pale version of its own button's fill. Colour extends past the capsule, which makes the primary action noticeably louder than everything beside it.
F3Raised white plate7/7/7
A white pad with its own soft shadow, so the plate floats and the button sits on the plate. Two levels of elevation instead of one.
F4Weighted pad5/5/9
Asymmetric: 5px above and to the sides, 9px below. The pad reads as sitting under the button rather than merely around it — the closest to the sketch.
F5Weighted pad and ledge5/5/10
The asymmetric pad plus the darker ledge under the fill. Three stacked parts: fill, ledge, pad. The most physical of the five, and the heaviest.
On white
Half the product's buttons sit on white cards, not on the app background. A pad that reads well on grey can disappear — or turn into a smudge — on white.
Density check
The pad costs real space on every side. This is F4 at the workbench's actual toolbar gap — judge whether four controls still breathe.
Depth layer
Five readings of a layer sitting slightly below the capsule's edge. Every one presses: the ledge collapses and the button sinks by the same distance, so the travel is mechanical rather than decorative.
Today
The shipped capsule: a tinted shadow and a 1px sink on press. No ledge.
L1Solid ledge
A hard sliver of a deeper tone directly under the fill, inset by 1px so it reads as a shelf rather than a border. The most literal reading, and the one that survives at small sizes.
Press and hold a button to see the layer collapse.
L2Inner lip
The layer lives inside the capsule: a dark band along the bottom edge of the fill itself. Nothing extends past the silhouette, so the shape stays exactly as approved.
Press and hold a button to see the layer collapse.
L3Offset plate
A second full capsule sitting 4px lower and slightly narrower, dimmed. Reads as two stacked physical parts — the most visible layer of the five.
Press and hold a button to see the layer collapse.
L4Hairline shelf
A one-pixel darker outline all the way round, thickening into a 2px shelf underneath. Quiet, precise, closest to how instrument software draws a raised key.
Press and hold a button to see the layer collapse.
L5Soft shelf
The ledge is a translucent black rather than a second colour, so it works on any fill without a matching tone. Two pixels, low opacity, plus a wide soft shadow further out.
Press and hold a button to see the layer collapse.
White-on-fill contrast
The chosen capsule ships with white labels on saturated fills, and both fills currently sit below the WCAG AA floor for 13px text. Three ways to fix it, rendered side by side.
The problem
White on #1677FF = 4.10:1
White on #E5484D = 3.91:1
13px text needs 4.5:1. Both fills fall short, which is why the labels read as washed out rather than white.
1Separate fill tone5.26:1 · 5.44:1
Keep #1677FF for links, focus rings, target rings and every thin element. Add one deeper tone used only where white text sits on top of it.
- Keeps
- The brand blue stays exactly as it is everywhere it already reads well.
- Costs
- Two blues in the token set — fill tone and accent tone.
2One darker blue4.61:1 · 4.86:1
Move the whole accent down a step. One blue, used everywhere, comfortably above AA on both fills.
- Keeps
- One accent token. Nothing to remember, nothing to mix up.
- Costs
- Slightly less electric than the blue in the brief.
3Ink primary, blue accent16.1:1 · 6.37:1
The primary fill becomes near-black; blue moves to the icon and to everything the agent points at. Highest contrast by a wide margin.
- Keeps
- Unmissable hierarchy, and blue is freed up to mean 'the agent is pointing here'.
- Costs
- The main action is no longer blue — a real brand shift.
The eight directions
Kept as the record of what was compared and what was rejected.
Shortlisted: A
AFull capsule
CHOSEN. Fully round ends, 44px tall, every role filled. Now shipping as the product's Button in src/components/ui/button.tsx.
BSoft oval
16px corners instead of a full pill. Reads a little more like software, a little less like a tag.
CNavy command
Deep navy primary with a blue icon. The strongest hierarchy in the set — you cannot miss the main action.
DSemantic tint
One saturated primary; the rest are soft washes of the colour that carries their meaning. Blue = suggested, red = irreversible.
EInk primary
Vercel-style near-black primary. Very current, but the brand blue drops to a supporting role.
FGrounded edge
Each fill sits on a darker sliver of itself. Gives real weight without a bevel — and the press animation actually lands.
GIndigo weight
Stripe-adjacent. Slightly deeper indigo, 12px corners, restrained shadow. The most 'financial software' of the set.
HWarm capsule
Warmer off-white surfaces and a calmer blue. Editorial rather than technical — softer on the eye over a 35-minute build.