Skip to content

Commit 81eee36

Browse files
committed
Merge branch 'stepper' of github.com:angular/material2 into steps1
2 parents 1bd2486 + d72c1bc commit 81eee36

File tree

6 files changed

+94
-45
lines changed

6 files changed

+94
-45
lines changed

src/cdk/stepper/stepper.ts

+5-2
Original file line numberDiff line numberDiff line change
@@ -130,9 +130,12 @@ export class CdkStepper {
130130
get selectedIndex() { return this._selectedIndex; }
131131
set selectedIndex(index: number) {
132132
if (index < this._selectedIndex && !this._steps.toArray()[index].editable) { return; }
133-
if (this._selectedIndex != index && !this._anyControlsInvalid(index)) {
133+
if (this._anyControlsInvalid(index)) {
134+
// remove focus from clicked step header if the step is not able to be selected
135+
this._stepHeader.toArray()[index].nativeElement.blur();
136+
} else if (this._selectedIndex != index) {
134137
this._emitStepperSelectionEvent(index);
135-
this._focusStep(this._selectedIndex);
138+
this._focusIndex = this._selectedIndex;
136139
}
137140
}
138141
private _selectedIndex: number = 0;

src/lib/stepper/_stepper-theme.scss

+7-2
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,11 @@
99

1010
.mat-horizontal-stepper-header, .mat-vertical-stepper-header {
1111

12+
&:focus,
13+
&:hover {
14+
background-color: mat-color($background, hover);
15+
}
16+
1217
.mat-stepper-label-active {
1318
color: mat-color($foreground, text);
1419
}
@@ -39,11 +44,11 @@
3944
background-color: mat-color($background, card);
4045
}
4146

42-
.mat-vertical-content-container {
47+
.mat-stepper-vertical-line::before {
4348
border-left-color: mat-color($foreground, divider);
4449
}
4550

46-
.mat-connector-line {
51+
.mat-stepper-horizontal-line {
4752
border-top-color: mat-color($foreground, divider);
4853
}
4954
}

src/lib/stepper/stepper-horizontal.html

+1-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
</div>
3131
</div>
3232

33-
<div *ngIf="!isLast" class="mat-connector-line"></div>
33+
<div *ngIf="!isLast" class="mat-stepper-horizontal-line"></div>
3434
</ng-container>
3535
</div>
3636
<div class="mat-horizontal-content-container">

src/lib/stepper/stepper-vertical.html

+1-1
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
</div>
2929
</div>
3030

31-
<div class="mat-vertical-content-container">
31+
<div class="mat-vertical-content-container" [class.mat-stepper-vertical-line]="!isLast">
3232
<div class="mat-vertical-stepper-content" role="tabpanel"
3333
[@stepTransition]="_getAnimationDirection(i)"
3434
[id]="_getStepContentId(i)"

src/lib/stepper/stepper.scss

+35-39
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,16 @@
11
@import '../core/style/variables';
22

33
$mat-horizontal-stepper-header-height: 72px !default;
4-
$mat-label-header-height: 24px !default;
4+
$mat-stepper-label-header-height: 24px !default;
55
$mat-stepper-label-min-width: 50px !default;
66
$mat-stepper-side-gap: 24px !default;
7-
$mat-vertical-stepper-content-margin: 12px !default;
8-
$mat-vertical-content-padding-bottom: 32px !default;
9-
$mat-vertical-content-container-padding: 8px !default;
10-
$mat-connector-line-width: 1px !default;
11-
$mat-connector-line-gap: 8px !default;
12-
$mat-horizontal-connector-line-size: 5% !default;
13-
$mat-vertical-stepper-margin-top: $mat-stepper-side-gap - $mat-connector-line-gap !default;
14-
$mat-step-optional-label-font-size: 12px;
7+
$mat-vertical-stepper-content-margin: 36px !default;
8+
$mat-stepper-line-width: 1px !default;
9+
$mat-stepper-line-gap: 8px !default;
10+
$mat-step-optional-font-size: 12px;
1511

1612
:host {
1713
display: block;
18-
padding: 0 $mat-stepper-side-gap $mat-stepper-side-gap $mat-stepper-side-gap;
1914
}
2015

2116
.mat-stepper-label-active,
@@ -32,10 +27,10 @@ $mat-step-optional-label-font-size: 12px;
3227
.mat-stepper-index-new ,
3328
.mat-stepper-index-interacted {
3429
border-radius: 50%;
35-
height: $mat-label-header-height;
36-
width: $mat-label-header-height;
30+
height: $mat-stepper-label-header-height;
31+
width: $mat-stepper-label-header-height;
3732
text-align: center;
38-
line-height: $mat-label-header-height;
33+
line-height: $mat-stepper-label-header-height;
3934
display: inline-block;
4035
}
4136

@@ -51,38 +46,39 @@ $mat-step-optional-label-font-size: 12px;
5146
overflow: hidden;
5247
align-items: center;
5348
outline: none;
49+
padding: 0 $mat-stepper-side-gap;
5450

5551
.mat-stepper-index-new ,
5652
.mat-stepper-index-interacted {
57-
margin-right: $mat-connector-line-gap;
53+
margin-right: $mat-stepper-line-gap;
5854
flex: none;
5955
}
6056
}
6157

6258
.mat-vertical-stepper-header {
6359
display: flex;
6460
align-items: center;
65-
margin: $mat-connector-line-gap 0;
61+
padding: $mat-stepper-side-gap;
6662
outline: none;
67-
max-height: $mat-label-header-height;
63+
max-height: $mat-stepper-label-header-height;
6864

6965
.mat-stepper-index-new ,
7066
.mat-stepper-index-interacted {
71-
margin-right: $mat-vertical-stepper-content-margin;
67+
margin-right: $mat-vertical-stepper-content-margin - $mat-stepper-side-gap;
7268
}
7369
}
7470

7571
.mat-step-optional {
76-
font-size: $mat-step-optional-label-font-size;
72+
font-size: $mat-step-optional-font-size;
7773
}
7874

79-
.mat-connector-line {
80-
border-top-width: $mat-connector-line-width;
75+
.mat-stepper-horizontal-line {
76+
border-top-width: $mat-stepper-line-width;
8177
border-top-style: solid;
82-
width: $mat-horizontal-connector-line-size;
8378
flex: auto;
84-
margin: 0 $mat-connector-line-gap;
8579
height: 0;
80+
margin: 0 $mat-stepper-line-gap - $mat-stepper-side-gap;
81+
min-width: $mat-stepper-line-gap + $mat-stepper-side-gap;
8682
}
8783

8884
.mat-horizontal-stepper-content {
@@ -95,35 +91,35 @@ $mat-step-optional-label-font-size: 12px;
9591

9692
.mat-horizontal-content-container {
9793
overflow: hidden;
94+
padding: 0 $mat-stepper-side-gap $mat-stepper-side-gap $mat-stepper-side-gap;
9895
}
9996

10097
.mat-vertical-content-container {
101-
border-left-width: $mat-connector-line-width;
102-
border-left-style: solid;
10398
margin-left: $mat-vertical-stepper-content-margin;
104-
padding: $mat-vertical-content-container-padding 0;
99+
border: 0;
100+
position: relative;
101+
}
102+
103+
.mat-stepper-vertical-line::before {
104+
content: '';
105+
position: absolute;
106+
top: $mat-stepper-line-gap - $mat-stepper-side-gap;
107+
bottom: $mat-stepper-line-gap - $mat-stepper-side-gap;
108+
left: 0;
109+
border-left-width: $mat-stepper-line-width;
110+
border-left-style: solid;
105111
}
106112

107113
.mat-vertical-stepper-content {
108-
padding-left: $mat-stepper-side-gap;
109114
overflow: hidden;
110115
}
111116

112117
.mat-vertical-content {
113-
padding-bottom: $mat-vertical-content-padding-bottom;
118+
padding: 0 $mat-stepper-side-gap $mat-stepper-side-gap $mat-stepper-side-gap;
114119
}
115120

116-
.mat-step {
117-
margin-top: $mat-connector-line-gap;
118-
119-
&:last-child {
120-
.mat-vertical-content-container {
121-
border: none;
122-
}
123-
}
124-
125-
&:first-child {
126-
margin-top: 0;
127-
padding-top: $mat-vertical-stepper-margin-top;
121+
.mat-step:last-child {
122+
.mat-vertical-content-container {
123+
border: none;
128124
}
129125
}

src/lib/stepper/stepper.spec.ts

+45
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,12 @@ describe('MdHorizontalStepper', () => {
7676
checkKeyboardEvent(stepperComponent, fixture, stepHeaders);
7777
});
7878

79+
it('should not set focus on header of selected step if header is not clicked', () => {
80+
let stepHeaderEl = fixture.debugElement
81+
.queryAll(By.css('.mat-horizontal-stepper-header'))[1].nativeElement;
82+
checkStepHeaderFocusNotCalled(stepHeaderEl, stepperComponent, fixture);
83+
});
84+
7985
it('should only be able to return to a previous step if it is editable', () => {
8086
checkEditableStep(stepperComponent, fixture);
8187
});
@@ -116,6 +122,12 @@ describe('MdHorizontalStepper', () => {
116122
checkLinearStepperValidity(stepHeaderEl, stepperComponent, testComponent, fixture);
117123
});
118124

125+
it('should not focus step header upon click if it is not able to be selected', () => {
126+
let stepHeaderEl = fixture.debugElement
127+
.queryAll(By.css('.mat-horizontal-stepper-header'))[1].nativeElement;
128+
checkStepHeaderBlur(stepHeaderEl, fixture);
129+
});
130+
119131
it('should be able to move to next step even when invalid if current step is optional', () => {
120132
checkOptionalStep(stepperComponent, testComponent, fixture);
121133
});
@@ -188,6 +200,12 @@ describe('MdVerticalStepper', () => {
188200
checkKeyboardEvent(stepperComponent, fixture, stepHeaders);
189201
});
190202

203+
it('should not set focus on header of selected step if header is not clicked', () => {
204+
let stepHeaderEl = fixture.debugElement
205+
.queryAll(By.css('.mat-vertical-stepper-header'))[1].nativeElement;
206+
checkStepHeaderFocusNotCalled(stepHeaderEl, stepperComponent, fixture);
207+
});
208+
191209
it('should only be able to return to a previous step if it is editable', () => {
192210
checkEditableStep(stepperComponent, fixture);
193211
});
@@ -229,6 +247,12 @@ describe('MdVerticalStepper', () => {
229247
checkLinearStepperValidity(stepHeaderEl, stepperComponent, testComponent, fixture);
230248
});
231249

250+
it('should not focus step header upon click if it is not able to be selected', () => {
251+
let stepHeaderEl = fixture.debugElement
252+
.queryAll(By.css('.mat-vertical-stepper-header'))[1].nativeElement;
253+
checkStepHeaderBlur(stepHeaderEl, fixture);
254+
});
255+
232256
it('should be able to move to next step even when invalid if current step is optional', () => {
233257
checkOptionalStep(stepperComponent, testComponent, fixture);
234258
});
@@ -415,6 +439,19 @@ function checkKeyboardEvent(stepperComponent: MdStepper,
415439
'Expected index of selected step to change to index of focused step after SPACE event.');
416440
}
417441

442+
function checkStepHeaderFocusNotCalled(stepHeaderEl: HTMLElement,
443+
stepperComponent: MdStepper,
444+
fixture: ComponentFixture<any>) {
445+
let nextButtonNativeEl = fixture.debugElement
446+
.queryAll(By.directive(MdStepperNext))[0].nativeElement;
447+
spyOn(stepHeaderEl, 'focus');
448+
nextButtonNativeEl.click();
449+
fixture.detectChanges();
450+
451+
expect(stepperComponent.selectedIndex).toBe(1);
452+
expect(stepHeaderEl.focus).not.toHaveBeenCalled();
453+
}
454+
418455
function checkLinearStepperValidity(stepHeaderEl: HTMLElement,
419456
stepperComponent: MdStepper,
420457
testComponent:
@@ -440,6 +477,14 @@ function checkLinearStepperValidity(stepHeaderEl: HTMLElement,
440477
expect(stepperComponent.selectedIndex).toBe(1);
441478
}
442479

480+
function checkStepHeaderBlur(stepHeaderEl: HTMLElement, fixture: ComponentFixture<any>) {
481+
spyOn(stepHeaderEl, 'blur');
482+
stepHeaderEl.click();
483+
fixture.detectChanges();
484+
485+
expect(stepHeaderEl.blur).toHaveBeenCalled();
486+
}
487+
443488
function checkEditableStep(stepperComponent: MdStepper,
444489
fixture: ComponentFixture<any>) {
445490
stepperComponent.selectedIndex = 1;

0 commit comments

Comments
 (0)