Skip to content

Commit

Permalink
feat(tabs): ability to assign an icon (#607)
Browse files Browse the repository at this point in the history
Closes #288
  • Loading branch information
nnixaa authored Aug 7, 2018
1 parent 9be2fcb commit b78b8d3
Show file tree
Hide file tree
Showing 14 changed files with 293 additions and 105 deletions.
34 changes: 17 additions & 17 deletions e2e/route-tabset.e2e-spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,62 +10,62 @@ import { hasClass } from './e2e-helper';

describe('nb-route-tabset', () => {
beforeEach((done) => {
browser.get('#/tabset/route-tabset-test.component').then(() => done());
browser.get('#/tabset/route-tabset-showcase.component').then(() => done());
});

it('should display default route-tabset', () => {
expect(element(by.css('nb-route-tabset:nth-child(1) > ul > li:nth-child(1)'))
.getText()).toEqual('Tab #1');
expect(element(by.css('nb-card:nth-child(1) nb-route-tabset > ul > li:nth-child(1)'))
.getText()).toEqual('Users');

expect(element(by.css('nb-route-tabset:nth-child(1) > ul > li:nth-child(2)'))
.getText()).toEqual('Tab #2');
expect(element(by.css('nb-card:nth-child(1) nb-route-tabset > ul > li:nth-child(2)'))
.getText()).toEqual('Orders');
});

it('should change tabs of a route-tabset"', () => {
const tab2 = by.css('nb-route-tabset:nth-child(1) > ul > li:nth-child(2)');
const tab2 = by.css('nb-card:nth-child(1) nb-route-tabset > ul > li:nth-child(2)');

element(tab2).click()
.then(() => {
expect(hasClass(element(tab2), 'active')).toBeTruthy();
expect(browser.getCurrentUrl()).toContain('/#/tabset/route-tabset-test.component/tab2');
expect(browser.getCurrentUrl()).toContain('/#/tabset/route-tabset-showcase.component/tab2');
});

const tab1 = by.css('nb-route-tabset:nth-child(1) > ul > li:nth-child(1)');
const tab1 = by.css('nb-card:nth-child(1) nb-route-tabset > ul > li:nth-child(1)');

element(tab1).click()
.then(() => {
expect(hasClass(element(tab1), 'active')).toBeTruthy();
expect(browser.getCurrentUrl()).toContain('/#/tabset/route-tabset-test.component/tab1');
expect(browser.getCurrentUrl()).toContain('/#/tabset/route-tabset-showcase.component/tab1');
});
});

it('should display a full-width route-tabset', () => {
const tab1 = by.css('nb-route-tabset:nth-child(2) > ul > li:nth-child(1)');
const tab1 = by.css('nb-card:nth-child(2) nb-route-tabset > ul > li:nth-child(1)');

expect(element(tab1)
.getText()).toEqual('Tab #1');
.getText()).toEqual('Users');

const tab2 = by.css('nb-route-tabset:nth-child(2) > ul > li:nth-child(2)');
const tab2 = by.css('nb-card:nth-child(2) nb-route-tabset > ul > li:nth-child(2)');

expect(element(tab2)
.getText()).toEqual('Tab #2');
.getText()).toEqual('Orders');
});

it('should change tabs of a full-width route-tabset', () => {
const tab2 = by.css('nb-route-tabset:nth-child(2) > ul > li:nth-child(2)');
const tab2 = by.css('nb-card:nth-child(2) nb-route-tabset > ul > li:nth-child(2)');

element(tab2).click()
.then(() => {
expect(hasClass(element(tab2), 'active')).toBeTruthy();
expect(browser.getCurrentUrl()).toContain('/#/tabset/route-tabset-test.component/tab2');
expect(browser.getCurrentUrl()).toContain('/#/tabset/route-tabset-showcase.component/tab2');
});

const tab1 = by.css('nb-route-tabset:nth-child(2) > ul > li:nth-child(1)');
const tab1 = by.css('nb-card:nth-child(2) nb-route-tabset > ul > li:nth-child(1)');

element(tab1).click()
.then(() => {
expect(hasClass(element(tab1), 'active')).toBeTruthy();
expect(browser.getCurrentUrl()).toContain('/#/tabset/route-tabset-test.component/tab1');
expect(browser.getCurrentUrl()).toContain('/#/tabset/route-tabset-showcase.component/tab1');
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,14 @@
color: nb-theme(route-tabs-fg-heading);
}
}

&.responsive {
@media screen and (max-width: nb-theme(route-tabs-icon-only-max-width)) {
a span {
display: none;
}
}
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*/

@import '../../styles/core/mixins';

ul {
display: flex;
flex-direction: row;
Expand Down Expand Up @@ -34,6 +36,16 @@ ul {
bottom: -2px;
left: 0;
}

i {
font-size: 1.5rem;
vertical-align: middle;
}

i + span {
@include nb-ltr(margin-left, 0.5rem);
@include nb-rtl(margin-right, 0.5rem);
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ import { convertToBoolProperty } from '../helpers';
* {
* title: 'Route tab #1',
* route: '/pages/description',
* icon: 'nb-home',
* responsive: true, // hide title before `route-tabs-icon-only-max-width` value
* },
* {
* title: 'Route tab #2',
Expand All @@ -30,6 +32,8 @@ import { convertToBoolProperty } from '../helpers';
* <nb-route-tabset [tabs]="tabs"></nb-route-tabset>
* ```
*
* @stacked-example(Route Tabset, tabset/route-tabset-showcase.component)
*
* @styles
*
* route-tabs-font-family:
Expand All @@ -43,6 +47,7 @@ import { convertToBoolProperty } from '../helpers';
* route-tabs-fg-heading:
* route-tabs-bg:
* route-tabs-selected:
* route-tabs-icon-only-max-width:
*/
@Component({
selector: 'nb-route-tabset',
Expand All @@ -53,8 +58,12 @@ import { convertToBoolProperty } from '../helpers';
(click)="$event.preventDefault(); selectTab(tab)"
routerLink="{{tab.route}}"
routerLinkActive="active"
[routerLinkActiveOptions]="{ exact: true }">
<a href>{{tab.title}}</a>
[routerLinkActiveOptions]="{ exact: true }"
[class.responsive]="tab.responsive">
<a href>
<i *ngIf="tab.icon" [class]="tab.icon"></i>
<span *ngIf="tab.title">{{ tab.title }}</span>
</a>
</li>
</ul>
<router-outlet></router-outlet>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,14 @@
color: nb-theme(tabs-fg-heading);
}
}

&.responsive {
@media screen and (max-width: nb-theme(tabs-icon-only-max-width)) {
a span {
display: none;
}
}
}
}
}

Expand Down
67 changes: 39 additions & 28 deletions src/framework/theme/components/tabset/tabset.component.scss
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*/

@import '../../styles/core/mixins';

:host {
display: block;

Expand All @@ -21,38 +23,47 @@
display: block;
}
}
}
ul {
display: flex;
flex-direction: row;
list-style-type: none;
margin: 0;

ul {
display: flex;
flex-direction: row;
list-style-type: none;
margin: 0;
li {
cursor: pointer;
margin-bottom: -1px;
text-align: center;
position: relative;

li {
cursor: pointer;
margin-bottom: -1px;
text-align: center;
position: relative;
&.active a::before {
display: block;
}

&.active a::before {
display: block;
}
a {
display: flex;
position: relative;
text-decoration: none;

a {
position: relative;
text-decoration: none;
display: inline-block;

&::before {
display: none;
position: absolute;
content: '';
width: 100%;
height: 6px;
border-radius: 3px;
bottom: -2px;
left: 0;
&::before {
display: none;
position: absolute;
content: '';
width: 100%;
height: 6px;
border-radius: 3px;
bottom: -2px;
left: 0;
}

i {
font-size: 1.5rem;
vertical-align: middle;
}

i + span {
@include nb-ltr(margin-left, 0.5rem);
@include nb-rtl(margin-right, 0.5rem);
}
}
}
}
Expand Down
40 changes: 38 additions & 2 deletions src/framework/theme/components/tabset/tabset.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,13 +41,38 @@ import { convertToBoolProperty } from '../helpers';
})
export class NbTabComponent {

/**
* Tab title
* @type {string}
*/
@Input() tabTitle: string;

/**
* Tab icon
* @type {string}
*/
@Input() tabIcon: string;

/**
* Show only icons when width is smaller than `tabs-icon-only-max-width`
* @type {boolean}
*/
@Input()
set responsive(val: boolean) {
this.responsiveValue = convertToBoolProperty(val);
}

get responsive() {
return this.responsiveValue;
}

@Input() route: string;

@HostBinding('class.content-active')
activeValue: boolean = false;

responsiveValue: boolean = false;

/**
* Specifies active tab
* @returns {boolean}
Expand Down Expand Up @@ -125,6 +150,13 @@ export class NbTabComponent {
* and we can set it to full a width of a parent component
* @stacked-example(Full Width, tabset/tabset-width.component)
*
* `tabIcon` should be used to add an icon to the tab. Icon can also be combined with title.
* `responsive` tab property if set allows you to hide the title on smaller screens
* (`tabs-icon-only-max-width` property) for better responsive behaviour. You can open the following example and make
* your screen smaller - titles will be hidden in the last tabset in the list:
*
* @stacked-example(Icon, tabset/tabset-icon.component)
*
* @styles
*
* tabs-font-family:
Expand All @@ -142,8 +174,8 @@ export class NbTabComponent {
* tabs-fg-heading:
* tabs-bg:
* tabs-selected:
* tabs-icon-only-max-width
*
```
*/
@Component({
selector: 'nb-tabset',
Expand All @@ -152,8 +184,12 @@ export class NbTabComponent {
<ul>
<li *ngFor="let tab of tabs"
(click)="selectTab(tab)"
[class.responsive]="tab.responsive"
[class.active]="tab.active">
<a href (click)="$event.preventDefault()">{{ tab.tabTitle }}</a>
<a href (click)="$event.preventDefault()">
<i *ngIf="tab.tabIcon" [class]="tab.tabIcon"></i>
<span *ngIf="tab.tabTitle">{{ tab.tabTitle }}</span>
</a>
<nb-badge *ngIf="tab.badgeText"
[text]="tab.badgeText"
[status]="tab.badgeStatus"
Expand Down
2 changes: 2 additions & 0 deletions src/framework/theme/styles/themes/_default.scss
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,7 @@ $theme: (
tabs-fg-heading: color-fg-heading,
tabs-bg: transparent,
tabs-selected: color-success,
tabs-icon-only-max-width: 576px,

route-tabs-font-family: font-secondary,
route-tabs-font-size: font-size-lg,
Expand All @@ -222,6 +223,7 @@ $theme: (
route-tabs-fg-heading: color-fg-heading,
route-tabs-bg: transparent,
route-tabs-selected: color-success,
route-tabs-icon-only-max-width: 576px,

user-font-size: font-size,
user-line-height: line-height,
Expand Down
Loading

0 comments on commit b78b8d3

Please sign in to comment.