Skip to content

Control radius: the size-invariant ramp member (D56) - #59

Merged
handamade merged 7 commits into
mainfrom
d56-control-radius
Jul 31, 2026
Merged

Control radius: the size-invariant ramp member (D56)#59
handamade merged 7 commits into
mainfrom
d56-control-radius

Conversation

@handamade

Copy link
Copy Markdown
Owner

Completes the --psi-control-* family that D54–D55 (#58) introduced. That decision moved control height, gap, padding and font onto a shared per-size, token-only family; radius was the one geometry property left binding raw rungs, so a customer wanting sharper controls had to fork component CSS.

What changed

One size-invariant key on the family — radius does not ride the size ramp, because border-radius sits on each component's base rule rather than in its .size{n} blocks, and all four sizes resolve to radius-8:

--psi-control-radius:      var(--psi-radius-8)

--psi-button-radius:       var(--psi-control-radius)     # Button + IconButton
--psi-input-radius:        var(--psi-control-radius)
--psi-select-radius:       var(--psi-control-radius)
--psi-checkbox-box-radius: min(var(--psi-control-radius), var(--psi-radius-4))
--psi-tooltip-radius:      min(var(--psi-control-radius), var(--psi-radius-6))

Six border-radius declarations rebind. Tag and Switch keep --psi-radius-full — pill-ness is component identity, not theme expression.

A theme now retunes control shape in one line, which Palette + SlotMap could not express:

[data-psi-theme="acme"] { --psi-control-radius: var(--psi-radius-4); }

Rendered no-op

Every default resolves to its current value. Verified in chromium against the built Storybook: control/button/input/select 8px, checkbox 4px, tooltip 6px — identical to the literals they replace. The min() caps behave as designed live (--psi-control-radius: 0px → checkbox 0px; 20px → checkbox holds 4px).

⚠️ The VR gate is what actually gates this

pnpm vr could not be run locally and CI's vr job is the acceptance criterion. Baselines are ubuntu-latest renders: macOS fails all 180 on the platform suffix, and playwright:v1.61.1-jammy produced 156/180 diffs on stories containing no controls at all (font-stack drift), so neither is a valid oracle. If vr reports any diff, this is not ready.

Local gates: pnpm build, pnpm test (60 files, 529 tests), pnpm lint all pass.

Reviewer notes

  • --psi-control-radius deliberately never appears in component CSS — the stylelint boundary excludes it, so all indirection lives in the token layer, matching how --psi-surface-radius already works for Dialog/Panel/Menu.
  • Checkbox's cap is a no-op for every on-scale value: radiusScale is [4,6,8,12] with no rung below radius-4. It only bites off-scale (e.g. 0px). Tooltip's radius-6 ceiling does track, down to radius-4. This is recorded accurately in the changeset and guidance after a final-review correction.
  • Follow-up for D57 (theme console): --psi-card-radius sits on neither dial and strands at radius-8 when a theme retunes controls.

Spec: docs/superpowers/specs/2026-07-31-control-radius-design.md
Plan: docs/superpowers/plans/2026-07-31-control-radius.md

🤖 Generated with Claude Code

handamade and others added 7 commits July 31, 2026 19:40
D54-D55 (e851be0) moved control height, gap, padding, icon inset and font
onto the shared --psi-control-* family. Radius was the one geometry property
left behind: all six control border-radius declarations still bind rungs
directly, so a customer wanting sharper controls must fork component CSS.

Adds one size-invariant key to the existing family. Radius does NOT join the
size ramp: border-radius sits on each component's base rule, never in the
.size{n} blocks, and all four sizes resolve to radius-8 — making it per-size
would encode variation that doesn't exist and cost the theme console its
single dial.

Checkbox and Tooltip cap themselves via min() so a sharp theme squares them
without a soft theme over-rounding small objects. Tag and Switch stay pill.

Rendered no-op by construction — zero VR diff is the acceptance signal.

Renumbered from D54 after a numbering collision with e851be0; density, which
an earlier draft deferred, shipped there.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Four tasks: family key, five component aliases, six CSS rebinds, guidance +
changeset. Plan records the two existing control-tokens assertions that break
on the new key (the size|space|text rung regex and the 28-token count) and
fixes both in the task that causes them.

Guidance entry added beyond the spec: guidance.json is a published artifact
and D54-D55 established a geometry block, so an undiscoverable token would be
a regression for agents.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…s (D56)

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Six border-radius declarations move off raw rungs onto the per-component
tokens that alias --psi-control-radius. Tag and Switch keep --psi-radius-full.

Defaults are unchanged: computed values verified in chromium against the built
Storybook - button/iconbutton/input/select 8px, checkbox 4px, tooltip 6px. The
min() caps behave as designed: at --psi-control-radius 0px the checkbox tracks
to 0px, at 20px it holds at 4px.

VR is deferred to CI: the committed baselines are ubuntu-latest renders and
neither macOS nor the jammy image reproduces them (156/180 diffs on stories
with no controls). Plan step corrected accordingly.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Three documentation errors, no mechanism change:

1. The changeset told consumers to override --psi-{component}-radius. That
   pattern is wrong for Checkbox, whose token is --psi-checkbox-box-radius —
   an agent following the text would synthesize --psi-checkbox-radius and get
   silence. All five tokens are now named explicitly.
2. "A sharp theme squares them" was false on-scale. radiusScale is [4,6,8,12]
   with no rung below radius-4, so min(control, radius-4) evaluates to 4px at
   every on-scale value; Checkbox only moves at an off-scale value like 0px.
   Tooltip's radius-6 ceiling does track, down to radius-4.
3. The changeset asserted "the VR suite reports zero diff pixels". It has not
   run — CI gates it. Reworded to claim no visible change by construction.

Guidance also now records that Psi has two radius dials (--psi-control-radius,
--psi-surface-radius) and that --psi-card-radius sits on neither.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@cursor

cursor Bot commented Jul 31, 2026

Copy link
Copy Markdown

Bugbot is not enabled for your account, so this pull request was not reviewed.

Enable Bugbot in the Cursor dashboard to get automatic reviews on future PRs.

@vercel

vercel Bot commented Jul 31, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
psi Ready Ready Preview Jul 31, 2026 7:29pm

@handamade
handamade enabled auto-merge (squash) July 31, 2026 19:29
@handamade
handamade merged commit dedb5b2 into main Jul 31, 2026
3 checks passed
@handamade
handamade deleted the d56-control-radius branch July 31, 2026 19:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant