feat: add release reactions and a GitHub-like reaction bar (#38415)

Adds emoji reactions to releases and moves the reaction picker of
issues, comments and releases into a GitHub-like reaction bar.

- Releases omit 👎 or 😕
- Drafts and tags can't be reacted to
- Moved menu to tippy
- Added keyboard navigation

Fixes: https://github.com/go-gitea/gitea/issues/34268
Fixes: https://github.com/go-gitea/gitea/issues/16676
Co-authored-by: silverwind <me@silverwind.io>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
This commit is contained in:
authored and GitHub committed 2026-10-20 15:04:10 +02:00
1 parent e645afbb3f
commit edd0c0e2ce
42 files changed
+508 -313

No files matched your search

+5 -7
View File
@@ -55,9 +55,6 @@
</div>
{{end}}
{{end}}
{{if not $repo.IsArchived}}
{{template "repo/issue/view_content/add_reaction" dict "ActionURL" (printf "%s/comments/%d/reactions" $repoLink $comment.ID)}}
{{end}}
{{template "repo/issue/view_content/context_menu" dict "ConvContentType" "issue_comment" "ConvContentPage" "pr-files" "ConvContentItem" $comment}}
</div>
</div>
@@ -76,10 +73,11 @@
{{template "repo/issue/view_content/attachments" dict "Attachments" $comment.Attachments "RenderedContent" $comment.RenderedContent}}
{{end}}
</div>
{{$reactions := $comment.Reactions.GroupByType}}
{{if $reactions}}
{{template "repo/issue/view_content/reactions" dict "ActionURL" (printf "%s/comments/%d/reactions" $repoLink $comment.ID) "Reactions" $reactions}}
{{end}}
{{template "shared/reactions" dict
"AllowedReactions" $root.AllowedIssueReactions
"ActionURL" (printf "%s/comments/%d/reactions" $repoLink $comment.ID)
"Reactions" $comment.Reactions.GroupByType
}}
</div>
</div>
{{end}}
+5 -7
View File
@@ -38,9 +38,6 @@
</div>
<div class="comment-header-right">
{{template "repo/issue/view_content/show_role" dict "ShowRole" .Issue.ShowRole "IgnorePoster" true}}
{{if not $.Repository.IsArchived}}
{{template "repo/issue/view_content/add_reaction" dict "ActionURL" (printf "%s/issues/%d/reactions" $.RepoLink .Issue.Index)}}
{{end}}
{{template "repo/issue/view_content/context_menu" dict "ConvContentType" "issue_main" "ConvContentItem" .Issue}}
</div>
</div>
@@ -58,10 +55,11 @@
{{template "repo/issue/view_content/attachments" dict "Attachments" .Issue.Attachments "RenderedContent" .Issue.RenderedContent}}
{{end}}
</div>
{{$reactions := .Issue.Reactions.GroupByType}}
{{if $reactions}}
{{template "repo/issue/view_content/reactions" dict "ActionURL" (printf "%s/issues/%d/reactions" $.RepoLink .Issue.Index) "Reactions" $reactions}}
{{end}}
{{template "shared/reactions" dict
"AllowedReactions" $.AllowedIssueReactions
"ActionURL" (printf "%s/issues/%d/reactions" $.RepoLink .Issue.Index)
"Reactions" .Issue.Reactions.GroupByType
}}
</div>
</div>
@@ -1,10 +0,0 @@
{{if ctx.RootData.IsSigned}}
<div class="item action ui dropdown jump pointing top right select-reaction" data-action-url="{{.ActionURL}}" aria-label="{{ctx.Locale.Tr "repo.reactions"}}">
<a class="muted">{{svg "octicon-smiley"}}</a>
<div class="menu">
{{range $value := AllowedReactions}}
<a class="item emoji" data-tooltip-content="{{$value}}" aria-label="{{$value}}" data-reaction-content="{{$value}}" data-global-click="onCommentReactionButtonClick">{{ReactionToEmoji $value}}</a>
{{end}}
</div>
</div>
{{end}}
+10 -12
View File
@@ -53,9 +53,6 @@
</div>
<div class="comment-header-right">
{{template "repo/issue/view_content/show_role" dict "ShowRole" .ShowRole}}
{{if not $.Repository.IsArchived}}
{{template "repo/issue/view_content/add_reaction" dict "ActionURL" (printf "%s/comments/%d/reactions" $.RepoLink .ID)}}
{{end}}
{{template "repo/issue/view_content/context_menu" dict "ConvContentType" "issue_comment" "ConvContentItem" $comment}}
</div>
</div>
@@ -73,10 +70,11 @@
{{template "repo/issue/view_content/attachments" dict "Attachments" .Attachments "RenderedContent" .RenderedContent}}
{{end}}
</div>
{{$reactions := .Reactions.GroupByType}}
{{if $reactions}}
{{template "repo/issue/view_content/reactions" dict "ActionURL" (printf "%s/comments/%d/reactions" $.RepoLink .ID) "Reactions" $reactions}}
{{end}}
{{template "shared/reactions" dict
"AllowedReactions" $.AllowedIssueReactions
"ActionURL" (printf "%s/comments/%d/reactions" $.RepoLink .ID)
"Reactions" .Reactions.GroupByType
}}
</div>
</div>
{{else if eq .Type 1}}
@@ -423,7 +421,6 @@
<div class="comment-header-right">
{{template "repo/issue/view_content/show_role" dict "ShowRole" .ShowRole}}
{{if not $.Repository.IsArchived}}
{{template "repo/issue/view_content/add_reaction" dict "ActionURL" (printf "%s/comments/%d/reactions" $.RepoLink .ID)}}
{{template "repo/issue/view_content/context_menu" dict "ConvContentType" "pull_review" "ConvContentItem" $comment}}
{{end}}
</div>
@@ -442,10 +439,11 @@
{{template "repo/issue/view_content/attachments" dict "Attachments" .Attachments "RenderedContent" .RenderedContent}}
{{end}}
</div>
{{$reactions := .Reactions.GroupByType}}
{{if $reactions}}
{{template "repo/issue/view_content/reactions" dict "ActionURL" (printf "%s/comments/%d/reactions" $.RepoLink .ID) "Reactions" $reactions}}
{{end}}
{{template "shared/reactions" dict
"AllowedReactions" $.AllowedIssueReactions
"ActionURL" (printf "%s/comments/%d/reactions" $.RepoLink .ID)
"Reactions" .Reactions.GroupByType
}}
</div>
</div>
{{end}}
@@ -92,7 +92,6 @@ The variables in "ctx.Data" are different in each case, making this template fra
<div class="comment-header-right">
{{template "repo/issue/view_content/show_role" dict "ShowRole" $comment.ShowRole}}
{{if not $repo.IsArchived}}
{{template "repo/issue/view_content/add_reaction" dict "ActionURL" (printf "%s/comments/%d/reactions" $repoLink $comment.ID)}}
{{template "repo/issue/view_content/context_menu" dict "ConvContentType" "issue_comment" "ConvContentItem" $comment}}
{{end}}
</div>
@@ -112,10 +111,11 @@ The variables in "ctx.Data" are different in each case, making this template fra
{{template "repo/issue/view_content/attachments" dict "Attachments" $comment.Attachments "RenderedContent" $comment.RenderedContent}}
{{end}}
</div>
{{$reactions := $comment.Reactions.GroupByType}}
{{if $reactions}}
{{template "repo/issue/view_content/reactions" dict "ActionURL" (printf "%s/comments/%d/reactions" $repoLink $comment.ID) "Reactions" $reactions}}
{{end}}
{{template "shared/reactions" dict
"AllowedReactions" $root.AllowedIssueReactions
"ActionURL" (printf "%s/comments/%d/reactions" $repoLink $comment.ID)
"Reactions" $comment.Reactions.GroupByType
}}
</div>
</div>
{{end}}
@@ -1,17 +0,0 @@
<div class="bottom-reactions" data-action-url="{{$.ActionURL}}" role="group" aria-label="{{ctx.Locale.Tr "repo.reactions"}}">
{{range $key, $value := .Reactions}}
{{$hasReacted := $value.HasUser ctx.RootData.SignedUserID}}
<a role="button" class="ui label basic{{if $hasReacted}} primary{{end}}{{if not ctx.RootData.IsSigned}} disabled{{end}}"
data-global-click="onCommentReactionButtonClick"
data-tooltip-content title="{{$value.GetFirstUsers}}{{if gt ($value.GetMoreUserCount) 0}} {{ctx.Locale.Tr "repo.reactions_more" $value.GetMoreUserCount}}{{end}}"
aria-label="{{$key}}: {{$value.GetFirstUsers}}{{if gt ($value.GetMoreUserCount) 0}} {{ctx.Locale.Tr "repo.reactions_more" $value.GetMoreUserCount}}{{end}}"
data-tooltip-placement="bottom-start"
data-reaction-content="{{$key}}" data-has-reacted="{{$hasReacted}}">
<span class="reaction">{{ReactionToEmoji $key}}</span>
<span class="reaction-count">{{len $value}}</span>
</a>
{{end}}
{{if AllowedReactions}}
{{template "repo/issue/view_content/add_reaction" dict "ActionURL" .ActionURL}}
{{end}}
</div>
+7
View File
@@ -107,6 +107,13 @@
{{end}}
</ul>
</details>
{{if not (or $release.IsTag $release.IsDraft)}}
{{template "shared/reactions" dict
"ActionURL" (printf "%s/releases/%d/reactions" $.RepoLink $release.ID)
"Reactions" $info.Reactions.GroupByType
"AllowedReactions" $.AllowedReleaseReactions
}}
{{end}}
</div>
</li>
{{end}}
+28
View File
@@ -0,0 +1,28 @@
{{$allowedReactions := $.AllowedReactions}}
{{$canReact := and $allowedReactions ctx.RootData.IsSigned (not ctx.RootData.Repository.IsArchived)}}
{{if or .Reactions $canReact}}
<div class="bottom-reactions" data-action-url="{{$.ActionURL}}" role="group" aria-label="{{ctx.Locale.Tr "repo.reactions"}}">
{{if $canReact}}
<button type="button" class="select-reaction" data-global-click="onReactionPickerClick" aria-label="{{ctx.Locale.Tr "repo.reactions"}}">{{svg "octicon-smiley"}}</button>
<div class="tippy-target">
<div class="reaction-picker">
{{range $value := $allowedReactions}}
<a class="item emoji" role="menuitem" data-tooltip-content="{{$value}}" aria-label="{{$value}}" data-reaction-content="{{$value}}" data-has-reacted="{{(index $.Reactions $value).HasUser ctx.RootData.SignedUserID}}" data-global-click="onCommentReactionButtonClick">{{ReactionToEmoji $value}}</a>
{{end}}
</div>
</div>
{{end}}
{{range $key, $value := .Reactions}}
{{$hasReacted := $value.HasUser ctx.RootData.SignedUserID}}
<a role="button" class="ui label basic{{if not $canReact}} disabled{{end}}"
data-global-click="onCommentReactionButtonClick"
data-tooltip-content="{{$value.GetFirstUsers}}{{if gt ($value.GetMoreUserCount) 0}} {{ctx.Locale.Tr "repo.reactions_more" $value.GetMoreUserCount}}{{end}}"
aria-label="{{$key}}: {{$value.GetFirstUsers}}{{if gt ($value.GetMoreUserCount) 0}} {{ctx.Locale.Tr "repo.reactions_more" $value.GetMoreUserCount}}{{end}}"
data-tooltip-placement="bottom-start"
data-reaction-content="{{$key}}" data-has-reacted="{{$hasReacted}}">
<span class="reaction">{{ReactionToEmoji $key}}</span>
<span>{{len $value}}</span>
</a>
{{end}}
</div>
{{end}}