Skip to content
This repository was archived by the owner on Jan 13, 2025. It is now read-only.

Commit c8af69b

Browse files
authored
feat(tab-indicator): Remove transitionend event handling (#3337)
BREAKING CHANGE: Removes handleTransitionEnd foundation API. Removes [de]registerEventHandler adapter APIs.
1 parent 1245573 commit c8af69b

File tree

12 files changed

+26
-207
lines changed

12 files changed

+26
-207
lines changed

packages/mdc-tab-indicator/README.md

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -146,8 +146,6 @@ Method Signature | Description
146146
--- | ---
147147
`addClass(className: string) => void` | Adds a class to the root element.
148148
`removeClass(className: string) => void` | Removes a class from the root element.
149-
`registerEventHandler(evtType: string, handler: EventListener) => void` | Registers an event listener on the root element.
150-
`deregisterEventHandler(evtType: string, handler: EventListener) => void` | Deregisters an event listener on the root element.
151149
`setContentStyleProp(property: string, value: string) => void` | Sets the style property of the content element.
152150
`computeContentClientRect() => ClientRect` | Returns the content element's bounding client rect.
153151

packages/mdc-tab-indicator/adapter.js

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -28,20 +28,6 @@
2828
* @record
2929
*/
3030
class MDCTabIndicatorAdapter {
31-
/**
32-
* Registers an event listener on the root element for a given event.
33-
* @param {string} evtType
34-
* @param {function(!Event): undefined} handler
35-
*/
36-
registerEventHandler(evtType, handler) {}
37-
38-
/**
39-
* Deregisters an event listener on the root element for a given event.
40-
* @param {string} evtType
41-
* @param {function(!Event): undefined} handler
42-
*/
43-
deregisterEventHandler(evtType, handler) {}
44-
4531
/**
4632
* Adds the given className to the root element.
4733
* @param {string} className The className to add

packages/mdc-tab-indicator/constants.js

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,7 @@
1919
const cssClasses = {
2020
ACTIVE: 'mdc-tab-indicator--active',
2121
FADE: 'mdc-tab-indicator--fade',
22-
FADING_ACTIVATE: 'mdc-tab-indicator--fading-activate',
23-
FADING_DEACTIVATE: 'mdc-tab-indicator--fading-deactivate',
24-
SLIDING_ACTIVATE: 'mdc-tab-indicator--sliding-activate',
22+
NO_TRANSITION: 'mdc-tab-indicator--no-transition',
2523
};
2624

2725
/** @enum {string} */

packages/mdc-tab-indicator/fading-foundation.js

Lines changed: 0 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -22,30 +22,11 @@ import MDCTabIndicatorFoundation from './foundation';
2222
* @final
2323
*/
2424
class MDCFadingTabIndicatorFoundation extends MDCTabIndicatorFoundation {
25-
/** @param {...?} args */
26-
constructor(...args) {
27-
super(...args);
28-
29-
/** @private {function(?Event): undefined} */
30-
this.handleTransitionEnd_ = () => this.handleTransitionEnd();
31-
}
32-
33-
/** Handles the transitionend event */
34-
handleTransitionEnd() {
35-
this.adapter_.deregisterEventHandler('transitionend', this.handleTransitionEnd_);
36-
this.adapter_.removeClass(MDCTabIndicatorFoundation.cssClasses.FADING_ACTIVATE);
37-
this.adapter_.removeClass(MDCTabIndicatorFoundation.cssClasses.FADING_DEACTIVATE);
38-
}
39-
4025
activate() {
41-
this.adapter_.registerEventHandler('transitionend', this.handleTransitionEnd_);
42-
this.adapter_.addClass(MDCTabIndicatorFoundation.cssClasses.FADING_ACTIVATE);
4326
this.adapter_.addClass(MDCTabIndicatorFoundation.cssClasses.ACTIVE);
4427
}
4528

4629
deactivate() {
47-
this.adapter_.registerEventHandler('transitionend', this.handleTransitionEnd_);
48-
this.adapter_.addClass(MDCTabIndicatorFoundation.cssClasses.FADING_DEACTIVATE);
4930
this.adapter_.removeClass(MDCTabIndicatorFoundation.cssClasses.ACTIVE);
5031
}
5132
}

packages/mdc-tab-indicator/foundation.js

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,6 @@ class MDCTabIndicatorFoundation extends MDCFoundation {
4343
*/
4444
static get defaultAdapter() {
4545
return /** @type {!MDCTabIndicatorAdapter} */ ({
46-
registerEventHandler: () => {},
47-
deregisterEventHandler: () => {},
4846
addClass: () => {},
4947
removeClass: () => {},
5048
computeContentClientRect: () => {},

packages/mdc-tab-indicator/index.js

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,6 @@ class MDCTabIndicator extends MDCComponent {
6161
*/
6262
getDefaultFoundation() {
6363
const adapter = /** @type {!MDCTabIndicatorAdapter} */ (Object.assign({
64-
registerEventHandler: (evtType, handler) => this.root_.addEventListener(evtType, handler),
65-
deregisterEventHandler: (evtType, handler) => this.root_.removeEventListener(evtType, handler),
6664
addClass: (className) => this.root_.classList.add(className),
6765
removeClass: (className) => this.root_.classList.remove(className),
6866
computeContentClientRect: () => this.content_.getBoundingClientRect(),

packages/mdc-tab-indicator/mdc-tab-indicator.scss

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -53,16 +53,20 @@
5353
opacity: 1;
5454
}
5555

56-
.mdc-tab-indicator--sliding-activate > .mdc-tab-indicator__content {
56+
// Slide by default
57+
.mdc-tab-indicator > .mdc-tab-indicator__content {
5758
transition: 250ms transform $mdc-animation-standard-curve-timing-function;
5859
}
5960

60-
.mdc-tab-indicator--fading-activate > .mdc-tab-indicator__content,
61-
.mdc-tab-indicator--fading-deactivate > .mdc-tab-indicator__content {
61+
// --no-transition is applied in cases where styles need to be applied immediately to set up a transition
62+
.mdc-tab-indicator--no-transition > .mdc-tab-indicator__content {
63+
transition: none;
64+
}
65+
66+
.mdc-tab-indicator--fade > .mdc-tab-indicator__content {
6267
transition: 150ms opacity linear;
6368
}
6469

65-
.mdc-tab-indicator--fading-activate > .mdc-tab-indicator__content {
70+
.mdc-tab-indicator--active.mdc-tab-indicator--fade > .mdc-tab-indicator__content {
6671
transition-delay: 100ms;
6772
}
68-

packages/mdc-tab-indicator/sliding-foundation.js

Lines changed: 6 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -22,27 +22,12 @@ import MDCTabIndicatorFoundation from './foundation';
2222
* @final
2323
*/
2424
class MDCSlidingTabIndicatorFoundation extends MDCTabIndicatorFoundation {
25-
/** @param {...?} args */
26-
constructor(...args) {
27-
super(...args);
28-
29-
/** @private {function(?Event): undefined} */
30-
this.handleTransitionEnd_ = () => this.handleTransitionEnd();
31-
}
32-
33-
/** Handles the transitionend event */
34-
handleTransitionEnd() {
35-
this.adapter_.deregisterEventHandler('transitionend', this.handleTransitionEnd_);
36-
this.adapter_.removeClass(MDCTabIndicatorFoundation.cssClasses.SLIDING_ACTIVATE);
37-
}
38-
3925
/** @param {!ClientRect=} previousIndicatorClientRect */
4026
activate(previousIndicatorClientRect) {
41-
this.adapter_.addClass(MDCTabIndicatorFoundation.cssClasses.ACTIVE);
42-
4327
// Early exit if no indicator is present to handle cases where an indicator
4428
// may be activated without a prior indicator state
4529
if (!previousIndicatorClientRect) {
30+
this.adapter_.addClass(MDCTabIndicatorFoundation.cssClasses.ACTIVE);
4631
return;
4732
}
4833

@@ -53,26 +38,19 @@ class MDCSlidingTabIndicatorFoundation extends MDCTabIndicatorFoundation {
5338
const currentClientRect = this.computeContentClientRect();
5439
const widthDelta = previousIndicatorClientRect.width / currentClientRect.width;
5540
const xPosition = previousIndicatorClientRect.left - currentClientRect.left;
41+
this.adapter_.addClass(MDCTabIndicatorFoundation.cssClasses.NO_TRANSITION);
5642
this.adapter_.setContentStyleProperty('transform', `translateX(${xPosition}px) scaleX(${widthDelta})`);
5743

58-
// Force repaint
44+
// Force repaint before updating classes and transform to ensure the transform properly takes effect
5945
this.computeContentClientRect();
6046

61-
// Add animating class and remove transformation in a new frame
62-
requestAnimationFrame(() => {
63-
this.adapter_.addClass(MDCTabIndicatorFoundation.cssClasses.SLIDING_ACTIVATE);
64-
this.adapter_.setContentStyleProperty('transform', '');
65-
});
66-
67-
this.adapter_.registerEventHandler('transitionend', this.handleTransitionEnd_);
47+
this.adapter_.removeClass(MDCTabIndicatorFoundation.cssClasses.NO_TRANSITION);
48+
this.adapter_.addClass(MDCTabIndicatorFoundation.cssClasses.ACTIVE);
49+
this.adapter_.setContentStyleProperty('transform', '');
6850
}
6951

7052
deactivate() {
7153
this.adapter_.removeClass(MDCTabIndicatorFoundation.cssClasses.ACTIVE);
72-
// We remove the animating class in deactivate in case the Tab is deactivated before the animation completes and
73-
// the "transitionend" handler isn't called.
74-
this.adapter_.removeClass(MDCTabIndicatorFoundation.cssClasses.SLIDING_ACTIVATE);
75-
this.adapter_.deregisterEventHandler('transitionend', this.handleTransitionEnd_);
7654
}
7755
}
7856

test/unit/mdc-tab-indicator/fading-foundation.test.js

Lines changed: 0 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -17,70 +17,21 @@
1717

1818
import td from 'testdouble';
1919

20-
import {captureHandlers} from '../helpers/foundation';
2120
import {setupFoundationTest} from '../helpers/setup';
2221
import MDCFadingTabIndicatorFoundation from '../../../packages/mdc-tab-indicator/fading-foundation';
2322

2423
suite('MDCFadingTabIndicatorFoundation');
2524

2625
const setupTest = () => setupFoundationTest(MDCFadingTabIndicatorFoundation);
2726

28-
test('#activate registers a transitionend handler', () => {
29-
const {foundation, mockAdapter} = setupTest();
30-
foundation.activate();
31-
td.verify(mockAdapter.registerEventHandler('transitionend', td.matchers.isA(Function)));
32-
});
33-
3427
test(`#activate adds the ${MDCFadingTabIndicatorFoundation.cssClasses.ACTIVE} class`, () => {
3528
const {foundation, mockAdapter} = setupTest();
3629
foundation.activate();
3730
td.verify(mockAdapter.addClass(MDCFadingTabIndicatorFoundation.cssClasses.ACTIVE));
3831
});
3932

40-
test(`#activate adds the ${MDCFadingTabIndicatorFoundation.cssClasses.FADING_ACTIVATE} class`, () => {
41-
const {foundation, mockAdapter} = setupTest();
42-
foundation.activate();
43-
td.verify(mockAdapter.addClass(MDCFadingTabIndicatorFoundation.cssClasses.FADING_ACTIVATE));
44-
});
45-
46-
test('#deactivate registers a transitionend handler', () => {
47-
const {foundation, mockAdapter} = setupTest();
48-
foundation.deactivate();
49-
td.verify(mockAdapter.registerEventHandler('transitionend', td.matchers.isA(Function)));
50-
});
51-
5233
test(`#deactivate removes the ${MDCFadingTabIndicatorFoundation.cssClasses.ACTIVE} class`, () => {
5334
const {foundation, mockAdapter} = setupTest();
5435
foundation.deactivate();
5536
td.verify(mockAdapter.removeClass(MDCFadingTabIndicatorFoundation.cssClasses.ACTIVE));
5637
});
57-
58-
test(`#deactivate adds the ${MDCFadingTabIndicatorFoundation.cssClasses.FADING_DEACTIVATE} class`, () => {
59-
const {foundation, mockAdapter} = setupTest();
60-
foundation.deactivate();
61-
td.verify(mockAdapter.addClass(MDCFadingTabIndicatorFoundation.cssClasses.FADING_DEACTIVATE));
62-
});
63-
64-
test('on transitionend, deregister the transitionend handler', () => {
65-
const {foundation, mockAdapter} = setupTest();
66-
const handlers = captureHandlers(mockAdapter, 'registerEventHandler');
67-
foundation.activate();
68-
handlers.transitionend();
69-
td.verify(mockAdapter.deregisterEventHandler('transitionend', td.matchers.isA(Function)));
70-
});
71-
72-
test(`on transitionend, remove the ${MDCFadingTabIndicatorFoundation.cssClasses.FADING_ACTIVATE} class`, () => {
73-
const {foundation, mockAdapter} = setupTest();
74-
const handlers = captureHandlers(mockAdapter, 'registerEventHandler');
75-
foundation.activate();
76-
handlers.transitionend();
77-
td.verify(mockAdapter.removeClass(MDCFadingTabIndicatorFoundation.cssClasses.FADING_ACTIVATE));
78-
});
79-
80-
test(`on transitionend, remove the ${MDCFadingTabIndicatorFoundation.cssClasses.FADING_DEACTIVATE} class`, () => {
81-
const {foundation, mockAdapter} = setupTest();
82-
const handlers = captureHandlers(mockAdapter, 'registerEventHandler');
83-
foundation.activate();
84-
handlers.transitionend();
85-
td.verify(mockAdapter.removeClass(MDCFadingTabIndicatorFoundation.cssClasses.FADING_DEACTIVATE));
86-
});

test/unit/mdc-tab-indicator/foundation.test.js

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@ test('exports strings', () => {
3434

3535
test('defaultAdapter returns a complete adapter implementation', () => {
3636
verifyDefaultAdapter(MDCTabIndicatorFoundation, [
37-
'registerEventHandler', 'deregisterEventHandler',
3837
'addClass', 'removeClass',
3938
'setContentStyleProperty',
4039
'computeContentClientRect',
@@ -52,13 +51,13 @@ test('#computeContentClientRect returns the client rect', () => {
5251
test('#activate is abstract and does nothing', () => {
5352
const {foundation, mockAdapter} = setupTest();
5453
foundation.activate();
55-
td.verify(mockAdapter.addClass, {times: 0});
56-
td.verify(mockAdapter.removeClass, {times: 0});
54+
td.verify(mockAdapter.addClass(td.matchers.isA(String)), {times: 0});
55+
td.verify(mockAdapter.removeClass(td.matchers.isA(String)), {times: 0});
5756
});
5857

5958
test('#deactivate is abstract and does nothing', () => {
6059
const {foundation, mockAdapter} = setupTest();
6160
foundation.deactivate();
62-
td.verify(mockAdapter.addClass, {times: 0});
63-
td.verify(mockAdapter.removeClass, {times: 0});
61+
td.verify(mockAdapter.addClass(td.matchers.isA(String)), {times: 0});
62+
td.verify(mockAdapter.removeClass(td.matchers.isA(String)), {times: 0});
6463
});

0 commit comments

Comments
 (0)