fix(slide-toggle): invert the thumb and slide gesture in rtl (#12284)

This commit is contained in:
Kristiyan Kostadinov
2018-07-20 18:31:47 +02:00
committed by Joey Perrott
parent f9d37571ce
commit 9a191b344d
4 changed files with 74 additions and 6 deletions
+1
View File
@@ -11,6 +11,7 @@ ng_module(
deps = [
"//src/lib/core",
"//src/cdk/a11y",
"//src/cdk/bidi",
"//src/cdk/coercion",
"//src/cdk/observers",
"//src/cdk/platform",
+17 -1
View File
@@ -33,6 +33,10 @@ $mat-slide-toggle-bar-track-width: $mat-slide-toggle-bar-width - $mat-slide-togg
&.mat-checked {
.mat-slide-toggle-thumb-container {
transform: translate3d($mat-slide-toggle-bar-track-width, 0, 0);
[dir='rtl'] & {
transform: translate3d(-$mat-slide-toggle-bar-track-width, 0, 0);
}
}
}
@@ -115,6 +119,11 @@ $mat-slide-toggle-bar-track-width: $mat-slide-toggle-bar-width - $mat-slide-togg
._mat-animation-noopable & {
transition: none;
}
[dir='rtl'] & {
left: auto;
right: 0;
}
}
// The visual thumb element that moves inside of the thumb bar.
@@ -147,8 +156,15 @@ $mat-slide-toggle-bar-track-width: $mat-slide-toggle-bar-width - $mat-slide-togg
.mat-slide-toggle-input {
// Move the input to the bottom and in the middle of the thumb.
// Visual improvement to properly show browser popups when being required.
$horizontal-offset: $mat-slide-toggle-thumb-size / 2;
bottom: 0;
left: $mat-slide-toggle-thumb-size / 2;
left: $horizontal-offset;
[dir='rtl'] & {
left: auto;
right: $horizontal-offset;
}
}
.mat-slide-toggle-bar,
+50 -2
View File
@@ -5,6 +5,7 @@ import {ComponentFixture, fakeAsync, flushMicrotasks, TestBed, tick} from '@angu
import {FormControl, FormsModule, NgModel, ReactiveFormsModule} from '@angular/forms';
import {defaultRippleAnimationConfig} from '@angular/material/core';
import {By, HAMMER_GESTURE_CONFIG} from '@angular/platform-browser';
import {BidiModule, Direction} from '@angular/cdk/bidi';
import {TestGestureConfig} from '../slider/test-gesture-config';
import {MAT_SLIDE_TOGGLE_DEFAULT_OPTIONS} from './slide-toggle-config';
import {MatSlideToggle, MatSlideToggleChange, MatSlideToggleModule} from './index';
@@ -18,7 +19,7 @@ describe('MatSlideToggle without forms', () => {
mutationObserverCallbacks = [];
TestBed.configureTestingModule({
imports: [MatSlideToggleModule],
imports: [MatSlideToggleModule, BidiModule],
declarations: [
SlideToggleBasic,
SlideToggleWithTabindexAttr,
@@ -493,6 +494,29 @@ describe('MatSlideToggle without forms', () => {
expect(slideThumbContainer.classList).not.toContain('mat-dragging');
}));
it('should drag from start to end in RTL', fakeAsync(() => {
testComponent.direction = 'rtl';
fixture.detectChanges();
expect(slideToggle.checked).toBe(false);
gestureConfig.emitEventForElement('slidestart', slideThumbContainer);
expect(slideThumbContainer.classList).toContain('mat-dragging');
gestureConfig.emitEventForElement('slide', slideThumbContainer, {
deltaX: -200 // Arbitrary, large delta that will be clamped to the end of the slide-toggle.
});
gestureConfig.emitEventForElement('slideend', slideThumbContainer);
// Flush the timeout for the slide ending.
tick();
expect(slideToggle.checked).toBe(true);
expect(slideThumbContainer.classList).not.toContain('mat-dragging');
}));
it('should drag from end to start', fakeAsync(() => {
slideToggle.checked = true;
@@ -513,6 +537,29 @@ describe('MatSlideToggle without forms', () => {
expect(slideThumbContainer.classList).not.toContain('mat-dragging');
}));
it('should drag from end to start in RTL', fakeAsync(() => {
testComponent.direction = 'rtl';
fixture.detectChanges();
slideToggle.checked = true;
gestureConfig.emitEventForElement('slidestart', slideThumbContainer);
expect(slideThumbContainer.classList).toContain('mat-dragging');
gestureConfig.emitEventForElement('slide', slideThumbContainer, {
deltaX: 200 // Arbitrary, large delta that will be clamped to the end of the slide-toggle.
});
gestureConfig.emitEventForElement('slideend', slideThumbContainer);
// Flush the timeout for the slide ending.
tick();
expect(slideToggle.checked).toBe(false);
expect(slideThumbContainer.classList).not.toContain('mat-dragging');
}));
it('should not drag when disabled', fakeAsync(() => {
slideToggle.disabled = true;
@@ -943,7 +990,7 @@ describe('MatSlideToggle with forms', () => {
@Component({
template: `
<mat-slide-toggle [required]="isRequired"
<mat-slide-toggle [dir]="direction" [required]="isRequired"
[disabled]="isDisabled"
[color]="slideColor"
[id]="slideId"
@@ -976,6 +1023,7 @@ class SlideToggleBasic {
labelPosition: string;
toggleTriggered: number = 0;
dragTriggered: number = 0;
direction: Direction = 'ltr';
onSlideClick: (event?: Event) => void = () => {};
onSlideChange = (event: MatSlideToggleChange) => this.lastEvent = event;
+6 -3
View File
@@ -7,6 +7,7 @@
*/
import {FocusMonitor, FocusOrigin} from '@angular/cdk/a11y';
import {Directionality} from '@angular/cdk/bidi';
import {coerceBooleanProperty} from '@angular/cdk/coercion';
import {Platform} from '@angular/cdk/platform';
import {
@@ -193,7 +194,8 @@ export class MatSlideToggle extends _MatSlideToggleMixinBase implements OnDestro
private _ngZone: NgZone,
@Inject(MAT_SLIDE_TOGGLE_DEFAULT_OPTIONS)
public defaults: MatSlideToggleDefaultOptions,
@Optional() @Inject(ANIMATION_MODULE_TYPE) public _animationMode?: string) {
@Optional() @Inject(ANIMATION_MODULE_TYPE) public _animationMode?: string,
@Optional() private _dir?: Directionality) {
super(elementRef);
this.tabIndex = parseInt(tabIndex) || 0;
}
@@ -330,9 +332,10 @@ export class MatSlideToggle extends _MatSlideToggleMixinBase implements OnDestro
_onDrag(event: HammerInput) {
if (this._dragging) {
this._dragPercentage = this._getDragPercentage(event.deltaX);
const direction = this._dir && this._dir.value === 'rtl' ? -1 : 1;
this._dragPercentage = this._getDragPercentage(event.deltaX * direction);
// Calculate the moved distance based on the thumb bar width.
const dragX = (this._dragPercentage / 100) * this._thumbBarWidth;
const dragX = (this._dragPercentage / 100) * this._thumbBarWidth * direction;
this._thumbEl.nativeElement.style.transform = `translate3d(${dragX}px, 0, 0)`;
}
}