Skip to main content

max / goingson

Reveal the month-goal delete button on focus, and stop advertising .row Two findings from re-auditing adoption 1 rather than from adopting anything new. .month-goal-delete-btn rests at opacity 0 and was revealed only on .month-goal-item:hover, so a keyboard user who tabbed to it held an invisible focused button. It is a real <button>. .task-row-action and .kebab-btn had both already grown the focus escape; this was the one outlier. The vocabulary header advertised a .row layout primitive with no rule behind it and no call site, so anyone composing from the doc would have written a class that did nothing. Its gap modifiers were stale too: the numeric .row-flex-{2,3,4} / .stack-{2,3,4} / .mb-{1,2} spellings were renamed to bound/peer/group/section, and .mb- only ever had two. The name now belongs to the generated layout.css, which keys the list row on .row, so the entry says not to reach for it instead of dropping quietly.
Co-Authored-By
Claude Opus 5 (1M context) <noreply@anthropic.com>
Author: Max Johnson <me@maxj.phd> · 2026-07-30 02:06 UTC
Signed with PGP, not checked
Commit: 4029f15f40fb721691ce877be0fb90e43ba5df01
Parent: 7010eee
1 file changed, +15 insertions, -8 deletions
@@ -6,7 +6,7 @@
6 6 1. Use a UTILITY class for one-off adjustments (.mb-section, .mb-peer, .flex-1,
7 7 .text-sm-secondary, .hidden)
8 8 2. Use a LAYOUT PRIMITIVE to position content (.row-flex + .row-flex-{peer,
9 - group,section}, .row,
9 + group,section}, .stack +
10 10 .stack-{peer,group,section})
11 11 3. Use a COMPONENT PRIMITIVE for a UI element (.card, .button, .field,
12 12 .modal, .badge,
@@ -136,8 +136,9 @@
136 136 EXISTING VOCABULARY: grep before inventing a new class.
137 137
138 138 UTILITIES
139 - Layout .flex-1, .row, .row-flex + .row-flex-{2,3,4},
140 - .stack-{2,3,4}, .mb-{1,2}
139 + Layout .flex-1, .row-flex + .row-flex-{bound,peer,group,section},
140 + .stack + .stack-{bound,peer,group,section},
141 + .mb-{peer,section}
141 142 Text .text-sm-secondary, .text-xs-secondary, .text-center,
142 143 .text-left, .text-muted, .text-accent-red
143 144 Sizing .flex-1, .w-full
@@ -145,8 +146,10 @@
145 146
146 147 LAYOUT PRIMITIVES
147 148 .row-flex (display:flex; align-items:center) + gap modifier .row-flex-N
148 - .row (display:flex, no align) + gap modifier .row-flex-N
149 - .stack (vertical) + gap modifier
149 + .stack (vertical) + gap modifier .stack-N
150 + NOT .row: it has no rule here, and the generated layout.css claims the
151 + name for a LIST ROW (makeover-layout RowPart, its parts .row-primary /
152 + -secondary / -meta / -actions). Do not write class="row" for a flex row.
150 153
151 154 COMPONENT PRIMITIVES
152 155 .button + .button--primary / --secondary / --danger / --sm
@@ -358,8 +361,8 @@
358 361
359 362 /* 4. Utility Classes (Shadow, Hover, Border) */
360 363 /* --- LAYOUT UTILITIES */
361 - /* Compose: .row-flex + .row-flex-{2,3,4} for align-items:center rows.
362 - .row for raw flex with no align. .flex-1 to grow a child. */
364 + /* Compose: .row-flex + .row-flex-{bound,peer,group,section} for
365 + align-items:center rows. .flex-1 to grow a child. */
363 366 .flex-1 { flex: 1; }
364 367 .text-accent-red { color: var(--danger); }
365 368 .mb-section { margin-bottom: var(--gap-section); }
@@ -6753,7 +6756,11 @@
6753 6756 opacity: 0;
6754 6757 }
6755 6758
6756 - .month-goal-item:hover .month-goal-delete-btn {
6759 + /* Focus reveals it too, the way .task-row-action and .kebab-btn already do.
6760 + Hover alone left a keyboard user holding an invisible focused button. */
6761 + .month-goal-item:hover .month-goal-delete-btn,
6762 + .month-goal-item:focus-within .month-goal-delete-btn,
6763 + .month-goal-delete-btn:focus {
6757 6764 opacity: 1;
6758 6765 }
6759 6766