Our client rised a "bug". The bug is about having one button stuck with blue background (hovered) even after a pointer was moved outside.
I've created a MWE locally and moved it to Stackblitz (sorry, not working on IE, lol).
I've also add links to YouTube videos to show the issue as it turned out You had some hard time reproducing it.
To reproduce locally, just create a new Angular project , ng add @ng-bootstrap/ng-bootstrap
.
Angular 11, "@ng-bootstrap/ng-bootstrap": "^9.0.2", "bootstrap": "^4.6.0",
Here is the view app.component.ts:
import { Component } from '@angular/core';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
toggle: boolean;
}
Here is the view app.component.html:
<div [ngSwitch]="toggle">
<button *ngSwitchCase="true" type="button" class="btn btn-primary" (click)="toggle = !toggle" ngbPopover="You see, I show up on hover1!" placement="right" triggers="mouseenter:mouseleave">Primary1</button>
<button *ngSwitchDefault type="button" class="btn btn-outline-primary" (click)="toggle = !toggle" ngbPopover="You see, I show up on hover2!" placement="right" triggers="mouseenter:mouseleave">Primary2</button>
</div>
Key points:
- having two buttons
- button 1 on click will be hidden, button 2 will be showed
- button 2 on click will be hidden, button 1 will be showed
- button 1 and 2 have different bootstrap styles to make things simple
- both buttons displays a tooltip on hover, dismiss them on leave
How to reproduce:
- click on button
- immediately after click move a mouse on tooltip (but You need to be very, very fast)
Effect:
- button 1 is hidden (removed from DOM),
- button 2 is shown (added to DOM),
- button 2 is not hovered,
- tooltips are dismissed
- IE still aplies
.btn-outline-primary:hover
even the button is not hovered, - hovering over the button and moving pointer out fixes the issue - IE will apply
.btn-outline-primary
as expected.
What we think? That IE after adding button 2 is not aware that user already move cursor out (so IE "thinks" that no hover state was changed, so it keeps the :hover styling but the button is different). BUT mouseleave
and mouseout
is fired for the new button.
We weren't able to reproduce on Chrome after many many tries.
What we have tried:
- we dissabled transisions - Chrome by default is adding prefers-reduced-motion media query, IE is not supported. That fixed blinking effect but hover issue remains.
- we tried to separate the button to component and call
detectChanges
with/withoutsetTimeout
to let IE "rethink" the situation and then rerender the button with proper styles - didn't help - ultimately I have added a switch like this:
<div [ngSwitch]="forceRefresh">
<div *ngSwitchCase="true">...</div>
<div *ngSwitchDefault>...</div>
</div>
and I change forceRefresh
value from false
to true
in setTimeout
to force IE to think it has to render entirely different DOM (both cases renders the same button). It worked.
I would like to know is there more elegant way to workaround this IE-specific issue?
Note: In our project this happens even after removing tooltops, so I doubt it is connected with Bootstrap popovers. I assume it can be fixed easiliy by keeping only one button but then we will have to apply many conditional expressions for each attribute for such a button. Using ng-templates
for grouping buttons is much more preferable.
Video (from home, MWE, Chrome, IE11, Edge): https://www.youtube.com/watch?v=oeG-11TzS-Q