Skip to content

Commit 737b608

Browse files
authored
fix(slider): make min value style match mocks (#2641)
* make slider disabled state match mocks * added test * fix lint * min value style * thumb label min value style * fix lint & add tests * fix lint * addressed comments
1 parent 7562322 commit 737b608

File tree

4 files changed

+140
-22
lines changed

4 files changed

+140
-22
lines changed

src/lib/slider/_slider-theme.scss

Lines changed: 52 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,11 @@
55
@mixin md-slider-theme($theme) {
66
$accent: map-get($theme, accent);
77

8-
// TODO(iveysaur): Find an implementation to hide the track under a disabled thumb.
98
$md-slider-off-color: rgba(black, 0.26);
10-
$md-slider-focused-color: rgba(black, 0.38);
9+
$md-slider-off-focused-color: rgba(black, 0.38);
1110
$md-slider-disabled-color: rgba(black, 0.26);
11+
$md-slider-labeled-min-value-thumb-color: black;
12+
$md-slider-labeled-min-value-thumb-label-color: rgba(black, 0.26);
1213

1314
.md-slider-track-background {
1415
background-color: $md-slider-off-color;
@@ -30,10 +31,58 @@
3031
color: md-color($accent, default-contrast);
3132
}
3233

34+
md-slider:hover,
35+
.md-slider-active {
36+
.md-slider-track-background {
37+
background-color: $md-slider-off-focused-color;
38+
}
39+
}
40+
3341
.md-slider-disabled {
42+
.md-slider-track-background,
3443
.md-slider-track-fill,
3544
.md-slider-thumb {
36-
background-color: $md-slider-off-color;
45+
background-color: $md-slider-disabled-color;
46+
}
47+
48+
&:hover {
49+
.md-slider-track-background {
50+
background-color: $md-slider-disabled-color;
51+
}
52+
}
53+
}
54+
55+
.md-slider-min-value {
56+
&.md-slider-thumb-label-showing {
57+
.md-slider-thumb,
58+
.md-slider-thumb-label {
59+
background-color: $md-slider-labeled-min-value-thumb-color;
60+
}
61+
62+
&.md-slider-active {
63+
.md-slider-thumb,
64+
.md-slider-thumb-label {
65+
background-color: $md-slider-labeled-min-value-thumb-label-color;
66+
}
67+
}
68+
}
69+
70+
&:not(.md-slider-thumb-label-showing) {
71+
.md-slider-thumb {
72+
border-color: $md-slider-off-color;
73+
background-color: transparent;
74+
}
75+
76+
&:hover,
77+
&.md-slider-active {
78+
.md-slider-thumb {
79+
border-color: $md-slider-off-focused-color;
80+
}
81+
82+
&.md-slider-disabled .md-slider-thumb {
83+
border-color: $md-slider-disabled-color;
84+
}
85+
}
3786
}
3887
}
3988
}

src/lib/slider/slider.scss

Lines changed: 29 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@ $md-slider-padding: 8px !default;
99

1010
$md-slider-track-thickness: 2px !default;
1111
$md-slider-thumb-size: 20px !default;
12+
$md-slider-thumb-border-width: 3px !default;
13+
$md-slider-thumb-border-width-active: 2px !default;
14+
$md-slider-thumb-border-width-disabled: 4px !default;
1215

1316
$md-slider-thumb-default-scale: 0.7 !default;
1417
$md-slider-thumb-focus-scale: 1 !default;
@@ -45,13 +48,15 @@ md-slider {
4548
.md-slider-track-fill {
4649
position: absolute;
4750
transform-origin: 0 0;
48-
transition: transform $swift-ease-out-duration $swift-ease-out-timing-function;
51+
transition: transform $swift-ease-out-duration $swift-ease-out-timing-function,
52+
background-color $swift-ease-out-duration $swift-ease-out-timing-function;
4953
}
5054

5155
.md-slider-track-background {
5256
position: absolute;
5357
transform-origin: 100% 100%;
54-
transition: transform $swift-ease-out-duration $swift-ease-out-timing-function;
58+
transition: transform $swift-ease-out-duration $swift-ease-out-timing-function,
59+
background-color $swift-ease-out-duration $swift-ease-out-timing-function;
5560
}
5661

5762
.md-slider-ticks-container {
@@ -62,6 +67,7 @@ md-slider {
6267
}
6368

6469
.md-slider-ticks {
70+
box-sizing: border-box;
6571
opacity: 0;
6672
transition: opacity $swift-ease-out-duration $swift-ease-out-timing-function;
6773
}
@@ -76,11 +82,15 @@ md-slider {
7682
position: absolute;
7783
right: -$md-slider-thumb-size / 2;
7884
bottom: -$md-slider-thumb-size / 2;
85+
box-sizing: border-box;
7986
width: $md-slider-thumb-size;
8087
height: $md-slider-thumb-size;
88+
border: $md-slider-thumb-border-width solid transparent;
8189
border-radius: 50%;
8290
transform: scale($md-slider-thumb-default-scale);
83-
transition: transform $swift-ease-out-duration $swift-ease-out-timing-function;
91+
transition: transform $swift-ease-out-duration $swift-ease-out-timing-function,
92+
background-color $swift-ease-out-duration $swift-ease-out-timing-function,
93+
border-color $swift-ease-out-duration $swift-ease-out-timing-function;
8494
}
8595

8696
.md-slider-thumb-label {
@@ -91,16 +101,17 @@ md-slider {
91101
width: $md-slider-thumb-label-size;
92102
height: $md-slider-thumb-label-size;
93103
border-radius: 50%;
94-
transition: 300ms $swift-ease-in-out-timing-function;
95-
transition-property: transform, border-radius;
104+
transition: transform $swift-ease-out-duration $swift-ease-out-timing-function,
105+
border-radius $swift-ease-out-duration $swift-ease-out-timing-function,
106+
background-color $swift-ease-out-duration $swift-ease-out-timing-function;
96107
}
97108

98109
.md-slider-thumb-label-text {
99110
z-index: 1;
100111
font-size: 12px;
101112
font-weight: bold;
102113
opacity: 0;
103-
transition: opacity 300ms $swift-ease-in-out-timing-function;
114+
transition: opacity $swift-ease-out-duration $swift-ease-out-timing-function;
104115
}
105116

106117

@@ -123,13 +134,15 @@ md-slider {
123134
position: absolute;
124135
border: 0 solid $md-slider-tick-color;
125136
opacity: 0;
126-
transition: opacity 300ms $swift-ease-in-out-timing-function;
137+
transition: opacity $swift-ease-out-duration $swift-ease-out-timing-function;
127138
}
128139

129140
&.md-slider-active,
130141
&:hover {
131-
.md-slider-wrapper::after {
132-
opacity: 1;
142+
&:not(.md-slider-hide-last-tick) {
143+
.md-slider-wrapper::after {
144+
opacity: 1;
145+
}
133146
}
134147

135148
.md-slider-ticks {
@@ -162,6 +175,7 @@ md-slider {
162175
// Active slider.
163176
.md-slider-active {
164177
.md-slider-thumb {
178+
border-width: $md-slider-thumb-border-width-active;
165179
transform: scale($md-slider-thumb-focus-scale);
166180
}
167181

@@ -182,6 +196,7 @@ md-slider {
182196
// Disabled slider.
183197
.md-slider-disabled {
184198
.md-slider-thumb {
199+
border-width: $md-slider-thumb-border-width-disabled;
185200
transform: scale($md-slider-thumb-disabled-scale);
186201
}
187202

@@ -239,6 +254,7 @@ md-slider {
239254
// (see https://bugzilla.mozilla.org/show_bug.cgi?id=1314319).
240255
background: -moz-repeating-linear-gradient(0.0001deg, $md-slider-tick-color,
241256
$md-slider-tick-color $md-slider-tick-size, transparent 0, transparent) repeat;
257+
background-clip: content-box;
242258
height: $md-slider-track-thickness;
243259
width: 100%;
244260
}
@@ -252,7 +268,7 @@ md-slider {
252268
.md-slider-thumb-label {
253269
right: -$md-slider-thumb-label-size / 2;
254270
top: -($md-slider-thumb-label-size + $md-slider-thumb-arrow-gap);
255-
transform: translateY($md-slider-thumb-label-size / 2 + $md-slider-thumb-arrow-gap) scale(0.4)
271+
transform: translateY($md-slider-thumb-label-size / 2 + $md-slider-thumb-arrow-gap) scale(0.01)
256272
rotate(45deg);
257273
}
258274

@@ -312,6 +328,7 @@ md-slider {
312328
.md-slider-ticks {
313329
background: repeating-linear-gradient(to bottom, $md-slider-tick-color,
314330
$md-slider-tick-color $md-slider-tick-size, transparent 0, transparent) repeat;
331+
background-clip: content-box;
315332
width: $md-slider-track-thickness;
316333
height: 100%;
317334
}
@@ -325,8 +342,8 @@ md-slider {
325342
.md-slider-thumb-label {
326343
bottom: -$md-slider-thumb-label-size / 2;
327344
left: -($md-slider-thumb-label-size + $md-slider-thumb-arrow-gap);
328-
transform: translateX($md-slider-thumb-label-size / 2 + $md-slider-thumb-arrow-gap)
329-
scale(0.4) rotate(-45deg);
345+
transform: translateX($md-slider-thumb-label-size / 2 + $md-slider-thumb-arrow-gap) scale(0.01)
346+
rotate(-45deg);
330347
}
331348

332349
.md-slider-thumb-label-text {

src/lib/slider/slider.spec.ts

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,23 @@ describe('MdSlider', () => {
162162

163163
expect(sliderNativeElement.classList).not.toContain('md-slider-sliding');
164164
});
165+
166+
it('should have thumb gap when at min value', () => {
167+
expect(trackFillElement.style.transform).toContain('translateX(-7px)');
168+
169+
dispatchClickEventSequence(sliderNativeElement, 0);
170+
fixture.detectChanges();
171+
172+
expect(trackFillElement.style.transform).toContain('translateX(-10px)');
173+
});
174+
175+
it('should not have thumb gap when not at min value', () => {
176+
dispatchClickEventSequence(sliderNativeElement, 1);
177+
fixture.detectChanges();
178+
179+
// Some browsers use '0' and some use '0px', so leave off the closing paren.
180+
expect(trackFillElement.style.transform).toContain('translateX(0');
181+
});
165182
});
166183

167184
describe('disabled slider', () => {
@@ -1038,6 +1055,14 @@ describe('MdSlider', () => {
10381055

10391056
expect(sliderInstance.value).toBe(1);
10401057
});
1058+
1059+
it('should hide last tick when inverted and at min value', () => {
1060+
testComponent.invert = true;
1061+
fixture.detectChanges();
1062+
1063+
expect(sliderNativeElement.classList.contains('md-slider-hide-last-tick'))
1064+
.toBe(true, 'last tick should be hidden');
1065+
});
10411066
});
10421067

10431068
describe('vertical slider', () => {
@@ -1198,7 +1223,7 @@ class SliderWithChangeHandler {
11981223
}
11991224

12001225
@Component({
1201-
template: `<div [dir]="dir"><md-slider [invert]="invert"></md-slider></div>`,
1226+
template: `<div [dir]="dir"><md-slider [invert]="invert" tickInterval="5"></md-slider></div>`,
12021227
styles: [styles],
12031228
})
12041229
class SliderWithDirAndInvert {

src/lib/slider/slider.ts

Lines changed: 33 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import {
1717
HammerInput,
1818
coerceBooleanProperty,
1919
coerceNumberProperty,
20-
DefaultStyleCompatibilityModeModule,
20+
DefaultStyleCompatibilityModeModule
2121
} from '../core';
2222
import {Dir} from '../core/rtl/dir';
2323
import {CommonModule} from '@angular/common';
@@ -29,7 +29,7 @@ import {
2929
LEFT_ARROW,
3030
UP_ARROW,
3131
RIGHT_ARROW,
32-
DOWN_ARROW,
32+
DOWN_ARROW
3333
} from '../core/keyboard/keycodes';
3434

3535
/**
@@ -41,6 +41,12 @@ const MIN_AUTO_TICK_SEPARATION = 30;
4141
/** The thumb gap size for a disabled slider. */
4242
const DISABLED_THUMB_GAP = 7;
4343

44+
/** The thumb gap size for a non-active slider at its minimum value. */
45+
const MIN_VALUE_NONACTIVE_THUMB_GAP = 7;
46+
47+
/** The thumb gap size for an active slider at its minimum value. */
48+
const MIN_VALUE_ACTIVE_THUMB_GAP = 10;
49+
4450
/**
4551
* Provider Expression that allows md-slider to register as a ControlValueAccessor.
4652
* This allows it to support [(ngModel)] and [formControl].
@@ -87,7 +93,8 @@ export class MdSliderChange {
8793
'[class.md-slider-sliding]': '_isSliding',
8894
'[class.md-slider-thumb-label-showing]': 'thumbLabel',
8995
'[class.md-slider-vertical]': 'vertical',
90-
'[class.md-slider-min-value]': 'value === min',
96+
'[class.md-slider-min-value]': '_isMinValue',
97+
'[class.md-slider-hide-last-tick]': '_isMinValue && _thumbGap && invertAxis',
9198
},
9299
templateUrl: 'slider.html',
93100
styleUrls: ['slider.css'],
@@ -249,12 +256,23 @@ export class MdSlider implements ControlValueAccessor {
249256
return (this.direction == 'rtl' && !this.vertical) ? !this.invertAxis : this.invertAxis;
250257
}
251258

259+
/** Whether the slider is at its minimum value. */
260+
get _isMinValue() {
261+
return this.percent === 0;
262+
}
263+
252264
/**
253265
* The amount of space to leave between the slider thumb and the track fill & track background
254266
* elements.
255267
*/
256-
private get _thumbGap() {
257-
return this.disabled ? DISABLED_THUMB_GAP : 0;
268+
get _thumbGap() {
269+
if (this.disabled) {
270+
return DISABLED_THUMB_GAP;
271+
}
272+
if (this._isMinValue && !this.thumbLabel) {
273+
return this._isActive ? MIN_VALUE_ACTIVE_THUMB_GAP : MIN_VALUE_NONACTIVE_THUMB_GAP;
274+
}
275+
return 0;
258276
}
259277

260278
/** CSS styles for the track background element. */
@@ -297,11 +315,20 @@ export class MdSlider implements ControlValueAccessor {
297315
// ticks 180 degrees so we're really cutting off the end edge abd not the start.
298316
let sign = !this.vertical && this.direction == 'rtl' ? '-' : '';
299317
let rotate = !this.vertical && this.direction == 'rtl' ? ' rotate(180deg)' : '';
300-
return {
318+
let styles: { [key: string]: string } = {
301319
'backgroundSize': backgroundSize,
302320
// Without translateZ ticks sometimes jitter as the slider moves on Chrome & Firefox.
303321
'transform': `translateZ(0) translate${axis}(${sign}${tickSize / 2}%)${rotate}`
304322
};
323+
324+
if (this._isMinValue && this._thumbGap) {
325+
let side = this.vertical ?
326+
(this.invertAxis ? 'Bottom' : 'Top') :
327+
(this.invertAxis ? 'Right' : 'Left');
328+
styles[`padding${side}`] = `${this._thumbGap}px`;
329+
}
330+
331+
return styles;
305332
}
306333

307334
get thumbContainerStyles(): { [key: string]: string } {

0 commit comments

Comments
 (0)