Skip to content

Commit 7209236

Browse files
fix(tab): replace ripple_directive with lazy ripple
PiperOrigin-RevId: 343978924
1 parent e85aa60 commit 7209236

File tree

3 files changed

+94
-215
lines changed

3 files changed

+94
-215
lines changed

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,11 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
66

77
## Unreleased
88

9+
### Changed
10+
11+
- `ripple_directive`
12+
- Remove in favor of `mwc-ripple`
13+
914
### Added
1015

1116
- `button`

packages/ripple/ripple-directive.ts

Lines changed: 0 additions & 202 deletions
This file was deleted.

packages/tab/mwc-tab-base.ts

Lines changed: 89 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,17 @@ limitations under the License.
1616
*/
1717
// Make TypeScript not remove the import.
1818
import '@material/mwc-tab-indicator';
19+
import '@material/mwc-ripple';
20+
1921

2022
import {addHasRemoveClass, BaseElement} from '@material/mwc-base/base-element';
2123
import {observer} from '@material/mwc-base/observer';
22-
import {ripple} from '@material/mwc-ripple/ripple-directive';
24+
import {Ripple} from '@material/mwc-ripple/mwc-ripple';
25+
import {RippleHandlers} from '@material/mwc-ripple/ripple-handlers';
2326
import {TabIndicator} from '@material/mwc-tab-indicator';
2427
import {MDCTabAdapter} from '@material/tab/adapter';
2528
import MDCTabFoundation from '@material/tab/foundation';
26-
import {html, property, query} from 'lit-element';
29+
import {eventOptions, html, internalProperty, property, query, queryAsync} from 'lit-element';
2730
import {classMap} from 'lit-html/directives/class-map';
2831

2932
export interface TabInteractionEventDetail {
@@ -83,9 +86,11 @@ export class TabBase extends BaseElement {
8386

8487
@query('.mdc-tab__content') private _contentElement!: HTMLElement;
8588

86-
private _handleClick() {
87-
this.mdcFoundation.handleClick();
88-
}
89+
@internalProperty() protected shouldRenderRipple = false;
90+
91+
@queryAsync('mwc-ripple') ripple!: Promise<Ripple|null>;
92+
93+
private rippleElement: Ripple|null = null;
8994

9095
protected createRenderRoot() {
9196
return this.attachShadow({mode: 'open', delegatesFocus: true});
@@ -123,25 +128,28 @@ export class TabBase extends BaseElement {
123128
<span class="mdc-tab__text-label">${this.label}</span>`;
124129
}
125130

126-
const rippleDirective = ripple({
127-
interactionNode: this,
128-
unbounded: false,
129-
});
130-
131131
return html`
132132
<button
133-
@click="${this._handleClick}"
133+
@click="${this.handleClick}"
134134
class="mdc-tab ${classMap(classes)}"
135135
role="tab"
136136
aria-selected="false"
137-
tabindex="-1">
137+
tabindex="-1"
138+
@focus="${this.focus}"
139+
@blur="${this.handleBlur}"
140+
@mousedown="${this.handleRippleMouseDown}"
141+
@mouseenter="${this.handleRippleMouseEnter}"
142+
@mouseleave="${this.handleRippleMouseLeave}"
143+
@touchstart="${this.handleRippleTouchStart}"
144+
@touchend="${this.handleRippleDeactivate}"
145+
@touchcancel="${this.handleRippleDeactivate}">
138146
<span class="mdc-tab__content">
139147
${iconTemplate}
140148
${labelTemplate}
141149
${this.isMinWidthIndicator ? this.renderIndicator() : ''}
142150
</span>
143151
${this.isMinWidthIndicator ? '' : this.renderIndicator()}
144-
<span class="mdc-tab__ripple" .ripple="${rippleDirective}"></span>
152+
${this.renderRipple()}
145153
</button>`;
146154
}
147155

@@ -151,6 +159,14 @@ export class TabBase extends BaseElement {
151159
.fade="${this.isFadingIndicator}"></mwc-tab-indicator>`;
152160
}
153161

162+
// TODO(dfreedm): Make this use selected as a param after Polymer/internal#739
163+
/** @soyCompatible */
164+
protected renderRipple() {
165+
return this.shouldRenderRipple ? html`
166+
<mwc-ripple primary></mwc-ripple>
167+
` :
168+
'';
169+
}
154170

155171
protected createAdapter(): MDCTabAdapter {
156172
return {
@@ -221,5 +237,65 @@ export class TabBase extends BaseElement {
221237
// NOTE: needed only for ShadyDOM where delegatesFocus is not implemented
222238
focus() {
223239
this.mdcRoot.focus();
240+
this.handleFocus();
241+
}
242+
243+
protected rippleHandlers: RippleHandlers = new RippleHandlers(() => {
244+
this.shouldRenderRipple = true;
245+
this.ripple.then((v) => this.rippleElement = v);
246+
return this.ripple;
247+
});
248+
249+
private handleClick() {
250+
this.handleFocus();
251+
this.mdcFoundation.handleClick();
252+
}
253+
254+
private handleFocus() {
255+
this.handleRippleFocus();
256+
}
257+
258+
private handleBlur() {
259+
this.handleRippleBlur();
260+
}
261+
262+
protected handleRippleMouseDown(event: Event) {
263+
const onUp = () => {
264+
window.removeEventListener('mouseup', onUp);
265+
266+
this.handleRippleDeactivate();
267+
};
268+
269+
window.addEventListener('mouseup', onUp);
270+
this.rippleHandlers.startPress(event);
271+
}
272+
273+
@eventOptions({passive: true})
274+
protected handleRippleTouchStart(event: Event) {
275+
this.rippleHandlers.startPress(event);
276+
}
277+
278+
protected handleRippleDeactivate() {
279+
this.rippleHandlers.endPress();
280+
}
281+
282+
protected handleRippleMouseEnter() {
283+
this.rippleHandlers.startHover();
284+
}
285+
286+
protected handleRippleMouseLeave() {
287+
this.rippleHandlers.endHover();
288+
}
289+
290+
protected handleRippleFocus() {
291+
this.rippleHandlers.startFocus();
292+
}
293+
294+
protected handleRippleBlur() {
295+
this.rippleHandlers.endFocus();
296+
}
297+
298+
get isRippleActive() {
299+
return this.rippleElement?.isActive || false;
224300
}
225301
}

0 commit comments

Comments
 (0)