Skip to content

Commit 63b3fc3

Browse files
committed
feat(stepper): Add initial styles to stepper based on Material guidelines (#6242)
* Add initial styles to stepper based on Material guidelines * Fix flex-shrink and min-width * Changes made based on review * Fix alignment * Margin modifications
1 parent 9de35e6 commit 63b3fc3

9 files changed

+297
-35
lines changed

src/demo-app/stepper/stepper-demo.html

+110
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,113 @@
1+
<h2>Vertical Stepper Demo</h2>
2+
<md-vertical-stepper>
3+
<md-step>
4+
<ng-template mdStepLabel>Fill out your name</ng-template>
5+
<md-input-container>
6+
<input mdInput placeholder="First Name">
7+
<md-error>This field is required</md-error>
8+
</md-input-container>
9+
10+
<md-input-container>
11+
<input mdInput placeholder="Last Name">
12+
<md-error>This field is required</md-error>
13+
</md-input-container>
14+
<div>
15+
<button md-button mdStepperNext type="button">Next</button>
16+
</div>
17+
</md-step>
18+
19+
<md-step>
20+
<ng-template mdStepLabel>
21+
<div>Fill out your phone number</div>
22+
</ng-template>
23+
<md-input-container>
24+
<input mdInput placeholder="Phone number">
25+
<md-error>This field is required</md-error>
26+
</md-input-container>
27+
<div>
28+
<button md-button mdStepperPrevious type="button">Back</button>
29+
<button md-button mdStepperNext type="button">Next</button>
30+
</div>
31+
</md-step>
32+
33+
<md-step>
34+
<ng-template mdStepLabel>
35+
<div>Fill out your address</div>
36+
</ng-template>
37+
<md-input-container>
38+
<input mdInput placeholder="Address">
39+
<md-error>This field is required</md-error>
40+
</md-input-container>
41+
<div>
42+
<button md-button mdStepperPrevious type="button">Back</button>
43+
<button md-button mdStepperNext type="button">Next</button>
44+
</div>
45+
</md-step>
46+
47+
<md-step>
48+
<ng-template mdStepLabel>Confirm your information</ng-template>
49+
Everything seems correct.
50+
<div>
51+
<button md-button>Done</button>
52+
</div>
53+
</md-step>
54+
</md-vertical-stepper>
55+
56+
<h2>Horizontal Stepper Demo</h2>
57+
<md-horizontal-stepper>
58+
<md-step>
59+
<ng-template mdStepLabel>Fill out your name</ng-template>
60+
<md-input-container>
61+
<input mdInput placeholder="First Name">
62+
<md-error>This field is required</md-error>
63+
</md-input-container>
64+
65+
<md-input-container>
66+
<input mdInput placeholder="Last Name">
67+
<md-error>This field is required</md-error>
68+
</md-input-container>
69+
<div>
70+
<button md-button mdStepperNext type="button">Next</button>
71+
</div>
72+
</md-step>
73+
74+
<md-step>
75+
<ng-template mdStepLabel>
76+
<div>Fill out your phone number</div>
77+
</ng-template>
78+
<md-input-container>
79+
<input mdInput placeholder="Phone number">
80+
<md-error>This field is required</md-error>
81+
</md-input-container>
82+
<div>
83+
<button md-button mdStepperPrevious type="button">Back</button>
84+
<button md-button mdStepperNext type="button">Next</button>
85+
</div>
86+
</md-step>
87+
88+
<md-step>
89+
<ng-template mdStepLabel>
90+
<div>Fill out your address</div>
91+
</ng-template>
92+
<md-input-container>
93+
<input mdInput placeholder="Address">
94+
<md-error>This field is required</md-error>
95+
</md-input-container>
96+
<div>
97+
<button md-button mdStepperPrevious type="button">Back</button>
98+
<button md-button mdStepperNext type="button">Next</button>
99+
</div>
100+
</md-step>
101+
102+
<md-step>
103+
<ng-template mdStepLabel>Confirm your information</ng-template>
104+
Everything seems correct.
105+
<div>
106+
<button md-button>Done</button>
107+
</div>
108+
</md-step>
109+
</md-horizontal-stepper>
110+
1111
<h2>Horizontal Stepper Demo</h2>
2112
<md-horizontal-stepper>
3113
<md-step *ngFor="let step of steps" [label]="step.label">

src/lib/core/theming/_all-theme.scss

+2
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
@import '../../sidenav/sidenav-theme';
2424
@import '../../slide-toggle/slide-toggle-theme';
2525
@import '../../slider/slider-theme';
26+
@import '../../stepper/stepper-theme';
2627
@import '../../tabs/tabs-theme';
2728
@import '../../toolbar/toolbar-theme';
2829
@import '../../tooltip/tooltip-theme';
@@ -57,6 +58,7 @@
5758
@include mat-sidenav-theme($theme);
5859
@include mat-slide-toggle-theme($theme);
5960
@include mat-slider-theme($theme);
61+
@include mat-stepper-theme($theme);
6062
@include mat-tabs-theme($theme);
6163
@include mat-toolbar-theme($theme);
6264
@include mat-tooltip-theme($theme);

src/lib/stepper/_stepper-theme.scss

+43
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
@import '../core/theming/palette';
2+
@import '../core/theming/theming';
3+
@import '../core/typography/_typography-utils.scss';
4+
5+
@mixin mat-stepper-theme($theme) {
6+
$foreground: map-get($theme, foreground);
7+
$background: map-get($theme, background);
8+
$primary: map-get($theme, primary);
9+
10+
.mat-horizontal-stepper-header, .mat-vertical-stepper-header {
11+
12+
.mat-stepper-label {
13+
color: mat-color($foreground, text);
14+
}
15+
16+
.mat-stepper-index {
17+
background-color: mat-color($primary);
18+
color: mat-color($primary, default-contrast);
19+
}
20+
21+
&[aria-selected='false'] {
22+
.mat-stepper-label {
23+
color: mat-color($foreground, disabled-text);
24+
}
25+
26+
.mat-stepper-index {
27+
background-color: mat-color($foreground, disabled-text);
28+
}
29+
}
30+
}
31+
32+
.mat-stepper-horizontal, .mat-stepper-vertical {
33+
background-color: mat-color($background, card);
34+
}
35+
36+
.vertical-content-container {
37+
border-left-color: mat-color($foreground, divider);
38+
}
39+
40+
.connector-line {
41+
border-top-color: mat-color($foreground, divider);
42+
}
43+
}

src/lib/stepper/stepper-horizontal.html

+24-20
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,32 @@
1-
<div #stepHeader *ngFor="let step of _steps; let i = index; let isLast = last"
2-
class="mat-stepper-header" role="tab"
3-
[id]="_getStepLabelId(i)"
4-
[attr.aria-controls]="_getStepContentId(i)"
5-
[attr.aria-selected]="selectedIndex == i"
6-
[tabIndex]="_focusIndex == i ? 0 : -1"
7-
(click)="step.select()"
8-
(keydown)="_onKeydown($event)">
9-
<div class="mat-stepper-index">
10-
{{i + 1}}
11-
</div>
1+
<div class="mat-horizontal-stepper-header-container">
2+
<ng-container *ngFor="let step of _steps; let i = index; let isLast = last">
3+
<div #stepHeader class="mat-horizontal-stepper-header"
4+
role="tab"
5+
[id]="_getStepLabelId(i)"
6+
[attr.aria-controls]="_getStepContentId(i)"
7+
[attr.aria-selected]="selectedIndex == i"
8+
[tabIndex]="_focusIndex == i ? 0 : -1"
9+
(click)="step.select()"
10+
(keydown)="_onKeydown($event)">
11+
<div class="mat-stepper-index">
12+
{{i + 1}}
13+
</div>
1214

13-
<div class="mat-stepper-label">
14-
<!-- If there is a label template, use it. -->
15-
<ng-container *ngIf="step.stepLabel" [ngTemplateOutlet]="step.stepLabel.template">
16-
</ng-container>
17-
<!-- It there is no label template, fall back to the text label. -->
18-
<div *ngIf="!step.stepLabel">{{step.label}}</div>
19-
</div>
15+
<div class="mat-stepper-label">
16+
<!-- If there is a label template, use it. -->
17+
<ng-container *ngIf="step.stepLabel" [ngTemplateOutlet]="step.stepLabel.template">
18+
</ng-container>
19+
<!-- It there is no label template, fall back to the text label. -->
20+
<div *ngIf="!step.stepLabel">{{step.label}}</div>
21+
</div>
22+
</div>
2023

21-
<div *ngIf="!isLast" class="connector-line"></div>
24+
<div *ngIf="!isLast" class="connector-line"></div>
25+
</ng-container>
2226
</div>
2327

2428
<div *ngFor="let step of _steps; let i = index"
25-
class="mat-stepper-content" role="tabpanel"
29+
class="mat-horizontal-stepper-content" role="tabpanel"
2630
[id]="_getStepContentId(i)"
2731
[attr.aria-labelledby]="_getStepLabelId(i)"
2832
[attr.aria-expanded]="selectedIndex == i">

src/lib/stepper/stepper-horizontal.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import {MdStepper} from './stepper';
1313
moduleId: module.id,
1414
selector: 'md-horizontal-stepper, mat-horizontal-stepper',
1515
templateUrl: 'stepper-horizontal.html',
16-
styleUrls: ['stepper.scss'],
16+
styleUrls: ['stepper.css'],
1717
inputs: ['selectedIndex'],
1818
host: {
1919
'class': 'mat-stepper-horizontal',

src/lib/stepper/stepper-vertical.html

+9-8
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
<div *ngFor="let step of _steps; let i = index; let isLast = last">
2-
<div #stepHeader class="mat-stepper-header" role="tab"
1+
<div class="mat-step" *ngFor="let step of _steps; let i = index; let isLast = last">
2+
<div #stepHeader class="mat-vertical-stepper-header" role="tab"
33
[id]="_getStepLabelId(i)"
44
[attr.aria-controls]="_getStepContentId(i)"
55
[attr.aria-selected]="selectedIndex == i"
@@ -19,11 +19,12 @@
1919
</div>
2020

2121
</div>
22-
<div *ngIf="!isLast" class="connector-line"></div>
23-
<div class="mat-stepper-content" role="tabpanel"
24-
[id]="_getStepContentId(i)"
25-
[attr.aria-labelledby]="_getStepLabelId(i)"
26-
[attr.aria-expanded]="selectedIndex == i">
27-
<ng-container [ngTemplateOutlet]="step.content"></ng-container>
22+
<div class="vertical-content-container">
23+
<div class="mat-vertical-stepper-content" role="tabpanel"
24+
[id]="_getStepContentId(i)"
25+
[attr.aria-labelledby]="_getStepLabelId(i)"
26+
[attr.aria-expanded]="selectedIndex == i">
27+
<ng-container [ngTemplateOutlet]="step.content"></ng-container>
28+
</div>
2829
</div>
2930
</div>

src/lib/stepper/stepper-vertical.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import {MdStepper} from './stepper';
1313
moduleId: module.id,
1414
selector: 'md-vertical-stepper, mat-vertical-stepper',
1515
templateUrl: 'stepper-vertical.html',
16-
styleUrls: ['stepper.scss'],
16+
styleUrls: ['stepper.css'],
1717
inputs: ['selectedIndex'],
1818
host: {
1919
'class': 'mat-stepper-vertical',

src/lib/stepper/stepper.scss

+106-4
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,109 @@
1-
.mat-stepper-content[aria-expanded='false'] {
2-
display: none;
1+
$mat-horizontal-stepper-header-height: 72px !default;
2+
$mat-label-header-height: 24px !default;
3+
$mat-stepper-label-min-width: 50px !default;
4+
$mat-stepper-side-gap: 24px !default;
5+
$mat-vertical-stepper-content-margin: 12px !default;
6+
$mat-vertical-stepper-content-padding: 16px 0 32px $mat-stepper-side-gap !default;
7+
$mat-vertical-content-container-padding: 8px !default;
8+
$mat-connector-line-width: 1px !default;
9+
$mat-connector-line-gap: 8px !default;
10+
$mat-horizontal-connector-line-size: 5% !default;
11+
$mat-vertical-stepper-margin-top: $mat-stepper-side-gap - $mat-connector-line-gap !default;
12+
13+
:host {
14+
display: block;
15+
padding: 0 $mat-stepper-side-gap $mat-stepper-side-gap $mat-stepper-side-gap;
16+
}
17+
18+
.mat-stepper-label {
19+
display: inline-flex;
20+
white-space: nowrap;
21+
overflow: hidden;
22+
// TODO(jwshin): text-overflow does not work as expected.
23+
text-overflow: ellipsis;
24+
min-width: $mat-stepper-label-min-width;
25+
}
26+
27+
.mat-stepper-index {
28+
border-radius: 50%;
29+
height: $mat-label-header-height;
30+
width: $mat-label-header-height;
31+
text-align: center;
32+
line-height: $mat-label-header-height;
33+
}
34+
35+
.mat-horizontal-stepper-header-container {
36+
white-space: nowrap;
37+
display: flex;
38+
align-items: center;
39+
}
40+
41+
.mat-horizontal-stepper-header {
42+
display: inline-flex;
43+
line-height: $mat-horizontal-stepper-header-height;
44+
overflow: hidden;
45+
align-items: center;
46+
47+
.mat-stepper-index {
48+
margin-right: $mat-connector-line-gap;
49+
display: inline-block;
50+
flex: none;
51+
}
52+
}
53+
54+
.mat-vertical-stepper-header {
55+
display: flex;
56+
align-items: center;
57+
margin: $mat-connector-line-gap 0;
58+
59+
.mat-stepper-index {
60+
margin-right: $mat-vertical-stepper-content-margin;
61+
}
362
}
463

5-
.mat-stepper-index, .mat-stepper-label {
6-
display: inline-block;
64+
.connector-line {
65+
border-top-width: $mat-connector-line-width;
66+
border-top-style: solid;
67+
width: $mat-horizontal-connector-line-size;
68+
flex: auto;
69+
margin: 0 $mat-connector-line-gap;
70+
height: 0;
71+
}
72+
73+
.mat-horizontal-stepper-content[aria-expanded='false'] {
74+
display: none;
75+
}
76+
77+
.vertical-content-container {
78+
border-left-width: $mat-connector-line-width;
79+
border-left-style: solid;
80+
margin-left: $mat-vertical-stepper-content-margin;
81+
padding: $mat-vertical-content-container-padding 0;
82+
}
83+
84+
.mat-vertical-stepper-content {
85+
padding-left: $mat-stepper-side-gap;
86+
87+
&[aria-expanded='false'] {
88+
display: none;
89+
}
90+
91+
&[aria-expanded='true'] {
92+
padding: $mat-vertical-stepper-content-padding;
93+
}
94+
}
95+
96+
.mat-step {
97+
margin-top: $mat-connector-line-gap;
98+
99+
&:last-child {
100+
.vertical-content-container {
101+
border: none;
102+
}
103+
}
104+
105+
&:first-child {
106+
margin-top: 0;
107+
padding-top: $mat-vertical-stepper-margin-top;
108+
}
7109
}

src/lib/stepper/stepper.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ import {MdStepLabel} from './step-label';
2323
@Component({
2424
moduleId: module.id,
2525
selector: 'md-step, mat-step',
26-
templateUrl: 'step.html',
26+
templateUrl: 'step.html'
2727
})
2828
export class MdStep extends CdkStep {
2929
/** Content for step label given by <ng-template matStepLabel> or <ng-template mdStepLabel>. */

0 commit comments

Comments
 (0)