mirror of
				https://github.com/go-gitea/gitea.git
				synced 2025-10-31 19:06:18 +01: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", | ||||
|         "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", | ||||
|   | ||||
| @@ -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", | ||||
|   | ||||
| @@ -2,6 +2,7 @@ import $ from 'jquery'; | ||||
| import Vue from 'vue'; | ||||
| import ContextPopup from '../components/ContextPopup.vue'; | ||||
| import {parseIssueHref} from '../utils.js'; | ||||
| import {createTippy} from '../modules/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 = '<div></div>'; | ||||
|     this.parentNode.insertBefore(el, this.nextSibling); | ||||
|  | ||||
| @@ -33,17 +33,12 @@ export default function initContextPopups() { | ||||
|       el.textContent = 'ContextPopup failed to load'; | ||||
|     } | ||||
|  | ||||
|     $(this).popup({ | ||||
|       variation: 'wide', | ||||
|       delay: { | ||||
|         show: 250 | ||||
|       }, | ||||
|     createTippy(this, { | ||||
|       content: el, | ||||
|       interactive: true, | ||||
|       onShow: () => { | ||||
|         view.$emit('load-context-popup', {owner, repo, index}, () => { | ||||
|           $(this).popup('reposition'); | ||||
|         }); | ||||
|       }, | ||||
|       popup: $(el), | ||||
|         view.$emit('load-context-popup', {owner, repo, index}); | ||||
|       } | ||||
|     }); | ||||
|   }); | ||||
| } | ||||
|   | ||||
							
								
								
									
										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/codeeditor.less"; | ||||
| @import "./features/projects.less"; | ||||
| @import "./modules/tippy.less"; | ||||
| @import "./markup/content.less"; | ||||
| @import "./markup/codecopy.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