Commit 03fe6e4437
03fe6e44370f8129c9ac68f13fe674cc271f5ffa
parent: 43a8eaa579
Verified · cmc
cmc <hello@cleberg.net> · 2026-09-04 04:20 UTC
web: tabs wrap on a phone, and the landing page says what the forge does
On a phone the tab bar scrolled sideways with its scrollbar hidden, so
the tabs past the edge looked absent; they wrap to a second row
instead. The landing page had a paragraph and a code block; it now
says in three short sections what a reader, a writer and a reviewer
can do.
The header stays the same on every tab: it sits above the tab bar,
and hiding the description and topics off the code tab moved the
navigation between clicks, which TestReadmeRelativeLinks guards.
Closes #134
Layout: unified · split
internal/web/static/style.css
+7
| @@ -420,6 +420,9 @@ nav.tabs a i { |
| 420 | .railpinned { border-top: 0; padding: 0; } |
420 | .railpinned { border-top: 0; padding: 0; } |
| 421 | .content { padding: var(--sp-4) var(--sp-4) var(--sp-5); } |
421 | .content { padding: var(--sp-4) var(--sp-4) var(--sp-5); } |
| 422 | .repohead { padding: var(--sp-3) var(--sp-4) 0; } |
422 | .repohead { padding: var(--sp-3) var(--sp-4) 0; } |
| |
423 | /* seven tabs do not fit a phone in one row; a hidden scrollbar made |
| |
424 | the ones past the edge look absent. Two rows show all of them. */ |
| |
425 | nav.tabs { flex-wrap: wrap; overflow: visible; } |
| 423 | } |
426 | } |
| 424 | |
427 | |
| 425 | /* tables */ |
428 | /* tables */ |
| @@ -740,6 +743,10 @@ pre.quickstart { |
| 740 | margin: 0 0 var(--sp-4); |
743 | margin: 0 0 var(--sp-4); |
| 741 | } |
744 | } |
| 742 | .landing .explorelink { font-weight: 550; } |
745 | .landing .explorelink { font-weight: 550; } |
| |
746 | .landing .facets { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--sp-5); margin: var(--sp-5) 0; } |
| |
747 | .landing .facets h2 { font-size: var(--fs-3); margin: 0 0 var(--sp-1); } |
| |
748 | .landing .facets p { margin: 0; color: var(--muted); font-size: var(--fs-2); line-height: 1.6; } |
| |
749 | @media (max-width: 40rem) { .landing .facets { grid-template-columns: 1fr; gap: var(--sp-4); } } |
| 743 | |
750 | |
| 744 | /* index toolbar */ |
751 | /* index toolbar */ |
| 745 | p.toolbar { color: var(--muted); font-size: var(--fs-2); margin-top: var(--sp-4); } |
752 | p.toolbar { color: var(--muted); font-size: var(--fs-2); margin-top: var(--sp-4); } |
internal/web/templates/landing.html
+5
| @@ -7,6 +7,11 @@ merge requests are managed from your terminal with nothing but OpenSSH — |
| 7 | the web is a fast, readable rendering of that state.</p> |
7 | the web is a fast, readable rendering of that state.</p> |
| 8 | <pre class="quickstart">ssh git@{{.Host}} help # every command, no client needed |
8 | <pre class="quickstart">ssh git@{{.Host}} help # every command, no client needed |
| 9 | git clone ssh://git@{{.Host}}/owner/repo.git</pre> |
9 | git clone ssh://git@{{.Host}}/owner/repo.git</pre> |
| |
10 | <div class="facets"> |
| |
11 | <section><h2>Read</h2><p>Browse and clone any public repository, over HTTPS or <code>git://</code>, with no account. Every commit shows whether its signature was verified.</p></section> |
| |
12 | <section><h2>Write</h2><p>Push over SSH with the key you already have. <code>ssh git@{{.Host}} repo create you/project</code> is the whole onboarding; issues, merge requests and reviews are commands too.</p></section> |
| |
13 | <section><h2>Review</h2><p>The web is a rendering of the same state: read a diff, comment on a line, approve, merge. Everything it can do, the terminal can do first.</p></section> |
| |
14 | </div> |
| 10 | <p><a class="explorelink" href="/explore">explore public repositories →</a></p> |
15 | <p><a class="explorelink" href="/explore">explore public repositories →</a></p> |
| 11 | {{if .Accounts}}<p class="meta">have an account? mint a browser session from your terminal: <code>gitbay web login</code>{{if .Signup}} · new here? <a href="/register">create an account</a>{{end}}</p>{{end}} |
16 | {{if .Accounts}}<p class="meta">have an account? mint a browser session from your terminal: <code>gitbay web login</code>{{if .Signup}} · new here? <a href="/register">create an account</a>{{end}}</p>{{end}} |
| 12 | </div> |
17 | </div> |
internal/web/templates/layout.html
+4 −1
| @@ -61,13 +61,16 @@ |
| 61 | <span class="grow"></span> |
61 | <span class="grow"></span> |
| 62 | {{if $.Viewer}}<form method="post" action="/{{.OwnerName}}/{{.Name}}/pin" class="inline"><button type="submit" class="btn" aria-pressed="{{if field $ "Pinned"}}true{{else}}false{{end}}"><span aria-hidden="true">{{if field $ "Pinned"}}★{{else}}☆{{end}}</span> {{if field $ "Pinned"}}Pinned{{else}}Pin{{end}}</button></form>{{end}} |
62 | {{if $.Viewer}}<form method="post" action="/{{.OwnerName}}/{{.Name}}/pin" class="inline"><button type="submit" class="btn" aria-pressed="{{if field $ "Pinned"}}true{{else}}false{{end}}"><span aria-hidden="true">{{if field $ "Pinned"}}★{{else}}☆{{end}}</span> {{if field $ "Pinned"}}Pinned{{else}}Pin{{end}}</button></form>{{end}} |
| 63 | </div> |
63 | </div> |
| |
64 | {{$top := topTab (str $ "Tab")}} |
| |
65 | {{/* The header is the same on every tab: it sits above the tab bar, |
| |
66 | and anything shown on one tab and not another would move the |
| |
67 | navigation between clicks of that navigation. */}} |
| 64 | {{with field $ "Desc"}}<p class="repodesc">{{.}}</p>{{end}} |
68 | {{with field $ "Desc"}}<p class="repodesc">{{.}}</p>{{end}} |
| 65 | {{with field $ "Topics"}}<p class="topics">{{range .}}<a class="chip topic" href="/explore?q={{.}}">{{.}}</a> {{end}}</p>{{end}} |
69 | {{with field $ "Topics"}}<p class="topics">{{range .}}<a class="chip topic" href="/explore?q={{.}}">{{.}}</a> {{end}}</p>{{end}} |
| 66 | {{with $.Repo.Settings.Website}}<p class="repometa"><a href="{{.}}" rel="nofollow">{{.}}</a></p>{{end}} |
70 | {{with $.Repo.Settings.Website}}<p class="repometa"><a href="{{.}}" rel="nofollow">{{.}}</a></p>{{end}} |
| 67 | {{range field $ "Mirrors"}}<p class="repometa">{{if eq .Direction "push"}}Mirrors to{{else}}Mirrors from{{end}} <a href="{{.URL}}" rel="nofollow">{{.Target}}</a>{{if .Error}} · <span class="bad">sync error: {{.Error}}</span>{{else if .Synced}} · synced {{.Synced}}{{end}}</p> |
71 | {{range field $ "Mirrors"}}<p class="repometa">{{if eq .Direction "push"}}Mirrors to{{else}}Mirrors from{{end}} <a href="{{.URL}}" rel="nofollow">{{.Target}}</a>{{if .Error}} · <span class="bad">sync error: {{.Error}}</span>{{else if .Synced}} · synced {{.Synced}}{{end}}</p> |
| 68 | {{end}} |
72 | {{end}} |
| 69 | <nav class="tabs" aria-label="Repository"> |
73 | <nav class="tabs" aria-label="Repository"> |
| 70 | {{$top := topTab (str $ "Tab")}} |
| |
| 71 | <a {{if eq $top "code"}}aria-current="page" {{end}}href="/{{.OwnerName}}/{{.Name}}">Code</a> |
74 | <a {{if eq $top "code"}}aria-current="page" {{end}}href="/{{.OwnerName}}/{{.Name}}">Code</a> |
| 72 | <a {{if eq $top "issues"}}aria-current="page" {{end}}href="/{{.OwnerName}}/{{.Name}}/issues">Issues{{with field $ "OpenIssues"}}{{if .}} <i>{{.}}</i>{{end}}{{end}}</a> |
75 | <a {{if eq $top "issues"}}aria-current="page" {{end}}href="/{{.OwnerName}}/{{.Name}}/issues">Issues{{with field $ "OpenIssues"}}{{if .}} <i>{{.}}</i>{{end}}{{end}}</a> |
| 73 | <a {{if eq $top "mrs"}}aria-current="page" {{end}}href="/{{.OwnerName}}/{{.Name}}/mrs">Merge requests{{with field $ "OpenMRs"}}{{if .}} <i>{{.}}</i>{{end}}{{end}}</a> |
76 | <a {{if eq $top "mrs"}}aria-current="page" {{end}}href="/{{.OwnerName}}/{{.Name}}/mrs">Merge requests{{with field $ "OpenMRs"}}{{if .}} <i>{{.}}</i>{{end}}{{end}}</a> |