Skip to content

Commit 38cfdad

Browse files
committed
fix(aria/menu): focus flicker bug
* Fixes an issue in standalone menus and context menus where focus would flicker when opening a menu.
1 parent 324fd01 commit 38cfdad

File tree

3 files changed

+19
-1
lines changed

3 files changed

+19
-1
lines changed

src/aria/menu/menu.spec.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -444,6 +444,16 @@ describe('Standalone Menu Pattern', () => {
444444
expect(document.activeElement).toBe(berries);
445445
});
446446
});
447+
448+
it('should not reset default state on hover triggers expansion', async () => {
449+
TestBed.configureTestingModule({});
450+
fixture = TestBed.createComponent(StandaloneMenuExample);
451+
fixture.detectChanges();
452+
453+
const berries = getItem('Berries');
454+
await mouseover(berries!);
455+
expect(berries?.getAttribute('data-active')).toBe('true');
456+
});
447457
});
448458

449459
describe('Menu Trigger Pattern', () => {

src/aria/menu/menu.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -261,7 +261,11 @@ export class Menu<V> {
261261
});
262262

263263
afterRenderEffect(() => {
264-
if (!this._pattern.hasBeenFocused() && this._items().length) {
264+
if (
265+
!this._pattern.hasBeenFocused() &&
266+
!this._pattern.hasBeenHovered() &&
267+
this._items().length
268+
) {
265269
untracked(() => this._pattern.setDefaultState());
266270
}
267271
});

src/aria/private/menu/menu.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,9 @@ export class MenuPattern<V> {
9191
/** Whether the menu has received focus. */
9292
hasBeenFocused = signal(false);
9393

94+
/** Whether the menu trigger has been hovered. */
95+
hasBeenHovered = signal(false);
96+
9497
/** Timeout used to open sub-menus on hover. */
9598
_openTimeout: any;
9699

@@ -195,6 +198,7 @@ export class MenuPattern<V> {
195198
return;
196199
}
197200

201+
this.hasBeenHovered.set(true);
198202
const item = this.inputs.items().find(i => i.element()?.contains(event.target as Node));
199203

200204
if (!item) {

0 commit comments

Comments
 (0)