Skip to content

Commit a3a0974

Browse files
committed
refactor(material/slider): mdc slider rewrite (#25692)
* refactor(material/slider): mdc slider rewrite * fixup! refactor(material/slider): mdc slider rewrite * fixup! refactor(material/slider): mdc slider rewrite * fixup! refactor(material/slider): mdc slider rewrite * fixup! refactor(material/slider): mdc slider rewrite * fixup! refactor(material/slider): mdc slider rewrite * fixup! refactor(material/slider): mdc slider rewrite * fixup! refactor(material/slider): mdc slider rewrite * fixup! refactor(material/slider): mdc slider rewrite * fixup! refactor(material/slider): mdc slider rewrite * fixup! refactor(material/slider): mdc slider rewrite * fixup! refactor(material/slider): mdc slider rewrite * fixup! refactor(material/slider): mdc slider rewrite * fixup! refactor(material/slider): mdc slider rewrite * fixup! refactor(material/slider): mdc slider rewrite * fixup! refactor(material/slider): mdc slider rewrite * fixup! refactor(material/slider): mdc slider rewrite * fixup! refactor(material/slider): mdc slider rewrite * fixup! refactor(material/slider): mdc slider rewrite * fixup! refactor(material/slider): mdc slider rewrite * fixup! refactor(material/slider): mdc slider rewrite * fixup! refactor(material/slider): mdc slider rewrite * fixup! refactor(material/slider): mdc slider rewrite * fixup! refactor(material/slider): mdc slider rewrite * fixup! refactor(material/slider): mdc slider rewrite * fixup! refactor(material/slider): mdc slider rewrite * fixup! refactor(material/slider): mdc slider rewrite * fixup! refactor(material/slider): mdc slider rewrite * fixup! refactor(material/slider): mdc slider rewrite * fixup! refactor(material/slider): mdc slider rewrite * fixup! refactor(material/slider): mdc slider rewrite * fixup! refactor(material/slider): mdc slider rewrite * fix(material/slider): unit test fixes * refactor(material/slider): set width style directly in JS * fixup! refactor(material/slider): set width style directly in JS * fix(material/slider): target 'demo-' classes in demo styles * fix(material/slider): use 'class.' instead of 'ngClass' * refactor(material/slider): use ngModel for two-way value binding demo * refactor(material/slider): move tick mark transform logic into new fn * refactor(material/slider): remove ng-container by moving ngFor * refactor(material/slider): remove commented out styles * fix(material/slider): use docs-private for thumb docs * fixup! refactor(material/slider): move tick mark transform logic into new fn * refactor(material/slider): create _sliderInputEl convenience var * refactor(material/slider): remove unnecessary runOutsideAngular * refactor(material/slider): simplify hover ripple logic * refactor(material/slider): remove unused providers line * refactor(material/slider): make _hasSetInitialValue private * refactor(material/slider): rename __sibling to _sibling * refactor(material/slider): directly set transition in JS * fix(material/slider): fix step typing * refactor(material/slider): simplify tickmark logic * fix(material/slider): update thumb ui on value change fix * refactor(material/slider): use classes to enable/disable animations * fix(material/slider): remove ref to nonexistent var * fixup! refactor(material/slider): use classes to enable/disable animations * refactor(material/slider): use classes to handle input left/right alignment * fix(material/slider): remove unneeded detectChanges * fixup! refactor(material/slider): use classes to enable/disable animations * fixup! fix(material/slider): remove unneeded detectChanges * refactor(material/slider): set thumb transform directly w/ JS * refactor(material/slider): move track styles from JS to CSS * fix(material/slider): add & remove VI class to avoid calling change detection * fix(material/slider): update slider dimensions on mousedown * also switch to using clientX instead of pageX for pointer event calculations * fix(material/slider): update public api guard * refactor(material/slider): remove unneeded track styles * refactor(material/slider): use css class to set no pointer events on input * also stop setting isActive to false on blur * also remove unused class vars from range thumb * fix(material/slider): update public api guard * fix(material/slider): several fixes * clean up comments * fix return type of _getValueIndicatorContainer() * change _isActive to not be readonly * refactor(material/slider): set input padding directly w/ JS * fix(material/slider): update public api guard * fix(material/slider): fix unit test failures * force min number of active & inactive tick marks to be 0 * add undefined check for _valueIndicatorContainer * refactor(material/slider): make _translateX private * perf(material/slider): avoid using hostlisteners for pointer events * refactor(material/slider): simplify ng control logic * perf(material/slider): remove resize polling * fixup! refactor(material/slider): simplify ng control logic * fix(material/slider): fix sliding interaction for range sliders * fix event listener overriding * correct setting of inactive & active widths for the hidden native slider * refactor(material/slider): split slider.ts into multiple files * fix(material/slider): update ts public api guard * fix(material/slider): add docs for interface properties * fixup! fix(material/slider): add docs for interface properties * fix(material/slider): reduce flicker * fix floating point imprecision which caused values to get manually updated more often than they needed to * fix(material/slider): keep focus ripple when ripples are disabled * refactor(material/slider): remove _updateHidden fn * Also call tick after setting value by slide in unit tests to avoid race conditions * fix(material/slider): update ts public api guard * fix(material/slider): fix range slider minmax initialization * fix(material/slider): linted * fix(material/slider): several fixes for tgp * fix value indicator hiding & showing * add drag start & end events back * remove forgotten console.logs * fix(material/slider): improve value fixing precision * improve the precision of value calculated in _fixValue by rounding to more (or less) decimal places based on total number of possible values * remove _setValue which only existed as a convenience fn for tests * refactor(material/slider): simiplify updateThumbUI * refactor(material/slider): simplify overlapping thumb logic * refactor(material/slider): simplify _setTrackActiveStyles * fix(material/slider): rename custom css classes * rename custom css classes to match with our naming conventions * refactor(material/slider): small code cleanup * refactor(material/slider): rename interfaces * fix(material/slider): rename tokens and their generic values * fix(material/slider): remove dep on @Material * copy over Thumb and TickMark and rename them to _MatThumb and _MatTickMark * fixup! fix(material/slider): remove dep on @Material * refactor(material/slider): change pointer callbacks to regular fns * change pointer callbacks to regular fns instead of arrow functions * call .bind(this) since we are now longer using arrow functions * remove 'Hander' functions since they are no longer needed to override the callback fns * fixup! refactor(material/slider): change pointer callbacks to regular fns * fix(material/slider): fix unit tests * displayWith tests were failing due to floating point imprecision on Firefox * fix(material/slider): correct data type for two-way value binding * fixup! fix(material/slider): correct data type for two-way value binding * fix(material/slider): set thumb tx after checking value * switch to using mouse position to set the translateX of the thumb if the slider does not have a step * set the thumb position even if the value does not need to be corrected - this is necessary bc a previous change prevented the regular ui update from triggering until the new value was verified in _fixValue * fix(material/slider): fix tick mark calculations * fix(material/slider): make slider width work like the mdc impl * make the slider track stretch to the min/max width instead of having the slider thumb ripple be what reaches the min/max width. * the slider knob/ripple now overflow past the bounds of the mat-mdc-slider host element as they used to in the mdc impl. * fixup! fix(material/slider): make slider width work like the mdc impl * fix(material/slider): fix value indicator classes * add 'mdc-slider__thumb--short-value' class to vi when text is short * directly add/remove 'mdc-slider__thumb--focused' class instead of using host binding * fixup! fix(material/slider): fix value indicator classes (cherry picked from commit 0950eb0)
1 parent a4e39db commit a3a0974

21 files changed

+3408
-2499
lines changed

src/dev-app/slider/BUILD.bazel

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
load("//tools:defaults.bzl", "ng_module")
1+
load("//tools:defaults.bzl", "ng_module", "sass_binary")
22

33
package(default_visibility = ["//visibility:public"])
44

@@ -7,10 +7,17 @@ ng_module(
77
srcs = glob(["**/*.ts"]),
88
assets = [
99
"slider-demo.html",
10+
":slider_demo_scss",
1011
],
1112
deps = [
13+
"//src/material/button-toggle",
1214
"//src/material/slider",
1315
"//src/material/tabs",
1416
"@npm//@angular/forms",
1517
],
1618
)
19+
20+
sass_binary(
21+
name = "slider_demo_scss",
22+
src = "slider-demo.scss",
23+
)

src/dev-app/slider/slider-demo.html

Lines changed: 183 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -1,88 +1,191 @@
1-
<h1>Default Slider</h1>
2-
<span>Label</span>
3-
<mat-slider>
4-
<input #slidey matSliderThumb>
5-
</mat-slider>
6-
{{slidey.value}}
1+
<h1>Color Picker</h1>
2+
<mat-button-toggle-group [(ngModel)]="colorModel" aria-label="Slider color options">
3+
<mat-button-toggle value="primary">Primary</mat-button-toggle>
4+
<mat-button-toggle value="accent">Accent</mat-button-toggle>
5+
<mat-button-toggle value="warn">Warn</mat-button-toggle>
6+
</mat-button-toggle-group>
77

8-
<h1>Colors</h1>
9-
<mat-slider color="primary" discrete>
10-
<input value="50" matSliderThumb>
11-
</mat-slider>
12-
<mat-slider color="accent" discrete>
13-
<input value="50" matSliderThumb>
14-
</mat-slider>
15-
<mat-slider color="warn">
16-
<input value="50" matSliderThumb>
17-
</mat-slider>
8+
<br><br><br>
189

19-
<h1>Slider with Min and Max</h1>
20-
<input [(ngModel)]="min" type="number">
21-
<mat-slider [min]="min" [max]="max" step="5" discrete showTickMarks>
22-
<input #slider2 matSliderThumb>
23-
</mat-slider>
24-
{{slider2.value}}
25-
<input [(ngModel)]="max" type="number">
26-
27-
<h1>Disabled Slider</h1>
28-
<mat-slider disabled [step]="1">
29-
<input [(ngModel)]="disabledValue" matSliderThumb>
30-
</mat-slider>
31-
<input [(ngModel)]="disabledValue" type="number">
32-
33-
<h1>Slider with set value</h1>
34-
<mat-slider>
35-
<input value="43" matSliderThumb>
36-
</mat-slider>
37-
38-
<h1>Slider with step defined</h1>
39-
<mat-slider min="1" max="100" step="20">
40-
<input #slider5 matSliderThumb>
41-
</mat-slider>
42-
{{slider5.value}}
43-
44-
<h1>Slider with set tick interval</h1>
45-
<mat-slider discrete showTickMarks>
46-
<input matSliderThumb>
47-
</mat-slider>
48-
<mat-slider step="9" discrete showTickMarks>
49-
<input matSliderThumb>
50-
</mat-slider>
51-
52-
<h1>Slider with Thumb Label</h1>
53-
<mat-slider discrete>
54-
<input matSliderThumb>
55-
</mat-slider>
56-
57-
<h1>Slider with one-way binding</h1>
58-
<mat-slider step="10">
59-
<input [value]="val" matSliderThumb>
60-
</mat-slider>
61-
<input [(ngModel)]="val" type="number">
10+
<mat-tab-group color="{{colorModel}}">
11+
<mat-tab label="Reactive form controls">
12+
<table class="demo-data-table">
13+
<tr>
14+
<th class="demo-table-header">Inputs</th>
15+
<th class="demo-table-header">Controls</th>
16+
<th class="demo-table-header">Native Slider</th>
17+
<th class="demo-table-header">Single Slider</th>
18+
<th class="demo-table-header">Double Slider</th>
19+
</tr>
20+
<tr>
21+
<th class="demo-table-header">Value</th>
22+
<td class="demo-control-cell"><input class="demo-slider-control" type="number" (input)="updateControlValue($event.target)" /></td>
23+
<td class="demo-value-cell">{{nativeSlider1.value}}</td>
24+
<td class="demo-value-cell">{{ngThumb1.value}}</td>
25+
<td class="demo-value-cell">{{ngStartThumb1.value}} : {{ngEndThumb1.value}}</td>
26+
</tr>
27+
<tr>
28+
<th class="demo-table-header">Disabled</th>
29+
<td class="demo-control-cell"><input class="demo-slider-control" type="checkbox" (input)="updateControlDisabledState($event.target)" /></td>
30+
<td class="demo-value-cell">{{nativeSlider1.disabled}}</td>
31+
<td class="demo-value-cell">{{ngThumb1.disabled}}</td>
32+
<td class="demo-value-cell">{{ngStartThumb1.disabled}} : {{ngEndThumb1.disabled}}</td>
33+
</tr>
34+
</table>
35+
36+
<input class="demo-native-slider" type="range" [formControl]="control" #nativeSlider1 />
37+
<br>
38+
<mat-slider discrete showTickMarks color="{{colorModel}}">
39+
<input matSliderThumb [formControl]="control" #ngThumb1 />
40+
</mat-slider>
41+
<br>
42+
<mat-slider discrete showTickMarks color="{{colorModel}}">
43+
<input matSliderStartThumb [formControl]="control" #ngStartThumb1 />
44+
<input matSliderEndThumb #ngEndThumb1 />
45+
</mat-slider>
46+
</mat-tab>
6247

63-
<h1>Slider with two-way binding</h1>
64-
<mat-slider step="40">
65-
<input [(ngModel)]="demo" matSliderThumb>
66-
</mat-slider>
67-
<input [(ngModel)]="demo" type="number">
48+
<mat-tab label="Template-driven form controls">
49+
<table class="demo-data-table">
50+
<tr>
51+
<th class="demo-table-header">Inputs</th>
52+
<th class="demo-table-header">Controls</th>
53+
<th class="demo-table-header">Native Slider</th>
54+
<th class="demo-table-header">Slider</th>
55+
<th class="demo-table-header">Range Slider</th>
56+
</tr>
57+
<tr>
58+
<th class="demo-table-header">Value</th>
59+
<td class="demo-control-cell"><input class="demo-slider-control" type="number" [(ngModel)]="valueModel" /></td>
60+
<td class="demo-value-cell">{{nativeSlider2.value}}</td>
61+
<td class="demo-value-cell">{{ngThumb2.value}}</td>
62+
<td class="demo-value-cell">{{ngStartThumb2.value}} : {{ngEndThumb2.value}}</td>
63+
</tr>
64+
<tr>
65+
<th class="demo-table-header">Min</th>
66+
<td class="demo-control-cell"><input class="demo-slider-control" type="number" [(ngModel)]="minModel" /></td>
67+
<td class="demo-value-cell">{{nativeSlider2.min}}</td>
68+
<td class="demo-value-cell">{{ngThumb2.min}}</td>
69+
<td class="demo-value-cell">{{ngStartThumb2.min}} : {{ngEndThumb2.min}}</td>
70+
</tr>
71+
<tr>
72+
<th class="demo-table-header">Max</th>
73+
<td class="demo-control-cell"><input class="demo-slider-control" type="number" [(ngModel)]="maxModel" /></td>
74+
<td class="demo-value-cell">{{nativeSlider2.max}}</td>
75+
<td class="demo-value-cell">{{ngThumb2.max}}</td>
76+
<td class="demo-value-cell">{{ngStartThumb2.max}} : {{ngEndThumb2.max}}</td>
77+
</tr>
78+
<tr>
79+
<th class="demo-table-header">Step</th>
80+
<td class="demo-control-cell"><input class="demo-slider-control" type="number" [(ngModel)]="stepModel" /></td>
81+
<td class="demo-value-cell">{{nativeSlider2.step}}</td>
82+
<td class="demo-value-cell">{{ngThumb2.step}}</td>
83+
<td class="demo-value-cell">{{ngStartThumb2.step}} : {{ngEndThumb2.step}}</td>
84+
</tr>
85+
<tr>
86+
<th class="demo-table-header">Disabled</th>
87+
<td class="demo-control-cell"><input class="demo-slider-control" type="checkbox" [(ngModel)]="disabledModel" /></td>
88+
<td class="demo-value-cell">{{nativeSlider2.disabled}}</td>
89+
<td class="demo-value-cell">{{ngThumb2.disabled}}</td>
90+
<td class="demo-value-cell">{{ngStartThumb2.disabled}} : {{ngEndThumb2.disabled}}</td>
91+
</tr>
92+
</table>
93+
94+
<br>
95+
96+
<input class="demo-native-slider" type="range" #nativeSlider2 [(ngModel)]="valueModel" [min]="minModel" [max]="maxModel" [step]="stepModel" [disabled]="disabledModel" />
97+
<br>
98+
<mat-slider discrete showTickMarks color="{{colorModel}}" [min]="minModel" [max]="maxModel" [step]="stepModel" [disabled]="disabledModel">
99+
<input matSliderThumb #ngThumb2 [(ngModel)]="valueModel" />
100+
</mat-slider>
101+
<br>
102+
<mat-slider discrete showTickMarks color="{{colorModel}}" [min]="minModel" [max]="maxModel" [step]="stepModel" [disabled]="disabledModel">
103+
<input matSliderStartThumb #ngStartThumb2 [(ngModel)]="valueModel" />
104+
<input matSliderEndThumb #ngEndThumb2 />
105+
</mat-slider>
106+
</mat-tab>
68107

69-
<h1>Set/lost focus to show thumblabel programmatically</h1>
70-
<mat-slider discrete>
71-
<input #demoSlider="matSliderThumb" matSliderThumb>
72-
</mat-slider>
73-
<button (click)="demoSlider.focus()">Focus Slider</button>
74-
<button (click)="demoSlider.blur()">Blur Slider</button>
108+
<mat-tab label="One-way property bindings">
109+
<table class="demo-data-table">
110+
<tr>
111+
<th class="demo-table-header">Inputs</th>
112+
<th class="demo-table-header">Controls</th>
113+
<th class="demo-table-header">Native Slider</th>
114+
<th class="demo-table-header">Slider</th>
115+
<th class="demo-table-header">Range Slider</th>
116+
</tr>
117+
<tr>
118+
<th class="demo-table-header">Value</th>
119+
<td class="demo-control-cell"><input class="demo-slider-control" type="number" (input)="updateValue($event.target)" [value]="value" /></td>
120+
<td class="demo-value-cell">{{nativeSlider3.value}}</td>
121+
<td class="demo-value-cell">{{ngThumb3.value}}</td>
122+
<td class="demo-value-cell">{{ngStartThumb3.value}} : {{ngEndThumb3.value}}</td>
123+
</tr>
124+
<tr>
125+
<th class="demo-table-header">Min</th>
126+
<td class="demo-control-cell"><input class="demo-slider-control" type="number" (input)="updateMin($event.target)" [value]="min" /></td>
127+
<td class="demo-value-cell">{{nativeSlider3.min}}</td>
128+
<td class="demo-value-cell">{{ngThumb3.min}}</td>
129+
<td class="demo-value-cell">{{ngStartThumb3.min}} : {{ngEndThumb3.min}}</td>
130+
</tr>
131+
<tr>
132+
<th class="demo-table-header">Max</th>
133+
<td class="demo-control-cell"><input class="demo-slider-control" type="number" (input)="updateMax($event.target)" [value]="max" /></td>
134+
<td class="demo-value-cell">{{nativeSlider3.max}}</td>
135+
<td class="demo-value-cell">{{ngThumb3.max}}</td>
136+
<td class="demo-value-cell">{{ngStartThumb3.max}} : {{ngEndThumb3.max}}</td>
137+
</tr>
138+
<tr>
139+
<th class="demo-table-header">Step</th>
140+
<td class="demo-control-cell"><input class="demo-slider-control" type="number" (input)="updateStep($event.target)" [value]="step" /></td>
141+
<td class="demo-value-cell">{{nativeSlider3.step}}</td>
142+
<td class="demo-value-cell">{{ngThumb3.step}}</td>
143+
<td class="demo-value-cell">{{ngStartThumb3.step}} : {{ngEndThumb3.step}}</td>
144+
</tr>
145+
<tr>
146+
<th class="demo-table-header">Disabled</th>
147+
<td class="demo-control-cell"><input class="demo-slider-control" type="checkbox" (input)="updateDisabledState($event.target)" [value]="disabled" /></td>
148+
<td class="demo-value-cell">{{nativeSlider3.disabled}}</td>
149+
<td class="demo-value-cell">{{ngThumb3.disabled}}</td>
150+
<td class="demo-value-cell">{{ngStartThumb3.disabled}} : {{ngEndThumb3.disabled}}</td>
151+
</tr>
152+
</table>
75153

76-
<mat-tab-group>
77-
<mat-tab label="One">
78-
<mat-slider min="1" max="5">
79-
<input value="3" matSliderThumb>
154+
<input class="demo-native-slider" type="range" #nativeSlider3 [value]="value" [min]="min" [max]="max" [step]="step" [disabled]="disabled" />
155+
<br>
156+
<mat-slider discrete showTickMarks color="{{colorModel}}" [min]="min" [max]="max" [step]="step" [disabled]="disabled">
157+
<input matSliderThumb #ngThumb3 [value]="value" />
158+
</mat-slider>
159+
<br>
160+
<mat-slider discrete showTickMarks color="{{colorModel}}" [min]="min" [max]="max" [step]="step" [disabled]="disabled">
161+
<input matSliderStartThumb #ngStartThumb3 [value]="value" />
162+
<input matSliderEndThumb #ngEndThumb3 />
80163
</mat-slider>
81164
</mat-tab>
82-
</mat-tab-group>
83165

84-
<h1>Range slider</h1>
85-
<mat-slider min="200" max="500" step="100" discrete showTickMarks>
86-
<input value="300" matSliderStartThumb>
87-
<input value="400" matSliderEndThumb>
88-
</mat-slider>
166+
<mat-tab label="Two-way property bindings">
167+
<table class="demo-data-table">
168+
<tr>
169+
<th class="demo-table-header">Inputs</th>
170+
<th class="demo-table-header">Controls</th>
171+
<th class="demo-table-header">Slider</th>
172+
<th class="demo-table-header">Range Slider</th>
173+
</tr>
174+
<tr>
175+
<th class="demo-table-header">Value</th>
176+
<td class="demo-control-cell"><input class="demo-slider-control" type="number" [(ngModel)]="twoWayValue" /></td>
177+
<td class="demo-value-cell">{{ngThumb4.value}}</td>
178+
<td class="demo-value-cell">{{ngStartThumb4.value}} : {{ngEndThumb4.value}}</td>
179+
</tr>
180+
</table>
181+
182+
<mat-slider discrete showTickMarks color="{{colorModel}}">
183+
<input matSliderThumb #ngThumb4 [(value)]="twoWayValue" />
184+
</mat-slider>
185+
<br>
186+
<mat-slider discrete showTickMarks color="{{colorModel}}">
187+
<input matSliderStartThumb #ngStartThumb4 [(value)]="twoWayValue" />
188+
<input matSliderEndThumb #ngEndThumb4 />
189+
</mat-slider>
190+
</mat-tab>
191+
</mat-tab-group>

src/dev-app/slider/slider-demo.scss

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
.demo-data-table {
2+
font-family: arial, sans-serif;
3+
border-collapse: collapse;
4+
margin: 24px;
5+
}
6+
7+
.demo-value-cell,
8+
.demo-control-cell,
9+
.demo-table-header {
10+
border: 1px solid #aaa;
11+
text-align: left;
12+
padding: 8px;
13+
}
14+
15+
@media (max-width: 600px) {
16+
.demo-data-table {
17+
font-size: 12px;
18+
margin: 24px 0;
19+
}
20+
.demo-table-header {
21+
text-align: center;
22+
}
23+
.demo-control-cell {
24+
max-width: 130px;
25+
.demo-slider-control {
26+
width: calc(100% - 8px);
27+
}
28+
}
29+
}
30+
31+
.demo-value-cell {
32+
width: 130px;
33+
}
34+
.mat-mdc-slider {
35+
width: calc(100% - 48px);
36+
margin: 0 24px;
37+
}
38+
.demo-native-slider {
39+
margin: 0;
40+
padding: 16px;
41+
width: calc(100% - 16px);
42+
}
43+
.mat-mdc-tab-group {
44+
border: 1px solid;
45+
border-radius: 5px;
46+
min-width: 300px;
47+
}

0 commit comments

Comments
 (0)