Skip to content

Commit

Permalink
refactor(core): add focusin event to on hover trigger of @defer
Browse files Browse the repository at this point in the history
… block

This commit adds the `focusin` event to `on hover` trigger of `@defer` block to improve compatibility with screen readers.
  • Loading branch information
AndrewKushnir committed Oct 5, 2023
1 parent 5b88d13 commit 919fb43
Show file tree
Hide file tree
Showing 2 changed files with 19 additions and 6 deletions.
11 changes: 9 additions & 2 deletions packages/core/src/render3/instructions/defer_events.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ const interactionTriggers = new WeakMap<Element, DeferEventEntry>();
/** Names of the events considered as interaction events. */
const interactionEventNames = ['click', 'keydown'] as const;

/** Names of the events considered as hover events. */
const hoverEventNames = ['mouseenter', 'focusin'];

/** Object keeping track of registered callbacks for a deferred block trigger. */
class DeferEventEntry {
callbacks = new Set<() => void>();
Expand Down Expand Up @@ -103,7 +106,9 @@ export function onHover(
// Ensure that the handler runs in the NgZone since it gets
// registered in `afterRender` which runs outside.
injector.get(NgZone).run(() => {
trigger.addEventListener('mouseenter', entry!.listener, eventListenerOptions);
for (const name of hoverEventNames) {
trigger.addEventListener(name, entry!.listener, eventListenerOptions);
}
});
}

Expand All @@ -114,7 +119,9 @@ export function onHover(
callbacks.delete(callback);

if (callbacks.size === 0) {
trigger.removeEventListener('mouseenter', listener, eventListenerOptions);
for (const name of hoverEventNames) {
trigger.removeEventListener(name, listener, eventListenerOptions);
}
hoverTriggers.delete(trigger);
}
};
Expand Down
14 changes: 10 additions & 4 deletions packages/core/test/acceptance/defer_spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2499,8 +2499,9 @@ describe('@defer', () => {
fixture.detectChanges();
flush();

expect(spy).toHaveBeenCalledTimes(1);
expect(spy).toHaveBeenCalledTimes(2);
expect(spy).toHaveBeenCalledWith('mouseenter', jasmine.any(Function), jasmine.any(Object));
expect(spy).toHaveBeenCalledWith('focusin', jasmine.any(Function), jasmine.any(Object));
}));

it('should unbind the trigger events when the trigger is destroyed', fakeAsync(() => {
Expand Down Expand Up @@ -2533,8 +2534,9 @@ describe('@defer', () => {
fixture.componentInstance.renderBlock = false;
fixture.detectChanges();

expect(spy).toHaveBeenCalledTimes(1);
expect(spy).toHaveBeenCalledTimes(2);
expect(spy).toHaveBeenCalledWith('mouseenter', jasmine.any(Function), jasmine.any(Object));
expect(spy).toHaveBeenCalledWith('focusin', jasmine.any(Function), jasmine.any(Object));
}));

it('should unbind the trigger events when the deferred block is destroyed', fakeAsync(() => {
Expand Down Expand Up @@ -2568,8 +2570,9 @@ describe('@defer', () => {
fixture.componentInstance.renderBlock = false;
fixture.detectChanges();

expect(spy).toHaveBeenCalledTimes(1);
expect(spy).toHaveBeenCalledTimes(2);
expect(spy).toHaveBeenCalledWith('mouseenter', jasmine.any(Function), jasmine.any(Object));
expect(spy).toHaveBeenCalledWith('focusin', jasmine.any(Function), jasmine.any(Object));
}));

it('should bind the trigger events inside the NgZone', fakeAsync(() => {
Expand All @@ -2595,7 +2598,10 @@ describe('@defer', () => {
});
fixture.detectChanges();

expect(eventsInZone).toEqual({mouseenter: true});
expect(eventsInZone).toEqual({
mouseenter: true,
focusin: true,
});
}));

it('should prefetch resources on hover', fakeAsync(() => {
Expand Down

0 comments on commit 919fb43

Please sign in to comment.