Skip to content

Commit f491377

Browse files
silverwindSysoev, Vladimir
authored andcommittedAug 10, 2022
Replace fomantic popup module with tippy.js (go-gitea#20428)
- replace fomantic popup module with tippy.js - fix chaining and add comment - add 100ms delay to tooltips - stopwatch improvments, raise default maxWidth - update web_src/js/features/common-global.js - use type=submit instead of js
1 parent 08daa7b commit f491377

28 files changed

+199
-2129
lines changed
 

‎templates/admin/user/edit.tmpl‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@
117117
</div>
118118
</div>
119119
<div class="inline field"{{if DisableGitHooks}} hidden{{end}}>
120-
<div class="ui checkbox tooltip" data-content="{{.locale.Tr "admin.users.allow_git_hook_tooltip"}}" data-variation="very wide">
120+
<div class="ui checkbox tooltip" data-content="{{.locale.Tr "admin.users.allow_git_hook_tooltip"}}">
121121
<label><strong>{{.locale.Tr "admin.users.allow_git_hook"}}</strong></label>
122122
<input name="allow_git_hook" type="checkbox" {{if .User.CanEditGitHook}}checked{{end}} {{if DisableGitHooks}}disabled{{end}}>
123123
</div>

‎templates/base/head_navbar.tmpl‎

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,10 +86,10 @@
8686
<span class="sr-mobile-only">{{.locale.Tr "active_stopwatch"}}</span>
8787
</span>
8888
</a>
89-
<div class="ui popup very wide">
89+
<div class="active-stopwatch-popup hide">
9090
<div class="df ac">
9191
<a class="stopwatch-link df ac" href="{{.ActiveStopwatch.IssueLink}}">
92-
{{svg "octicon-issue-opened"}}
92+
{{svg "octicon-issue-opened" 16 "mr-3"}}
9393
<span class="stopwatch-issue">{{.ActiveStopwatch.RepoSlug}}#{{.ActiveStopwatch.IssueIndex}}</span>
9494
<span class="ui primary label stopwatch-time my-0 mx-4" data-seconds="{{.ActiveStopwatch.Seconds}}">
9595
{{if .ActiveStopwatch}}{{Sec2Time .ActiveStopwatch.Seconds}}{{end}}
@@ -98,6 +98,7 @@
9898
<form class="stopwatch-commit" method="POST" action="{{.ActiveStopwatch.IssueLink}}/times/stopwatch/toggle">
9999
{{.CsrfTokenHtml}}
100100
<button
101+
type="submit"
101102
class="ui button mini compact basic icon fitted tooltip"
102103
data-content="{{.locale.Tr "repo.issues.stop_tracking"}}"
103104
data-position="top right"
@@ -106,6 +107,7 @@
106107
<form class="stopwatch-cancel" method="POST" action="{{.ActiveStopwatch.IssueLink}}/times/stopwatch/cancel">
107108
{{.CsrfTokenHtml}}
108109
<button
110+
type="submit"
109111
class="ui button mini compact basic icon fitted tooltip"
110112
data-content="{{.locale.Tr "repo.issues.cancel_tracking"}}"
111113
data-position="top right"

‎templates/repo/commit_statuses.tmpl‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<a class="ui link commit-statuses-trigger">{{template "repo/commit_status" .Status}}</a>
2-
<div class="ui popup very wide fixed basic commit-statuses">
2+
<div class="ui commit-statuses-popup commit-statuses hide">
33
<div class="ui relaxed list divided">
44
{{range .Statuses}}
55
<div class="ui item singular-status df">

‎templates/repo/diff/stats.tmpl‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
{{Add .file.Addition .file.Deletion}}
2-
<span class="diff-stats-bar tooltip mx-3" data-content="{{.root.locale.Tr "repo.diff.stats_desc_file" (Add .file.Addition .file.Deletion) .file.Addition .file.Deletion | Str2html}}" data-variation="wide">
2+
<span class="diff-stats-bar tooltip mx-3" data-content="{{.root.locale.Tr "repo.diff.stats_desc_file" (Add .file.Addition .file.Deletion) .file.Addition .file.Deletion | Str2html}}">
33
<div class="diff-stats-add-bar" style="width: {{DiffStatsWidth .file.Addition .file.Deletion}}%"></div>
44
</span>

‎templates/repo/header.tmpl‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@
9898
{{else if and (not $.CanSignedUserFork) (eq (len $.UserAndOrgForks) 0)}}
9999
data-content="{{$.locale.Tr "repo.fork_from_self"}}"
100100
{{end}}
101-
data-position="top center" data-variation="tiny" tabindex="0">
101+
data-position="top center" tabindex="0">
102102
<a class="ui compact{{if $.ShowForkModal}} show-modal{{end}} small basic button"
103103
{{if not $.CanSignedUserFork}}
104104
{{if gt (len $.UserAndOrgForks) 1}}

‎templates/repo/issue/view_content/add_reaction.tmpl‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
<div class="header">{{ .ctx.locale.Tr "repo.pick_reaction"}}</div>
88
<div class="divider"></div>
99
{{range $value := AllowedReactions}}
10-
<div class="item reaction" data-content="{{$value}}">{{ReactionToEmoji $value}}</div>
10+
<div class="item reaction tooltip" data-content="{{$value}}">{{ReactionToEmoji $value}}</div>
1111
{{end}}
1212
</div>
1313
</div>

‎templates/repo/settings/deploy_keys.tmpl‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@
5656
</button>
5757
</div>
5858
<div class="left floated content">
59-
<i class="{{if .HasRecentActivity}}green{{end}}" {{if .HasRecentActivity}}data-content="{{$.locale.Tr "settings.key_state_desc"}}" data-variation="inverted"{{end}}>{{svg "octicon-key" 32}}</i>
59+
<i class="tooltip{{if .HasRecentActivity}} green{{end}}" {{if .HasRecentActivity}}data-content="{{$.locale.Tr "settings.key_state_desc"}}"{{end}}>{{svg "octicon-key" 32}}</i>
6060
</div>
6161
<div class="content">
6262
<strong>{{.Name}}</strong>

‎templates/repo/settings/webhook/history.tmpl‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@
4444
<div class="right menu">
4545
<form class="item" action="{{$.Link}}/replay/{{.UUID}}" method="post">
4646
{{$.CsrfTokenHtml}}
47-
<button class="ui tiny button tooltip" data-content="{{$.locale.Tr "repo.settings.webhook.replay.description"}}" data-variation="inverted tiny">{{svg "octicon-sync"}}</button>
47+
<button class="ui tiny button tooltip" data-content="{{$.locale.Tr "repo.settings.webhook.replay.description"}}">{{svg "octicon-sync"}}</button>
4848
</form>
4949
</div>
5050
{{end}}

‎templates/repo/view_file.tmpl‎

Lines changed: 6 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -120,22 +120,12 @@
120120
{{end}}
121121
</tbody>
122122
</table>
123-
<div class="code-line-menu ui fluid popup transition hidden">
124-
<div class="ui column relaxed equal height">
125-
<div class="column">
126-
{{if $.Permission.CanRead $.UnitTypeIssues}}
127-
<div class="ui link list">
128-
<a class="item ref-in-new-issue" href="{{.RepoLink}}/issues/new?body={{.Repository.HTMLURL}}{{printf "/src/commit/" }}{{PathEscape .CommitID}}/{{PathEscapeSegments .TreePath}}" rel="nofollow noindex">{{.locale.Tr "repo.issues.context.reference_issue"}}</a>
129-
</div>
130-
{{end}}
131-
<div class="ui link list">
132-
<a class="item view_git_blame" href="{{.Repository.HTMLURL}}/blame/commit/{{PathEscape .CommitID}}/{{PathEscapeSegments .TreePath}}">{{.locale.Tr "repo.view_git_blame"}}</a>
133-
</div>
134-
<div class="ui link list">
135-
<a data-clipboard-text="{{.Repository.HTMLURL}}/src/commit/{{PathEscape .CommitID}}/{{PathEscapeSegments .TreePath}}" class="item copy-line-permalink">{{.locale.Tr "repo.file_copy_permalink"}}</a>
136-
</div>
137-
</div>
138-
</div>
123+
<div class="code-line-menu ui vertical pointing menu hide">
124+
{{if $.Permission.CanRead $.UnitTypeIssues}}
125+
<a class="item ref-in-new-issue" href="{{.RepoLink}}/issues/new?body={{.Repository.HTMLURL}}{{printf "/src/commit/" }}{{PathEscape .CommitID}}/{{PathEscapeSegments .TreePath}}" rel="nofollow noindex">{{.locale.Tr "repo.issues.context.reference_issue"}}</a>
126+
{{end}}
127+
<a class="item view_git_blame" href="{{.Repository.HTMLURL}}/blame/commit/{{PathEscape .CommitID}}/{{PathEscapeSegments .TreePath}}">{{.locale.Tr "repo.view_git_blame"}}</a>
128+
<a class="item copy-line-permalink" data-url="{{.Repository.HTMLURL}}/src/commit/{{PathEscape .CommitID}}/{{PathEscapeSegments .TreePath}}">{{.locale.Tr "repo.file_copy_permalink"}}</a>
139129
</div>
140130
{{end}}
141131
{{end}}

‎templates/user/settings/applications.tmpl‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
{{$.locale.Tr "settings.delete_token"}}
2020
</button>
2121
</div>
22-
<i class="big send icon {{if .HasRecentActivity}}green{{end}}" {{if .HasRecentActivity}}data-content="{{$.locale.Tr "settings.token_state_desc"}}" data-variation="inverted tiny"{{end}}></i>
22+
<i class="big send icon tooltip{{if .HasRecentActivity}} green{{end}}" {{if .HasRecentActivity}}data-content="{{$.locale.Tr "settings.token_state_desc"}}"{{end}}></i>
2323
<div class="content">
2424
<strong>{{.Name}}</strong>
2525
<div class="activity meta">

‎templates/user/settings/keys_principal.tmpl‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
{{$.locale.Tr "settings.delete_key"}}
2222
</button>
2323
</div>
24-
<i class="big send icon {{if .HasRecentActivity}}green{{end}}" {{if .HasRecentActivity}}data-content="{{$.locale.Tr "settings.principal_state_desc"}}" data-variation="inverted tiny"{{end}}></i>
24+
<i class="big send icon tooltip{{if .HasRecentActivity}} green{{end}}" {{if .HasRecentActivity}}data-content="{{$.locale.Tr "settings.principal_state_desc"}}"{{end}}></i>
2525
<div class="content">
2626
<strong>{{.Name}}</strong>
2727
<div class="activity meta">

‎templates/user/settings/keys_ssh.tmpl‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@
4747

4848
</div>
4949
<div class="left floated content">
50-
<span class="{{if .HasRecentActivity}}green{{end}}" {{if .HasRecentActivity}}data-content="{{$.locale.Tr "settings.key_state_desc"}}" data-variation="inverted tiny"{{end}}>{{svg "octicon-key" 32}}</span>
50+
<span class="tooltip{{if .HasRecentActivity}} green{{end}}" {{if .HasRecentActivity}}data-content="{{$.locale.Tr "settings.key_state_desc"}}"{{end}}>{{svg "octicon-key" 32}}</span>
5151
</div>
5252
<div class="content">
5353
{{if .Verified}}

‎web_src/fomantic/build/semantic.css‎

Lines changed: 0 additions & 421 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎web_src/fomantic/build/semantic.js‎

Lines changed: 0 additions & 1542 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎web_src/fomantic/semantic.json‎

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,6 @@
4444
"menu",
4545
"message",
4646
"modal",
47-
"popup",
4847
"reset",
4948
"search",
5049
"segment",

‎web_src/js/components/DashboardRepoList.js‎

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import Vue from 'vue';
22
import $ from 'jquery';
33
import {initVueSvg, vueDelimiters} from './VueComponentLoader.js';
4+
import {initTooltip} from '../modules/tippy.js';
45

56
const {appSubUrl, assetUrlPrefix, pageData} = window.config;
67

@@ -138,7 +139,9 @@ function initVueComponents() {
138139

139140
mounted() {
140141
this.changeReposFilter(this.reposFilter);
141-
$(this.$el).find('.tooltip').popup();
142+
for (const el of this.$el.querySelectorAll('.tooltip')) {
143+
initTooltip(el);
144+
}
142145
$(this.$el).find('.dropdown').dropdown();
143146
this.setCheckboxes();
144147
Vue.nextTick(() => {

‎web_src/js/features/clipboard.js‎

Lines changed: 10 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,15 @@
1-
import $ from 'jquery';
1+
import {showTemporaryTooltip} from '../modules/tippy.js';
22

33
const {copy_success, copy_error} = window.config.i18n;
44

5-
function onSuccess(btn) {
6-
btn.setAttribute('data-variation', 'inverted tiny');
7-
$(btn).popup('destroy');
8-
const oldContent = btn.getAttribute('data-content');
9-
btn.setAttribute('data-content', copy_success);
10-
$(btn).popup('show');
11-
btn.setAttribute('data-content', oldContent || '');
5+
export async function copyToClipboard(text) {
6+
try {
7+
await navigator.clipboard.writeText(text);
8+
} catch {
9+
return fallbackCopyToClipboard(text);
10+
}
11+
return true;
1212
}
13-
function onError(btn) {
14-
btn.setAttribute('data-variation', 'inverted tiny');
15-
const oldContent = btn.getAttribute('data-content');
16-
$(btn).popup('destroy');
17-
btn.setAttribute('data-content', copy_error);
18-
$(btn).popup('show');
19-
btn.setAttribute('data-content', oldContent || '');
20-
}
21-
2213

2314
// Fallback to use if navigator.clipboard doesn't exist. Achieved via creating
2415
// a temporary textarea element, selecting the text, and using document.execCommand
@@ -60,16 +51,8 @@ export default function initGlobalCopyToClipboardListener() {
6051
e.preventDefault();
6152

6253
(async() => {
63-
try {
64-
await navigator.clipboard.writeText(text);
65-
onSuccess(target);
66-
} catch {
67-
if (fallbackCopyToClipboard(text)) {
68-
onSuccess(target);
69-
} else {
70-
onError(target);
71-
}
72-
}
54+
const success = await copyToClipboard(text);
55+
showTemporaryTooltip(target, success ? copy_success : copy_error);
7356
})();
7457

7558
break;

‎web_src/js/features/common-global.js‎

Lines changed: 11 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import {initCompColorPicker} from './comp/ColorPicker.js';
66
import {showGlobalErrorMessage} from '../bootstrap.js';
77
import {attachDropdownAria} from './aria.js';
88
import {handleGlobalEnterQuickSubmit} from './comp/QuickSubmit.js';
9+
import {initTooltip} from '../modules/tippy.js';
910

1011
const {appUrl, csrfToken} = window.config;
1112

@@ -62,18 +63,10 @@ export function initGlobalButtonClickOnEnter() {
6263
});
6364
}
6465

65-
export function initPopup(target) {
66-
const $el = $(target);
67-
const attr = $el.attr('data-variation');
68-
const attrs = attr ? attr.split(' ') : [];
69-
const variations = new Set([...attrs, 'inverted', 'tiny']);
70-
$el.attr('data-variation', [...variations].join(' ')).popup();
71-
}
72-
73-
export function initGlobalPopups() {
74-
$('.tooltip').each((_, el) => {
75-
initPopup(el);
76-
});
66+
export function initGlobalTooltips() {
67+
for (const el of document.getElementsByClassName('tooltip')) {
68+
initTooltip(el);
69+
}
7770
}
7871

7972
export function initGlobalCommon() {
@@ -106,7 +99,12 @@ export function initGlobalCommon() {
10699
$uiDropdowns.filter('.jump').dropdown({
107100
action: 'hide',
108101
onShow() {
109-
$('.tooltip').popup('hide');
102+
// hide associated tooltip while dropdown is open
103+
this._tippy?.hide();
104+
this._tippy?.disable();
105+
},
106+
onHide() {
107+
this._tippy?.enable();
110108
},
111109
fullTextSearch: 'exact'
112110
});
@@ -122,13 +120,6 @@ export function initGlobalCommon() {
122120

123121
$('.ui.checkbox').checkbox();
124122

125-
$('.top.menu .tooltip').popup({
126-
onShow() {
127-
if ($('.top.menu .menu.transition').hasClass('visible')) {
128-
return false;
129-
}
130-
}
131-
});
132123
$('.tabular.menu .item').tab();
133124
$('.tabable.menu .item').tab();
134125

‎web_src/js/features/comp/ReactionSelector.js‎

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,20 @@
11
import $ from 'jquery';
2+
import {createTippy} from '../../modules/tippy.js';
3+
24
const {csrfToken} = window.config;
35

46
export function initCompReactionSelector(parent) {
5-
let reactions = '';
7+
let selector = 'a.label';
68
if (!parent) {
79
parent = $(document);
8-
reactions = '.reactions > ';
10+
selector = `.reactions ${selector}`;
911
}
1012

11-
parent.find(`${reactions}a.label`).popup({position: 'bottom left', metadata: {content: 'title', title: 'none'}});
13+
for (const el of parent[0].querySelectorAll(selector)) {
14+
createTippy(el, {placement: 'bottom-start', content: el.getAttribute('data-title')});
15+
}
1216

13-
parent.find(`.select-reaction > .menu > .item, ${reactions}a.label`).on('click', function (e) {
17+
parent.find(`.select-reaction > .menu > .item, ${selector}`).on('click', function (e) {
1418
e.preventDefault();
1519

1620
if ($(this).hasClass('disabled')) return;

‎web_src/js/features/repo-code.js‎

Lines changed: 38 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import $ from 'jquery';
22
import {svg} from '../svg.js';
33
import {invertFileFolding} from './file-fold.js';
4+
import {createTippy} from '../modules/tippy.js';
5+
import {copyToClipboard} from './clipboard.js';
46

57
function changeHash(hash) {
68
if (window.history.pushState) {
@@ -39,13 +41,13 @@ function selectRange($list, $select, $from) {
3941
$viewGitBlame.attr('href', href);
4042
};
4143

42-
const updateCopyPermalinkHref = function(anchor) {
44+
const updateCopyPermalinkUrl = function(anchor) {
4345
if ($copyPermalink.length === 0) {
4446
return;
4547
}
46-
let link = $copyPermalink.attr('data-clipboard-text');
48+
let link = $copyPermalink.attr('data-url');
4749
link = `${link.replace(/#L\d+$|#L\d+-L\d+$/, '')}#${anchor}`;
48-
$copyPermalink.attr('data-clipboard-text', link);
50+
$copyPermalink.attr('data-url', link);
4951
};
5052

5153
if ($from) {
@@ -67,7 +69,7 @@ function selectRange($list, $select, $from) {
6769

6870
updateIssueHref(`L${a}-L${b}`);
6971
updateViewGitBlameFragment(`L${a}-L${b}`);
70-
updateCopyPermalinkHref(`L${a}-L${b}`);
72+
updateCopyPermalinkUrl(`L${a}-L${b}`);
7173
return;
7274
}
7375
}
@@ -76,17 +78,36 @@ function selectRange($list, $select, $from) {
7678

7779
updateIssueHref($select.attr('rel'));
7880
updateViewGitBlameFragment($select.attr('rel'));
79-
updateCopyPermalinkHref($select.attr('rel'));
81+
updateCopyPermalinkUrl($select.attr('rel'));
8082
}
8183

8284
function showLineButton() {
83-
if ($('.code-line-menu').length === 0) return;
84-
$('.code-line-button').remove();
85-
$('.code-view td.lines-code.active').closest('tr').find('td:eq(0)').first().prepend(
86-
$(`<button class="code-line-button">${svg('octicon-kebab-horizontal')}</button>`)
87-
);
88-
$('.code-line-menu').appendTo($('.code-view'));
89-
$('.code-line-button').popup({popup: $('.code-line-menu'), on: 'click'});
85+
const menu = document.querySelector('.code-line-menu');
86+
if (!menu) return;
87+
88+
// remove all other line buttons
89+
for (const el of document.querySelectorAll('.code-line-button')) {
90+
el.remove();
91+
}
92+
93+
// find active row and add button
94+
const tr = document.querySelector('.code-view td.lines-code.active').closest('tr');
95+
const td = tr.querySelector('td');
96+
const btn = document.createElement('button');
97+
btn.classList.add('code-line-button');
98+
btn.innerHTML = svg('octicon-kebab-horizontal');
99+
td.prepend(btn);
100+
101+
// put a copy of the menu back into DOM for the next click
102+
btn.closest('.code-view').appendChild(menu.cloneNode(true));
103+
104+
createTippy(btn, {
105+
trigger: 'click',
106+
content: menu,
107+
placement: 'right-start',
108+
role: 'menu',
109+
interactive: 'true',
110+
});
90111
}
91112

92113
export function initRepoCodeView() {
@@ -159,4 +180,9 @@ export function initRepoCodeView() {
159180
const blob = await $.get(`${url}?${query}&anchor=${anchor}`);
160181
currentTarget.closest('tr').outerHTML = blob;
161182
});
183+
$(document).on('click', '.copy-line-permalink', async (e) => {
184+
const success = await copyToClipboard(e.currentTarget.getAttribute('data-url'));
185+
if (!success) return;
186+
document.querySelector('.code-line-button')?._tippy?.hide();
187+
});
162188
}

‎web_src/js/features/repo-commit.js‎

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import $ from 'jquery';
2+
import {createTippy} from '../modules/tippy.js';
23

34
const {csrfToken} = window.config;
45

@@ -58,12 +59,12 @@ export function initRepoCommitLastCommitLoader() {
5859
export function initCommitStatuses() {
5960
$('.commit-statuses-trigger').each(function () {
6061
const positionRight = $('.repository.file.list').length > 0 || $('.repository.diff').length > 0;
61-
const popupPosition = positionRight ? 'right center' : 'left center';
62-
$(this)
63-
.popup({
64-
on: 'click',
65-
lastResort: popupPosition, // prevent error message "Popup does not fit within the boundaries of the viewport"
66-
position: popupPosition,
67-
});
62+
63+
createTippy(this, {
64+
trigger: 'click',
65+
content: this.nextSibling,
66+
placement: positionRight ? 'right' : 'left',
67+
interactive: true,
68+
});
6869
});
6970
}

‎web_src/js/features/repo-diff.js‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import {initCompReactionSelector} from './comp/ReactionSelector.js';
33
import {initRepoIssueContentHistory} from './repo-issue-content.js';
44
import {validateTextareaNonEmpty} from './comp/EasyMDE.js';
55
import {initViewedCheckboxListenerFor, countAndUpdateViewedFiles} from './pull-view-file.js';
6-
import {initPopup} from './common-global.js';
6+
import {initTooltip} from '../modules/tippy.js';
77

88
const {csrfToken} = window.config;
99

@@ -53,7 +53,7 @@ export function initRepoDiffConversationForm() {
5353
const newConversationHolder = $(await $.post(form.attr('action'), form.serialize()));
5454
const {path, side, idx} = newConversationHolder.data();
5555

56-
initPopup(newConversationHolder.find('.tooltip'));
56+
initTooltip(newConversationHolder.find('.tooltip'));
5757
form.closest('.conversation-holder').replaceWith(newConversationHolder);
5858
if (form.closest('tr').data('line-type') === 'same') {
5959
$(`[data-path="${path}"] a.add-code-comment[data-idx="${idx}"]`).addClass('invisible');

‎web_src/js/features/repo-issue.js‎

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import attachTribute from './tribute.js';
44
import {createCommentEasyMDE, getAttachedEasyMDE} from './comp/EasyMDE.js';
55
import {initEasyMDEImagePaste} from './comp/ImagePaste.js';
66
import {initCompMarkupContentPreviewTab} from './comp/MarkupContentPreview.js';
7+
import {initTooltip, showTemporaryTooltip} from '../modules/tippy.js';
78

89
const {appSubUrl, csrfToken} = window.config;
910

@@ -278,7 +279,8 @@ export function initRepoPullRequestAllowMaintainerEdit() {
278279

279280
const promptTip = $checkbox.attr('data-prompt-tip');
280281
const promptError = $checkbox.attr('data-prompt-error');
281-
$checkbox.popup({content: promptTip});
282+
283+
initTooltip($checkbox[0], {content: promptTip});
282284
$checkbox.checkbox({
283285
'onChange': () => {
284286
const checked = $checkbox.checkbox('is checked');
@@ -288,14 +290,7 @@ export function initRepoPullRequestAllowMaintainerEdit() {
288290
$.ajax({url, type: 'POST',
289291
data: {_csrf: csrfToken, allow_maintainer_edit: checked},
290292
error: () => {
291-
$checkbox.popup({
292-
content: promptError,
293-
onHidden: () => {
294-
// the error popup should be shown only once, then we restore the popup to the default message
295-
$checkbox.popup({content: promptTip});
296-
},
297-
});
298-
$checkbox.popup('show');
293+
showTemporaryTooltip($checkbox[0], promptError);
299294
},
300295
complete: () => {
301296
$checkbox.checkbox('set enabled');

‎web_src/js/features/stopwatch.js‎

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import $ from 'jquery';
22
import prettyMilliseconds from 'pretty-ms';
3+
import {createTippy} from '../modules/tippy.js';
34

45
const {appSubUrl, csrfToken, notificationSettings, enableTimeTracking} = window.config;
56

@@ -8,21 +9,21 @@ export function initStopwatch() {
89
return;
910
}
1011

11-
const stopwatchEl = $('.active-stopwatch-trigger');
12+
const stopwatchEl = document.querySelector('.active-stopwatch-trigger');
13+
const stopwatchPopup = document.querySelector('.active-stopwatch-popup');
1214

13-
if (!stopwatchEl.length) {
15+
if (!stopwatchEl || !stopwatchPopup) {
1416
return;
1517
}
1618

17-
stopwatchEl.removeAttr('href'); // intended for noscript mode only
18-
stopwatchEl.popup({
19-
position: 'bottom right',
20-
hoverable: true,
21-
});
19+
stopwatchEl.removeAttribute('href'); // intended for noscript mode only
2220

23-
// form handlers
24-
$('form > button', stopwatchEl).on('click', function () {
25-
$(this).parent().trigger('submit');
21+
createTippy(stopwatchEl, {
22+
content: stopwatchPopup,
23+
placement: 'bottom-end',
24+
trigger: 'click',
25+
maxWidth: 'none',
26+
interactive: true,
2627
});
2728

2829
// global stop watch (in the head_navbar), it should always work in any case either the EventSource or the PeriodicPoller is used.

‎web_src/js/index.js‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ import {
5656
initGlobalFormDirtyLeaveConfirm,
5757
initGlobalLinkActions,
5858
initHeadNavbarContentToggle,
59-
initGlobalPopups,
59+
initGlobalTooltips,
6060
} from './features/common-global.js';
6161
import {initRepoTopicBar} from './features/repo-home.js';
6262
import {initAdminEmails} from './features/admin-emails.js';
@@ -100,7 +100,7 @@ initVueEnv();
100100
$(document).ready(() => {
101101
initGlobalCommon();
102102

103-
initGlobalPopups();
103+
initGlobalTooltips();
104104
initGlobalButtonClickOnEnter();
105105
initGlobalButtons();
106106
initGlobalCopyToClipboardListener();

‎web_src/js/modules/tippy.js‎

Lines changed: 46 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,56 @@
11
import tippy from 'tippy.js';
22

3-
export function createTippy(target, opts) {
4-
return tippy(target, {
3+
export function createTippy(target, opts = {}) {
4+
const instance = tippy(target, {
55
appendTo: document.body,
66
placement: 'top-start',
77
animation: false,
88
allowHTML: true,
9+
maxWidth: 500, // increase over default 350px
910
arrow: `<svg width="16" height="7"><path d="m0 7 8-7 8 7Z" class="tippy-svg-arrow-outer"/><path d="m0 8 8-7 8 7Z" class="tippy-svg-arrow-inner"/></svg>`,
11+
...(opts?.role && {theme: opts.role}),
1012
...opts,
1113
});
14+
15+
// for popups where content refers to a DOM element, we use the 'hide' class to initially hide
16+
// the content, now we can remove it as the content has been removed from the DOM by tippy
17+
if (opts.content instanceof Element) {
18+
opts.content.classList.remove('hide');
19+
}
20+
21+
return instance;
22+
}
23+
24+
export function initTooltip(el, props = {}) {
25+
const content = el.getAttribute('data-content') || props.content;
26+
if (!content) return null;
27+
return createTippy(el, {
28+
content,
29+
delay: 100,
30+
role: 'tooltip',
31+
...props,
32+
});
33+
}
34+
35+
export function showTemporaryTooltip(target, content) {
36+
let tippy, oldContent;
37+
if (target._tippy) {
38+
tippy = target._tippy;
39+
oldContent = tippy.props.content;
40+
} else {
41+
tippy = initTooltip(target, {content});
42+
}
43+
44+
tippy.setContent(content);
45+
tippy.show();
46+
tippy.setProps({
47+
onHidden: (tippy) => {
48+
if (oldContent) {
49+
tippy.setContent(oldContent);
50+
} else {
51+
tippy.destroy();
52+
}
53+
tippy.setProps({onHidden: undefined});
54+
},
55+
});
1256
}

‎web_src/less/_base.less‎

Lines changed: 3 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,8 @@
155155
--color-caret: var(--color-text-dark);
156156
--color-reaction-bg: #0000000a;
157157
--color-reaction-active-bg: var(--color-primary-alpha-20);
158+
--color-tooltip-bg: #000000f0;
159+
--color-tooltip-text: #ffffff;
158160
/* backgrounds */
159161
--checkbox-mask-checked: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="-1 -1 18 18" width="16" height="16"><path fill-rule="evenodd" d="M13.78 4.22a.75.75 0 010 1.06l-7.25 7.25a.75.75 0 01-1.06 0L2.22 9.28a.75.75 0 011.06-1.06L6 10.94l6.72-6.72a.75.75 0 011.06 0z"></path></svg>');
160162
--checkbox-mask-indeterminate: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M2 7.75A.75.75 0 012.75 7h10a.75.75 0 010 1.5h-10A.75.75 0 012 7.75z"></path></svg>');
@@ -1313,7 +1315,7 @@ footer {
13131315
}
13141316

13151317
.hide {
1316-
display: none;
1318+
display: none !important;
13171319

13181320
&.show-outdated {
13191321
display: none !important;
@@ -1873,41 +1875,6 @@ a.ui.basic.label:hover {
18731875
color: #f05133; /* from https://upload.wikimedia.org/wikipedia/commons/e/e0/Git-logo.svg */
18741876
}
18751877

1876-
.ui.popup {
1877-
background-color: var(--color-body);
1878-
color: var(--color-secondary-dark-6);
1879-
border-color: var(--color-secondary);
1880-
}
1881-
1882-
.ui.popup::before {
1883-
box-shadow: 1px 1px 0 0 var(--color-secondary);
1884-
}
1885-
1886-
.ui.bottom.popup::before,
1887-
.ui.top.popup::before,
1888-
.ui.right.center.popup::before,
1889-
.ui.left.center.popup::before {
1890-
background-color: var(--color-body);
1891-
}
1892-
1893-
.ui.bottom.left.popup::before,
1894-
.ui.bottom.right.popup::before,
1895-
.ui.bottom.center.popup::before {
1896-
box-shadow: -1px -1px 0 0 var(--color-secondary);
1897-
}
1898-
1899-
.ui.left.center.popup::before {
1900-
box-shadow: 1px -1px 0 0 var(--color-secondary);
1901-
}
1902-
1903-
.ui.right.center.popup::before {
1904-
box-shadow: -1px 1px 0 0 var(--color-secondary);
1905-
}
1906-
1907-
.ui.popup .ui.label {
1908-
margin-bottom: .4em;
1909-
}
1910-
19111878
.color-icon {
19121879
display: inline-block;
19131880
border-radius: 100%;

‎web_src/less/modules/tippy.less‎

Lines changed: 32 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,5 @@
11
/* styles are based on node_modules/tippy.js/dist/tippy.css */
22

3-
.tippy-box[data-animation="fade"][data-state="hidden"] {
4-
opacity: 0;
5-
}
6-
73
[data-tippy-root] {
84
max-width: calc(100vw - 10px);
95
}
@@ -15,7 +11,21 @@
1511
border: 1px solid var(--color-secondary);
1612
border-radius: var(--border-radius);
1713
font-size: 1rem;
18-
transition-property: transform, visibility, opacity;
14+
}
15+
16+
.tippy-box[data-theme="tooltip"] {
17+
background-color: var(--color-tooltip-bg);
18+
color: var(--color-tooltip-text);
19+
border: none;
20+
}
21+
22+
.tippy-box[data-theme="menu"] {
23+
background-color: none;
24+
color: var(--color-tooltip-text);
25+
}
26+
27+
.tippy-box[data-theme="menu"] .ui.menu {
28+
border: none;
1929
}
2030

2131
.tippy-content {
@@ -24,6 +34,14 @@
2434
z-index: 1;
2535
}
2636

37+
.tippy-box[data-theme="tooltip"] .tippy-content {
38+
padding: .5rem 1rem;
39+
}
40+
41+
.tippy-box[data-theme="menu"] .tippy-content {
42+
padding: 0;
43+
}
44+
2745
.tippy-box[data-placement^="top"] > .tippy-svg-arrow {
2846
bottom: 0;
2947
}
@@ -82,3 +100,12 @@
82100
.tippy-svg-arrow-inner {
83101
fill: var(--color-body);
84102
}
103+
104+
.tippy-box[data-theme="tooltip"] .tippy-svg-arrow-inner,
105+
.tippy-box[data-theme="tooltip"] .tippy-svg-arrow-outer {
106+
fill: var(--color-tooltip-bg);
107+
}
108+
109+
.tippy-box[data-theme="menu"] .tippy-svg-arrow-inner {
110+
fill: var(--color-menu);
111+
}

0 commit comments

Comments
 (0)
Please sign in to comment.