mirror of
				https://github.com/go-gitea/gitea.git
				synced 2025-10-26 12:27:06 +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
	 silverwind
					silverwind