Skip to content

Commit

Permalink
fix(checkbox): Disable transitions when using mdc-checkbox-anim* clas…
Browse files Browse the repository at this point in the history
…ses (#285)

- Adds a mdc-checkbox--upgraded mod class which is attached by the
  foundation when a JS checkbox is used.
- Disables all transitions when the animation classes are used. Fixes an
  issue in Safari where the the paint/compositing looked janky/broken
  due to animations and transitions conflicting with one another.
- (tech debt) Removed template strings from cssClasses object. This will
  be required in order for our internal infra to work correctly.

Fixes #205
  • Loading branch information
traviskaufman committed Feb 13, 2017
1 parent fd0ac4e commit 3effc35
Show file tree
Hide file tree
Showing 4 changed files with 40 additions and 16 deletions.
20 changes: 10 additions & 10 deletions packages/mdc-checkbox/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,18 @@
*/

const ROOT = 'mdc-checkbox';
const ANIM = `${ROOT}--anim`;

export const cssClasses = {
ROOT,
CHECKED: `${ROOT}--checked`,
INDETERMINATE: `${ROOT}--indeterminate`,
ANIM_UNCHECKED_CHECKED: `${ANIM}-unchecked-checked`,
ANIM_UNCHECKED_INDETERMINATE: `${ANIM}-unchecked-indeterminate`,
ANIM_CHECKED_UNCHECKED: `${ANIM}-checked-unchecked`,
ANIM_CHECKED_INDETERMINATE: `${ANIM}-checked-indeterminate`,
ANIM_INDETERMINATE_CHECKED: `${ANIM}-indeterminate-checked`,
ANIM_INDETERMINATE_UNCHECKED: `${ANIM}-indeterminate-unchecked`,
ROOT: 'mdc-checkbox',
UPGRADED: 'mdc-checkbox--upgraded',
CHECKED: 'mdc-checkbox--checked',
INDETERMINATE: 'mdc-checkbox--indeterminate',
ANIM_UNCHECKED_CHECKED: 'mdc-checkbox--anim-unchecked-checked',
ANIM_UNCHECKED_INDETERMINATE: 'mdc-checkbox--anim-unchecked-indeterminate',
ANIM_CHECKED_UNCHECKED: 'mdc-checkbox--anim-checked-unchecked',
ANIM_CHECKED_INDETERMINATE: 'mdc-checkbox--anim-checked-indeterminate',
ANIM_INDETERMINATE_CHECKED: 'mdc-checkbox--anim-indeterminate-checked',
ANIM_INDETERMINATE_UNCHECKED: 'mdc-checkbox--anim-indeterminate-unchecked',
};

export const strings = {
Expand Down
1 change: 1 addition & 0 deletions packages/mdc-checkbox/foundation.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ export default class MDCCheckboxFoundation extends MDCFoundation {
}

init() {
this.adapter_.addClass(cssClasses.UPGRADED);
this.adapter_.registerChangeHandler(this.changeHandler_);
this.installPropertyChangeHooks_();
}
Expand Down
21 changes: 17 additions & 4 deletions packages/mdc-checkbox/mdc-checkbox.scss
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
//
//
// Copyright 2016 Google Inc. All Rights Reserved.
//
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//
// http://www.apache.org/licenses/LICENSE-2.0
//
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
Expand Down Expand Up @@ -235,6 +235,19 @@ fieldset:disabled .mdc-checkbox__native-control,
}
}

.mdc-checkbox--upgraded {
.mdc-checkbox__background,
.mdc-checkbox__checkmark,
.mdc-checkbox__checkmark__path,
.mdc-checkbox__mixedmark {
// Due to the myriad of selector combos used to properly style a CSS-only checkbox, all of
// which have varying selector precedence and make use of transitions, it is cleaner and more
// efficient here to simply use !important, since the mdc-checkbox--anim-* classes will take
// over from here.
transition: none !important;
}
}

.mdc-checkbox--anim {
$_mdc-checkbox-indeterminate-change-duration: 500ms;

Expand Down
14 changes: 12 additions & 2 deletions test/unit/mdc-checkbox/foundation.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,14 @@ test('defaultAdapter returns a complete adapter implementation', (t) => {
t.end();
});

test('#init adds the upgraded class to the root element', (t) => {
const {foundation, mockAdapter} = setupTest();

foundation.init();
t.doesNotThrow(() => td.verify(mockAdapter.addClass(cssClasses.UPGRADED)));
t.end();
});

test('#init calls adapter.registerChangeHandler() with a change handler function', (t) => {
const {foundation, mockAdapter} = setupTest();
const {isA} = td.matchers;
Expand Down Expand Up @@ -406,19 +414,21 @@ test('change handler triggers layout for changes within the same frame to correc

test('change handler does not add animation classes when isAttachedToDOM() is falsy', (t) => {
const {mockAdapter, change} = setupChangeHandlerTest();
const animClassArg = td.matchers.argThat((cls) => cls.indexOf('mdc-checkbox--anim') >= 0);
td.when(mockAdapter.isAttachedToDOM()).thenReturn(false);

change({checked: true, indeterminate: false});
t.doesNotThrow(() => td.verify(mockAdapter.addClass(td.matchers.anything()), {times: 0}));
t.doesNotThrow(() => td.verify(mockAdapter.addClass(animClassArg), {times: 0}));

t.end();
});

test('change handler does not add animation classes for bogus changes (init -> unchecked)', (t) => {
const {mockAdapter, change} = setupChangeHandlerTest();
const animClassArg = td.matchers.argThat((cls) => cls.indexOf('mdc-checkbox--anim') >= 0);

change({checked: false, indeterminate: false});
t.doesNotThrow(() => td.verify(mockAdapter.addClass(td.matchers.anything()), {times: 0}));
t.doesNotThrow(() => td.verify(mockAdapter.addClass(animClassArg), {times: 0}));
t.end();
});

Expand Down

0 comments on commit 3effc35

Please sign in to comment.