fabrica

hanna/fabrica

style(web): align inline admin controls to a uniform height

c13693a · hanna committed on 2026-07-26

The inline submit buttons in the admin form rows (Set password, Create
invite) rendered shorter than the taller native select/inputs beside
them, leaving lopsided vertical gaps. Give every control in an
.admin-form-row the same explicit 2.4rem height (the convention already
used by .collab-add), and tighten the empty-state line above each create
form so it sits snug against the form.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed by hannaSSH key fingerprint: SHA256:4g9cWhkAAw8gwqhJUcVbSnGEvdGwklW+1Aa/fMUu59k
2 files changed · +16 −3UnifiedSplit
assets/base.css +13 −0
@@ -998,6 +998,7 @@ body.drawer-open .drawer-backdrop {
998998 }
999999 .admin-form-row {
10001000 display: flex;
1001+ align-items: center;
10011002 gap: 0.5rem;
10021003 flex-wrap: wrap;
10031004 margin-bottom: 0.5rem;
@@ -1007,6 +1008,14 @@ body.drawer-open .drawer-backdrop {
10071008 flex: 1;
10081009 min-width: 9rem;
10091010 }
1011+/* Give every control the same explicit height so inputs, selects, and the
1012+ inline submit button line up exactly (native selects render taller than a
1013+ button would otherwise, so flex `stretch` alone is not enough). */
1014+.admin-form-row > input,
1015+.admin-form-row > select,
1016+.admin-form-row > button {
1017+ height: 2.4rem;
1018+}
10101019 /* A control row that is the last thing in its form carries no trailing gap. */
10111020 .admin-form-row-last {
10121021 margin-bottom: 0;
@@ -1029,6 +1038,10 @@ body.drawer-open .drawer-backdrop {
10291038 .form-field label {
10301039 margin-top: 0;
10311040 }
1041+/* Empty-state line above a create form: keep it snug against the form. */
1042+.empty-note {
1043+ margin: 0 0 0.75rem;
1044+}
10321045
10331046 /* Settings: a left tab rail and the active tab's content. */
10341047 .settings-layout {
crates/web/src/admin.rs +3 −3
@@ -439,7 +439,7 @@ pub async fn repos(
439439 h2 { "Repositories" }
440440 section class="listing" {
441441 div class="card" {
442- @if repos.is_empty() { p class="muted" { "No repositories." } }
442+ @if repos.is_empty() { p class="muted empty-note" { "No repositories." } }
443443 ul class="entry-list admin-list" {
444444 @for r in &repos {
445445 @let owner = owners.get(&r.owner_id).cloned().unwrap_or_else(|| r.owner_id.clone());
@@ -510,7 +510,7 @@ pub async fn groups(
510510 h2 { "Groups" }
511511 section class="listing" {
512512 div class="card" {
513- @if groups.is_empty() { p class="muted" { "No groups." } }
513+ @if groups.is_empty() { p class="muted empty-note" { "No groups." } }
514514 ul class="entry-list admin-list" {
515515 @for g in &groups {
516516 @let owner = owners.get(&g.owner_id).cloned().unwrap_or_else(|| g.owner_id.clone());
@@ -573,7 +573,7 @@ pub async fn invites(
573573 }
574574 section class="listing" {
575575 div class="card" {
576- @if invites.is_empty() { p class="muted" { "No invites." } }
576+ @if invites.is_empty() { p class="muted empty-note" { "No invites." } }
577577 ul class="entry-list admin-list" {
578578 @for iv in &invites {
579579 li class="entry-row" {