Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions src/lib/stepper/stepper.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -40,6 +40,12 @@ For more complex labels, add a template with the `matStepLabel` directive inside
</mat-vertical-stepper>
```

#### Label position
For `mat-horizontal-stepper` it's possible to define the position of the label. `end` is the default value, while `bottom` will place it under the step icon instead of at its side.
This behaviour is controlled by `labelPosition` property.

<!-- example(stepper-label-position-bottom) -->

### Stepper buttons
There are two button directives to support navigation between different steps:
`matStepperPrevious` and `matStepperNext`.
Expand Down
58 changes: 58 additions & 0 deletions src/lib/stepper/stepper.scss
Original file line numberDiff line numberDiff line change
Expand Up@@ -2,6 +2,7 @@

$mat-horizontal-stepper-header-height: 72px !default;
$mat-stepper-label-header-height: 24px !default;
$mat-stepper-label-position-bottom-top-gap: 16px !default;
$mat-stepper-side-gap: 24px !default;
$mat-vertical-stepper-content-margin: 36px !default;
$mat-stepper-line-width: 1px !default;
Expand All@@ -16,6 +17,10 @@ $mat-stepper-line-gap: 8px !default;
white-space: nowrap;
display: flex;
align-items: center;

.mat-stepper-label-position-bottom & {
align-items: flex-start;
}
}

.mat-stepper-horizontal-line {
Expand All@@ -25,6 +30,25 @@ $mat-stepper-line-gap: 8px !default;
height: 0;
margin: 0 $mat-stepper-line-gap - $mat-stepper-side-gap;
min-width: $mat-stepper-line-gap + $mat-stepper-side-gap;

.mat-stepper-label-position-bottom & {
margin: 0;
min-width: 0;
position: relative;
top: $mat-stepper-side-gap + $mat-stepper-label-header-height / 2;
}
}

%mat-header-horizontal-line-label-position-bottom {
border-top-color: rgba(0, 0, 0, 0.12);
border-top-width: $mat-stepper-line-width;
border-top-style: solid;
content: '';
display: inline-block;
height: 0;
position: absolute;
top: $mat-stepper-side-gap + $mat-stepper-label-header-height / 2;
width: calc(50% - #{$mat-stepper-label-header-height / 2 + $mat-stepper-line-gap});
}

.mat-horizontal-stepper-header {
Expand All@@ -43,6 +67,40 @@ $mat-stepper-line-gap: 8px !default;
margin-left: $mat-stepper-line-gap;
}
}

.mat-stepper-label-position-bottom & {
box-sizing: border-box;
flex-direction: column;
// We use auto instead of fixed 104px (by spec) because when there is an optional step
// the height is greater than that
height: auto;
padding: $mat-stepper-side-gap;

[dir='ltr'] &:not(:last-child)::after,
[dir='rtl'] &:not(:first-child)::after {
@extend %mat-header-horizontal-line-label-position-bottom;
right: 0;
}

[dir='ltr'] &:not(:first-child)::before,
[dir='rtl'] &:not(:last-child)::before {
@extend %mat-header-horizontal-line-label-position-bottom;
left: 0;
}

& .mat-step-icon,
& .mat-step-icon-not-touched {
// Cleans margin both for ltr and rtl direction
margin-right: 0;
margin-left: 0;
}

& .mat-step-label {
padding: $mat-stepper-label-position-bottom-top-gap 0 0 0;
text-align: center;
width: 100%;
}
}
}

.mat-vertical-stepper-header {
Expand Down
12 changes: 10 additions & 2 deletions src/lib/stepper/stepper.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -27,6 +27,7 @@ import {
EventEmitter,
forwardRef,
Inject,
Input,
Optional,
Output,
QueryList,
Expand All@@ -38,9 +39,10 @@ import {
import {FormControl, FormGroupDirective, NgForm} from '@angular/forms';
import {DOCUMENT} from '@angular/common';
import {ErrorStateMatcher} from '@angular/material/core';
import {takeUntil} from 'rxjs/operators';

import {MatStepHeader} from './step-header';
import {MatStepLabel} from './step-label';
import {takeUntil} from 'rxjs/operators';
import {matStepperAnimations} from './stepper-animations';
import {MatStepperIcon, MatStepperIconContext} from './stepper-icon';

Expand DownExpand Up@@ -124,6 +126,8 @@ export class MatStepper extends _CdkStepper implements AfterContentInit {
inputs: ['selectedIndex'],
host: {
'class': 'mat-stepper-horizontal',
'[class.mat-stepper-label-position-end]': 'labelPosition == "end"',
'[class.mat-stepper-label-position-bottom]': 'labelPosition == "bottom"',
'aria-orientation': 'horizontal',
'role': 'tablist',
},
Expand All@@ -132,7 +136,11 @@ export class MatStepper extends _CdkStepper implements AfterContentInit {
encapsulation: ViewEncapsulation.None,
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class MatHorizontalStepper extends MatStepper { }
export class MatHorizontalStepper extends MatStepper {
/** Whether the label should display in bottom or end position. */
@Input()
labelPosition: 'bottom' | 'end' = 'end';
}

@Component({
moduleId: module.id,
Expand Down
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
/** No CSS for this example */
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
<mat-horizontal-stepper labelPosition="bottom" #stepper>
<mat-step [stepControl]="firstFormGroup">
<form [formGroup]="firstFormGroup">
<ng-template matStepLabel>Fill out your name</ng-template>
<mat-form-field>
<input matInput placeholder="Last name, First name" formControlName="firstCtrl" required>
</mat-form-field>
<div>
<button mat-button matStepperNext>Next</button>
</div>
</form>
</mat-step>
<mat-step [stepControl]="secondFormGroup" optional>
<form [formGroup]="secondFormGroup">
<ng-template matStepLabel>Fill out your address</ng-template>
<mat-form-field>
<input matInput placeholder="Address" formControlName="secondCtrl" required>
</mat-form-field>
<div>
<button mat-button matStepperPrevious>Back</button>
<button mat-button matStepperNext>Next</button>
</div>
</form>
</mat-step>
<mat-step>
<ng-template matStepLabel>Done</ng-template>
You are now done.
<div>
<button mat-button matStepperPrevious>Back</button>
<button mat-button (click)="stepper.reset()">Reset</button>
</div>
</mat-step>
</mat-horizontal-stepper>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
import {Component, OnInit} from '@angular/core';
import {FormBuilder, FormGroup, Validators} from '@angular/forms';

/**
* @title Stepper label bottom position
*/
@Component({
selector: 'stepper-label-position-bottom-example',
templateUrl: 'stepper-label-position-bottom-example.html',
styleUrls: ['stepper-label-position-bottom-example.css'],
})
export class StepperLabelPositionBottomExample implements OnInit {
firstFormGroup: FormGroup;
secondFormGroup: FormGroup;

constructor(private _formBuilder: FormBuilder) {}

ngOnInit() {
this.firstFormGroup = this._formBuilder.group({
firstCtrl: ['', Validators.required]
});
this.secondFormGroup = this._formBuilder.group({
secondCtrl: ['', Validators.required]
});
}
}