From 0cb0a1c6005a279ec4055448dae4b5fe7919665c Mon Sep 17 00:00:00 2001 From: Adam Bradley Date: Sat, 30 May 2015 20:51:56 -0500 Subject: [PATCH] basic tabs --- ionic/components/app/structure.scss | 16 ++++++++ ionic/components/tabs/tab-button.js | 40 +++++++++++++++++++ ionic/components/tabs/tab.js | 11 +++--- ionic/components/tabs/tabs.js | 60 ++++++++++++----------------- ionic/components/tabs/tabs.scss | 38 +++++++++--------- 5 files changed, 106 insertions(+), 59 deletions(-) create mode 100644 ionic/components/tabs/tab-button.js diff --git a/ionic/components/app/structure.scss b/ionic/components/app/structure.scss index b138e678ab..4af59411db 100644 --- a/ionic/components/app/structure.scss +++ b/ionic/components/app/structure.scss @@ -36,6 +36,22 @@ ion-tabs { padding: 0; } +ion-tab { + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + width: 100%; + height: 100%; + overflow: hidden; + + display: none; + &.show-tab { + display: block; + } +} + ion-nav { position: absolute; top: 0; diff --git a/ionic/components/tabs/tab-button.js b/ionic/components/tabs/tab-button.js new file mode 100644 index 0000000000..3130af7da7 --- /dev/null +++ b/ionic/components/tabs/tab-button.js @@ -0,0 +1,40 @@ +import {Parent} from 'angular2/src/core/annotations_impl/visibility'; +import {Directive, onInit} from 'angular2/src/core/annotations_impl/annotations'; +import {View} from 'angular2/src/core/annotations_impl/view'; + +import {Tabs} from './tabs'; + + +@Directive({ + selector: '.tab-button', + properties: ['tab'], + hostProperties: { + 'btnId': 'attr.id', + 'ariaControls': 'attr.aria-controls', + 'tab.isSelected': 'attr.aria-selected' + }, + hostAttributes: { + 'role': 'tab' + }, + hostListeners: { + '^click': 'onClick($event)' + }, + lifecycle: [onInit] +}) +export class TabButton { + constructor(@Parent() tabs: Tabs) { + this.tabs = tabs; + } + + onInit() { + this.btnId = 'tab-button-' + this.tab.id; + this.ariaControls = 'tab-content-' + this.tab.id; + } + + onClick(ev) { + ev.stopPropagation(); + ev.preventDefault(); + + this.tabs.selectTab(this.tab); + } +} diff --git a/ionic/components/tabs/tab.js b/ionic/components/tabs/tab.js index 485695b35b..107fdb0c31 100644 --- a/ionic/components/tabs/tab.js +++ b/ionic/components/tabs/tab.js @@ -21,7 +21,8 @@ import {NavBase} from '../nav/nav-base'; ], hostProperties: { 'contentId': 'attr.id', - 'labeledBy': 'attr.aria-labelledby' + 'labeledBy': 'attr.aria-labelledby', + 'isSelected': 'class.show-tab' }, hostAttributes: { 'role': 'tabpanel' @@ -39,9 +40,9 @@ export class Tab { this.config = Tab.config.invoke(this); - this.tabId = util.nextUid(); - this.contentId = 'tab-content-' + this.tabId; - this.labeledBy = 'tab-item-' + this.tabId; + this.id = util.nextUid(); + this.contentId = 'tab-content-' + this.id; + this.labeledBy = 'tab-button-' + this.id; tabs.addTab(this); } @@ -54,7 +55,7 @@ export class Tab { this.nav.initial = value; } - setSelected(isSelected) { + select(isSelected) { this.isSelected = isSelected; } diff --git a/ionic/components/tabs/tabs.js b/ionic/components/tabs/tabs.js index 633490b831..b8b7def17f 100644 --- a/ionic/components/tabs/tabs.js +++ b/ionic/components/tabs/tabs.js @@ -1,35 +1,30 @@ -import {Component, Directive} from 'angular2/src/core/annotations_impl/annotations'; +import {Component, onInit} from 'angular2/src/core/annotations_impl/annotations'; import {View} from 'angular2/src/core/annotations_impl/view'; -import {NgFor} from 'angular2/angular2'; import {ElementRef} from 'angular2/src/core/compiler/element_ref'; import {DynamicComponentLoader} from 'angular2/src/core/compiler/dynamic_component_loader'; import {Injector} from 'angular2/di'; +import {NgFor} from 'angular2/angular2'; -import {IonicComponent} from 'ionic/config/component'; +import {IonicComponent} from '../../config/component'; import {Tab} from './tab'; +import {TabButton} from './tab-button'; @Component({ selector: 'ion-tabs', - properties: { - tabBarPlacement: 'tab-bar-placement', - tabBarIcons: 'tab-bar-icons' - } + properties: [ + 'tabBarPlacement', + 'tabBarIcons' + ], + lifecycle: [onInit] }) @View({ template: ` @@ -37,39 +32,34 @@ import {Tab} from './tab'; `, - directives: [NgFor] + directives: [NgFor, TabButton] }) export class Tabs { constructor(elementRef: ElementRef, loader: DynamicComponentLoader, injector: Injector) { this.domElement = elementRef.domElement; this.config = Tabs.config.invoke(this); - this.tabs = []; } + onInit() { + if (this.tabs.length > 0) { + this.selectTab(this.tabs[0]); + } + } + addTab(tab) { this.tabs.push(tab); - if (this.tabs.length == 1) { - this.select(tab); - } } - select(tab) { + selectTab(tab) { + if (!tab || this._selected === tab) return; + this.tabs.forEach(otherTab => { - otherTab.setSelected(false); + otherTab.select(false); }); - tab.setSelected(true); - this.selectedTab = tab; - } - - onClickTabItem(ev, tab) { - ev.preventDefault(); - ev.stopPropagation(); - - if (this.selectedTab !== tab) { - this.select(tab); - } + tab.select(true); + this._selected = tab; } } diff --git a/ionic/components/tabs/tabs.scss b/ionic/components/tabs/tabs.scss index 0c474d1a73..42e37cf627 100644 --- a/ionic/components/tabs/tabs.scss +++ b/ionic/components/tabs/tabs.scss @@ -4,9 +4,9 @@ $tab-bar-background-color: #f7f7f8 !default; -$tab-bar-item-padding: 10px !default; -$tab-bar-item-min-width: 80px !default; -$tab-bar-item-max-width: 160px !default; +$tab-button-padding: 10px !default; +$tab-button-min-width: 80px !default; +$tab-button-max-width: 160px !default; .tab-bar-container { @@ -24,7 +24,7 @@ $tab-bar-item-max-width: 160px !default; background: $tab-bar-background-color; } -.tab-bar-item { +.tab-button { display: flex; flex-direction: column; justify-content: center; @@ -32,9 +32,9 @@ $tab-bar-item-max-width: 160px !default; align-self: center; align-items: center; - padding: $tab-bar-item-padding; - min-width: $tab-bar-item-min-width; - max-width: $tab-bar-item-max-width; + padding: $tab-button-padding; + min-width: $tab-button-min-width; + max-width: $tab-button-max-width; text-align: center; cursor: pointer; @@ -44,33 +44,33 @@ $tab-bar-item-max-width: 160px !default; background: none; } -[tab-bar-icons="bottom"] > .tab-bar-container .tab-bar-item { - .tab-bar-item-icon { +[tab-bar-icons="bottom"] > .tab-bar-container .tab-button { + .tab-button-icon { order: 10; } } -[tab-bar-icons="left"] > .tab-bar-container .tab-bar-item { +[tab-bar-icons="left"] > .tab-bar-container .tab-button { flex-direction: row; - .tab-bar-item-icon { + .tab-button-icon { text-align: right; padding-right: 5px; } } -[tab-bar-icons="right"] > .tab-bar-container .tab-bar-item { +[tab-bar-icons="right"] > .tab-bar-container .tab-button { flex-direction: row; - .tab-bar-item-icon { + .tab-button-icon { order: 10; text-align: left; padding-left: 5px; } } -.tab-bar-item-text, -.tab-bar-item-icon { +.tab-button-text, +.tab-button-icon { align-self: center; min-width: 26px; @@ -81,15 +81,15 @@ $tab-bar-item-max-width: 160px !default; text-overflow: ellipsis; } -.tab-bar-icon-only .tab-bar-item-text, -.tab-bar-text-only .tab-bar-item-icon { +.tab-bar-icon-only .tab-button-text, +.tab-bar-text-only .tab-button-icon { display: none; } -.tab-bar-item:hover { +.tab-button:hover { opacity: 0.6; } -.tab-bar-item[aria-selected="true"] { +.tab-button[aria-selected="true"] { color: red; }