Skip to content

Commit 2e96e82

Browse files
silverwindclaudewxiaoguang
authored
style: misc UI fixes (#37691)
- Action view sidebar: rename `job-brief-item` to `action-view-sidebar-item`, fix trash icon overflow on long artifact names, align artifact and workflow hover styles with the jobs list - Branches: expand new PR button cell to three wide so the button is not clipped on narrow viewports - Dashboard feed: add `tw-max-w-full` so long issue titles truncate - Reactions: tighten label padding <img width="261" height="65" alt="Screenshot 2026-05-13 at 16 18 33" src="https://github.com/user-attachments/assets/ecfe8f37-4a65-4839-b8c0-defccc85482c" /> <img width="154" height="126" alt="Screenshot 2026-05-13 at 16 19 25" src="https://github.com/user-attachments/assets/41302134-d1b7-401a-be2d-79173adb6d17" /> <img width="405" height="378" alt="Screenshot 2026-05-13 at 16 47 18" src="https://github.com/user-attachments/assets/e2c5cdd4-f11d-498c-b17e-c74c80c0ddf7" /> <img width="206" height="149" alt="Screenshot 2026-05-13 at 16 55 53" src="https://github.com/user-attachments/assets/7787125d-04b1-4500-b9b8-2637845509d6" /> <img width="858" height="135" alt="Screenshot 2026-05-13 at 16 58 41" src="https://github.com/user-attachments/assets/cb5bdf56-3891-469d-aa77-ea38855958c1" /> <img width="434" height="128" alt="Screenshot 2026-05-13 at 17 00 43" src="https://github.com/user-attachments/assets/60f2c34d-b345-4813-8f6d-a95bf51021b4" /> --- This PR was written with the help of Claude Opus 4.7 --------- Signed-off-by: silverwind <me@silverwind.io> Co-authored-by: Claude (Opus 4.7) <noreply@anthropic.com> Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
1 parent 93b8fdc commit 2e96e82

17 files changed

Lines changed: 154 additions & 125 deletions

File tree

modules/templates/util_render.go

Lines changed: 15 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -121,23 +121,7 @@ func (ut *RenderUtils) RenderIssueSimpleTitle(text string) template.HTML {
121121
return ret
122122
}
123123

124-
func (ut *RenderUtils) RenderLabelWithLink(label *issues_model.Label, link any) template.HTML {
125-
var attrHref template.HTML
126-
switch link.(type) {
127-
case template.URL, string:
128-
attrHref = htmlutil.HTMLFormat(`href="%s"`, link)
129-
default:
130-
panic(fmt.Sprintf("unexpected type %T for link", link))
131-
}
132-
return ut.renderLabelWithTag(label, "a", attrHref)
133-
}
134-
135124
func (ut *RenderUtils) RenderLabel(label *issues_model.Label) template.HTML {
136-
return ut.renderLabelWithTag(label, "span", "")
137-
}
138-
139-
// RenderLabel renders a label
140-
func (ut *RenderUtils) renderLabelWithTag(label *issues_model.Label, tagName, tagAttrs template.HTML) template.HTML {
141125
locale := ut.ctx.Value(translation.ContextKey).(translation.Locale)
142126
var extraCSSClasses string
143127
textColor := util.ContrastColor(label.Color)
@@ -151,8 +135,8 @@ func (ut *RenderUtils) renderLabelWithTag(label *issues_model.Label, tagName, ta
151135

152136
if labelScope == "" {
153137
// Regular label
154-
return htmlutil.HTMLFormat(`<%s %s class="ui label %s" style="color: %s !important; background-color: %s !important;" data-tooltip-content title="%s"><span class="gt-ellipsis">%s</span></%s>`,
155-
tagName, tagAttrs, extraCSSClasses, textColor, label.Color, descriptionText, ut.RenderEmoji(label.Name), tagName)
138+
return htmlutil.HTMLFormat(`<span class="ui label %s" style="color: %s !important; background-color: %s !important;" data-tooltip-content title="%s"><span class="gt-ellipsis">%s</span></span>`,
139+
extraCSSClasses, textColor, label.Color, descriptionText, ut.RenderEmoji(label.Name))
156140
}
157141

158142
// Scoped label
@@ -187,29 +171,25 @@ func (ut *RenderUtils) renderLabelWithTag(label *issues_model.Label, tagName, ta
187171

188172
if label.ExclusiveOrder > 0 {
189173
// <scope> | <label> | <order>
190-
return htmlutil.HTMLFormat(`<%s %s class="ui label %s scope-parent" data-tooltip-content title="%s">`+
174+
return htmlutil.HTMLFormat(`<span class="ui label %s scope-parent" data-tooltip-content title="%s">`+
191175
`<div class="ui label scope-left" style="color: %s !important; background-color: %s !important">%s</div>`+
192176
`<div class="ui label scope-middle" style="color: %s !important; background-color: %s !important">%s</div>`+
193177
`<div class="ui label scope-right">%d</div>`+
194-
`</%s>`,
195-
tagName, tagAttrs,
178+
`</span>`,
196179
extraCSSClasses, descriptionText,
197180
textColor, scopeColor, scopeHTML,
198181
textColor, itemColor, itemHTML,
199-
label.ExclusiveOrder,
200-
tagName)
182+
label.ExclusiveOrder)
201183
}
202184

203185
// <scope> | <label>
204-
return htmlutil.HTMLFormat(`<%s %s class="ui label %s scope-parent" data-tooltip-content title="%s">`+
186+
return htmlutil.HTMLFormat(`<span class="ui label %s scope-parent" data-tooltip-content title="%s">`+
205187
`<div class="ui label scope-left" style="color: %s !important; background-color: %s !important">%s</div>`+
206188
`<div class="ui label scope-right" style="color: %s !important; background-color: %s !important">%s</div>`+
207-
`</%s>`,
208-
tagName, tagAttrs,
189+
`</span>`,
209190
extraCSSClasses, descriptionText,
210191
textColor, scopeColor, scopeHTML,
211-
textColor, itemColor, itemHTML,
212-
tagName)
192+
textColor, itemColor, itemHTML)
213193
}
214194

215195
// RenderEmoji renders html text with emoji post processors
@@ -246,18 +226,19 @@ func (ut *RenderUtils) MarkdownToHtml(input string) template.HTML { //nolint:rev
246226
func (ut *RenderUtils) RenderLabels(labels []*issues_model.Label, repoLink string, issue *issues_model.Issue) template.HTML {
247227
isPullRequest := issue != nil && issue.IsPull
248228
baseLink := fmt.Sprintf("%s/%s", repoLink, util.Iif(isPullRequest, "pulls", "issues"))
249-
var htmlCode strings.Builder
250-
htmlCode.WriteString(`<span class="labels-list">`)
229+
var htmlCode htmlutil.HTMLBuilder
230+
htmlCode.WriteHTML(`<span class="labels-list">`)
251231
for _, label := range labels {
252232
// Protect against nil value in labels - shouldn't happen but would cause a panic if so
253233
if label == nil {
254234
continue
255235
}
256-
link := fmt.Sprintf("%s?labels=%d", baseLink, label.ID)
257-
htmlCode.WriteString(string(ut.RenderLabelWithLink(label, template.URL(link))))
236+
htmlCode.WriteFormat(`<a class="item" href="%s?labels=%d">`, baseLink, label.ID)
237+
htmlCode.WriteHTML(ut.RenderLabel(label))
238+
htmlCode.WriteHTML("</a>")
258239
}
259-
htmlCode.WriteString("</span>")
260-
return template.HTML(htmlCode.String())
240+
htmlCode.WriteHTML("</span>")
241+
return htmlCode.HTMLString()
261242
}
262243

263244
func (ut *RenderUtils) RenderThemeItem(info *webtheme.ThemeMetaInfo, iconSize int) template.HTML {

modules/templates/util_render_test.go

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -206,16 +206,15 @@ func TestRenderLabels(t *testing.T) {
206206
expected = `/owner/repo/pulls?labels=123`
207207
assert.Contains(t, ut.RenderLabels([]*issues.Label{label}, "/owner/repo", issue), expected)
208208

209-
expectedLabel := `<a href="&lt;&gt;" class="ui label " style="color: #fff !important; background-color: label-color !important;" data-tooltip-content title=""><span class="gt-ellipsis">label-name</span></a>`
210-
assert.Equal(t, expectedLabel, string(ut.RenderLabelWithLink(label, "<>")))
211-
assert.Equal(t, expectedLabel, string(ut.RenderLabelWithLink(label, template.URL("<>"))))
209+
expectedLabel := `<span class="ui label " style="color: #fff !important; background-color: label-color !important;" data-tooltip-content title=""><span class="gt-ellipsis">label-name</span></span>`
210+
assert.Equal(t, expectedLabel, string(ut.RenderLabel(label)))
212211

213212
label = &issues.Label{ID: 123, Name: "</>", Exclusive: true}
214-
expectedLabel = `<a href="" class="ui label scope-parent" data-tooltip-content title=""><div class="ui label scope-left" style="color: #fff !important; background-color: #000000 !important">&lt;</div><div class="ui label scope-right" style="color: #fff !important; background-color: #000000 !important">&gt;</div></a>`
215-
assert.Equal(t, expectedLabel, string(ut.RenderLabelWithLink(label, "")))
213+
expectedLabel = `<span class="ui label scope-parent" data-tooltip-content title=""><div class="ui label scope-left" style="color: #fff !important; background-color: #000000 !important">&lt;</div><div class="ui label scope-right" style="color: #fff !important; background-color: #000000 !important">&gt;</div></span>`
214+
assert.Equal(t, expectedLabel, string(ut.RenderLabel(label)))
216215
label = &issues.Label{ID: 123, Name: "</>", Exclusive: true, ExclusiveOrder: 1}
217-
expectedLabel = `<a href="" class="ui label scope-parent" data-tooltip-content title=""><div class="ui label scope-left" style="color: #fff !important; background-color: #000000 !important">&lt;</div><div class="ui label scope-middle" style="color: #fff !important; background-color: #000000 !important">&gt;</div><div class="ui label scope-right">1</div></a>`
218-
assert.Equal(t, expectedLabel, string(ut.RenderLabelWithLink(label, "")))
216+
expectedLabel = `<span class="ui label scope-parent" data-tooltip-content title=""><div class="ui label scope-left" style="color: #fff !important; background-color: #000000 !important">&lt;</div><div class="ui label scope-middle" style="color: #fff !important; background-color: #000000 !important">&gt;</div><div class="ui label scope-right">1</div></span>`
217+
assert.Equal(t, expectedLabel, string(ut.RenderLabel(label)))
219218
}
220219

221220
func TestUserMention(t *testing.T) {

templates/repo/branch/list.tmpl

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,8 @@
2929
</div>
3030
<p class="info tw-flex tw-items-center tw-my-1">{{svg "octicon-git-commit" 16 "tw-mr-1"}}<a href="{{.RepoLink}}/commit/{{PathEscape .DefaultBranchBranch.DBBranch.CommitID}}">{{ShortSha .DefaultBranchBranch.DBBranch.CommitID}}</a> · <span class="commit-message">{{ctx.RenderUtils.RenderCommitMessage .DefaultBranchBranch.DBBranch.CommitMessage .Repository}}</span> · {{ctx.Locale.Tr "org.repo_updated"}} {{DateUtils.TimeSince .DefaultBranchBranch.DBBranch.CommitTime}}{{if .DefaultBranchBranch.DBBranch.Pusher}} &nbsp;{{template "shared/user/avatarlink" dict "user" .DefaultBranchBranch.DBBranch.Pusher}}{{template "shared/user/namelink" .DefaultBranchBranch.DBBranch.Pusher}}{{end}}</p>
3131
</td>
32-
{{/* FIXME: here and below, the tw-overflow-visible is not quite right but it is still needed the moment: to show the important buttons when the width is narrow */}}
33-
<td class="tw-text-right tw-overflow-visible">
32+
<td>
33+
<div class="tw-flex tw-flex-wrap tw-justify-end">
3434
{{if and $.IsWriter $.Repository.CanContentChange (not .IsDeleted)}}
3535
<button class="btn interact-bg show-create-branch-modal tw-p-2"
3636
data-modal="#create-branch-modal"
@@ -63,6 +63,7 @@
6363
{{svg "octicon-pencil"}}
6464
</button>
6565
{{end}}
66+
</div>
6667
</td>
6768
</tr>
6869
</tbody>
@@ -71,9 +72,7 @@
7172
{{end}}
7273

7374
<h4 class="ui top attached header">
74-
<div class="flex-text-block">
75-
{{ctx.Locale.Tr "repo.branches"}}
76-
</div>
75+
{{ctx.Locale.Tr "repo.branches"}}
7776
</h4>
7877

7978
<div class="ui attached segment">
@@ -106,7 +105,7 @@
106105
<p class="info tw-flex tw-items-center tw-my-1">{{svg "octicon-git-commit" 16 "tw-mr-1"}}<a href="{{$.RepoLink}}/commit/{{PathEscape .DBBranch.CommitID}}">{{ShortSha .DBBranch.CommitID}}</a> · <span class="commit-message">{{ctx.RenderUtils.RenderCommitMessage .DBBranch.CommitMessage $.Repository}}</span> · {{ctx.Locale.Tr "org.repo_updated"}} {{DateUtils.TimeSince .DBBranch.CommitTime}}{{if .DBBranch.Pusher}} &nbsp;{{template "shared/user/avatarlink" dict "user" .DBBranch.Pusher}} &nbsp;{{template "shared/user/namelink" .DBBranch.Pusher}}{{end}}</p>
107106
{{end}}
108107
</td>
109-
<td class="two wide ui">
108+
<td class="two wide">
110109
{{if and (not .DBBranch.IsDeleted) $.DefaultBranchBranch}}
111110
{{$tooltipDivergence := ""}}
112111
{{if or .CommitsBehind .CommitsAhead}}
@@ -127,21 +126,21 @@
127126
</div>
128127
{{end}}
129128
</td>
130-
<td class="two wide tw-text-right">
129+
<td class="three wide tw-text-right">
131130
{{if not .LatestPullRequest}}
132131
{{if .IsIncluded}}
133132
<span class="ui orange large label" data-tooltip-content="{{ctx.Locale.Tr "repo.branch.included_desc"}}">
134133
{{svg "octicon-git-pull-request"}} {{ctx.Locale.Tr "repo.branch.included"}}
135134
</span>
136135
{{else if and (not .DBBranch.IsDeleted) $.AllowsPulls (gt .CommitsAhead 0)}}
137-
<a href="{{$.PullRequestCtx.MakeDefaultCompareLink .DBBranch.Name}}?expand=1">
138-
<button id="new-pull-request" class="ui compact basic button tw-mr-0">{{if $.CanPull}}{{ctx.Locale.Tr "repo.pulls.compare_changes"}}{{else}}{{ctx.Locale.Tr "action.compare_branch"}}{{end}}</button>
136+
<a class="ui compact basic button tw-m-0 tw-max-w-full" href="{{$.PullRequestCtx.MakeDefaultCompareLink .DBBranch.Name}}?expand=1">
137+
<span class="gt-ellipsis">{{if $.CanPull}}{{ctx.Locale.Tr "repo.pulls.compare_changes"}}{{else}}{{ctx.Locale.Tr "action.compare_branch"}}{{end}}</span>
139138
</a>
140139
{{end}}
141140
{{else if and .LatestPullRequest.HasMerged .MergeMovedOn}}
142141
{{if and (not .DBBranch.IsDeleted) $.AllowsPulls (gt .CommitsAhead 0)}}
143-
<a href="{{$.PullRequestCtx.MakeDefaultCompareLink .DBBranch.Name}}?expand=1">
144-
<button id="new-pull-request" class="ui compact basic button tw-mr-0">{{if $.CanPull}}{{ctx.Locale.Tr "repo.pulls.compare_changes"}}{{else}}{{ctx.Locale.Tr "action.compare_branch"}}{{end}}</button>
142+
<a class="ui compact basic button tw-m-0 tw-max-w-full" href="{{$.PullRequestCtx.MakeDefaultCompareLink .DBBranch.Name}}?expand=1">
143+
<span class="gt-ellipsis">{{if $.CanPull}}{{ctx.Locale.Tr "repo.pulls.compare_changes"}}{{else}}{{ctx.Locale.Tr "action.compare_branch"}}{{end}}</span>
145144
</a>
146145
{{end}}
147146
{{else}}
@@ -155,8 +154,8 @@
155154
{{end}}
156155
{{end}}
157156
</td>
158-
{{/* FIXME: here and above, the tw-overflow-visible is not quite right */}}
159-
<td class="three wide tw-text-right tw-overflow-visible">
157+
<td class="three wide">
158+
<div class="tw-flex tw-flex-wrap tw-justify-end">
160159
{{if and $.IsWriter $.Repository.CanContentChange (not .DBBranch.IsDeleted)}}
161160
<button class="btn interact-bg tw-p-2 show-modal show-create-branch-modal"
162161
data-branch-from="{{.DBBranch.Name}}"
@@ -202,6 +201,7 @@
202201
</button>
203202
{{end}}
204203
{{end}}
204+
</div>
205205
</td>
206206
</tr>
207207
{{end}}

templates/repo/issue/card.tmpl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@
6868
{{range $label := .Labels}}
6969
{{$link := print $.Issue.Repo.Link "/issues"}}
7070
{{$link = QueryBuild $link "labels" $label.ID}}
71-
{{ctx.RenderUtils.RenderLabelWithLink $label $link}}
71+
<a class="item" href="{{$link}}">{{ctx.RenderUtils.RenderLabel $label}}</a>
7272
{{end}}
7373
</div>
7474
{{if .Assignees}}

templates/repo/issue/view_content/comments.tmpl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,7 @@
169169
</div>
170170
{{else if eq .Type 7}}
171171
{{if or .AddedLabels .RemovedLabels}}
172-
<div class="timeline-item event with-labels-list-inline" id="{{.HashTag}}">
172+
<div class="timeline-item event" id="{{.HashTag}}">
173173
<span class="badge">{{svg "octicon-tag"}}</span>
174174
{{template "shared/user/avatarlink" dict "user" .Poster}}
175175
<span class="comment-text-line">

templates/shared/issuelist.tmpl

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,17 +15,19 @@
1515

1616
<div class="item-main">
1717
<div class="item-header">
18-
<div class="item-title">
19-
<a class="tw-no-underline issue-title" href="{{if .Link}}{{.Link}}{{else}}{{$.Link}}/{{.Index}}{{end}}">{{.Title | ctx.RenderUtils.RenderIssueSimpleTitle}}</a>
18+
<div>
19+
<a class="issue-item-title" href="{{if .Link}}{{.Link}}{{else}}{{$.Link}}/{{.Index}}{{end}}">{{.Title | ctx.RenderUtils.RenderIssueSimpleTitle}}</a>
2020
{{if .IsPull}}
2121
{{if (index $.CommitStatuses .PullRequest.ID)}}
22+
<span class="tw-align-[1px]">{{/* make the "flex" children align with parent "inline" */}}
2223
{{template "repo/commit_statuses" dict "Status" (index $.CommitLastStatus .PullRequest.ID) "Statuses" (index $.CommitStatuses .PullRequest.ID)}}
24+
</span>
2325
{{end}}
2426
{{end}}
2527
<span class="labels-list">
26-
{{range .Labels}}
27-
<a href="?q={{$.Keyword}}&type={{$.ViewType}}&state={{$.State}}&labels={{.ID}}{{if ne $.listType "milestone"}}&milestone={{$.MilestoneID}}{{end}}&assignee={{$.AssigneeID}}&poster={{$.PosterID}}{{if $.ShowArchivedLabels}}&archived=true{{end}}">{{ctx.RenderUtils.RenderLabel .}}</a>
28-
{{end}}
28+
{{- range .Labels -}}
29+
<a class="item" href="?q={{$.Keyword}}&type={{$.ViewType}}&state={{$.State}}&labels={{.ID}}{{if ne $.listType "milestone"}}&milestone={{$.MilestoneID}}{{end}}&assignee={{$.AssigneeID}}&poster={{$.PosterID}}{{if $.ShowArchivedLabels}}&archived=true{{end}}">{{ctx.RenderUtils.RenderLabel .}}</a>
30+
{{- end -}}
2931
</span>
3032
</div>
3133
{{if .TotalTrackedTime}}

templates/user/dashboard/feeds.tmpl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@
107107
{{else if .GetOpType.InActions "create_pull_request"}}
108108
<span class="tw-inline-block tw-truncate issue title">{{index .GetIssueInfos 1 | ctx.RenderUtils.RenderIssueSimpleTitle}}</span>
109109
{{else if .GetOpType.InActions "comment_issue" "approve_pull_request" "reject_pull_request" "comment_pull"}}
110-
<a href="{{.GetCommentLink ctx}}" class="tw-inline-block tw-truncate tw-self-start issue title">{{(.GetIssueTitle ctx) | ctx.RenderUtils.RenderIssueSimpleTitle}}</a>
110+
<a href="{{.GetCommentLink ctx}}" class="tw-inline-block tw-truncate tw-max-w-full tw-self-start issue title">{{(.GetIssueTitle ctx) | ctx.RenderUtils.RenderIssueSimpleTitle}}</a>
111111
{{$comment := index .GetIssueInfos 1}}
112112
{{if $comment}}
113113
<div class="render-content markup truncated-markup">{{ctx.RenderUtils.MarkdownToHtml $comment}}</div>

tests/integration/issue_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ import (
3434
func getIssuesSelection(t testing.TB, htmlDoc *HTMLDoc) *goquery.Selection {
3535
issueList := htmlDoc.doc.Find("#issue-list")
3636
assert.Equal(t, 1, issueList.Length())
37-
return issueList.Find(".item").Find(".issue-title")
37+
return issueList.Find(".item").Find(".issue-item-title")
3838
}
3939

4040
func getIssue(t *testing.T, repoID int64, issueSelection *goquery.Selection) *issues_model.Issue {

web_src/css/base.css

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -305,6 +305,15 @@ a.suppressed:hover {
305305
color: inherit;
306306
}
307307

308+
/* keyboard focus ring for interactive elements */
309+
a:focus-visible,
310+
button:focus-visible,
311+
.ui.button:focus-visible,
312+
[role="button"]:focus-visible {
313+
outline: 2px solid var(--color-primary);
314+
outline-offset: -2px;
315+
}
316+
308317
a.silenced:hover {
309318
text-decoration-line: none;
310319
}

web_src/css/modules/button.css

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,6 @@
2121
white-space: nowrap;
2222
}
2323

24-
.ui.button:focus-visible {
25-
box-shadow: inset 0 0 0 2px currentcolor;
26-
}
27-
2824
@media (max-width: 767.98px) {
2925
.ui.button {
3026
white-space: normal;

0 commit comments

Comments
 (0)