@@ -40,6 +40,7 @@ export function createTippy(target: Element, opts: TippyOpts = {}): Instance {
4040 }
4141 }
4242 visibleInstances . add ( instance ) ;
43+ target . setAttribute ( 'aria-controls' , instance . popper . id ) ;
4344 return onShow ?.( instance ) ;
4445 } ,
4546 arrow : arrow ?? ( theme === 'bare' ? false : arrowSvg ) ,
@@ -180,13 +181,25 @@ export function initGlobalTooltips(): void {
180181}
181182
182183export function showTemporaryTooltip ( target : Element , content : Content ) : void {
183- // if the target is inside a dropdown, the menu will be hidden soon
184- // so display the tooltip on the dropdown instead
185- target = target . closest ( '.ui.dropdown' ) || target ;
186- const tippy = target . _tippy ?? attachTooltip ( target , content ) ;
187- tippy . setContent ( content ) ;
188- if ( ! tippy . state . isShown ) tippy . show ( ) ;
189- tippy . setProps ( {
184+ // if the target is inside a dropdown or tippy popup, the menu will be hidden soon
185+ // so display the tooltip on the "aria-controls" element or dropdown instead
186+ let refClientRect : DOMRect ;
187+ const popupTippyId = target . closest ( `[data-tippy-root]` ) ?. id ;
188+ if ( popupTippyId ) {
189+ // for example, the "Copy Permalink" button in the "File View" page for the selected lines
190+ target = document . body ;
191+ refClientRect = document . querySelector ( `[aria-controls="${ CSS . escape ( popupTippyId ) } "]` ) ?. getBoundingClientRect ( ) ;
192+ refClientRect = refClientRect ?? new DOMRect ( 0 , 0 , 0 , 0 ) ; // fallback to empty rect if not found, tippy doesn't accept null
193+ } else {
194+ // for example, the "Copy Link" button in the issue header dropdown menu
195+ target = target . closest ( '.ui.dropdown' ) ?? target ;
196+ refClientRect = target . getBoundingClientRect ( ) ;
197+ }
198+ const tooltipTippy = target . _tippy ?? attachTooltip ( target , content ) ;
199+ tooltipTippy . setContent ( content ) ;
200+ tooltipTippy . setProps ( { getReferenceClientRect : ( ) => refClientRect } ) ;
201+ if ( ! tooltipTippy . state . isShown ) tooltipTippy . show ( ) ;
202+ tooltipTippy . setProps ( {
190203 onHidden : ( tippy ) => {
191204 // reset the default tooltip content, if no default, then this temporary tooltip could be destroyed
192205 if ( ! attachTooltip ( target ) ) {
0 commit comments