Skip to content
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

feat(tab-nav-bar): add initial functionality of tab nav bar #1589

Merged
merged 10 commits into from
Oct 26, 2016
6 changes: 2 additions & 4 deletions src/demo-app/demo-app-module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,7 @@ import {SidenavDemo} from './sidenav/sidenav-demo';
import {SnackBarDemo} from './snack-bar/snack-bar-demo';
import {PortalDemo, ScienceJoke} from './portal/portal-demo';
import {MenuDemo} from './menu/menu-demo';
import {TabsDemo} from './tabs/tab-group-demo';


import {TabsDemoModule} from './tabs/tabs-demo.module';

@NgModule({
imports: [
Expand All @@ -43,6 +41,7 @@ import {TabsDemo} from './tabs/tab-group-demo';
HttpModule,
RouterModule.forRoot(DEMO_APP_ROUTES),
MaterialModule.forRoot(),
TabsDemoModule,
],
declarations: [
BaselineDemo,
Expand Down Expand Up @@ -76,7 +75,6 @@ import {TabsDemo} from './tabs/tab-group-demo';
SliderDemo,
SlideToggleDemo,
SpagettiPanel,
TabsDemo,
ToolbarDemo,
TooltipDemo,
],
Expand Down
6 changes: 3 additions & 3 deletions src/demo-app/demo-app/routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import {Home} from './demo-app';
import {ButtonDemo} from '../button/button-demo';
import {BaselineDemo} from '../baseline/baseline-demo';
import {ButtonToggleDemo} from '../button-toggle/button-toggle-demo';
import {TabsDemo} from '../tabs/tab-group-demo';
import {TabsDemo} from '../tabs/tabs-demo';
import {GridListDemo} from '../grid-list/grid-list-demo';
import {GesturesDemo} from '../gestures/gestures-demo';
import {LiveAnnouncerDemo} from '../live-announcer/live-announcer-demo';
Expand All @@ -27,7 +27,7 @@ import {RippleDemo} from '../ripple/ripple-demo';
import {DialogDemo} from '../dialog/dialog-demo';
import {TooltipDemo} from '../tooltip/tooltip-demo';
import {SnackBarDemo} from '../snack-bar/snack-bar-demo';

import {TABS_DEMO_ROUTES} from '../tabs/routes';

export const DEMO_APP_ROUTES: Routes = [
{path: '', component: Home},
Expand All @@ -51,7 +51,7 @@ export const DEMO_APP_ROUTES: Routes = [
{path: 'live-announcer', component: LiveAnnouncerDemo},
{path: 'gestures', component: GesturesDemo},
{path: 'grid-list', component: GridListDemo},
{path: 'tabs', component: TabsDemo},
{path: 'tabs', component: TabsDemo, children: TABS_DEMO_ROUTES},
{path: 'button-toggle', component: ButtonToggleDemo},
{path: 'baseline', component: BaselineDemo},
{path: 'ripple', component: RippleDemo},
Expand Down
10 changes: 10 additions & 0 deletions src/demo-app/tabs/routes.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import {Routes} from '@angular/router';

import {SunnyTabContent, RainyTabContent, FoggyTabContent} from '../tabs/tabs-demo';

export const TABS_DEMO_ROUTES: Routes = [
{path: '', redirectTo: 'sunny-tab', pathMatch: 'full'},
{path: 'sunny-tab', component: SunnyTabContent},
{path: 'rainy-tab', component: RainyTabContent},
{path: 'foggy-tab', component: FoggyTabContent},
];
9 changes: 0 additions & 9 deletions src/demo-app/tabs/tab-group-demo.scss

This file was deleted.

26 changes: 0 additions & 26 deletions src/demo-app/tabs/tab-group-demo.ts

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,3 +1,19 @@
<h1>Tab Nav Bar</h1>

<div class="demo-nav-bar">
<nav md-tab-nav-bar aria-label="weather navigation links">
<a md-tab-link
*ngFor="let tabLink of tabLinks; let i = index"
[routerLink]="tabLink.link"
[active]="activeLinkIndex === i"
(click)="activeLinkIndex = i">
{{tabLink.label}}
</a>
</nav>
<router-outlet></router-outlet>
</div>


<h1>Tab Group Demo</h1>

<md-tab-group class="demo-tab-group">
Expand All @@ -13,6 +29,7 @@ <h1>Tab Group Demo</h1>
</md-tab>
</md-tab-group>


<h1>Async Tabs</h1>

<md-tab-group class="demo-tab-group">
Expand Down
23 changes: 23 additions & 0 deletions src/demo-app/tabs/tabs-demo.module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import {NgModule} from '@angular/core';
import {MaterialModule} from '@angular/material';
import {FormsModule} from '@angular/forms';
import {BrowserModule} from '@angular/platform-browser';
import {RouterModule} from '@angular/router';

import {TabsDemo, SunnyTabContent, RainyTabContent, FoggyTabContent} from './tabs-demo';

@NgModule({
imports: [
FormsModule,
BrowserModule,
MaterialModule,
RouterModule,
],
declarations: [
TabsDemo,
SunnyTabContent,
RainyTabContent,
FoggyTabContent,
]
})
export class TabsDemoModule {}
22 changes: 22 additions & 0 deletions src/demo-app/tabs/tabs-demo.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
.demo-nav-bar {
border: 1px solid #e0e0e0;
[md-tab-nav-bar] {
background: #f9f9f9;
}
sunny-routed-content,
rainy-routed-content,
foggy-routed-content {
display: block;
padding: 12px;
}
}

.demo-tab-group {
border: 1px solid #e0e0e0;
.md-tab-header {
background: #f9f9f9;
}
.md-tab-body {
padding: 12px;
}
}
65 changes: 65 additions & 0 deletions src/demo-app/tabs/tabs-demo.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import {Component, ViewEncapsulation} from '@angular/core';
import {Router} from '@angular/router';
import {Observable} from 'rxjs/Observable';

@Component({
moduleId: module.id,
selector: 'tabs-demo',
templateUrl: 'tabs-demo.html',
styleUrls: ['tabs-demo.css'],
encapsulation: ViewEncapsulation.None,
})
export class TabsDemo {
tabLinks = [
{ label: 'Sun', link: 'sunny-tab'},
{ label: 'Rain', link: 'rainy-tab'},
{ label: 'Fog', link: 'foggy-tab'},
];
activeLinkIndex = 0;

tabs = [
{ label: 'Tab One', content: 'This is the body of the first tab' },
{ label: 'Tab Two', content: 'This is the body of the second tab' },
{ label: 'Tab Three', content: 'This is the body of the third tab' },
];

asyncTabs: Observable<any>;

constructor(private router: Router) {
this.asyncTabs = Observable.create((observer: any) => {
setTimeout(() => {
observer.next(this.tabs);
}, 1000);
});

// Initialize the index by checking if a tab link is contained in the url.
// This is not an ideal check and can be removed if routerLink exposes if it is active.
// https://github.com/angular/angular/pull/12525
this.activeLinkIndex =
this.tabLinks.findIndex(routedTab => router.url.indexOf(routedTab.link) != -1);
}
}


@Component({
moduleId: module.id,
selector: 'sunny-routed-content',
template: 'This is the routed body of the sunny tab.',
})
export class SunnyTabContent {}


@Component({
moduleId: module.id,
selector: 'rainy-routed-content',
template: 'This is the routed body of the rainy tab.',
})
export class RainyTabContent {}


@Component({
moduleId: module.id,
selector: 'foggy-routed-content',
template: 'This is the routed body of the foggy tab.',
})
export class FoggyTabContent {}
1 change: 1 addition & 0 deletions src/lib/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,6 @@ export * from './slider/index';
export * from './slide-toggle/index';
export * from './snack-bar/index';
export * from './tabs/index';
export * from './tabs/tab-nav-bar/index';
export * from './toolbar/index';
export * from './tooltip/index';
40 changes: 40 additions & 0 deletions src/lib/tabs/_tabs-common.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
@import '../core/style/variables';

$md-tab-bar-height: 48px !default;

// Mixin styles for labels that are contained within the tab header.
@mixin tab-label {
line-height: $md-tab-bar-height;
height: $md-tab-bar-height;
padding: 0 12px;
font-size: $md-body-font-size-base;
font-family: $md-font-family;
font-weight: 500;
cursor: pointer;
box-sizing: border-box;
color: currentColor;
opacity: 0.6;
min-width: 160px;
text-align: center;
&:focus {
outline: none;
opacity: 1;
}
}

// Mixin styles for the top section of the view; contains the tab labels.
@mixin tab-header {
overflow: hidden;
position: relative;
display: flex;
flex-direction: row;
flex-shrink: 0;
}

// Mixin styles for the ink bar that displays near the active tab in the header.
@mixin ink-bar {
position: absolute;
bottom: 0;
height: 2px;
transition: 350ms ease-out;
}
3 changes: 2 additions & 1 deletion src/lib/tabs/_tabs-theme.scss
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@
$warn: map-get($theme, warn);
$background: map-get($theme, background);
$foreground: map-get($theme, foreground);


[md-tab-nav-bar],
.md-tab-header {
border-bottom: 1px solid md-color($background, status-bar);
}
Expand Down
49 changes: 13 additions & 36 deletions src/lib/tabs/tab-group.scss
Original file line number Diff line number Diff line change
@@ -1,41 +1,20 @@
@import '../core/style/variables';


$md-tab-bar-height: 48px !default;
@import 'tabs-common';

:host {
display: flex;
flex-direction: column;
font-family: $md-font-family;
}

// The top section of the view; contains the tab labels
// Styling for the heading containing the tab labels
.md-tab-header {
overflow: hidden;
position: relative;
display: flex;
flex-direction: row;
flex-shrink: 0;
@include tab-header;
}

// Wraps each tab label
// Wraps each tab label
.md-tab-label {
line-height: $md-tab-bar-height;
height: $md-tab-bar-height;
padding: 0 12px;
font-size: $md-body-font-size-base;
font-family: $md-font-family;
font-weight: 500;
cursor: pointer;
box-sizing: border-box;
color: currentColor;
opacity: 0.6;
min-width: 160px;
text-align: center;
&:focus {
outline: none;
opacity: 1;
}
@include tab-label;
}

@media ($md-xsmall) {
Expand All @@ -44,9 +23,9 @@ $md-tab-bar-height: 48px !default;
}
}

.md-tab-disabled {
cursor: default;
pointer-events: none;
// The ink bar that displays next to the active tab
md-ink-bar {
@include ink-bar;
}

// The bottom section of the view; contains the tab bodies
Expand All @@ -69,10 +48,8 @@ $md-tab-bar-height: 48px !default;
}
}

// The colored bar that underlines the active tab
md-ink-bar {
position: absolute;
bottom: 0;
height: 2px;
transition: 350ms ease-out;
}
// Styling for any tab that is marked disabled
.md-tab-disabled {
cursor: default;
pointer-events: none;
}
1 change: 1 addition & 0 deletions src/lib/tabs/tab-nav-bar/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './tab-nav-bar';
2 changes: 2 additions & 0 deletions src/lib/tabs/tab-nav-bar/tab-nav-bar.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
<ng-content></ng-content>
<md-ink-bar></md-ink-bar>
Loading