feat(ui): three button sizes, because the app has three kinds of button
CI & Build / Python lint (push) Successful in 4s
CI & Build / Plugin hooks (push) Successful in 10s
CI & Build / integration (push) Successful in 31s
CI & Build / TypeScript typecheck (push) Successful in 34s
CI & Build / Python tests (push) Successful in 1m4s
CI & Build / Build & push image (push) Successful in 45s

Measured before deciding: across the ~100 bespoke button rules, vertical
padding does not spread — it clusters. ~27 at 0.4–0.45rem, ~28 at 0.25–0.3rem,
~23 at 0.1–0.15rem. Those are three different components that happen to share a
name prefix: a page action, a row action, and an affordance that lives inside a
card.

Collapsing them to the single size the shared sheet had would have visibly
broken every card layout, which is why the one-off migration stopped here for a
decision rather than proceeding on the assumption that a button is a button.

  default        8px 16px   page action — what the house style specifies
  .btn-compact   4px 12px   toolbar, table row, list item controls
  .btn-inline    2px 4px    dismiss ×, confirm tick, add-chip

.btn-small and .btn-sm already sat at the compact step, so they are kept as
aliases for it — no template churn, and the two spellings stop being a third
thing that might drift.

.btn-inline is deliberately below the spacing scale's first step on the
vertical axis: 4px of padding on an 11px label already exceeds the line box
these sit in. Stated in the file so it reads as a measured exception rather
than someone ignoring the scale.

DesignView renders all three as real specimens. A size scale described in prose
is one nobody can check; rendered from the actual classes, it cannot claim
something the app does not do.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UaYUaouG9jjhATyuxCKrQs
This commit is contained in:
2026-08-01 22:21:44 -04:00
co-authored by Claude Opus 5
parent 97b93bcaea
commit 37616682f0
2 changed files with 43 additions and 3 deletions
+25 -2
View File
@@ -105,10 +105,33 @@
background: var(--color-action-destructive-hover); background: var(--color-action-destructive-hover);
} }
/* --- size modifiers ------------------------------------------------------ */ /* --- size modifiers ------------------------------------------------------
*
* THREE sizes, because the app genuinely has three. Measured across the ~100
* bespoke button rules before this scale existed, vertical padding fell into
* clusters rather than a spread: ~27 at 0.40.45rem, ~28 at 0.250.3rem, ~23
* at 0.10.15rem. Those are three different components — a page action, a row
* action, and an affordance living inside a card — that happen to share a name
* prefix. Collapsing them to one size would visibly break the card layouts.
*
* A button carries its size modifier; the DEFAULT (no modifier) is the page
* action, which is the one the house style specifies.
*/
.btn-small, /* Row actions: a toolbar, a table row, a list item's controls. */
.btn-compact,
.btn-small, /* pre-existing spellings, kept so no template churns */
.btn-sm { .btn-sm {
padding: var(--fs-space-1) var(--fs-space-3); /* 4px 12px */ padding: var(--fs-space-1) var(--fs-space-3); /* 4px 12px */
font-size: var(--fs-size-tiny); font-size: var(--fs-size-tiny);
} }
/* Inline affordances: a dismiss ×, a confirm tick, an add-chip — things that
* sit INSIDE a line of text or a card and must not disturb its rhythm. Below
* the spacing scale's first step on the vertical axis by necessity: 4px of
* padding on a 11px label already exceeds the line box these live in. */
.btn-inline {
padding: 2px var(--fs-space-1); /* 2px 4px */
font-size: var(--fs-size-tiny);
line-height: 1;
}
+18 -1
View File
@@ -237,7 +237,16 @@ const TYPE_SPECIMENS = [
<button class="btn-ghost">Cancel</button> <button class="btn-ghost">Cancel</button>
<button class="btn-danger">Delete</button> <button class="btn-danger">Delete</button>
<button class="btn-primary" disabled>Disabled</button> <button class="btn-primary" disabled>Disabled</button>
<button class="btn-ghost btn-small">Small</button> </div>
<p class="spec-caption">
Three sizes, because the app has three kinds of button: a page action, a
row action, and an affordance that sits inside a card without disturbing
its rhythm.
</p>
<div class="button-specimens">
<button class="btn-primary">Default — page action</button>
<button class="btn-primary btn-compact">Compact — row action</button>
<button class="btn-primary btn-inline">Inline</button>
</div> </div>
<ul class="spec-list"> <ul class="spec-list">
<li v-for="b in RULEBOOK_BUTTONS" :key="b.name"> <li v-for="b in RULEBOOK_BUTTONS" :key="b.name">
@@ -361,6 +370,14 @@ const TYPE_SPECIMENS = [
/* Gaps ------------------------------------------------------------------- */ /* Gaps ------------------------------------------------------------------- */
.spec-caption {
margin: 0 0 0.75rem;
color: var(--color-text-secondary);
font-size: 0.85rem;
line-height: 1.5;
max-width: 60ch;
}
/* Layout only. The buttons inside style themselves from the shared sheet — /* Layout only. The buttons inside style themselves from the shared sheet —
adding any appearance rule here would recreate the copy this section adding any appearance rule here would recreate the copy this section
just stopped being. */ just stopped being. */