chore: fix various layout problems (#37983)

Fix various misaligments, fix space between list item bar items, remove
deadcode (milestone dashboard)
This commit is contained in:
wxiaoguang
2026-06-06 17:24:03 +08:00
committed by GitHub
parent 4088d7e241
commit e88650cfcf
13 changed files with 93 additions and 148 deletions
+11 -11
View File
@@ -41,26 +41,26 @@
</div> </div>
</div> </div>
<div class="milestone-list"> <div class="flex-divided-list milestone-list">{{/* the milestone-list class is kept because many tests depend on it */}}
{{range .Projects}} {{range .Projects}}
<li class="milestone-card"> <div class="item flex-relaxed-list">
<h3 class="flex-text-block tw-m-0 tw-gap-3"> <span class="list-item-large-title">
{{svg .IconName 16}} {{svg .IconName 16}}
<a class="muted tw-break-anywhere" href="{{.Link ctx}}">{{.Title}}</a> <a class="muted" href="{{.Link ctx}}">{{.Title}}</a>
</h3> </span>
<div class="milestone-toolbar"> <div class="list-item-secondary-bar">
<div class="group"> <div class="flex-text-block tw-flex-wrap">
<div class="flex-text-block"> <div class="flex-text-inline">
{{svg "octicon-issue-opened" 14}} {{svg "octicon-issue-opened" 14}}
{{ctx.Locale.PrettyNumber .NumOpenIssues}}&nbsp;{{ctx.Locale.Tr "repo.issues.open_title"}} {{ctx.Locale.PrettyNumber .NumOpenIssues}}&nbsp;{{ctx.Locale.Tr "repo.issues.open_title"}}
</div> </div>
<div class="flex-text-block"> <div class="flex-text-inline">
{{svg "octicon-check" 14}} {{svg "octicon-check" 14}}
{{ctx.Locale.PrettyNumber .NumClosedIssues}}&nbsp;{{ctx.Locale.Tr "repo.issues.closed_title"}} {{ctx.Locale.PrettyNumber .NumClosedIssues}}&nbsp;{{ctx.Locale.Tr "repo.issues.closed_title"}}
</div> </div>
</div> </div>
{{if and $.CanWriteProjects (not $.Repository.IsArchived)}} {{if and $.CanWriteProjects (not $.Repository.IsArchived)}}
<div class="group"> <div class="flex-text-block tw-flex-wrap">
<a class="flex-text-inline" href="{{.Link ctx}}/edit">{{svg "octicon-pencil" 14}}{{ctx.Locale.Tr "repo.issues.label_edit"}}</a> <a class="flex-text-inline" href="{{.Link ctx}}/edit">{{svg "octicon-pencil" 14}}{{ctx.Locale.Tr "repo.issues.label_edit"}}</a>
{{if .IsClosed}} {{if .IsClosed}}
<a class="link-action flex-text-inline" href data-url="{{.Link ctx}}/open">{{svg "octicon-check" 14}}{{ctx.Locale.Tr "repo.projects.open"}}</a> <a class="link-action flex-text-inline" href data-url="{{.Link ctx}}/open">{{svg "octicon-check" 14}}{{ctx.Locale.Tr "repo.projects.open"}}</a>
@@ -74,7 +74,7 @@
{{if .Description}} {{if .Description}}
<div class="render-content markup">{{.RenderedContent}}</div> <div class="render-content markup">{{.RenderedContent}}</div>
{{end}} {{end}}
</li> </div>
{{else}} {{else}}
{{if and (eq .OpenCount 0) (eq .ClosedCount 0)}} {{if and (eq .OpenCount 0) (eq .ClosedCount 0)}}
<div class="empty-placeholder"> <div class="empty-placeholder">
+17 -17
View File
@@ -15,42 +15,42 @@
{{template "repo/issue/filters" .}} {{template "repo/issue/filters" .}}
<!-- milestone list --> <!-- milestone list -->
<div class="milestone-list"> <div class="flex-divided-list milestone-list">
{{range .Milestones}} {{range .Milestones}}
<li class="milestone-card"> <div class="item flex-relaxed-list">
<div class="milestone-header"> <div class="flex-left-right">
<h3 class="flex-text-block tw-m-0"> <span class="list-item-large-title">
{{svg "octicon-milestone" 16}} {{svg "octicon-milestone" 16}}
<a class="muted" href="{{$.RepoLink}}/milestone/{{.ID}}">{{.Name}}</a> <a class="muted" href="{{$.RepoLink}}/milestone/{{.ID}}">{{.Name}}</a>
</h3> </span>
<div class="tw-flex tw-items-center"> <div class="flex-text-inline">
<span class="tw-mr-2">{{.Completeness}}%</span> <span>{{.Completeness}}%</span>
<progress value="{{.Completeness}}" max="100"></progress> <progress class="list-item-title-progress" value="{{.Completeness}}" max="100"></progress>
</div> </div>
</div> </div>
<div class="milestone-toolbar"> <div class="list-item-secondary-bar">
<div class="group"> <div class="flex-text-block tw-flex-wrap">
<div class="flex-text-block"> <div class="flex-text-inline">
{{svg "octicon-issue-opened" 14}} {{svg "octicon-issue-opened" 14}}
{{ctx.Locale.PrettyNumber .NumOpenIssues}}&nbsp;{{ctx.Locale.Tr "repo.issues.open_title"}} {{ctx.Locale.PrettyNumber .NumOpenIssues}}&nbsp;{{ctx.Locale.Tr "repo.issues.open_title"}}
</div> </div>
<div class="flex-text-block"> <div class="flex-text-inline">
{{svg "octicon-check" 14}} {{svg "octicon-check" 14}}
{{ctx.Locale.PrettyNumber .NumClosedIssues}}&nbsp;{{ctx.Locale.Tr "repo.issues.closed_title"}} {{ctx.Locale.PrettyNumber .NumClosedIssues}}&nbsp;{{ctx.Locale.Tr "repo.issues.closed_title"}}
</div> </div>
{{if .TotalTrackedTime}} {{if .TotalTrackedTime}}
<div class="flex-text-block"> <div class="flex-text-inline">
{{svg "octicon-clock"}} {{svg "octicon-clock"}}
{{.TotalTrackedTime|Sec2Hour}} {{.TotalTrackedTime|Sec2Hour}}
</div> </div>
{{end}} {{end}}
{{if .UpdatedUnix}} {{if .UpdatedUnix}}
<div class="flex-text-block"> <div class="flex-text-inline">
{{svg "octicon-clock"}} {{svg "octicon-clock"}}
{{ctx.Locale.Tr "repo.milestones.update_ago" (DateUtils.TimeSince .UpdatedUnix)}} {{ctx.Locale.Tr "repo.milestones.update_ago" (DateUtils.TimeSince .UpdatedUnix)}}
</div> </div>
{{end}} {{end}}
<div class="flex-text-block"> <div class="flex-text-inline">
{{if .IsClosed}} {{if .IsClosed}}
{{$closedDate:= DateUtils.TimeSince .ClosedDateUnix}} {{$closedDate:= DateUtils.TimeSince .ClosedDateUnix}}
{{svg "octicon-clock" 14}} {{svg "octicon-clock" 14}}
@@ -69,7 +69,7 @@
</div> </div>
</div> </div>
{{if and (or $.CanWriteIssues $.CanWritePulls) (not $.Repository.IsArchived)}} {{if and (or $.CanWriteIssues $.CanWritePulls) (not $.Repository.IsArchived)}}
<div class="group"> <div class="flex-text-block tw-flex-wrap">
<a class="flex-text-inline" href="{{$.Link}}/{{.ID}}/edit">{{svg "octicon-pencil" 14}}{{ctx.Locale.Tr "repo.issues.label_edit"}}</a> <a class="flex-text-inline" href="{{$.Link}}/{{.ID}}/edit">{{svg "octicon-pencil" 14}}{{ctx.Locale.Tr "repo.issues.label_edit"}}</a>
{{if .IsClosed}} {{if .IsClosed}}
<a class="link-action flex-text-inline" href data-url="{{$.Link}}/{{.ID}}/open">{{svg "octicon-check" 14}}{{ctx.Locale.Tr "repo.milestones.open"}}</a> <a class="link-action flex-text-inline" href data-url="{{$.Link}}/{{.ID}}/open">{{svg "octicon-check" 14}}{{ctx.Locale.Tr "repo.milestones.open"}}</a>
@@ -83,7 +83,7 @@
{{if .Content}} {{if .Content}}
<div class="render-content markup">{{.RenderedContent}}</div> <div class="render-content markup">{{.RenderedContent}}</div>
{{end}} {{end}}
</li> </div>
{{end}} {{end}}
{{template "base/paginate" .}} {{template "base/paginate" .}}
+10 -8
View File
@@ -16,7 +16,7 @@
<div class="item-main"> <div class="item-main">
<div class="item-header"> <div class="item-header">
<div> <div>
<a class="issue-item-title" href="{{if .Link}}{{.Link}}{{else}}{{$.Link}}/{{.Index}}{{end}}">{{.Title | ctx.RenderUtils.RenderIssueSimpleTitle}}</a> <a class="list-item-large-title" href="{{if .Link}}{{.Link}}{{else}}{{$.Link}}/{{.Index}}{{end}}">{{.Title | ctx.RenderUtils.RenderIssueSimpleTitle}}</a>
{{if .IsPull}} {{if .IsPull}}
{{if (index $.CommitStatuses .PullRequest.ID)}} {{if (index $.CommitStatuses .PullRequest.ID)}}
<span class="tw-align-[1px]">{{/* make the "flex" children align with parent "inline" */}} <span class="tw-align-[1px]">{{/* make the "flex" children align with parent "inline" */}}
@@ -37,14 +37,16 @@
</div> </div>
{{end}} {{end}}
</div> </div>
<div class="item-body"> <div class="item-body tw-gap-2">
<a class="index" href="{{if .Link}}{{.Link}}{{else}}{{$.Link}}/{{.Index}}{{end}}"> <a class="index flex-text-inline" href="{{if .Link}}{{.Link}}{{else}}{{$.Link}}/{{.Index}}{{end}}">
{{if eq $.listType "dashboard"}} {{if eq $.listType "dashboard"}}
{{.Repo.FullName}}#{{.Index}} {{.Repo.FullName}}#{{.Index}}
{{else}} {{else}}
#{{.Index}} #{{.Index}}
{{end}} {{end}}
</a> </a>
<div class="flex-text-inline">
{{$timeStr := DateUtils.TimeSince .GetLastEventTimestamp}} {{$timeStr := DateUtils.TimeSince .GetLastEventTimestamp}}
{{if .OriginalAuthor}} {{if .OriginalAuthor}}
{{ctx.Locale.Tr .GetLastEventLabelFake $timeStr .OriginalAuthor}} {{ctx.Locale.Tr .GetLastEventLabelFake $timeStr .OriginalAuthor}}
@@ -53,6 +55,8 @@
{{else}} {{else}}
{{ctx.Locale.Tr .GetLastEventLabelFake $timeStr .Poster.GetDisplayName}} {{ctx.Locale.Tr .GetLastEventLabelFake $timeStr .Poster.GetDisplayName}}
{{end}} {{end}}
</div>
{{if .IsPull}} {{if .IsPull}}
<div class="branches flex-text-inline"> <div class="branches flex-text-inline">
<div class="branch"> <div class="branch">
@@ -99,11 +103,9 @@
</span> </span>
{{end}} {{end}}
{{if ne .DeadlineUnix 0}} {{if ne .DeadlineUnix 0}}
<span class="due-date flex-text-inline" data-tooltip-content="{{ctx.Locale.Tr "repo.issues.due_date"}}"> <span class="due-date flex-text-inline {{if .IsOverdue}}tw-text-red{{end}}" data-tooltip-content="{{ctx.Locale.Tr "repo.issues.due_date"}}">
<span{{if .IsOverdue}} class="tw-text-red"{{end}}> {{svg "octicon-calendar" 14}}
{{svg "octicon-calendar" 14}} {{DateUtils.AbsoluteShort .DeadlineUnix}}
{{DateUtils.AbsoluteShort .DeadlineUnix}}
</span>
</span> </span>
{{end}} {{end}}
{{if .IsPull}} {{if .IsPull}}
+16 -27
View File
@@ -71,45 +71,45 @@
</div> </div>
</div> </div>
</div> </div>
<div class="milestone-list"> <div class="flex-divided-list">
{{range .Milestones}} {{range .Milestones}}
<li class="milestone-card"> <div class="item flex-relaxed-list">
<div class="milestone-header"> <div class="flex-left-right">
<h3 class="flex-text-block tw-m-0"> <span class="list-item-large-title">
<span class="ui large label"> <span class="ui large label">
{{.Repo.FullName}} {{.Repo.FullName}}
</span> </span>
{{svg "octicon-milestone" 16}} {{svg "octicon-milestone" 16}}
<a class="muted" href="{{.Repo.Link}}/milestone/{{.ID}}">{{.Name}}</a> <a class="muted" href="{{.Repo.Link}}/milestone/{{.ID}}">{{.Name}}</a>
</h3> </span>
<div class="tw-flex tw-items-center"> <div class="flex-text-inline">
<span class="tw-mr-2">{{.Completeness}}%</span> <span>{{.Completeness}}%</span>
<progress value="{{.Completeness}}" max="100"></progress> <progress class="list-item-title-progress" value="{{.Completeness}}" max="100"></progress>
</div> </div>
</div> </div>
<div class="milestone-toolbar"> <div class="list-item-secondary-bar">
<div class="group"> <div class="flex-text-block tw-flex-wrap">
<div class="flex-text-block"> <div class="flex-text-inline">
{{svg "octicon-issue-opened" 14}} {{svg "octicon-issue-opened" 14}}
{{ctx.Locale.PrettyNumber .NumOpenIssues}}&nbsp;{{ctx.Locale.Tr "repo.issues.open_title"}} {{ctx.Locale.PrettyNumber .NumOpenIssues}}&nbsp;{{ctx.Locale.Tr "repo.issues.open_title"}}
</div> </div>
<div class="flex-text-block"> <div class="flex-text-inline">
{{svg "octicon-check" 14}} {{svg "octicon-check" 14}}
{{ctx.Locale.PrettyNumber .NumClosedIssues}}&nbsp;{{ctx.Locale.Tr "repo.issues.closed_title"}} {{ctx.Locale.PrettyNumber .NumClosedIssues}}&nbsp;{{ctx.Locale.Tr "repo.issues.closed_title"}}
</div> </div>
{{if .TotalTrackedTime}} {{if .TotalTrackedTime}}
<div class="flex-text-block"> <div class="flex-text-inline">
{{svg "octicon-clock"}} {{svg "octicon-clock"}}
{{.TotalTrackedTime|Sec2Hour}} {{.TotalTrackedTime|Sec2Hour}}
</div> </div>
{{end}} {{end}}
{{if .UpdatedUnix}} {{if .UpdatedUnix}}
<div class="flex-text-block"> <div class="flex-text-inline">
{{svg "octicon-clock"}} {{svg "octicon-clock"}}
{{ctx.Locale.Tr "repo.milestones.update_ago" (DateUtils.TimeSince .UpdatedUnix)}} {{ctx.Locale.Tr "repo.milestones.update_ago" (DateUtils.TimeSince .UpdatedUnix)}}
</div> </div>
{{end}} {{end}}
<div class="flex-text-block"> <div class="flex-text-inline">
{{if .IsClosed}} {{if .IsClosed}}
{{$closedDate:= DateUtils.TimeSince .ClosedDateUnix}} {{$closedDate:= DateUtils.TimeSince .ClosedDateUnix}}
{{svg "octicon-clock" 14}} {{svg "octicon-clock" 14}}
@@ -127,22 +127,11 @@
{{end}} {{end}}
</div> </div>
</div> </div>
{{if and (or $.CanWriteIssues $.CanWritePulls) (not $.Repository.IsArchived)}}
<div class="group">
<a class="flex-text-inline" href="{{$.Link}}/{{.ID}}/edit">{{svg "octicon-pencil" 14}}{{ctx.Locale.Tr "repo.issues.label_edit"}}</a>
{{if .IsClosed}}
<a class="link-action flex-text-inline" href data-url="{{$.Link}}/{{.ID}}/open">{{svg "octicon-check" 14}}{{ctx.Locale.Tr "repo.milestones.open"}}</a>
{{else}}
<a class="link-action flex-text-inline" href data-url="{{$.Link}}/{{.ID}}/close">{{svg "octicon-x" 14}}{{ctx.Locale.Tr "repo.milestones.close"}}</a>
{{end}}
<a class="delete-button flex-text-inline" href="#" data-url="{{$.RepoLink}}/milestones/delete" data-id="{{.ID}}">{{svg "octicon-trash" 14}}{{ctx.Locale.Tr "repo.issues.label_delete"}}</a>
</div>
{{end}}
</div> </div>
{{if .Content}} {{if .Content}}
<div class="render-content markup">{{.RenderedContent}}</div> <div class="render-content markup">{{.RenderedContent}}</div>
{{end}} {{end}}
</li> </div>
{{end}} {{end}}
{{template "base/paginate" .}} {{template "base/paginate" .}}
+1 -1
View File
@@ -372,7 +372,7 @@ test('close project and view in closed projects list', async ({page}) => {
await expect(page.locator('.milestone-list')).toContainText(closedProjectTitle); await expect(page.locator('.milestone-list')).toContainText(closedProjectTitle);
// Close the second project by clicking the close link // Close the second project by clicking the close link
const projectCard = page.locator('.milestone-card').filter({hasText: closedProjectTitle}); const projectCard = page.locator('.milestone-list > .item').filter({hasText: closedProjectTitle});
await projectCard.locator('a.link-action[data-url$="/close"]').click(); await projectCard.locator('a.link-action[data-url$="/close"]').click();
// Wait for redirect back to project view page // Wait for redirect back to project view page
+1 -1
View File
@@ -159,7 +159,7 @@ export async function createProject(
await page.waitForURL(new RegExp(`/${owner}/${repo}/projects$`)); await page.waitForURL(new RegExp(`/${owner}/${repo}/projects$`));
// Extract the project ID from the project link in the list // Extract the project ID from the project link in the list
const projectLink = page.locator('.milestone-list .milestone-card').filter({hasText: title}).locator('a').first(); const projectLink = page.locator('.milestone-list > .item').filter({hasText: title}).locator('a').first();
const href = await projectLink.getAttribute('href'); const href = await projectLink.getAttribute('href');
const match = /\/projects\/(\d+)/.exec(href || ''); const match = /\/projects\/(\d+)/.exec(href || '');
const id = match ? parseInt(match[1]) : 0; const id = match ? parseInt(match[1]) : 0;
+1 -1
View File
@@ -34,7 +34,7 @@ import (
func getIssuesSelection(t testing.TB, htmlDoc *HTMLDoc) *goquery.Selection { func getIssuesSelection(t testing.TB, htmlDoc *HTMLDoc) *goquery.Selection {
issueList := htmlDoc.doc.Find("#issue-list") issueList := htmlDoc.doc.Find("#issue-list")
assert.Equal(t, 1, issueList.Length()) assert.Equal(t, 1, issueList.Length())
return issueList.Find(".item").Find(".issue-item-title") return issueList.Find(".item").Find(".list-item-large-title")
} }
func getIssue(t *testing.T, repoID int64, issueSelection *goquery.Selection) *issues_model.Issue { func getIssue(t *testing.T, repoID int64, issueSelection *goquery.Selection) *issues_model.Issue {
-5
View File
@@ -454,11 +454,6 @@ img.ui.avatar,
margin-right: 4px; margin-right: 4px;
} }
.ui.inline.delete-button {
padding: 8px 15px;
font-weight: var(--font-weight-normal);
}
.ui .migrate { .ui .migrate {
color: var(--color-text-light-2) !important; color: var(--color-text-light-2) !important;
} }
-1
View File
@@ -37,7 +37,6 @@
@import "./modules/charescape.css"; @import "./modules/charescape.css";
@import "./shared/flex-list.css"; @import "./shared/flex-list.css";
@import "./shared/milestone.css";
@import "./shared/settings.css"; @import "./shared/settings.css";
@import "./features/dropzone.css"; @import "./features/dropzone.css";
+1 -1
View File
@@ -2,7 +2,7 @@
and material icons should have no "fill" set explicitly, otherwise some like ".editorconfig" won't render correctly */ and material icons should have no "fill" set explicitly, otherwise some like ".editorconfig" won't render correctly */
.svg:not(.git-entry-icon) { .svg:not(.git-entry-icon) {
display: inline-block; display: inline-block;
vertical-align: text-top; vertical-align: middle; /* middle is the best choice for different font sizes from 1px to 36px when no flex */
fill: currentcolor; fill: currentcolor;
} }
+30 -8
View File
@@ -34,14 +34,6 @@
} }
} }
#issue-list .issue-item-title {
font-size: 16px;
font-weight: var(--font-weight-semibold);
color: var(--color-text);
text-decoration: none;
overflow-wrap: anywhere;
}
#issue-list .branches { #issue-list .branches {
display: inline-flex; display: inline-flex;
} }
@@ -106,3 +98,33 @@
color: var(--color-primary); color: var(--color-primary);
text-decoration: underline; text-decoration: underline;
} }
.list-item-large-title {
font-size: 16px;
font-weight: var(--font-weight-semibold);
color: var(--color-text);
text-decoration: none;
overflow-wrap: anywhere;
}
.list-item-title-progress {
width: 200px;
height: 16px;
}
.list-item-secondary-bar {
display: flex;
flex-wrap: wrap;
gap: var(--gap-block);
justify-content: space-between;
color: var(--color-text-light-2);
}
.list-item-secondary-bar a {
color: var(--color-text-light-2);
text-decoration: none;
}
.list-item-secondary-bar a:hover {
color: var(--color-text);
}
+5 -5
View File
@@ -32,7 +32,7 @@
.items-with-main > .item { .items-with-main > .item {
display: flex; display: flex;
gap: 8px; gap: var(--gap-block);
align-items: flex-start; align-items: flex-start;
} }
@@ -44,7 +44,7 @@
.items-with-main > .item .item-main { .items-with-main > .item .item-main {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
gap: 0.25em; gap: var(--gap-inline);
flex-grow: 1; flex-grow: 1;
flex-basis: 60%; /* avoid wrapping the "item-trailing" too aggressively */ flex-basis: 60%; /* avoid wrapping the "item-trailing" too aggressively */
min-width: 0; /* make the "text truncate" work, otherwise the flex axis is not limited and the text just overflows */ min-width: 0; /* make the "text truncate" work, otherwise the flex axis is not limited and the text just overflows */
@@ -52,7 +52,7 @@
.items-with-main > .item .item-header { .items-with-main > .item .item-header {
display: flex; display: flex;
gap: .25rem; gap: var(--gap-inline);
justify-content: space-between; justify-content: space-between;
flex-wrap: wrap; flex-wrap: wrap;
} }
@@ -63,7 +63,7 @@
.items-with-main > .item .item-trailing { .items-with-main > .item .item-trailing {
display: flex; display: flex;
gap: 0.5rem; gap: var(--gap-block);
align-items: center; align-items: center;
flex-grow: 0; flex-grow: 0;
flex-wrap: wrap; flex-wrap: wrap;
@@ -92,7 +92,7 @@
display: flex; display: flex;
align-items: center; align-items: center;
flex-wrap: wrap; flex-wrap: wrap;
gap: .25rem; gap: var(--gap-inline);
color: var(--color-text-light-2); color: var(--color-text-light-2);
overflow-wrap: anywhere; overflow-wrap: anywhere;
} }
-62
View File
@@ -1,62 +0,0 @@
.milestone-list {
list-style: none;
}
.milestone-card {
width: 100%;
padding-top: 10px;
padding-bottom: 10px;
}
.milestone-card + .milestone-card {
border-top: 1px solid var(--color-secondary);
}
.milestone-card .render-content {
padding-top: 10px;
}
.milestone-header progress {
width: 200px;
height: 16px;
}
.milestone-header {
display: flex;
align-items: center;
margin: 0;
flex-wrap: wrap;
justify-content: space-between;
}
.milestone-toolbar {
padding-top: 5px;
display: flex;
flex-wrap: wrap;
gap: 8px;
justify-content: space-between;
}
.milestone-toolbar .group {
color: var(--color-text-light-2);
display: flex;
flex-wrap: wrap;
gap: 8px;
}
.milestone-toolbar .group > a {
font-size: 15px;
color: var(--color-text-light-2);
}
.milestone-toolbar .group > a:hover {
color: var(--color-text);
}
@media (max-width: 767.98px) {
.milestone-card {
display: flex;
flex-direction: column;
gap: 8px;
}
}