From ba0212fdea881db1697a6ff10f45276830d885cc Mon Sep 17 00:00:00 2001 From: silverwind Date: Sun, 17 Jul 2022 16:07:32 +0200 Subject: [PATCH 01/12] Use tippy.js for context popup By appending the tooltips to document.body, we can avoid any stacking context issues caused by surrounding element's CSS. I wasn't able to get this portalling to work with Fomantic popups, so this uses tippy.js instead of Fomantic popups. We should aim to replace all Fomantic popups with this eventually. Fixes: https://github.com/go-gitea/gitea/pull/20377 --- package-lock.json | 31 ++++++++++ package.json | 1 + web_src/js/features/contextpopup.js | 22 ++++---- web_src/less/features/tippy.less | 87 +++++++++++++++++++++++++++++ web_src/less/index.less | 1 + 5 files changed, 131 insertions(+), 11 deletions(-) create mode 100644 web_src/less/features/tippy.less diff --git a/package-lock.json b/package-lock.json index 605134201ebb9..05d728ccdce87 100644 --- a/package-lock.json +++ b/package-lock.json @@ -29,6 +29,7 @@ "pretty-ms": "7.0.1", "sortablejs": "1.15.0", "swagger-ui-dist": "4.11.1", + "tippy.js": "6.3.7", "tributejs": "5.1.3", "uint8-to-base64": "0.2.0", "vue": "2.6.14", @@ -1599,6 +1600,15 @@ "node": ">= 8" } }, + "node_modules/@popperjs/core": { + "version": "2.11.5", + "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.5.tgz", + "integrity": "sha512-9X2obfABZuDVLCgPK9aX0a/x4jaOEweTTWE2+9sr0Qqqevj2Uv5XorvusThmc9XGYpS9yI+fhh8RTafBtGposw==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/popperjs" + } + }, "node_modules/@primer/octicons": { "version": "17.2.0", "resolved": "https://registry.npmjs.org/@primer/octicons/-/octicons-17.2.0.tgz", @@ -11400,6 +11410,14 @@ "integrity": "sha512-8hmiGIJMDlwjg7dlJ4yKGLK8EsYqKgPWbG3b4wjJddKNwc7N7Dpn08Df4szr/sZdMVeOstrdYSsqzX6BYbcB+w==", "dev": true }, + "node_modules/tippy.js": { + "version": "6.3.7", + "resolved": "https://registry.npmjs.org/tippy.js/-/tippy.js-6.3.7.tgz", + "integrity": "sha512-E1d3oP2emgJ9dRQZdf3Kkn0qJgI6ZLpyS5z6ZkY1DF3kaQaBsGZsndEpHwx+eC+tYM41HaSNvNtLx8tU57FzTQ==", + "dependencies": { + "@popperjs/core": "^2.9.0" + } + }, "node_modules/tmpl": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", @@ -13567,6 +13585,11 @@ "fastq": "^1.6.0" } }, + "@popperjs/core": { + "version": "2.11.5", + "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.5.tgz", + "integrity": "sha512-9X2obfABZuDVLCgPK9aX0a/x4jaOEweTTWE2+9sr0Qqqevj2Uv5XorvusThmc9XGYpS9yI+fhh8RTafBtGposw==" + }, "@primer/octicons": { "version": "17.2.0", "resolved": "https://registry.npmjs.org/@primer/octicons/-/octicons-17.2.0.tgz", @@ -21235,6 +21258,14 @@ "integrity": "sha512-8hmiGIJMDlwjg7dlJ4yKGLK8EsYqKgPWbG3b4wjJddKNwc7N7Dpn08Df4szr/sZdMVeOstrdYSsqzX6BYbcB+w==", "dev": true }, + "tippy.js": { + "version": "6.3.7", + "resolved": "https://registry.npmjs.org/tippy.js/-/tippy.js-6.3.7.tgz", + "integrity": "sha512-E1d3oP2emgJ9dRQZdf3Kkn0qJgI6ZLpyS5z6ZkY1DF3kaQaBsGZsndEpHwx+eC+tYM41HaSNvNtLx8tU57FzTQ==", + "requires": { + "@popperjs/core": "^2.9.0" + } + }, "tmpl": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", diff --git a/package.json b/package.json index afc8d2a374e96..3ba0b956322df 100644 --- a/package.json +++ b/package.json @@ -29,6 +29,7 @@ "pretty-ms": "7.0.1", "sortablejs": "1.15.0", "swagger-ui-dist": "4.11.1", + "tippy.js": "6.3.7", "tributejs": "5.1.3", "uint8-to-base64": "0.2.0", "vue": "2.6.14", diff --git a/web_src/js/features/contextpopup.js b/web_src/js/features/contextpopup.js index 0cd47bf2bc6ec..f2e5f8b5b128b 100644 --- a/web_src/js/features/contextpopup.js +++ b/web_src/js/features/contextpopup.js @@ -2,6 +2,7 @@ import $ from 'jquery'; import Vue from 'vue'; import ContextPopup from '../components/ContextPopup.vue'; import {parseIssueHref} from '../utils.js'; +import tippy from 'tippy.js'; export default function initContextPopups() { const refIssues = $('.ref-issue'); @@ -16,7 +17,6 @@ export default function initContextPopups() { if (!owner) return; const el = document.createElement('div'); - el.className = 'ui custom popup hidden'; el.innerHTML = '
'; this.parentNode.insertBefore(el, this.nextSibling); @@ -33,17 +33,17 @@ export default function initContextPopups() { el.textContent = 'ContextPopup failed to load'; } - $(this).popup({ - variation: 'wide', - delay: { - show: 250 - }, + tippy(this, { + appendTo: () => document.body, + placement: 'top-start', + delay: 250, + content: el, + allowHTML: true, + interactive: true, + arrow: ``, onShow: () => { - view.$emit('load-context-popup', {owner, repo, index}, () => { - $(this).popup('reposition'); - }); - }, - popup: $(el), + view.$emit('load-context-popup', {owner, repo, index}); + } }); }); } diff --git a/web_src/less/features/tippy.less b/web_src/less/features/tippy.less new file mode 100644 index 0000000000000..4028ee741eb60 --- /dev/null +++ b/web_src/less/features/tippy.less @@ -0,0 +1,87 @@ +.tippy-box[data-animation="fade"][data-state="hidden"] { + opacity: 0; +} + +[data-tippy-root] { + max-width: calc(100vw - 10px); +} + +.tippy-box { + position: relative; + background-color: var(--color-body); + color: var(--color-secondary-dark-6); + border: 1px solid var(--color-secondary); + border-radius: var(--border-radius); + padding: .5em; + font-size: 1rem; + transition-property: transform, visibility, opacity; +} + +.tippy-box[data-inertia][data-state="visible"] { + transition-timing-function: cubic-bezier(0.54, 1.5, 0.38, 1.11); +} + +.tippy-content { + position: relative; + padding: 5px 9px; + z-index: 1; +} + +.tippy-svg-arrow { + fill: var(--color-secondary); +} + +.tippy-svg-arrow-content { + fill: var(--color-body); +} + +.tippy-box[data-placement^="top"] > .tippy-svg-arrow { + bottom: 0; +} + +.tippy-box[data-placement^="top"] > .tippy-svg-arrow:after, +.tippy-box[data-placement^="top"] > .tippy-svg-arrow > svg { + top: 16px; + transform: rotate(180deg); +} + +.tippy-box[data-placement^="bottom"] > .tippy-svg-arrow { + top: 0; +} + +.tippy-box[data-placement^="bottom"] > .tippy-svg-arrow > svg { + bottom: 16px; +} + +.tippy-box[data-placement^="left"] > .tippy-svg-arrow { + right: 0; +} + +.tippy-box[data-placement^="left"] > .tippy-svg-arrow:after, +.tippy-box[data-placement^="left"] > .tippy-svg-arrow > svg { + transform: rotate(90deg); + top: calc(50% - 3px); + left: 11px; +} + +.tippy-box[data-placement^="right"] > .tippy-svg-arrow { + left: 0; +} + +.tippy-box[data-placement^="right"] > .tippy-svg-arrow:after, +.tippy-box[data-placement^="right"] > .tippy-svg-arrow > svg { + transform: rotate(-90deg); + top: calc(50% - 3px); + right: 11px; +} + +.tippy-svg-arrow { + width: 16px; + height: 16px; + text-align: initial; +} + +.tippy-svg-arrow, +.tippy-svg-arrow > svg { + position: absolute; +} diff --git a/web_src/less/index.less b/web_src/less/index.less index 4a6bd330fe830..9001e4fc8362b 100644 --- a/web_src/less/index.less +++ b/web_src/less/index.less @@ -9,6 +9,7 @@ @import "./features/imagediff.less"; @import "./features/codeeditor.less"; @import "./features/projects.less"; +@import "./features/tippy.less"; @import "./markup/content.less"; @import "./markup/codecopy.less"; @import "./code/linebutton.less"; From e02397590280a0a7d515047faefe0aedb9fa9074 Mon Sep 17 00:00:00 2001 From: silverwind Date: Sun, 17 Jul 2022 16:23:08 +0200 Subject: [PATCH 02/12] css cleanup --- web_src/less/features/tippy.less | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/web_src/less/features/tippy.less b/web_src/less/features/tippy.less index 4028ee741eb60..f7f1faf9059e5 100644 --- a/web_src/less/features/tippy.less +++ b/web_src/less/features/tippy.less @@ -12,18 +12,13 @@ color: var(--color-secondary-dark-6); border: 1px solid var(--color-secondary); border-radius: var(--border-radius); - padding: .5em; font-size: 1rem; transition-property: transform, visibility, opacity; } -.tippy-box[data-inertia][data-state="visible"] { - transition-timing-function: cubic-bezier(0.54, 1.5, 0.38, 1.11); -} - .tippy-content { position: relative; - padding: 5px 9px; + padding: 1rem; z-index: 1; } From 260fe110e7d3854341c25a992ffa1fb5ece0e058 Mon Sep 17 00:00:00 2001 From: silverwind Date: Sun, 17 Jul 2022 16:27:00 +0200 Subject: [PATCH 03/12] use distinct classes for svg arrow fills --- web_src/js/features/contextpopup.js | 2 +- web_src/less/features/tippy.less | 16 ++++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/web_src/js/features/contextpopup.js b/web_src/js/features/contextpopup.js index f2e5f8b5b128b..9df5142577aba 100644 --- a/web_src/js/features/contextpopup.js +++ b/web_src/js/features/contextpopup.js @@ -40,7 +40,7 @@ export default function initContextPopups() { content: el, allowHTML: true, interactive: true, - arrow: ``, + arrow: ``, onShow: () => { view.$emit('load-context-popup', {owner, repo, index}); } diff --git a/web_src/less/features/tippy.less b/web_src/less/features/tippy.less index f7f1faf9059e5..77d184a328a74 100644 --- a/web_src/less/features/tippy.less +++ b/web_src/less/features/tippy.less @@ -22,14 +22,6 @@ z-index: 1; } -.tippy-svg-arrow { - fill: var(--color-secondary); -} - -.tippy-svg-arrow-content { - fill: var(--color-body); -} - .tippy-box[data-placement^="top"] > .tippy-svg-arrow { bottom: 0; } @@ -80,3 +72,11 @@ .tippy-svg-arrow > svg { position: absolute; } + +.tippy-svg-arrow-outer { + fill: var(--color-secondary); +} + +.tippy-svg-arrow-inner { + fill: var(--color-body); +} From 1efdacaebd4f81c6a3f49af95e599082f78028a4 Mon Sep 17 00:00:00 2001 From: silverwind Date: Sun, 17 Jul 2022 16:30:28 +0200 Subject: [PATCH 04/12] fix lint --- web_src/less/features/tippy.less | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/web_src/less/features/tippy.less b/web_src/less/features/tippy.less index 77d184a328a74..6f6b94558ec27 100644 --- a/web_src/less/features/tippy.less +++ b/web_src/less/features/tippy.less @@ -26,7 +26,7 @@ bottom: 0; } -.tippy-box[data-placement^="top"] > .tippy-svg-arrow:after, +.tippy-box[data-placement^="top"] > .tippy-svg-arrow::after, .tippy-box[data-placement^="top"] > .tippy-svg-arrow > svg { top: 16px; transform: rotate(180deg); @@ -44,7 +44,7 @@ right: 0; } -.tippy-box[data-placement^="left"] > .tippy-svg-arrow:after, +.tippy-box[data-placement^="left"] > .tippy-svg-arrow::after, .tippy-box[data-placement^="left"] > .tippy-svg-arrow > svg { transform: rotate(90deg); top: calc(50% - 3px); @@ -55,7 +55,7 @@ left: 0; } -.tippy-box[data-placement^="right"] > .tippy-svg-arrow:after, +.tippy-box[data-placement^="right"] > .tippy-svg-arrow::after, .tippy-box[data-placement^="right"] > .tippy-svg-arrow > svg { transform: rotate(-90deg); top: calc(50% - 3px); From bf74374afe574856a7ce72b41ab12684ffbac92a Mon Sep 17 00:00:00 2001 From: silverwind Date: Sun, 17 Jul 2022 16:48:09 +0200 Subject: [PATCH 05/12] extract popup creation to function --- web_src/js/features/contextpopup.js | 8 ++------ web_src/js/features/popup.js | 11 +++++++++++ 2 files changed, 13 insertions(+), 6 deletions(-) create mode 100644 web_src/js/features/popup.js diff --git a/web_src/js/features/contextpopup.js b/web_src/js/features/contextpopup.js index 9df5142577aba..7a294ef43e05b 100644 --- a/web_src/js/features/contextpopup.js +++ b/web_src/js/features/contextpopup.js @@ -2,7 +2,7 @@ import $ from 'jquery'; import Vue from 'vue'; import ContextPopup from '../components/ContextPopup.vue'; import {parseIssueHref} from '../utils.js'; -import tippy from 'tippy.js'; +import {createPopup} from './popup.js'; export default function initContextPopups() { const refIssues = $('.ref-issue'); @@ -33,14 +33,10 @@ export default function initContextPopups() { el.textContent = 'ContextPopup failed to load'; } - tippy(this, { - appendTo: () => document.body, - placement: 'top-start', + createPopup(this, { delay: 250, content: el, - allowHTML: true, interactive: true, - arrow: ``, onShow: () => { view.$emit('load-context-popup', {owner, repo, index}); } diff --git a/web_src/js/features/popup.js b/web_src/js/features/popup.js new file mode 100644 index 0000000000000..2eb3eae3007d0 --- /dev/null +++ b/web_src/js/features/popup.js @@ -0,0 +1,11 @@ +import tippy from 'tippy.js'; + +export function createPopup(target, opts = {}) { + return tippy(target, { + appendTo: () => document.body, + placement: 'top-start', + allowHTML: true, + arrow: ``, + ...opts, + }); +} From 8ab93993772089bda6f9ca017b12fbf4db6a6d92 Mon Sep 17 00:00:00 2001 From: silverwind Date: Sun, 17 Jul 2022 16:54:52 +0200 Subject: [PATCH 06/12] remove delay --- web_src/js/features/contextpopup.js | 1 - web_src/js/features/popup.js | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/web_src/js/features/contextpopup.js b/web_src/js/features/contextpopup.js index 7a294ef43e05b..a678b534b7aa6 100644 --- a/web_src/js/features/contextpopup.js +++ b/web_src/js/features/contextpopup.js @@ -34,7 +34,6 @@ export default function initContextPopups() { } createPopup(this, { - delay: 250, content: el, interactive: true, onShow: () => { diff --git a/web_src/js/features/popup.js b/web_src/js/features/popup.js index 2eb3eae3007d0..a2cb65cc35479 100644 --- a/web_src/js/features/popup.js +++ b/web_src/js/features/popup.js @@ -2,7 +2,7 @@ import tippy from 'tippy.js'; export function createPopup(target, opts = {}) { return tippy(target, { - appendTo: () => document.body, + appendTo: document.body, placement: 'top-start', allowHTML: true, arrow: ``, From 871daa47812fced4e6b6954653351e2d82394626 Mon Sep 17 00:00:00 2001 From: silverwind Date: Sun, 17 Jul 2022 16:56:49 +0200 Subject: [PATCH 07/12] rename file --- web_src/js/features/contextpopup.js | 4 ++-- web_src/js/features/{popup.js => tippy.js} | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) rename web_src/js/features/{popup.js => tippy.js} (86%) diff --git a/web_src/js/features/contextpopup.js b/web_src/js/features/contextpopup.js index a678b534b7aa6..a40331f47e834 100644 --- a/web_src/js/features/contextpopup.js +++ b/web_src/js/features/contextpopup.js @@ -2,7 +2,7 @@ import $ from 'jquery'; import Vue from 'vue'; import ContextPopup from '../components/ContextPopup.vue'; import {parseIssueHref} from '../utils.js'; -import {createPopup} from './popup.js'; +import {createTippy} from './tippy.js'; export default function initContextPopups() { const refIssues = $('.ref-issue'); @@ -33,7 +33,7 @@ export default function initContextPopups() { el.textContent = 'ContextPopup failed to load'; } - createPopup(this, { + createTippy(this, { content: el, interactive: true, onShow: () => { diff --git a/web_src/js/features/popup.js b/web_src/js/features/tippy.js similarity index 86% rename from web_src/js/features/popup.js rename to web_src/js/features/tippy.js index a2cb65cc35479..d314f5c84acdc 100644 --- a/web_src/js/features/popup.js +++ b/web_src/js/features/tippy.js @@ -1,6 +1,6 @@ import tippy from 'tippy.js'; -export function createPopup(target, opts = {}) { +export function createTippy(target, opts = {}) { return tippy(target, { appendTo: document.body, placement: 'top-start', From 452e2641fe1a2c006506e657d7c59086ba776b76 Mon Sep 17 00:00:00 2001 From: silverwind Date: Sun, 17 Jul 2022 17:50:14 +0200 Subject: [PATCH 08/12] move to modules dir, disable animation --- web_src/js/features/contextpopup.js | 2 +- web_src/js/{features => modules}/tippy.js | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) rename web_src/js/{features => modules}/tippy.js (94%) diff --git a/web_src/js/features/contextpopup.js b/web_src/js/features/contextpopup.js index a40331f47e834..f4e660be3fc00 100644 --- a/web_src/js/features/contextpopup.js +++ b/web_src/js/features/contextpopup.js @@ -2,7 +2,7 @@ import $ from 'jquery'; import Vue from 'vue'; import ContextPopup from '../components/ContextPopup.vue'; import {parseIssueHref} from '../utils.js'; -import {createTippy} from './tippy.js'; +import {createTippy} from '../modules/tippy.js'; export default function initContextPopups() { const refIssues = $('.ref-issue'); diff --git a/web_src/js/features/tippy.js b/web_src/js/modules/tippy.js similarity index 94% rename from web_src/js/features/tippy.js rename to web_src/js/modules/tippy.js index d314f5c84acdc..be4a238074e7b 100644 --- a/web_src/js/features/tippy.js +++ b/web_src/js/modules/tippy.js @@ -4,6 +4,7 @@ export function createTippy(target, opts = {}) { return tippy(target, { appendTo: document.body, placement: 'top-start', + animation: false, allowHTML: true, arrow: ``, ...opts, From 9534aa620645410be7f01a024fb07b5b9771ff22 Mon Sep 17 00:00:00 2001 From: silverwind Date: Sun, 17 Jul 2022 17:51:46 +0200 Subject: [PATCH 09/12] remove unnecessary default --- web_src/js/modules/tippy.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web_src/js/modules/tippy.js b/web_src/js/modules/tippy.js index be4a238074e7b..070720ce7267c 100644 --- a/web_src/js/modules/tippy.js +++ b/web_src/js/modules/tippy.js @@ -1,6 +1,6 @@ import tippy from 'tippy.js'; -export function createTippy(target, opts = {}) { +export function createTippy(target, opts) { return tippy(target, { appendTo: document.body, placement: 'top-start', From c899251f980689de5cd50af2867005dbd9ab429c Mon Sep 17 00:00:00 2001 From: silverwind Date: Sun, 17 Jul 2022 17:53:12 +0200 Subject: [PATCH 10/12] move css to modules dir as well --- web_src/less/index.less | 2 +- web_src/less/{features => modules}/tippy.less | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename web_src/less/{features => modules}/tippy.less (100%) diff --git a/web_src/less/index.less b/web_src/less/index.less index 9001e4fc8362b..4823c56173389 100644 --- a/web_src/less/index.less +++ b/web_src/less/index.less @@ -9,7 +9,7 @@ @import "./features/imagediff.less"; @import "./features/codeeditor.less"; @import "./features/projects.less"; -@import "./features/tippy.less"; +@import "./modules/tippy.less"; @import "./markup/content.less"; @import "./markup/codecopy.less"; @import "./code/linebutton.less"; diff --git a/web_src/less/features/tippy.less b/web_src/less/modules/tippy.less similarity index 100% rename from web_src/less/features/tippy.less rename to web_src/less/modules/tippy.less From 308396e18f469e44e7877c67442b444b9c42b2a5 Mon Sep 17 00:00:00 2001 From: silverwind Date: Sun, 17 Jul 2022 18:17:57 +0200 Subject: [PATCH 11/12] tweak svg arrow --- web_src/js/modules/tippy.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web_src/js/modules/tippy.js b/web_src/js/modules/tippy.js index 070720ce7267c..6fd466cd92293 100644 --- a/web_src/js/modules/tippy.js +++ b/web_src/js/modules/tippy.js @@ -6,7 +6,7 @@ export function createTippy(target, opts) { placement: 'top-start', animation: false, allowHTML: true, - arrow: ``, + arrow: ``, ...opts, }); } From 242a41882b64ace8689e9940954b18b795f5e930 Mon Sep 17 00:00:00 2001 From: silverwind Date: Mon, 18 Jul 2022 22:00:30 +0200 Subject: [PATCH 12/12] add comment on style source --- web_src/less/modules/tippy.less | 2 ++ 1 file changed, 2 insertions(+) diff --git a/web_src/less/modules/tippy.less b/web_src/less/modules/tippy.less index 6f6b94558ec27..aa2aed6ce2114 100644 --- a/web_src/less/modules/tippy.less +++ b/web_src/less/modules/tippy.less @@ -1,3 +1,5 @@ +/* styles are based on node_modules/tippy.js/dist/tippy.css */ + .tippy-box[data-animation="fade"][data-state="hidden"] { opacity: 0; }