fabrica

hanna/fabrica

fix(web): repo tabs, topbar search input, square avatars, form spacing

701baaf · hanna committed on 2026-07-25

Give .repo-tabs (and a shared .subnav) real tab styling — the rules were
scoped to .topbar .tabs a, so the repo sub-nav rendered as mashed-together
links. Replace the top-bar search icon with a growing search input, lay the
/search results box out inline (button to the right of the input), square
off avatars with rounded corners, and space card-form submit buttons.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed by hannaSSH key fingerprint: SHA256:4g9cWhkAAw8gwqhJUcVbSnGEvdGwklW+1Aa/fMUu59k
10 files changed · +109 −9UnifiedSplit
assets/base.css +81 −5
@@ -118,6 +118,24 @@ code, pre, .mono {
118118 background: var(--fb-bg-inset);
119119 }
120120
121+/* Top-bar search: a growing input with an inline submit icon. */
122+.topbar-search {
123+ display: flex;
124+ align-items: center;
125+ gap: 0.25rem;
126+ flex: 1;
127+ max-width: 34rem;
128+ margin: 0 auto;
129+}
130+.topbar-search input[type="search"] {
131+ width: 100%;
132+ padding: 0.3rem 0.6rem;
133+ background: var(--fb-bg-inset);
134+ border: 1px solid var(--fb-border);
135+ border-radius: var(--fb-radius);
136+ color: var(--fb-fg);
137+}
138+
121139 .icon-btn {
122140 display: inline-flex;
123141 align-items: center;
@@ -274,6 +292,11 @@ select:focus {
274292 outline: none;
275293 }
276294
295+/* Submit buttons in a card form get breathing room from the last field. */
296+.card form button[type="submit"] {
297+ margin-top: 1.1rem;
298+}
299+
277300 /* Centered auth card (sign in, invite activation). */
278301 .auth-wrap {
279302 display: flex;
@@ -338,6 +361,20 @@ select:focus {
338361 color: var(--fb-fg-muted);
339362 }
340363
364+/* Inline search row: input grows, button sits to its right with margin. */
365+.search-row {
366+ display: flex;
367+ align-items: stretch;
368+ gap: 0.6rem;
369+ margin: 0.75rem 0 1.25rem;
370+}
371+.search-row input[type="search"] {
372+ flex: 1;
373+}
374+.search-row .btn {
375+ flex: none;
376+}
377+
341378 /* ---- Repo/list rows ---- */
342379 .listing {
343380 margin-bottom: 1.5rem;
@@ -397,18 +434,27 @@ select:focus {
397434
398435 /* ---- Avatars & profile header ---- */
399436 .avatar {
400- border-radius: 50%;
437+ border-radius: 6px;
401438 object-fit: cover;
402439 background: var(--fb-bg-inset);
403440 border: 1px solid var(--fb-border);
404441 }
442+.avatar-sm {
443+ width: 1.75rem;
444+ height: 1.75rem;
445+ border-radius: 5px;
446+}
405447 .avatar-lg {
406448 width: 5rem;
407449 height: 5rem;
450+ border-radius: 8px;
408451 }
409452 .avatar-xl {
410- width: 6rem;
411- height: 6rem;
453+ width: 100%;
454+ max-width: 16rem;
455+ aspect-ratio: 1;
456+ height: auto;
457+ border-radius: 10px;
412458 }
413459 .profile-head {
414460 display: flex;
@@ -531,8 +577,38 @@ pre.code {
531577 .repo-slug a {
532578 color: var(--fb-accent);
533579 }
534-.repo-tabs {
535- margin: 0.5rem 0;
580+/* Horizontal tab strips (repo sub-nav, explore sub-nav). */
581+.repo-tabs,
582+.subnav {
583+ display: flex;
584+ gap: 0.25rem;
585+ flex-wrap: wrap;
586+ margin: 0.75rem 0;
587+ border-bottom: 1px solid var(--fb-border);
588+}
589+.repo-tabs a,
590+.subnav a {
591+ display: inline-flex;
592+ align-items: center;
593+ gap: 0.4rem;
594+ padding: 0.5rem 0.85rem;
595+ color: var(--fb-fg-muted);
596+ border-bottom: 2px solid transparent;
597+ margin-bottom: -1px;
598+}
599+.repo-tabs a:hover,
600+.subnav a:hover {
601+ color: var(--fb-fg);
602+ text-decoration: none;
603+}
604+.repo-tabs a[aria-current="page"],
605+.subnav a[aria-current="page"] {
606+ color: var(--fb-fg);
607+ border-bottom-color: var(--fb-accent);
608+ font-weight: 600;
609+}
610+.subnav {
611+ justify-content: center;
536612 }
537613 .ref-row,
538614 .clone-row {
crates/web/src/layout.rs +4 −2
@@ -72,8 +72,10 @@ fn topbar(chrome: &Chrome) -> Markup {
7272 button class="icon-btn" type="button" data-drawer-toggle aria-label="Menu"
7373 aria-controls="drawer" aria-expanded="false" { (icon(Icon::PanelLeft)) }
7474 span class="slug" { a href="/" { (chrome.instance_name) } }
75- nav class="tabs" aria-label="Primary" {}
76- a class="icon-btn" href="/search" aria-label="Search" { (icon(Icon::Search)) }
75+ form class="topbar-search" method="get" action="/search" role="search" {
76+ input type="search" name="q" placeholder="Search…" aria-label="Search";
77+ button class="icon-btn" type="submit" aria-label="Search" { (icon(Icon::Search)) }
78+ }
7779 a class="icon-btn" href="/" aria-label="Home" { (icon(Icon::House)) }
7880 }
7981 }
crates/web/src/search.rs +2 −2
@@ -388,10 +388,10 @@ pub async fn in_repo(
388388 /// The search input form.
389389 fn search_box(value: &str, action: Option<&str>) -> Markup {
390390 html! {
391- form method="get" action=[action] {
391+ form class="search-row" method="get" action=[action] {
392392 input type="search" name="q" value=(value) placeholder="Search…"
393393 data-search-input aria-label="Search query" autofocus;
394- button class="btn" type="submit" { "Search" }
394+ button class="btn btn-primary" type="submit" { "Search" }
395395 }
396396 }
397397 }
data/repos/01/01kyc0j4dzrnx6afv3wwfvxgn4.git/HEAD +1 −0
@@ -0,0 +1 @@
1+ref: refs/heads/main
data/repos/01/01kyc0j4dzrnx6afv3wwfvxgn4.git/config +9 −0
@@ -0,0 +1,9 @@
1+[core]
2+ bare = true
3+ repositoryformatversion = 0
4+ filemode = true
5+ logallrefupdates = true
6+[receive]
7+ denyNonFastForwards = false
8+[gc]
9+ auto = 0
data/repos/01/01kyc0j4dzrnx6afv3wwfvxgn4.git/description +1 −0
@@ -0,0 +1 @@
1+Unnamed repository; edit this file 'description' to name the repository.
data/repos/01/01kyc0j4dzrnx6afv3wwfvxgn4.git/hooks/README.sample +5 −0
@@ -0,0 +1,5 @@
1+#!/bin/sh
2+#
3+# Place appropriately named executable hook scripts into this directory
4+# to intercept various actions that git takes. See `git help hooks` for
5+# more information.
data/repos/01/01kyc0j4dzrnx6afv3wwfvxgn4.git/hooks/post-receive +2 −0
@@ -0,0 +1,2 @@
1+#!/bin/sh
2+exec "/nix/store/ccirpbv8km7dv6iwq7zka65sy94xbh5v-fabrica-0.1.0/bin/.fabrica-wrapped" hook post-receive
data/repos/01/01kyc0j4dzrnx6afv3wwfvxgn4.git/hooks/pre-receive +2 −0
@@ -0,0 +1,2 @@
1+#!/bin/sh
2+exit 0
data/repos/01/01kyc0j4dzrnx6afv3wwfvxgn4.git/info/exclude +2 −0
@@ -0,0 +1,2 @@
1+# File patterns to ignore; see `git help ignore` for more information.
2+# Lines that start with '#' are comments.