Skip to content

Commit

Permalink
feat(theme): add Stepper component
Browse files Browse the repository at this point in the history
  • Loading branch information
nnixaa committed Jun 26, 2018
1 parent 8ef7412 commit d474598
Show file tree
Hide file tree
Showing 24 changed files with 919 additions and 0 deletions.
34 changes: 34 additions & 0 deletions docs/assets/images/components/stepper.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
9 changes: 9 additions & 0 deletions docs/structure.ts
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,15 @@ export const structure = [
'NbRouteTabsetComponent',
],
},
{
type: 'tabs',
name: 'Stepper',
icon: 'stepper.svg',
source: [
'NbStepperComponent',
'NbStepComponent',
]
},
{
type: 'tabs',
name: 'Chat UI',
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
/**
* @license
* Copyright Akveo. All Rights Reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*/

@mixin nb-stepper-theme {

nb-stepper {

&.horizontal {
.header .step {
width: nb-theme(stepper-index-size);
margin: 0 nb-theme(stepper-index-size) / 2;
}

.header .connector {
margin-top: nb-theme(stepper-index-size) / 2;
}
}

&.vertical {
.header .connector {
margin: nb-theme(stepper-index-size) / 2;
}
}

.header {
.connector {
background-color: nb-theme(stepper-fg);
}

.connector-past {
background-color: nb-theme(stepper-accent-color);
}

.label {
font-size: nb-theme(stepper-label-font-size);
font-weight: nb-theme(stepper-label-font-weight);
color: nb-theme(stepper-fg);
}

.label-index {
width: nb-theme(stepper-index-size);
height: nb-theme(stepper-index-size);
border-radius: nb-theme(stepper-index-size) / 2;
border: 2px solid nb-theme(stepper-fg);
color: nb-theme(stepper-fg);
font-weight: nb-theme(stepper-label-font-weight);

.icon {
font-size: nb-theme(stepper-completed-icon-size);
font-weight: nb-theme(stepper-completed-icon-weight);
}
}

.step {

&.selected {
.label-index {
border: 2px solid nb-theme(stepper-accent-color);
color: nb-theme(stepper-accent-color);
}
.label {
color: nb-theme(stepper-accent-color);
}
}

&.completed {
.label-index {
background-color: nb-theme(stepper-accent-color);
border: 2px solid nb-theme(stepper-accent-color);
color: nb-theme(stepper-completed-fg);
}
.label {
color: nb-theme(stepper-accent-color);
}
}
}
}

.step-content {
padding: nb-theme(stepper-step-padding);
}
}
}
105 changes: 105 additions & 0 deletions src/framework/theme/components/stepper/step.component.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
import {
Component,
forwardRef,
Inject,
Input,
TemplateRef,
ViewChild,
} from '@angular/core';
import { AbstractControl } from '@angular/forms';
import { NbStepperComponent } from './stepper.component';
import { convertToBoolProperty } from '../helpers';

/**
* Component intended to be used within the `<nb-stepper>` component.
* Container for a step
*/
@Component({
selector: 'nb-step',
template: `
<ng-template>
<ng-content></ng-content>
</ng-template>
`,
})
export class NbStepComponent {

/**
* Step content
*
* @type {TemplateRef}
*/
@ViewChild(TemplateRef) content: TemplateRef<any>;

/**
* Top level abstract control of the step
*
* @type {AbstractControl}
*/
@Input() stepControl: AbstractControl;

/**
* Step label
*
* @type {string|TemplateRef<any>}
*/
@Input() label: string|TemplateRef<any>;

/**
* Whether step will be displayed in wizard
*
* @type {boolean}
*/
@Input() hidden: false;

/**
* Check that label is a TemplateRef.
*
* @return boolean
* */
get isLabelTemplate(): boolean {
return this.label instanceof TemplateRef;
}

/**
* Whether step is marked as completed.
*
* @type {boolean}
*/
@Input()
get completed(): boolean {
return this.completedValue || this.isCompleted;
}

set completed(value: boolean) {
this.completedValue = convertToBoolProperty(value);
}

private completedValue: boolean = false;

private get isCompleted() {
return this.stepControl ? this.stepControl.valid && this.interacted : this.interacted;
}

interacted = false;

constructor(@Inject(forwardRef(() => NbStepperComponent)) private stepper: NbStepperComponent) {
}

/**
* Mark step as selected
* */
select(): void {
this.stepper.selected = this;
}

/**
* Reset step and stepControl state
* */
reset(): void {
this.interacted = false;
if (this.stepControl) {
this.stepControl.reset();
}
}
}
34 changes: 34 additions & 0 deletions src/framework/theme/components/stepper/stepper-button.directive.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { NbStepperComponent } from './stepper.component';
import { Directive, HostBinding, HostListener, Input } from '@angular/core';

@Directive({
selector: 'button[nbStepperNext]',
})
export class NbStepperNextDirective {

@Input() @HostBinding('attr.type') type: string = 'submit';

constructor(private stepper: NbStepperComponent) {
}

@HostListener('click')
onClick() {
this.stepper.next();
}
}

@Directive({
selector: 'button[nbStepperPrevious]',
})
export class NbStepperPreviousDirective {

@Input() @HostBinding('attr.type') type: string = 'button';

constructor(private stepper: NbStepperComponent) {
}

@HostListener('click')
onClick() {
this.stepper.previous();
}
}
28 changes: 28 additions & 0 deletions src/framework/theme/components/stepper/stepper.component.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<ng-template><ng-content select="nb-step"></ng-content></ng-template>
<div class="header">
<ng-container *ngFor="let step of steps; let index = index; let first = first">

<div *ngIf="!first && !step.hidden"
[class.connector-past]="index < selectedIndex"
class="connector"></div>

<div *ngIf="!step.hidden" class="step"
[class.selected]="isStepSelected(step)"
[class.completed]="!isStepSelected(step) && step.completed"
(click)="step.select()">
<div class="label-index">
<span *ngIf="!step.completed || isStepSelected(step)">{{ index + 1 }}</span>
<i *ngIf="!isStepSelected(step) && step.completed" class="icon nb-checkmark"></i>
</div>
<div class="label">
<ng-container *ngIf="step.isLabelTemplate">
<ng-container *ngTemplateOutlet="step.label"></ng-container>
</ng-container>
<span *ngIf="!step.isLabelTemplate">{{ step.label }}</span>
</div>
</div>
</ng-container>
</div>
<div class="step-content">
<ng-container [ngTemplateOutlet]="selected?.content"></ng-container>
</div>
56 changes: 56 additions & 0 deletions src/framework/theme/components/stepper/stepper.component.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
:host {
&.horizontal .header {
.step {
flex-direction: column;
}

.connector {
height: 2px;
}
}

&.vertical {
display: flex;
height: 100%;

.header {
flex-direction: column;

.label {
margin: 0 10px;
}

.connector {
width: 2px;
}
}
}
}

.header {
display: flex;
justify-content: space-between;
align-items: flex-start;
margin-bottom: 10px;

.connector {
flex: auto;
}

.step {
display: flex;
align-items: center;
cursor: pointer;
}

.label-index {
margin-bottom: 10px;
display: flex;
justify-content: center;
align-items: center;
}

.label {
width: max-content;
}
}
Loading

0 comments on commit d474598

Please sign in to comment.