mirror of
				https://github.com/go-gitea/gitea.git
				synced 2025-11-04 01:34:27 +00:00 
			
		
		
		
	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.
This commit is contained in:
		
							
								
								
									
										31
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										31
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							@@ -29,6 +29,7 @@
 | 
				
			|||||||
        "pretty-ms": "7.0.1",
 | 
					        "pretty-ms": "7.0.1",
 | 
				
			||||||
        "sortablejs": "1.15.0",
 | 
					        "sortablejs": "1.15.0",
 | 
				
			||||||
        "swagger-ui-dist": "4.11.1",
 | 
					        "swagger-ui-dist": "4.11.1",
 | 
				
			||||||
 | 
					        "tippy.js": "6.3.7",
 | 
				
			||||||
        "tributejs": "5.1.3",
 | 
					        "tributejs": "5.1.3",
 | 
				
			||||||
        "uint8-to-base64": "0.2.0",
 | 
					        "uint8-to-base64": "0.2.0",
 | 
				
			||||||
        "vue": "2.6.14",
 | 
					        "vue": "2.6.14",
 | 
				
			||||||
@@ -1599,6 +1600,15 @@
 | 
				
			|||||||
        "node": ">= 8"
 | 
					        "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": {
 | 
					    "node_modules/@primer/octicons": {
 | 
				
			||||||
      "version": "17.2.0",
 | 
					      "version": "17.2.0",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/@primer/octicons/-/octicons-17.2.0.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/@primer/octicons/-/octicons-17.2.0.tgz",
 | 
				
			||||||
@@ -11400,6 +11410,14 @@
 | 
				
			|||||||
      "integrity": "sha512-8hmiGIJMDlwjg7dlJ4yKGLK8EsYqKgPWbG3b4wjJddKNwc7N7Dpn08Df4szr/sZdMVeOstrdYSsqzX6BYbcB+w==",
 | 
					      "integrity": "sha512-8hmiGIJMDlwjg7dlJ4yKGLK8EsYqKgPWbG3b4wjJddKNwc7N7Dpn08Df4szr/sZdMVeOstrdYSsqzX6BYbcB+w==",
 | 
				
			||||||
      "dev": true
 | 
					      "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": {
 | 
					    "node_modules/tmpl": {
 | 
				
			||||||
      "version": "1.0.5",
 | 
					      "version": "1.0.5",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz",
 | 
				
			||||||
@@ -13567,6 +13585,11 @@
 | 
				
			|||||||
        "fastq": "^1.6.0"
 | 
					        "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": {
 | 
					    "@primer/octicons": {
 | 
				
			||||||
      "version": "17.2.0",
 | 
					      "version": "17.2.0",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/@primer/octicons/-/octicons-17.2.0.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/@primer/octicons/-/octicons-17.2.0.tgz",
 | 
				
			||||||
@@ -21235,6 +21258,14 @@
 | 
				
			|||||||
      "integrity": "sha512-8hmiGIJMDlwjg7dlJ4yKGLK8EsYqKgPWbG3b4wjJddKNwc7N7Dpn08Df4szr/sZdMVeOstrdYSsqzX6BYbcB+w==",
 | 
					      "integrity": "sha512-8hmiGIJMDlwjg7dlJ4yKGLK8EsYqKgPWbG3b4wjJddKNwc7N7Dpn08Df4szr/sZdMVeOstrdYSsqzX6BYbcB+w==",
 | 
				
			||||||
      "dev": true
 | 
					      "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": {
 | 
					    "tmpl": {
 | 
				
			||||||
      "version": "1.0.5",
 | 
					      "version": "1.0.5",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz",
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -29,6 +29,7 @@
 | 
				
			|||||||
    "pretty-ms": "7.0.1",
 | 
					    "pretty-ms": "7.0.1",
 | 
				
			||||||
    "sortablejs": "1.15.0",
 | 
					    "sortablejs": "1.15.0",
 | 
				
			||||||
    "swagger-ui-dist": "4.11.1",
 | 
					    "swagger-ui-dist": "4.11.1",
 | 
				
			||||||
 | 
					    "tippy.js": "6.3.7",
 | 
				
			||||||
    "tributejs": "5.1.3",
 | 
					    "tributejs": "5.1.3",
 | 
				
			||||||
    "uint8-to-base64": "0.2.0",
 | 
					    "uint8-to-base64": "0.2.0",
 | 
				
			||||||
    "vue": "2.6.14",
 | 
					    "vue": "2.6.14",
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,6 +2,7 @@ import $ from 'jquery';
 | 
				
			|||||||
import Vue from 'vue';
 | 
					import Vue from 'vue';
 | 
				
			||||||
import ContextPopup from '../components/ContextPopup.vue';
 | 
					import ContextPopup from '../components/ContextPopup.vue';
 | 
				
			||||||
import {parseIssueHref} from '../utils.js';
 | 
					import {parseIssueHref} from '../utils.js';
 | 
				
			||||||
 | 
					import {createTippy} from '../modules/tippy.js';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default function initContextPopups() {
 | 
					export default function initContextPopups() {
 | 
				
			||||||
  const refIssues = $('.ref-issue');
 | 
					  const refIssues = $('.ref-issue');
 | 
				
			||||||
@@ -16,7 +17,6 @@ export default function initContextPopups() {
 | 
				
			|||||||
    if (!owner) return;
 | 
					    if (!owner) return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const el = document.createElement('div');
 | 
					    const el = document.createElement('div');
 | 
				
			||||||
    el.className = 'ui custom popup hidden';
 | 
					 | 
				
			||||||
    el.innerHTML = '<div></div>';
 | 
					    el.innerHTML = '<div></div>';
 | 
				
			||||||
    this.parentNode.insertBefore(el, this.nextSibling);
 | 
					    this.parentNode.insertBefore(el, this.nextSibling);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -33,17 +33,12 @@ export default function initContextPopups() {
 | 
				
			|||||||
      el.textContent = 'ContextPopup failed to load';
 | 
					      el.textContent = 'ContextPopup failed to load';
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    $(this).popup({
 | 
					    createTippy(this, {
 | 
				
			||||||
      variation: 'wide',
 | 
					      content: el,
 | 
				
			||||||
      delay: {
 | 
					      interactive: true,
 | 
				
			||||||
        show: 250
 | 
					 | 
				
			||||||
      },
 | 
					 | 
				
			||||||
      onShow: () => {
 | 
					      onShow: () => {
 | 
				
			||||||
        view.$emit('load-context-popup', {owner, repo, index}, () => {
 | 
					        view.$emit('load-context-popup', {owner, repo, index});
 | 
				
			||||||
          $(this).popup('reposition');
 | 
					      }
 | 
				
			||||||
        });
 | 
					 | 
				
			||||||
      },
 | 
					 | 
				
			||||||
      popup: $(el),
 | 
					 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
  });
 | 
					  });
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										12
									
								
								web_src/js/modules/tippy.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								web_src/js/modules/tippy.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,12 @@
 | 
				
			|||||||
 | 
					import tippy from 'tippy.js';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export function createTippy(target, opts) {
 | 
				
			||||||
 | 
					  return tippy(target, {
 | 
				
			||||||
 | 
					    appendTo: document.body,
 | 
				
			||||||
 | 
					    placement: 'top-start',
 | 
				
			||||||
 | 
					    animation: false,
 | 
				
			||||||
 | 
					    allowHTML: true,
 | 
				
			||||||
 | 
					    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>`,
 | 
				
			||||||
 | 
					    ...opts,
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -9,6 +9,7 @@
 | 
				
			|||||||
@import "./features/imagediff.less";
 | 
					@import "./features/imagediff.less";
 | 
				
			||||||
@import "./features/codeeditor.less";
 | 
					@import "./features/codeeditor.less";
 | 
				
			||||||
@import "./features/projects.less";
 | 
					@import "./features/projects.less";
 | 
				
			||||||
 | 
					@import "./modules/tippy.less";
 | 
				
			||||||
@import "./markup/content.less";
 | 
					@import "./markup/content.less";
 | 
				
			||||||
@import "./markup/codecopy.less";
 | 
					@import "./markup/codecopy.less";
 | 
				
			||||||
@import "./code/linebutton.less";
 | 
					@import "./code/linebutton.less";
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										84
									
								
								web_src/less/modules/tippy.less
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										84
									
								
								web_src/less/modules/tippy.less
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,84 @@
 | 
				
			|||||||
 | 
					/* styles are based on node_modules/tippy.js/dist/tippy.css */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.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);
 | 
				
			||||||
 | 
					  font-size: 1rem;
 | 
				
			||||||
 | 
					  transition-property: transform, visibility, opacity;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.tippy-content {
 | 
				
			||||||
 | 
					  position: relative;
 | 
				
			||||||
 | 
					  padding: 1rem;
 | 
				
			||||||
 | 
					  z-index: 1;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.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;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.tippy-svg-arrow-outer {
 | 
				
			||||||
 | 
					  fill: var(--color-secondary);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.tippy-svg-arrow-inner {
 | 
				
			||||||
 | 
					  fill: var(--color-body);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
		Reference in New Issue
	
	Block a user