Skip to content

Commit

Permalink
Differentiate sliders focused via keyboard vs other means
Browse files Browse the repository at this point in the history
  • Loading branch information
mmalerba committed Mar 7, 2017
1 parent 8b2ae0d commit dd93237
Show file tree
Hide file tree
Showing 6 changed files with 110 additions and 96 deletions.
16 changes: 13 additions & 3 deletions src/lib/slider/_slider-theme.scss
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
$mat-slider-disabled-color: rgba(black, 0.26);
$mat-slider-labeled-min-value-thumb-color: black;
$mat-slider-labeled-min-value-thumb-label-color: rgba(black, 0.26);
$mat-slider-focus-ring-color: rgba(mat-color($accent), 0.2);
$mat-slider-focus-ring-min-value-color: rgba(black, 0.12);

.mat-slider-track-background {
background-color: $mat-slider-off-color;
Expand All @@ -19,6 +21,10 @@
background-color: mat-color($accent);
}

.mat-slider-focus-ring {
background-color: $mat-slider-focus-ring-color;
}

.mat-slider-thumb {
background-color: mat-color($accent);
}
Expand All @@ -32,7 +38,7 @@
}

.mat-slider:hover,
.mat-slider-active {
.cdk-focused {
.mat-slider-track-background {
background-color: $mat-slider-off-focused-color;
}
Expand All @@ -53,13 +59,17 @@
}

.mat-slider-min-value {
.mat-slider-focus-ring {
background-color: $mat-slider-focus-ring-min-value-color;
}

&.mat-slider-thumb-label-showing {
.mat-slider-thumb,
.mat-slider-thumb-label {
background-color: $mat-slider-labeled-min-value-thumb-color;
}

&.mat-slider-active {
&.cdk-focused {
.mat-slider-thumb,
.mat-slider-thumb-label {
background-color: $mat-slider-labeled-min-value-thumb-label-color;
Expand All @@ -74,7 +84,7 @@
}

&:hover,
&.mat-slider-active {
&.cdk-focused {
.mat-slider-thumb {
border-color: $mat-slider-off-focused-color;
}
Expand Down
7 changes: 4 additions & 3 deletions src/lib/slider/index.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import {NgModule, ModuleWithProviders} from '@angular/core';
import {ModuleWithProviders, NgModule} from '@angular/core';
import {HAMMER_GESTURE_CONFIG} from '@angular/platform-browser';
import {CommonModule} from '@angular/common';
import {FormsModule} from '@angular/forms';
import {GestureConfig, CompatibilityModule} from '../core';
import {CompatibilityModule, GestureConfig, StyleModule} from '../core';
import {MdSlider} from './slider';
import {RtlModule} from '../core/rtl/dir';


@NgModule({
imports: [CommonModule, FormsModule, CompatibilityModule],
imports: [CommonModule, FormsModule, CompatibilityModule, StyleModule, RtlModule],
exports: [MdSlider, CompatibilityModule],
declarations: [MdSlider],
providers: [{provide: HAMMER_GESTURE_CONFIG, useClass: GestureConfig}]
Expand Down
1 change: 1 addition & 0 deletions src/lib/slider/slider.html
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
<div class="mat-slider-ticks" [ngStyle]="ticksStyles"></div>
</div>
<div class="mat-slider-thumb-container" [ngStyle]="thumbContainerStyles">
<div class="mat-slider-focus-ring"></div>
<div class="mat-slider-thumb"></div>
<div class="mat-slider-thumb-label">
<span class="mat-slider-thumb-label-text">{{displayValue}}</span>
Expand Down
68 changes: 53 additions & 15 deletions src/lib/slider/slider.scss
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ $mat-slider-thumb-label-size: 28px !default;
$mat-slider-tick-color: rgba(0, 0, 0, 0.6) !default;
$mat-slider-tick-size: 2px !default;

$mat-slider-focus-ring-size: 30px !default;


.mat-slider {
display: inline-block;
Expand Down Expand Up @@ -72,17 +74,29 @@ $mat-slider-tick-size: 2px !default;
transition: opacity $swift-ease-out-duration $swift-ease-out-timing-function;
}

// TODO(mmalerba): Simplify css to avoid unnecessary selectors.
.mat-slider-disabled .mat-slider-ticks {
opacity: 0;
}

.mat-slider-thumb-container {
position: absolute;
z-index: 1;
transition: transform $swift-ease-out-duration $swift-ease-out-timing-function;
}

.mat-slider-focus-ring {
position: absolute;
width: $mat-slider-focus-ring-size;
height: $mat-slider-focus-ring-size;
border-radius: 50%;
transform: scale(0);
opacity: 0;
transition: transform $swift-ease-out-duration $swift-ease-out-timing-function,
background-color $swift-ease-out-duration $swift-ease-out-timing-function,
opacity $swift-ease-out-duration $swift-ease-out-timing-function;

.cdk-keyboard-focused & {
transform: scale(1);
opacity: 1;
}
}

.mat-slider-thumb {
position: absolute;
right: -$mat-slider-thumb-size / 2;
Expand Down Expand Up @@ -143,15 +157,15 @@ $mat-slider-tick-size: 2px !default;
transition: opacity $swift-ease-out-duration $swift-ease-out-timing-function;
}

&.mat-slider-active,
&.cdk-focused,
&:hover {
&:not(.mat-slider-hide-last-tick) {
.mat-slider-wrapper::after {
opacity: 1;
}
}

.mat-slider-ticks {
&:not(.mat-slider-disabled) .mat-slider-ticks {
opacity: 1;
}
}
Expand All @@ -160,6 +174,11 @@ $mat-slider-tick-size: 2px !default;

// Slider with thumb label.
.mat-slider-thumb-label-showing {
.mat-slider-focus-ring {
transform: scale(0);
opacity: 0;
}

.mat-slider-thumb-label {
display: flex;
}
Expand All @@ -179,12 +198,7 @@ $mat-slider-tick-size: 2px !default;


// Active slider.
.mat-slider-active {
.mat-slider-thumb {
border-width: $mat-slider-thumb-border-width-active;
transform: scale($mat-slider-thumb-focus-scale);
}

.cdk-focused {
&.mat-slider-thumb-label-showing .mat-slider-thumb {
transform: scale(0);
}
Expand All @@ -198,9 +212,23 @@ $mat-slider-tick-size: 2px !default;
}
}

.cdk-mouse-focused,
.cdk-touch-focused,
.cdk-program-focused {
.mat-slider-thumb {
border-width: $mat-slider-thumb-border-width-active;
transform: scale($mat-slider-thumb-focus-scale);
}
}


// Disabled slider.
.mat-slider-disabled {
.mat-slider-focus-ring {
transform: scale(0);
opacity: 0;
}

.mat-slider-thumb {
border-width: $mat-slider-thumb-border-width-disabled;
transform: scale($mat-slider-thumb-disabled-scale);
Expand Down Expand Up @@ -271,6 +299,11 @@ $mat-slider-tick-size: 2px !default;
top: 50%;
}

.mat-slider-focus-ring {
top: -$mat-slider-focus-ring-size / 2;
right: -$mat-slider-focus-ring-size / 2;
}

.mat-slider-thumb-label {
right: -$mat-slider-thumb-label-size / 2;
top: -($mat-slider-thumb-label-size + $mat-slider-thumb-arrow-gap);
Expand All @@ -282,7 +315,7 @@ $mat-slider-tick-size: 2px !default;
transform: rotate(-45deg);
}

&.mat-slider-active {
&.cdk-focused {
.mat-slider-thumb-label {
transform: rotate(45deg);
}
Expand Down Expand Up @@ -331,6 +364,11 @@ $mat-slider-tick-size: 2px !default;
height: 100%;
}

.mat-slider-focus-ring {
bottom: -$mat-slider-focus-ring-size / 2;
left: -$mat-slider-focus-ring-size / 2;
}

.mat-slider-ticks {
background: repeating-linear-gradient(to bottom, $mat-slider-tick-color,
$mat-slider-tick-color $mat-slider-tick-size, transparent 0, transparent) repeat;
Expand All @@ -356,7 +394,7 @@ $mat-slider-tick-size: 2px !default;
transform: rotate(45deg);
}

&.mat-slider-active {
&.cdk-focused {
.mat-slider-thumb-label {
transform: rotate(-45deg);
}
Expand Down
64 changes: 7 additions & 57 deletions src/lib/slider/slider.spec.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
import {async, ComponentFixture, TestBed} from '@angular/core/testing';
import {ReactiveFormsModule, FormControl, FormsModule} from '@angular/forms';
import {FormControl, FormsModule, ReactiveFormsModule} from '@angular/forms';
import {Component, DebugElement} from '@angular/core';
import {By, HAMMER_GESTURE_CONFIG} from '@angular/platform-browser';
import {MdSlider, MdSliderModule} from './index';
import {TestGestureConfig} from './test-gesture-config';
import {RtlModule} from '../core/rtl/dir';
import {
UP_ARROW,
RIGHT_ARROW,
DOWN_ARROW,
PAGE_DOWN,
PAGE_UP,
END,
HOME,
LEFT_ARROW
LEFT_ARROW,
PAGE_DOWN,
PAGE_UP,
RIGHT_ARROW,
UP_ARROW
} from '../core/keyboard/keycodes';
import {dispatchKeyboardEvent, dispatchMouseEvent} from '../core/testing/dispatch-events';

Expand All @@ -23,7 +23,7 @@ describe('MdSlider', () => {

beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [MdSliderModule.forRoot(), RtlModule.forRoot(), ReactiveFormsModule, FormsModule],
imports: [MdSliderModule, ReactiveFormsModule, FormsModule, RtlModule],
declarations: [
StandardSlider,
DisabledSlider,
Expand Down Expand Up @@ -129,28 +129,6 @@ describe('MdSlider', () => {
expect(trackFillElement.style.transform).toContain('scaleX(0.86)');
});

it('should add the mat-slider-active class on click', () => {
expect(sliderNativeElement.classList).not.toContain('mat-slider-active');

dispatchClickEventSequence(sliderNativeElement, 0.23);
fixture.detectChanges();

expect(sliderNativeElement.classList).toContain('mat-slider-active');
});

it('should remove the mat-slider-active class on blur', () => {
dispatchClickEventSequence(sliderNativeElement, 0.95);
fixture.detectChanges();

expect(sliderNativeElement.classList).toContain('mat-slider-active');

// Call the `onBlur` handler directly because we cannot simulate a focus event in unit tests.
sliderInstance._onBlur();
fixture.detectChanges();

expect(sliderNativeElement.classList).not.toContain('mat-slider-active');
});

it('should add and remove the mat-slider-sliding class when sliding', () => {
expect(sliderNativeElement.classList).not.toContain('mat-slider-sliding');

Expand All @@ -167,11 +145,6 @@ describe('MdSlider', () => {

it('should have thumb gap when at min value', () => {
expect(trackFillElement.style.transform).toContain('translateX(-7px)');

dispatchClickEventSequence(sliderNativeElement, 0);
fixture.detectChanges();

expect(trackFillElement.style.transform).toContain('translateX(-10px)');
});

it('should not have thumb gap when not at min value', () => {
Expand Down Expand Up @@ -561,29 +534,6 @@ describe('MdSlider', () => {
// The thumb label text is set to the slider's value. These should always be the same.
expect(thumbLabelTextElement.textContent).toBe(`${sliderInstance.value}`);
});

it('should show the thumb label on click', () => {
expect(sliderNativeElement.classList).not.toContain('mat-slider-active');
expect(sliderNativeElement.classList).toContain('mat-slider-thumb-label-showing');

dispatchClickEventSequence(sliderNativeElement, 0.49);
fixture.detectChanges();

// The thumb label appears when the slider is active and the 'mat-slider-thumb-label-showing'
// class is applied.
expect(sliderNativeElement.classList).toContain('mat-slider-thumb-label-showing');
expect(sliderNativeElement.classList).toContain('mat-slider-active');
});

it('should show the thumb label on slide', () => {
expect(sliderNativeElement.classList).not.toContain('mat-slider-active');

dispatchSlideEventSequence(sliderNativeElement, 0, 0.91, gestureConfig);
fixture.detectChanges();

expect(sliderNativeElement.classList).toContain('mat-slider-thumb-label-showing');
expect(sliderNativeElement.classList).toContain('mat-slider-active');
});
});

describe('slider as a custom form control', () => {
Expand Down
Loading

0 comments on commit dd93237

Please sign in to comment.