mirror of
https://github.com/angular/angular.git
synced 2026-09-14 13:54:52 +08:00
Stepper alternative label (#12674)
Added the "alternative label" version, as by [(old) spec](https://material.io/archive/guidelines/components/steppers.html#steppers-types-of-steppers). Tryed on Chrome, Firefox, Edge and IE11 and everything seems fine. Added a paragraph in the stepper documentation and an example. I'm not sure the code style is ok so if you have suggestions I'll be happy to clean it up a bit, just tell me how :)
This commit is contained in:
@@ -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`.
|
||||
|
||||
@@ -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;
|
||||
@@ -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 {
|
||||
@@ -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 {
|
||||
@@ -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 {
|
||||
|
||||
@@ -27,6 +27,7 @@ import {
|
||||
EventEmitter,
|
||||
forwardRef,
|
||||
Inject,
|
||||
Input,
|
||||
Optional,
|
||||
Output,
|
||||
QueryList,
|
||||
@@ -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';
|
||||
|
||||
@@ -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',
|
||||
},
|
||||
@@ -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,
|
||||
|
||||
+1
@@ -0,0 +1 @@
|
||||
/** No CSS for this example */
|
||||
+33
@@ -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>
|
||||
+26
@@ -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]
|
||||
});
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user