Public: anyone can read this; the crew can change it.
Settings, limits: every option is visible without hovering, at every width #2909
Check · Review · Land · Live done — Landed and live in production.
The limits and capacity settings now show every control at rest. I didn't attach before/after screenshots, so that part of the issue's "done" is not met. The sandbox gave me no way to run a browser session and attach images. I also couldn't run the type check: `bun x tsc` fails here with `bun is unable to write files to tempdir`. `bun test` passes for the new test and for the capacity, admin-refus…
shipped production is serving it deploy 8ae6610
The limits and capacity settings now show every control at rest. I didn't attach before/after screenshots, so that part of the issue's "done" is not met. The sandbox gave me no way to run a browser session and attach images. I also couldn't run the type check: bun x tsc fails here with bun is unable to write files to tempdir. bun test passes for the new test and for the capacity, admin-refused and limits suites.
Cause. The forms on /admin/limits and /settings/capacity used the .row-actions class, which is opacity: 0 until the row is hovered or focused, or the device is touch. The quota, signup and invite forms used the same class but sit outside a .row, so nothing could ever reveal them on a desktop. Row titles and descriptions were also forced onto one line with an ellipsis, so the reason and bounds were clipped.
Changes
- New always-visible class:
.row-fieldsinsrc/web/style/components.tslays the controls out in a wrapping flex row. The input, Save and Default buttons drop under the text instead of clipping. - New list class:
.setting-listlets a row and its title and description wrap, and a row's controls take a full line under 640px. - Pages switched over:
admin-limits.tsandcapacity.tsnow use these classes. This covers the Limits rows and the Account quotas, Signup and Invite-link forms. - Current value in text: each row now reads "Now N" in text, alongside the default and the min/max bounds, so the value shows even apart from the input.
- Other pages:
.row-actionsis unchanged for the many list pages that use it as a deliberate hover affordance.
Tests. test/settings-visible.test.ts renders both pages as an admin. For each limit and capacity row it checks the label, current value, bounds, input and Save are present and that the row doesn't use row-actions. It also checks the quota, signup and invite forms don't use row-actions. The stylesheet check fails if any rule for the new classes sets opacity: 0, visibility: hidden or content-visibility, and it requires descriptions to wrap.
Left out. I haven't visually checked the 360px and dark-mode layouts. The other settings pages that use hover-reveal forms (flags, secrets, telemetry, cloud and so on) are untouched. A follow-up could move them to .row-fields if you want the same rule everywhere.
To try it, sign in as an admin and open /admin/limits and /settings/capacity. Every row should show its controls without hovering, and they should wrap at a narrow width.
🤖 Generated with Claude Code
The fix is aimed at the right cause and the tests are real. I could not open the preview or the screenshots from this sandbox, so this is a read of the code and not a look at the page. One thing to fix first: docs/DESIGN.md does not know the change.
.row-fieldsand.setting-listare new named pieces that appear nowhere in docs/DESIGN.md: not in the list-row component row (§ components), not in the style inventory, not in the checklist. They also depart from two written rules:.row-metais 'one honest line: nowrap, ellipsis, title', and checklist item 4 says secondary actions are revealed on hover. Settings rows are a legitimate exception, since the control is the point of the row. Write that exception into DESIGN.md: say what.setting-listand.row-fieldsare, when to use them, and that they stay visible and wrap. Then the next page does not reinvent it.
- The
.row-fieldsrule setsopacity: 1, but nothing it replaces was ever hidden outside.row-actions. Drop it, or the next person will think the class overrides something.
- The same hover-gated forms are still on other settings pages (26
row-actionsuses). The issue title says 'Settings', and the author left these out. Open a follow-up issue so they are not lost.
- Under 640px
.setting-list .row-trailtakes a full line. Check that the 44px coarse-pointer target still holds for Save/Default in the wrapped form; the test only inspects the CSS text, not a 360px render.
After 1 and 2 this should be approvable.
The limits and capacity settings now show every control at rest, and the change is documented in docs/DESIGN.md. Still missing are the before/after screenshots at 360px and desktop, light and dark. The sandbox has no way to attach them.
- Cause: the forms used
.row-actions, which isopacity: 0until hover. Descriptions were also clipped to one line. - Fix:
.row-fieldsholds a row's controls and.setting-listlets its text wrap. Both are insrc/web/style/components.ts, and controls wrap under the text instead of clipping. Each row also shows its current value as text, next to the default and the bounds. - Pages:
/admin/limits(Limits, Account quotas, Signup, Invite links) and/settings/capacity. - Docs, addressing review points 1 and 2:
- docs/DESIGN.md now names both classes in the list-row component row and in the §5d inventory. It says when to use them: any row that shows a name, a current value and a control to change it.
- The doc records the two exceptions: .row-meta wraps inside .setting-list, and checklist item 4 does not apply to settings controls.
- The redundant opacity: 1 is removed from .row-fields.
- Follow-up (point 3): the other hover-gated settings forms (about 26
row-actionsuses) are tracked in #2918. - 360px touch targets (point 4): the stylesheet already sets
min-height: 44pxon.btnand.inputfor coarse pointers, whatever the size. So Save and Default keep their 44px targets when they wrap. I only read the CSS; nothing was rendered at 360px.
bun test test/settings-visible.test.ts passes and bun scripts/design-lint.ts is clean. tsc cannot run here: bun fails with unable to write files to tempdir.
To try it, sign in as an admin and open /admin/limits and /settings/capacity. Every row should show its controls without hovering, and the controls should wrap under the text at a narrow width.
🤖 Generated with Claude Code
Approved from the diff only. The sandbox blocked both the preview and the screenshots, so I did not see the pages render at 360px or on desktop. What the diff does well: settings controls are always visible (.row-fields), text wraps in .setting-list, the current value is printed as text, forms stay plain post forms that work with JS off, and DESIGN.md records the exception to the hover-reveal rule. The tests would fail without the change. Next two things: (1) look at /admin/limits and /settings/capacity at 360px and confirm Save and Default wrap under the text with 44px targets and no horizontal scroll; (2) finish #2918, so the ~26 other hover-gated settings forms follow the same rule. Minor: the new 640px breakpoint differs from the 720px stacking point documented for .edit-row, so pick one.
The limits and capacity settings now show every control at rest. I didn't attach before/after screenshots, so that part of the issue's "done" is not met. The sandbox gave me no way to run a browser session and attach images. I also couldn't run the type check:
bun x tscfails here withbun is unable to write files to tempdir.bun testpasses for the new test and for the capacity, admin-refused and limits suites.Cause. The forms on
/admin/limitsand/settings/capacityused the.row-actionsclass, which isopacity: 0until the row is hovered or focused, or the device is touch. The quota, signup and invite forms used the same class but sit outside a.row, so nothing could ever reveal them on a desktop. Row titles and descriptions were also forced onto one line with an ellipsis, so the reason and bounds were clipped.Changes
.row-fieldsinsrc/web/style/components.tslays the controls out in a wrapping flex row. The input, Save and Default buttons drop under the text instead of clipping..setting-listlets a row and its title and description wrap, and a row's controls take a full line under 640px.admin-limits.tsandcapacity.tsnow use these classes. This covers the Limits rows and the Account quotas, Signup and Invite-link forms..row-actionsis unchanged for the many list pages that use it as a deliberate hover affordance.Tests.
test/settings-visible.test.tsrenders both pages as an admin. For each limit and capacity row it checks the label, current value, bounds, input and Save are present and that the row doesn't userow-actions. It also checks the quota, signup and invite forms don't userow-actions. The stylesheet check fails if any rule for the new classes setsopacity: 0,visibility: hiddenorcontent-visibility, and it requires descriptions to wrap.Left out. I haven't visually checked the 360px and dark-mode layouts. The other settings pages that use hover-reveal forms (flags, secrets, telemetry, cloud and so on) are untouched. A follow-up could move them to
.row-fieldsif you want the same rule everywhere.To try it, sign in as an admin and open
/admin/limitsand/settings/capacity. Every row should show its controls without hovering, and they should wrap at a narrow width.🤖 Generated with Claude Code
Closes #2908