diff --git a/chips/action/lib/action.ts b/chips/action/lib/action.ts index d64d3e9413..69912aa16f 100644 --- a/chips/action/lib/action.ts +++ b/chips/action/lib/action.ts @@ -96,12 +96,12 @@ export abstract class Action extends ActionElement { } protected handlePointerEnter(e: PointerEvent) { - this.ripple?.beginHover(e); + this.ripple?.handlePointerenter(e); } override handlePointerLeave(e: PointerEvent) { super.handlePointerLeave(e); - this.ripple?.endHover(); + this.ripple?.handlePointerleave(e); } override handlePointerDown(e: PointerEvent) { diff --git a/navigationtab/lib/navigation-tab.ts b/navigationtab/lib/navigation-tab.ts index fbfecf6c23..5885e70f74 100644 --- a/navigationtab/lib/navigation-tab.ts +++ b/navigationtab/lib/navigation-tab.ts @@ -153,12 +153,12 @@ export class NavigationTab extends ActionElement implements NavigationTabState { } protected handlePointerEnter(e: PointerEvent) { - this.ripple.beginHover(e); + this.ripple.handlePointerenter(e); } override handlePointerLeave(e: PointerEvent) { super.handlePointerLeave(e); - this.ripple.endHover(); + this.ripple.handlePointerleave(e); } protected handleFocus() { diff --git a/ripple/directive.ts b/ripple/directive.ts index f8a25b9285..297c831592 100644 --- a/ripple/directive.ts +++ b/ripple/directive.ts @@ -108,7 +108,7 @@ class RippleDirective extends Directive { this.pointerDown(ripple, event as PointerEvent); break; case 'pointerenter': - this.pointerEnter(ripple, event as PointerEvent); + ripple.handlePointerenter(event as PointerEvent); break; case 'pointerleave': this.pointerLeave(ripple, event as PointerEvent); @@ -266,15 +266,9 @@ class RippleDirective extends Directive { } } - private pointerEnter(ripple: Ripple, ev: PointerEvent) { - if (this.shouldReactToEvent(ripple, ev, true)) { - ripple.beginHover(ev); - } - } - private pointerLeave(ripple: Ripple, ev: PointerEvent) { if (this.shouldReactToEvent(ripple, ev, true)) { - ripple.endHover(); + ripple.handlePointerleave(ev); // release a held mouse or pen press that moves outside the element if (!this.isTouch(ev) && this.state !== State.INACTIVE) { this.endPress(ripple); @@ -291,4 +285,4 @@ class RippleDirective extends Directive { * keyboard interaction, pass `true` to enable press animations on Enter or * Spacebar */ -export const ripple = directive(RippleDirective); \ No newline at end of file +export const ripple = directive(RippleDirective); diff --git a/ripple/lib/ripple.ts b/ripple/lib/ripple.ts index 36dac1ed94..8514b41ad7 100644 --- a/ripple/lib/ripple.ts +++ b/ripple/lib/ripple.ts @@ -47,13 +47,19 @@ export class Ripple extends LitElement { private growAnimation?: Animation; private delayedEndPressHandle?: number; - beginHover(hoverEvent?: Event) { - if ((hoverEvent as PointerEvent)?.pointerType !== 'touch') { - this.hovered = true; + handlePointerenter(event: PointerEvent) { + if (this.isTouch(event) || !this.shouldReactToEvent(event)) { + return; } + + this.hovered = true; } - endHover() { + handlePointerleave(event: PointerEvent) { + if (!this.shouldReactToEvent(event)) { + return; + } + this.hovered = false; } @@ -95,7 +101,7 @@ export class Ripple extends LitElement { protected override update(changedProps: PropertyValues) { if (changedProps.has('disabled') && this.disabled) { - this.endHover(); + this.hovered = false; this.endFocus(); this.endPress(); } @@ -192,4 +198,17 @@ export class Ripple extends LitElement { fill: ANIMATION_FILL }); } + + /** + * Returns `true` if + * - the ripple element is enabled + * - the pointer is primary for the input type + */ + private shouldReactToEvent(event: PointerEvent) { + return !this.disabled && event.isPrimary; + } + + private isTouch({pointerType}: PointerEvent) { + return pointerType === 'touch'; + } } diff --git a/ripple/lib/ripple_test.ts b/ripple/lib/ripple_test.ts index b7fc2e6412..76ff350dd0 100644 --- a/ripple/lib/ripple_test.ts +++ b/ripple/lib/ripple_test.ts @@ -77,24 +77,28 @@ describe('ripple', () => { expect(surface).not.toHaveClass(RippleStateClasses.FOCUSED); }); - it('sets hover class on beginHover()', async () => { - element.beginHover(); + it('sets hover class on handlePointerenter()', async () => { + element.handlePointerenter( + new PointerEvent('pointerenter', {isPrimary: true})); await element.updateComplete; expect(surface).toHaveClass(RippleStateClasses.HOVERED); }); - it('removes hover class on endHover()', async () => { - element.beginHover(); + it('removes hover class on handlePointerleave()', async () => { + element.handlePointerenter( + new PointerEvent('pointerenter', {isPrimary: true})); await element.updateComplete; - element.endHover(); + element.handlePointerleave( + new PointerEvent('pointerleave', {isPrimary: true})); await element.updateComplete; expect(surface).not.toHaveClass(RippleStateClasses.HOVERED); }); it('stops hovering when disabled', async () => { - element.beginHover(); + element.handlePointerenter( + new PointerEvent('pointerenter', {isPrimary: true})); await element.updateComplete; element.disabled = true; await element.updateComplete; diff --git a/segmentedbutton/lib/segmented-button.ts b/segmentedbutton/lib/segmented-button.ts index 086478f50f..73e2e423fa 100644 --- a/segmentedbutton/lib/segmented-button.ts +++ b/segmentedbutton/lib/segmented-button.ts @@ -91,12 +91,12 @@ export class SegmentedButton extends ActionElement { } protected handlePointerEnter(e: PointerEvent) { - this.ripple.beginHover(e); + this.ripple.handlePointerenter(e); } override handlePointerLeave(e: PointerEvent) { super.handlePointerLeave(e); - this.ripple.endHover(); + this.ripple.handlePointerleave(e); } protected handleFocus() { diff --git a/slider/lib/slider.ts b/slider/lib/slider.ts index 2367164b27..c822a70a2c 100644 --- a/slider/lib/slider.ts +++ b/slider/lib/slider.ts @@ -347,13 +347,13 @@ export class Slider extends LitElement { }; return html` -
${when(this.allowRange, () => this.renderInput(inputAProps))} ${this.renderInput(inputBProps)} - ${this.renderTrack()} + ${this.renderTrack()}
@@ -416,7 +416,7 @@ export class Slider extends LitElement { this.allowRange ? (lesser ? 'Lesser' : 'Greater') : ''}">
${when(this.withLabel, () => this.renderLabel(label))} - + ${when(showRipple, () => this.renderRipple(id))} ${when(focusRequested, () => this.renderFocusRing(showFocus))} @@ -440,16 +440,16 @@ export class Slider extends LitElement { })}" @focus=${this.handleFocus} @blur=${this.handleBlur} - @pointerdown=${this.handleDown} - @pointerup=${this.handleUp} + @pointerdown=${this.handleDown} + @pointerup=${this.handleUp} @pointerenter=${this.handleEnter} @pointermove=${this.handleMove} @pointerleave=${this.handleLeave} - @input=${this.handleInput} + @input=${this.handleInput} @change=${this.handleChange} .disabled=${this.disabled} - .min=${String(this.min)} - .max=${String(this.max)} + .min=${String(this.min)} + .max=${String(this.max)} .step=${String(this.step)} .value=${String(value)} .tabIndex=${lesser ? 1 : 0} @@ -484,10 +484,13 @@ export class Slider extends LitElement { if (!rippleEl) { return; } + // TODO(b/269799771): improve slider ripple connection if (hovering) { - rippleEl.beginHover(); + rippleEl.handlePointerenter( + new PointerEvent('pointerenter', {isPrimary: true})); } else { - rippleEl.endHover(); + rippleEl.handlePointerleave( + new PointerEvent('pointerleave', {isPrimary: true})); } }