Skip to content

Commit 00d3876

Browse files
authored
Use tippy.js for context popup (#20393)
By appending the tooltips to `document.body`, we can avoid any stacking context issues caused by surrounding element's CSS. This uses [tippy.js](https://github.com/atomiks/tippyjs) instead of Fomantic popups. We should aim to replace all Fomantic popups with this eventually and then get rid of the Fomantic `popup` module completely.
1 parent 17ce5f8 commit 00d3876

File tree

6 files changed

+135
-11
lines changed

6 files changed

+135
-11
lines changed

package-lock.json

+31
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+1
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
"pretty-ms": "7.0.1",
3030
"sortablejs": "1.15.0",
3131
"swagger-ui-dist": "4.11.1",
32+
"tippy.js": "6.3.7",
3233
"tributejs": "5.1.3",
3334
"uint8-to-base64": "0.2.0",
3435
"vue": "2.6.14",

web_src/js/features/contextpopup.js

+6-11
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import $ from 'jquery';
22
import Vue from 'vue';
33
import ContextPopup from '../components/ContextPopup.vue';
44
import {parseIssueHref} from '../utils.js';
5+
import {createTippy} from '../modules/tippy.js';
56

67
export default function initContextPopups() {
78
const refIssues = $('.ref-issue');
@@ -16,7 +17,6 @@ export default function initContextPopups() {
1617
if (!owner) return;
1718

1819
const el = document.createElement('div');
19-
el.className = 'ui custom popup hidden';
2020
el.innerHTML = '<div></div>';
2121
this.parentNode.insertBefore(el, this.nextSibling);
2222

@@ -33,17 +33,12 @@ export default function initContextPopups() {
3333
el.textContent = 'ContextPopup failed to load';
3434
}
3535

36-
$(this).popup({
37-
variation: 'wide',
38-
delay: {
39-
show: 250
40-
},
36+
createTippy(this, {
37+
content: el,
38+
interactive: true,
4139
onShow: () => {
42-
view.$emit('load-context-popup', {owner, repo, index}, () => {
43-
$(this).popup('reposition');
44-
});
45-
},
46-
popup: $(el),
40+
view.$emit('load-context-popup', {owner, repo, index});
41+
}
4742
});
4843
});
4944
}

web_src/js/modules/tippy.js

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import tippy from 'tippy.js';
2+
3+
export function createTippy(target, opts) {
4+
return tippy(target, {
5+
appendTo: document.body,
6+
placement: 'top-start',
7+
animation: false,
8+
allowHTML: true,
9+
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>`,
10+
...opts,
11+
});
12+
}

web_src/less/index.less

+1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
@import "./features/imagediff.less";
1010
@import "./features/codeeditor.less";
1111
@import "./features/projects.less";
12+
@import "./modules/tippy.less";
1213
@import "./markup/content.less";
1314
@import "./markup/codecopy.less";
1415
@import "./code/linebutton.less";

web_src/less/modules/tippy.less

+84
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
/* styles are based on node_modules/tippy.js/dist/tippy.css */
2+
3+
.tippy-box[data-animation="fade"][data-state="hidden"] {
4+
opacity: 0;
5+
}
6+
7+
[data-tippy-root] {
8+
max-width: calc(100vw - 10px);
9+
}
10+
11+
.tippy-box {
12+
position: relative;
13+
background-color: var(--color-body);
14+
color: var(--color-secondary-dark-6);
15+
border: 1px solid var(--color-secondary);
16+
border-radius: var(--border-radius);
17+
font-size: 1rem;
18+
transition-property: transform, visibility, opacity;
19+
}
20+
21+
.tippy-content {
22+
position: relative;
23+
padding: 1rem;
24+
z-index: 1;
25+
}
26+
27+
.tippy-box[data-placement^="top"] > .tippy-svg-arrow {
28+
bottom: 0;
29+
}
30+
31+
.tippy-box[data-placement^="top"] > .tippy-svg-arrow::after,
32+
.tippy-box[data-placement^="top"] > .tippy-svg-arrow > svg {
33+
top: 16px;
34+
transform: rotate(180deg);
35+
}
36+
37+
.tippy-box[data-placement^="bottom"] > .tippy-svg-arrow {
38+
top: 0;
39+
}
40+
41+
.tippy-box[data-placement^="bottom"] > .tippy-svg-arrow > svg {
42+
bottom: 16px;
43+
}
44+
45+
.tippy-box[data-placement^="left"] > .tippy-svg-arrow {
46+
right: 0;
47+
}
48+
49+
.tippy-box[data-placement^="left"] > .tippy-svg-arrow::after,
50+
.tippy-box[data-placement^="left"] > .tippy-svg-arrow > svg {
51+
transform: rotate(90deg);
52+
top: calc(50% - 3px);
53+
left: 11px;
54+
}
55+
56+
.tippy-box[data-placement^="right"] > .tippy-svg-arrow {
57+
left: 0;
58+
}
59+
60+
.tippy-box[data-placement^="right"] > .tippy-svg-arrow::after,
61+
.tippy-box[data-placement^="right"] > .tippy-svg-arrow > svg {
62+
transform: rotate(-90deg);
63+
top: calc(50% - 3px);
64+
right: 11px;
65+
}
66+
67+
.tippy-svg-arrow {
68+
width: 16px;
69+
height: 16px;
70+
text-align: initial;
71+
}
72+
73+
.tippy-svg-arrow,
74+
.tippy-svg-arrow > svg {
75+
position: absolute;
76+
}
77+
78+
.tippy-svg-arrow-outer {
79+
fill: var(--color-secondary);
80+
}
81+
82+
.tippy-svg-arrow-inner {
83+
fill: var(--color-body);
84+
}

0 commit comments

Comments
 (0)