-
Notifications
You must be signed in to change notification settings - Fork 6.8k
feat(stepper): Add animation to stepper #6361
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 4 commits
a43faac
23ebe6f
15a04f4
31e2197
6346757
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -20,7 +20,7 @@ import { | |
Component, | ||
ContentChild, | ||
ViewChild, | ||
TemplateRef | ||
TemplateRef, AfterContentChecked | ||
} from '@angular/core'; | ||
import {LEFT_ARROW, RIGHT_ARROW, ENTER, SPACE} from '@angular/cdk/keyboard'; | ||
import {CdkStepLabel} from './step-label'; | ||
|
@@ -30,6 +30,12 @@ import {AbstractControl} from '@angular/forms'; | |
/** Used to generate unique ID for each stepper component. */ | ||
let nextId = 0; | ||
|
||
/** | ||
* Position state of the content of each step in horizontal stepper that is used for transitioning | ||
* the content into correct position upon step selection change. | ||
*/ | ||
export type CdkStepContentPositionState = 'left' | 'center' | 'right'; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can this be generalized such that it isn't only for horizontal steps? Maybe There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Don't need to prefix this with |
||
|
||
/** Change event emitted on selection changes. */ | ||
export class CdkStepperSelectionEvent { | ||
/** Index of the step now selected. */ | ||
|
@@ -71,6 +77,20 @@ export class CdkStep { | |
@Input() | ||
label: string; | ||
|
||
/** Position state of step. */ | ||
_position: CdkStepContentPositionState; | ||
|
||
/** Sets the CdkStepContentPositionState of step. */ | ||
set position(position: number) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Rather than having a setter for this and reading the property, why not just always read a function like |
||
if (position < 0) { | ||
this._position = 'left'; | ||
} else if (position > 0) { | ||
this._position = 'right'; | ||
} else { | ||
this._position = 'center'; | ||
} | ||
} | ||
|
||
constructor(private _stepper: CdkStepper) { } | ||
|
||
/** Selects this step component. */ | ||
|
@@ -86,7 +106,7 @@ export class CdkStep { | |
'(keydown)': '_onKeydown($event)' | ||
}, | ||
}) | ||
export class CdkStepper { | ||
export class CdkStepper implements AfterContentChecked { | ||
/** The list of step components that the stepper is holding. */ | ||
@ContentChildren(CdkStep) _steps: QueryList<CdkStep>; | ||
|
||
|
@@ -106,6 +126,7 @@ export class CdkStepper { | |
if (this._selectedIndex != index && !this._anyControlsInvalid(index)) { | ||
this._emitStepperSelectionEvent(index); | ||
this._focusStep(this._selectedIndex); | ||
this._setStepPosition(); | ||
} | ||
} | ||
private _selectedIndex: number = 0; | ||
|
@@ -131,6 +152,10 @@ export class CdkStepper { | |
this._groupId = nextId++; | ||
} | ||
|
||
ngAfterContentChecked(): void { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is called every change detection run, which seems like it may be overkill. Can you clarify why this is necessary? Would There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Now neither is needed with the new change :) |
||
this._setStepPosition(); | ||
} | ||
|
||
/** Selects and focuses the next step in list. */ | ||
next(): void { | ||
this.selectedIndex = Math.min(this._selectedIndex + 1, this._steps.length - 1); | ||
|
@@ -181,6 +206,11 @@ export class CdkStepper { | |
event.preventDefault(); | ||
} | ||
|
||
/** Get whether a step has 'expanded' or 'collapsed' state for vertical stepper. */ | ||
_getExpandedState(index: number) { | ||
return index == this._selectedIndex ? 'expanded' : 'collapsed'; | ||
} | ||
|
||
private _focusStep(index: number) { | ||
this._focusIndex = index; | ||
this._stepHeader.toArray()[this._focusIndex].nativeElement.focus(); | ||
|
@@ -198,4 +228,14 @@ export class CdkStepper { | |
} | ||
return false; | ||
} | ||
|
||
/** | ||
* Set the shifted index position of each step in horizontal stepper, where zero represents | ||
* the selected step. | ||
*/ | ||
private _setStepPosition() { | ||
this._steps.forEach((step: CdkStep, index: number) => { | ||
step.position = index - this._selectedIndex; | ||
}); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,6 +8,7 @@ | |
|
||
import {Component} from '@angular/core'; | ||
import {MdStepper} from './stepper'; | ||
import {animate, state, style, transition, trigger} from '@angular/animations'; | ||
|
||
@Component({ | ||
moduleId: module.id, | ||
|
@@ -19,6 +20,15 @@ import {MdStepper} from './stepper'; | |
'class': 'mat-stepper-horizontal', | ||
'role': 'tablist', | ||
}, | ||
animations: [ | ||
trigger('stepEnterExit', [ | ||
state('left', style({transform: 'translate3d(-100%, 0, 0)'})), | ||
state('center', style({transform: 'translate3d(0%, 0, 0)'})), | ||
state('right', style({transform: 'translate3d(100%, 0, 0)'})), | ||
transition('* => left, * => right, left => center, right => center', | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could you do |
||
animate('500ms cubic-bezier(0.35, 0, 0.25, 1)')) | ||
]) | ||
], | ||
providers: [{provide: MdStepper, useExisting: MdHorizontalStepper}] | ||
}) | ||
export class MdHorizontalStepper extends MdStepper { } |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,9 +1,11 @@ | ||
@import '../core/style/variables'; | ||
|
||
$mat-horizontal-stepper-header-height: 72px !default; | ||
$mat-label-header-height: 24px !default; | ||
$mat-stepper-label-min-width: 50px !default; | ||
$mat-stepper-side-gap: 24px !default; | ||
$mat-vertical-stepper-content-margin: 12px !default; | ||
$mat-vertical-stepper-content-padding: 16px 0 32px $mat-stepper-side-gap !default; | ||
$mat-vertical-content-padding-bottom: 32px !default; | ||
$mat-vertical-content-container-padding: 8px !default; | ||
$mat-connector-line-width: 1px !default; | ||
$mat-connector-line-gap: 8px !default; | ||
|
@@ -43,6 +45,7 @@ $mat-vertical-stepper-margin-top: $mat-stepper-side-gap - $mat-connector-line-ga | |
line-height: $mat-horizontal-stepper-header-height; | ||
overflow: hidden; | ||
align-items: center; | ||
outline: none; | ||
|
||
.mat-stepper-index { | ||
margin-right: $mat-connector-line-gap; | ||
|
@@ -55,6 +58,7 @@ $mat-vertical-stepper-margin-top: $mat-stepper-side-gap - $mat-connector-line-ga | |
display: flex; | ||
align-items: center; | ||
margin: $mat-connector-line-gap 0; | ||
outline: none; | ||
|
||
.mat-stepper-index { | ||
margin-right: $mat-vertical-stepper-content-margin; | ||
|
@@ -70,8 +74,16 @@ $mat-vertical-stepper-margin-top: $mat-stepper-side-gap - $mat-connector-line-ga | |
height: 0; | ||
} | ||
|
||
.mat-horizontal-stepper-content[aria-expanded='false'] { | ||
display: none; | ||
.mat-horizontal-stepper-content { | ||
overflow: hidden; | ||
|
||
&[aria-expanded='false'] { | ||
height: 0; | ||
} | ||
} | ||
|
||
.horizontal-content-container { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Prefix all css classes with |
||
overflow: hidden; | ||
} | ||
|
||
.vertical-content-container { | ||
|
@@ -83,14 +95,11 @@ $mat-vertical-stepper-margin-top: $mat-stepper-side-gap - $mat-connector-line-ga | |
|
||
.mat-vertical-stepper-content { | ||
padding-left: $mat-stepper-side-gap; | ||
overflow: hidden; | ||
} | ||
|
||
&[aria-expanded='false'] { | ||
display: none; | ||
} | ||
|
||
&[aria-expanded='true'] { | ||
padding: $mat-vertical-stepper-content-padding; | ||
} | ||
.vertical-content { | ||
padding-bottom: $mat-vertical-content-padding-bottom; | ||
} | ||
|
||
.mat-step { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does this need to take RTL into consideration?
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, it would need to once the
Directionality
related things are added to stepper, but I haven't added any code dealing withDirectionality
. I am thinking about addressing them all at once, since it will also influence other interactions such as_foucsIndex
management for horizontal stepper.