Skip to content

Commit

Permalink
[#55581] make hover card work with avatar fallbacks
Browse files Browse the repository at this point in the history
This was a hard one to debug. When you hover over an avatar as soon as
the page loads, you will hover over the fallback first. Within the
timeout, the actual avatar image loads and replaces the fallback. After
that, the timeout of the hover trigger runs out and displays the hover
cards, but does no longer have an element to position relative to. So,
we check for the existence of the hovered element before showing a hover
card to fix this.
  • Loading branch information
EinLama committed Nov 29, 2024
1 parent 6ce763e commit e6aca92
Showing 1 changed file with 26 additions and 19 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -87,25 +87,7 @@ export class HoverCardTriggerService {

// Set a delay before showing the hover card
this.hoverTimeout = window.setTimeout(() => {
this.parseHoverCardOptions(el);

// There is only one possible slot to insert a modal. If that slot is taken, we assume the other modal
// to be more important than a hover card and give up.
const modal = this.opModalService.showIfNotActive(
HoverCardComponent,
this.injector,
{ turboFrameSrc: cleanedTurboFrameUrl, event: e },
true,
false,
this.modalTarget,
);

modal?.subscribe((previewModal) => {
this.modalElement = previewModal.elementRef.nativeElement as HTMLElement;
previewModal.alignment = 'top';

void previewModal.reposition(this.modalElement, el);
});
this.showHoverCard(el, cleanedTurboFrameUrl, e);
}, this.OPEN_DELAY_IN_MS);
});

Expand All @@ -126,6 +108,31 @@ export class HoverCardTriggerService {
});
}

private showHoverCard(el:HTMLElement, cleanedTurboFrameUrl:string, e:JQuery.MouseOverEvent) {
// Abort if the element is no longer present in the DOM. This can happen when this method is called after a delay.
if (!document.body.contains(el)) { return; }

this.parseHoverCardOptions(el);

// There is only one possible slot to insert a modal. If that slot is taken, we assume the other modal
// to be more important than a hover card and give up.
const modal = this.opModalService.showIfNotActive(
HoverCardComponent,
this.injector,
{ turboFrameSrc: cleanedTurboFrameUrl, event: e },
true,
false,
this.modalTarget,
);

modal?.subscribe((previewModal) => {
this.modalElement = previewModal.elementRef.nativeElement as HTMLElement;
previewModal.alignment = 'top';

void previewModal.reposition(this.modalElement, el);
});
}

// Should be called when the mouse leaves the hover-zone so that we no longer attempt ot display the hover card.
private clearHoverTimer() {
if (this.hoverTimeout) {
Expand Down

0 comments on commit e6aca92

Please sign in to comment.