Skip to content

Commit 7cad5e1

Browse files
committed
refactor(carousel): simplify pointer/focus event handlers
1 parent 0b8f084 commit 7cad5e1

File tree

2 files changed

+28
-49
lines changed

2 files changed

+28
-49
lines changed

src/components/carousel/carousel.spec.ts

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ import {
1616
enterKey,
1717
homeKey,
1818
spaceBar,
19-
tabKey,
2019
} from '../common/controllers/key-bindings.js';
2120
import { defineComponents } from '../common/definitions/defineComponents.js';
2221
import {
@@ -713,18 +712,18 @@ describe('Carousel', () => {
713712
expect(carousel.isPaused).to.be.true;
714713
expect(divContainer.ariaLive).to.equal('polite');
715714

716-
// focus with keyboard
717-
simulateKeyboard(prevButton, tabKey);
715+
// focus a focusable element
716+
carousel.dispatchEvent(new FocusEvent('focusin'));
718717
carousel.dispatchEvent(new PointerEvent('pointerleave'));
719718
await elementUpdated(carousel);
720719

721-
// keyboard focus/interaction is present
720+
// element focus/interaction is present
722721
// -> should not start rotation on pointerleave
723722
expect(carousel.isPlaying).to.be.false;
724723
expect(carousel.isPaused).to.be.true;
725724
expect(divContainer.ariaLive).to.equal('polite');
726725

727-
// loose keyboard focus
726+
// loose focus
728727
carousel.dispatchEvent(new PointerEvent('pointerdown'));
729728
await elementUpdated(carousel);
730729

@@ -765,8 +764,8 @@ describe('Carousel', () => {
765764
expect(carousel.isPaused).to.be.true;
766765
expect(carousel.current).to.equal(0);
767766

768-
// focus on next button/focusable element
769-
nextButton.dispatchEvent(new FocusEvent('focusin', { bubbles: true }));
767+
// focus a focusable element
768+
carousel.dispatchEvent(new FocusEvent('focusin'));
770769
await elementUpdated(carousel);
771770

772771
// hover out of the carousel
@@ -781,7 +780,7 @@ describe('Carousel', () => {
781780
expect(carousel.isPaused).to.be.true;
782781
expect(carousel.current).to.equal(0);
783782

784-
nextButton.dispatchEvent(new FocusEvent('focusout', { bubbles: true }));
783+
carousel.dispatchEvent(new FocusEvent('focusout'));
785784
await elementUpdated(carousel);
786785

787786
await clock.tickAsync(200);

src/components/carousel/carousel.ts

Lines changed: 21 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -105,11 +105,11 @@ export default class IgcCarouselComponent extends EventEmitterMixin<
105105
private static readonly increment = createCounter();
106106
private readonly _carouselId = `igc-carousel-${IgcCarouselComponent.increment()}`;
107107

108+
private _paused = false;
108109
private _lastInterval!: ReturnType<typeof setInterval> | null;
109110
private _hasKeyboardInteractionOnIndicators = false;
110-
private _hasMouseStop = false;
111-
private _hasKeyboardFocus = false;
112-
private _hasMouseFocus = false;
111+
private _hasPointerInteraction = false;
112+
private _hasInnerFocus = false;
113113

114114
private _context = new ContextProvider(this, {
115115
context: carouselContext,
@@ -152,9 +152,6 @@ export default class IgcCarouselComponent extends EventEmitterMixin<
152152
@state()
153153
private _playing = false;
154154

155-
@state()
156-
private _paused = false;
157-
158155
private _observerCallback({
159156
changes: { added, attributes },
160157
}: MutationControllerParams<IgcCarouselSlideComponent>) {
@@ -330,14 +327,13 @@ export default class IgcCarouselComponent extends EventEmitterMixin<
330327

331328
addThemingController(this, all);
332329

333-
addSafeEventListener(this, 'pointerenter', this.handlePointerEnter);
334-
addSafeEventListener(this, 'pointerleave', this.handlePointerLeave);
330+
addSafeEventListener(this, 'pointerenter', this.handlePointerInteraction);
331+
addSafeEventListener(this, 'pointerleave', this.handlePointerInteraction);
335332
addSafeEventListener(this, 'pointerdown', () => {
336-
this._hasKeyboardFocus = false;
337-
});
338-
addSafeEventListener(this, 'keyup', () => {
339-
this._hasKeyboardFocus = true;
333+
this._hasInnerFocus = false;
340334
});
335+
addSafeEventListener(this, 'focusin', this.handleFocusInteraction);
336+
addSafeEventListener(this, 'focusout', this.handleFocusInteraction);
341337

342338
addGesturesController(this, {
343339
ref: this._carouselSlidesContainerRef,
@@ -390,43 +386,27 @@ export default class IgcCarouselComponent extends EventEmitterMixin<
390386
this.requestUpdate();
391387
}
392388

393-
private handlePointerEnter(): void {
394-
this._hasMouseStop = true;
395-
if (this._hasKeyboardFocus || this._hasMouseFocus) {
396-
return;
397-
}
398-
this.handlePauseOnInteraction();
399-
}
400-
401-
private handlePointerLeave(): void {
402-
this._hasMouseStop = false;
403-
if (this._hasKeyboardFocus || this._hasMouseFocus) {
404-
return;
405-
}
406-
this.handlePauseOnInteraction();
407-
}
389+
private handlePointerInteraction(event: PointerEvent): void {
390+
this._hasPointerInteraction = event.type === 'pointerenter';
408391

409-
private handleFocusIn(): void {
410-
if (this._hasKeyboardFocus || this._hasMouseStop || this._hasMouseFocus) {
411-
this._hasMouseFocus = !this._hasKeyboardFocus && this._hasMouseStop;
412-
return;
392+
if (!this._hasInnerFocus) {
393+
this.handlePauseOnInteraction();
413394
}
414-
this.handlePauseOnInteraction();
415395
}
416396

417-
private handleFocusOut(event: FocusEvent): void {
397+
private handleFocusInteraction(event: FocusEvent): void {
398+
// focusin - element that lost focus
399+
// focusout - element that gained focus
418400
const node = event.relatedTarget as Node;
419401

420-
if (this.contains(node) || this.renderRoot.contains(node)) {
402+
if (this.contains(node)) {
421403
return;
422404
}
423405

424-
if (this._hasKeyboardFocus || this._hasMouseFocus) {
425-
this._hasKeyboardFocus = this._hasMouseFocus = false;
406+
this._hasInnerFocus = event.type === 'focusin';
426407

427-
if (!this._hasMouseStop) {
428-
this.handlePauseOnInteraction();
429-
}
408+
if (!this._hasPointerInteraction) {
409+
this.handlePauseOnInteraction();
430410
}
431411
}
432412

@@ -791,7 +771,7 @@ export default class IgcCarouselComponent extends EventEmitterMixin<
791771

792772
protected override render() {
793773
return html`
794-
<section @focusin=${this.handleFocusIn} @focusout=${this.handleFocusOut}>
774+
<section>
795775
${this.hideNavigation ? nothing : this.navigationTemplate()}
796776
${this.hideIndicators || this.showIndicatorsLabel
797777
? nothing
@@ -802,7 +782,7 @@ export default class IgcCarouselComponent extends EventEmitterMixin<
802782
<div
803783
${ref(this._carouselSlidesContainerRef)}
804784
id=${this._carouselId}
805-
aria-live=${this.interval && this.isPlaying ? 'off' : 'polite'}
785+
aria-live=${this.interval && this._playing ? 'off' : 'polite'}
806786
>
807787
<slot @slotchange=${this.handleSlotChange}></slot>
808788
</div>

0 commit comments

Comments
 (0)