web: the About block sits beside the file table on a wide overview !418

merged merged by cmc on 2026-09-19 02:07 UTC · krz/gitbay:stack-228 into main

3 files changed, +30 −7

Layout: unified · split

e2e/design_test.go +8 −1
@@ -390,8 +390,15 @@ func TestTreeSearchCodeAndClone(t *testing.T) {
390 if !strings.Contains(body, `<span class="fieldname">SSH</span>`) || !strings.Contains(body, `<span class="fieldname">HTTPS</span>`) { 390 if !strings.Contains(body, `<span class="fieldname">SSH</span>`) || !strings.Contains(body, `<span class="fieldname">HTTPS</span>`) {
391 t.Error("clone blocks are not labelled") 391 t.Error("clone blocks are not labelled")
392 } 392 }
393 if !strings.Contains(body, `class="overview withfacts"`) {
394 t.Error("root overview is not the two-column withfacts layout")
395 }
393 // Clone and about belong to the repository root, not a subdirectory. 396 // Clone and about belong to the repository root, not a subdirectory.
394 if _, sub := inst.get(t, "/alice/app/tree/main/docs"); strings.Contains(sub, `<div class="facts">`) { 397 _, sub := inst.get(t, "/alice/app/tree/main/docs")
398 if strings.Contains(sub, `<div class="facts">`) {
395 t.Error("subdirectory listing still shows the clone/about facts block") 399 t.Error("subdirectory listing still shows the clone/about facts block")
396 } 400 }
401 if !strings.Contains(sub, `class="overview"`) || strings.Contains(sub, `class="overview withfacts"`) {
402 t.Error("subdirectory listing should have a plain overview, not withfacts")
403 }
397} 404}
internal/web/static/style.css +13 −1
@@ -1323,6 +1323,18 @@ details.refmenu .refdrop a.allrefs {
1323 margin-top: var(--sp-1); 1323 margin-top: var(--sp-1);
1324} 1324}
1325 1325
1326/* ---- repository overview layout ---- */
1327.overview { display: block; }
1328.overviewmain { min-width: 0; }
1329/* the side column exists only above 62rem; below it .facts keeps its
1330 own two-up layout and the 40rem factgrid rule applies untouched */
1331@media (min-width: 62.01rem) {
1332 .overview.withfacts { display: grid; grid-template-columns: minmax(0, 1fr) 18rem; gap: var(--sp-6); align-items: start; }
1333 .overview.withfacts .facts { display: block; margin-top: 0; max-width: none; }
1334 .overview.withfacts .facts .factgrid { grid-template-columns: repeat(2, auto); }
1335 .overview.withfacts .clone pre { white-space: pre-wrap; word-break: break-all; }
1336}
1337
1326/* ---- repository facts ---- */ 1338/* ---- repository facts ---- */
1327.facts { display: grid; grid-template-columns: 1fr 1fr; gap: var(--sp-5); margin: var(--sp-5) 0 var(--sp-4); max-width: 72rem; } 1339.facts { display: grid; grid-template-columns: 1fr 1fr; gap: var(--sp-5); margin: var(--sp-5) 0 var(--sp-4); max-width: 72rem; }
1328.facts h2 { 1340.facts h2 {
@@ -1334,7 +1346,7 @@ details.refmenu .refdrop a.allrefs {
1334 color: var(--muted); 1346 color: var(--muted);
1335} 1347}
1336.clone { margin: 0 0 var(--sp-3); } 1348.clone { margin: 0 0 var(--sp-3); }
1337.facts .about { min-width: 0; } 1349.facts .about { min-width: 0; margin-bottom: var(--sp-5); }
1338.clone .fieldname { font-size: var(--fs-1); color: var(--muted); font-weight: 500; margin-bottom: 2px; } 1350.clone .fieldname { font-size: var(--fs-1); color: var(--muted); font-weight: 500; margin-bottom: 2px; }
1339.clone pre { margin-bottom: var(--sp-3); user-select: all; } 1351.clone pre { margin-bottom: var(--sp-3); user-select: all; }
1340.factgrid { display: grid; grid-template-columns: repeat(4, auto); gap: var(--sp-2) var(--sp-4); font-size: var(--fs-2); margin-bottom: var(--sp-3); } 1352.factgrid { display: grid; grid-template-columns: repeat(4, auto); gap: var(--sp-2) var(--sp-4); font-size: var(--fs-2); margin-bottom: var(--sp-3); }
internal/web/templates/tree.html +9 −5
@@ -3,6 +3,8 @@
3{{define "content"}} 3{{define "content"}}
4{{if .Notice}}<p class="error" role="alert">{{.Notice}}</p>{{end}} 4{{if .Notice}}<p class="error" role="alert">{{.Notice}}</p>{{end}}
5{{if .DirPath}}<h1 class="vh">{{.DirPath}}</h1>{{end}} 5{{if .DirPath}}<h1 class="vh">{{.DirPath}}</h1>{{end}}
6<div class="overview{{if and .Entries (not .DirPath)}} withfacts{{end}}">
7<div class="overviewmain">
6<div class="pathbar"> 8<div class="pathbar">
7 {{template "refmenu" .}} 9 {{template "refmenu" .}}
8 <span class="crumbs"><a href="/{{.Repo.OwnerName}}/{{.Repo.Name}}">{{.Repo.Name}}</a>/{{range .Crumbs}}<a href="{{.URL}}">{{.Name}}</a>/{{end}}</span> 10 <span class="crumbs"><a href="/{{.Repo.OwnerName}}/{{.Repo.Name}}">{{.Repo.Name}}</a>/{{range .Crumbs}}<a href="{{.URL}}">{{.Name}}</a>/{{end}}</span>
@@ -29,12 +31,8 @@
29<div class="cardhead"><a href="/{{.Repo.OwnerName}}/{{.Repo.Name}}/blob/{{.Ref}}/{{.Prefix}}{{.ReadmeName}}">{{.ReadmeName}}</a></div> 31<div class="cardhead"><a href="/{{.Repo.OwnerName}}/{{.Repo.Name}}/blob/{{.Ref}}/{{.Prefix}}{{.ReadmeName}}">{{.ReadmeName}}</a></div>
30<div class="rendered">{{.ReadmeHTML}}</div> 32<div class="rendered">{{.ReadmeHTML}}</div>
31</section>{{end}} 33</section>{{end}}
34</div>
32{{if and .Entries (not .DirPath)}}<div class="facts"> 35{{if and .Entries (not .DirPath)}}<div class="facts">
33 <div class="clone">
34 <h2>Clone</h2>
35 <span class="fieldname">SSH</span><pre><code>git clone {{.SSHCloneURL}}</code></pre>
36 <span class="fieldname">HTTPS</span><pre><code>git clone {{.CloneURL}}</code></pre>
37 </div>
38 {{if .Facts.Commits}}{{$r := printf "/%s/%s" .Repo.OwnerName .Repo.Name}}<div class="about"> 36 {{if .Facts.Commits}}{{$r := printf "/%s/%s" .Repo.OwnerName .Repo.Name}}<div class="about">
39 <h2>About</h2> 37 <h2>About</h2>
40 <div class="factgrid"> 38 <div class="factgrid">
@@ -50,5 +48,11 @@
50 <p class="langs">{{range .}}<span class="lang-name"><span class="dot lang-{{slug .Name}}"></span>{{.Name}} <span class="muted">{{pct .Percent}}%</span></span>{{end}}</p>{{end}} 48 <p class="langs">{{range .}}<span class="lang-name"><span class="dot lang-{{slug .Name}}"></span>{{.Name}} <span class="muted">{{pct .Percent}}%</span></span>{{end}}</p>{{end}}
51 {{with .Facts.Contributors}}<p class="contribs"><span class="label">{{len .}} contributor{{if ne (len .) 1}}s{{end}}</span>{{range .}}{{template "authorname" dict "Name" .Name "User" .User "Email" .Title}}{{end}}</p>{{end}} 49 {{with .Facts.Contributors}}<p class="contribs"><span class="label">{{len .}} contributor{{if ne (len .) 1}}s{{end}}</span>{{range .}}{{template "authorname" dict "Name" .Name "User" .User "Email" .Title}}{{end}}</p>{{end}}
52 </div>{{end}} 50 </div>{{end}}
51 <div class="clone">
52 <h2>Clone</h2>
53 <span class="fieldname">SSH</span><pre><code>git clone {{.SSHCloneURL}}</code></pre>
54 <span class="fieldname">HTTPS</span><pre><code>git clone {{.CloneURL}}</code></pre>
55 </div>
53</div>{{end}} 56</div>{{end}}
57</div>
54{{end}} 58{{end}}