mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2026-03-13 10:22:08 +08:00
chore(build): rename ionic directory to src and update all references in the build process.
This commit is contained in:
58
src/components/tabs/tab-button.ts
Normal file
58
src/components/tabs/tab-button.ts
Normal file
@@ -0,0 +1,58 @@
|
||||
import {Component, Directive, ElementRef, Optional, Host, forwardRef, ViewContainerRef, HostListener, EventEmitter, Output, Input, Renderer} from '@angular/core';
|
||||
|
||||
import {Tab} from './tab';
|
||||
import {Ion} from '../ion';
|
||||
import {Config} from '../../config/config';
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
@Directive({
|
||||
selector: '.tab-button',
|
||||
host: {
|
||||
'[attr.id]': 'tab._btnId',
|
||||
'[attr.aria-controls]': 'tab._panelId',
|
||||
'[attr.aria-selected]': 'tab.isSelected',
|
||||
'[class.has-title]': 'hasTitle',
|
||||
'[class.has-icon]': 'hasIcon',
|
||||
'[class.has-title-only]': 'hasTitleOnly',
|
||||
'[class.icon-only]': 'hasIconOnly',
|
||||
'[class.has-badge]': 'hasBadge',
|
||||
'[class.disable-hover]': 'disHover'
|
||||
}
|
||||
})
|
||||
export class TabButton extends Ion {
|
||||
private disHover: boolean;
|
||||
private hasTitle: boolean;
|
||||
private hasIcon: boolean;
|
||||
private hasTitleOnly: boolean;
|
||||
private hasIconOnly: boolean;
|
||||
private hasBadge: boolean;
|
||||
private _layout: string;
|
||||
|
||||
@Input() tab: Tab;
|
||||
@Output() select: EventEmitter<Tab> = new EventEmitter();
|
||||
|
||||
constructor(config: Config, elementRef: ElementRef) {
|
||||
super(elementRef);
|
||||
this.disHover = (config.get('hoverCSS') === false);
|
||||
this._layout = config.get('tabbarLayout');
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.tab.btn = this;
|
||||
this._layout = this.tab.parent.tabbarLayout || this._layout;
|
||||
|
||||
this.hasTitle = !!this.tab.tabTitle;
|
||||
this.hasIcon = !!this.tab.tabIcon && this._layout !== 'icon-hide';
|
||||
this.hasTitleOnly = (this.hasTitle && !this.hasIcon);
|
||||
this.hasIconOnly = (this.hasIcon && !this.hasTitle);
|
||||
this.hasBadge = !!this.tab.tabBadge;
|
||||
}
|
||||
|
||||
@HostListener('click')
|
||||
private onClick() {
|
||||
this.select.emit(this.tab);
|
||||
}
|
||||
}
|
||||
31
src/components/tabs/tab-highlight.ts
Normal file
31
src/components/tabs/tab-highlight.ts
Normal file
@@ -0,0 +1,31 @@
|
||||
import {Directive, ElementRef} from '@angular/core';
|
||||
|
||||
import {rafFrames} from '../../util/dom';
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
@Directive({
|
||||
selector: 'tab-highlight'
|
||||
})
|
||||
export class TabHighlight {
|
||||
private _init: boolean;
|
||||
|
||||
constructor(private _elementRef: ElementRef) {}
|
||||
|
||||
select(tab) {
|
||||
rafFrames(3, () => {
|
||||
let d = tab.btn.getDimensions();
|
||||
let ele = this._elementRef.nativeElement;
|
||||
ele.style.transform = 'translate3d(' + d.left + 'px,0,0) scaleX(' + d.width + ')';
|
||||
|
||||
if (!this._init) {
|
||||
this._init = true;
|
||||
rafFrames(6, () => {
|
||||
ele.classList.add('animate');
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
344
src/components/tabs/tab.ts
Normal file
344
src/components/tabs/tab.ts
Normal file
@@ -0,0 +1,344 @@
|
||||
import {Component, Inject, forwardRef, ElementRef, NgZone, Renderer, DynamicComponentLoader, ViewContainerRef, ViewChild, Type, ViewEncapsulation, ChangeDetectorRef, EventEmitter, Input, Output} from '@angular/core';
|
||||
|
||||
import {IonicApp} from '../app/app';
|
||||
import {Config} from '../../config/config';
|
||||
import {isTrueProperty} from '../../util/util';
|
||||
import {Keyboard} from '../../util/keyboard';
|
||||
import {NavController, NavOptions} from '../nav/nav-controller';
|
||||
import {ViewController} from '../nav/view-controller';
|
||||
import {Tabs} from './tabs';
|
||||
import {TabButton} from './tab-button';
|
||||
|
||||
|
||||
/**
|
||||
* @name Tab
|
||||
* @description
|
||||
* The Tab component, written `<ion-tab>`, is styled based on the mode and should
|
||||
* be used in conjunction with the [Tabs](../Tabs/) component.
|
||||
*
|
||||
* Each tab has a separate navigation controller. For more information on using
|
||||
* navigation controllers take a look at the [NavController API Docs](../../nav/NavController/).
|
||||
*
|
||||
* See the [Tabs API Docs](../Tabs/) for more details on configuring Tabs.
|
||||
*
|
||||
* @usage
|
||||
*
|
||||
* To add a basic tab, you can use the following markup where the `root` property
|
||||
* is the page you want to load for that tab, `tabTitle` is the optional text to
|
||||
* display on the tab, and `tabIcon` is the optional [icon](../../icon/Icon/).
|
||||
*
|
||||
* ```html
|
||||
* <ion-tabs>
|
||||
* <ion-tab [root]="chatRoot" tabTitle="Chat" tabIcon="chat"><ion-tab>
|
||||
* </ion-tabs>
|
||||
* ```
|
||||
*
|
||||
* Then, in your class you can set `chatRoot` to an imported class:
|
||||
*
|
||||
* ```ts
|
||||
* import {ChatPage} from '../chat/chat';
|
||||
*
|
||||
* export class Tabs {
|
||||
* // here we'll set the property of chatRoot to
|
||||
* // the imported class of ChatPage
|
||||
* chatRoot = ChatPage;
|
||||
*
|
||||
* constructor() {
|
||||
*
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* You can also pass some parameters to the root page of the tab through
|
||||
* `rootParams`. Below we pass `chatParams` to the Chat tab:
|
||||
*
|
||||
* ```html
|
||||
* <ion-tabs>
|
||||
* <ion-tab [root]="chatRoot" [rootParams]="chatParams" tabTitle="Chat" tabIcon="chat"><ion-tab>
|
||||
* </ion-tabs>
|
||||
* ```
|
||||
*
|
||||
* ```ts
|
||||
* export class Tabs {
|
||||
* chatRoot = ChatPage;
|
||||
*
|
||||
* // set some user information on chatParams
|
||||
* chatParams = {
|
||||
* user1: "admin",
|
||||
* user2: "ionic"
|
||||
* };
|
||||
*
|
||||
* constructor() {
|
||||
*
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* And in `ChatPage` you can get the data from `NavParams`:
|
||||
*
|
||||
* ```ts
|
||||
* export class ChatPage {
|
||||
* constructor(navParams: NavParams) {
|
||||
* console.log("Passed params", navParams.data);
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* Sometimes you may want to call a method instead of navigating to a new
|
||||
* page. You can use the `(select)` event to call a method on your class when
|
||||
* the tab is selected. Below is an example of presenting a modal from one of
|
||||
* the tabs.
|
||||
*
|
||||
* ```html
|
||||
* <ion-tabs preloadTabs="false">
|
||||
* <ion-tab (select)="chat()"></ion-tab>
|
||||
* </ion-tabs>
|
||||
* ```
|
||||
*
|
||||
* ```ts
|
||||
* export class Tabs {
|
||||
* constructor(nav: NavController) {
|
||||
* this.nav = nav;
|
||||
* }
|
||||
*
|
||||
* chat() {
|
||||
* let modal = Modal.create(ChatPage);
|
||||
* this.nav.present(modal);
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
*
|
||||
* @demo /docs/v2/demos/tabs/
|
||||
* @see {@link /docs/v2/components#tabs Tabs Component Docs}
|
||||
* @see {@link ../../tabs/Tabs Tabs API Docs}
|
||||
* @see {@link ../../nav/Nav Nav API Docs}
|
||||
* @see {@link ../../nav/NavController NavController API Docs}
|
||||
*/
|
||||
@Component({
|
||||
selector: 'ion-tab',
|
||||
host: {
|
||||
'[class.show-tab]': 'isSelected',
|
||||
'[attr.id]': '_panelId',
|
||||
'[attr.aria-labelledby]': '_btnId',
|
||||
'role': 'tabpanel'
|
||||
},
|
||||
template: '<div #viewport></div>',
|
||||
encapsulation: ViewEncapsulation.None,
|
||||
})
|
||||
export class Tab extends NavController {
|
||||
private _isInitial: boolean;
|
||||
private _isEnabled: boolean = true;
|
||||
private _isShown: boolean = true;
|
||||
private _panelId: string;
|
||||
private _btnId: string;
|
||||
private _loaded: boolean;
|
||||
private _loadTmr: any;
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
isSelected: boolean;
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
btn: TabButton;
|
||||
|
||||
/**
|
||||
* @input {Page} Set the root page for this tab.
|
||||
*/
|
||||
@Input() root: Type;
|
||||
|
||||
/**
|
||||
* @input {object} Any nav-params to pass to the root page of this tab.
|
||||
*/
|
||||
@Input() rootParams: any;
|
||||
|
||||
/**
|
||||
* @input {string} The title of the tab button.
|
||||
*/
|
||||
@Input() tabTitle: string;
|
||||
|
||||
/**
|
||||
* @input {string} The icon for the tab button.
|
||||
*/
|
||||
@Input() tabIcon: string;
|
||||
|
||||
/**
|
||||
* @input {string} The badge for the tab button.
|
||||
*/
|
||||
@Input() tabBadge: string;
|
||||
|
||||
/**
|
||||
* @input {string} The badge color for the tab button.
|
||||
*/
|
||||
@Input() tabBadgeStyle: string;
|
||||
|
||||
/**
|
||||
* @input {boolean} If the tab is enabled or not. If the tab
|
||||
* is not enabled then the tab button will still show, however,
|
||||
* the button will appear grayed out and will not be clickable.
|
||||
* Defaults to `true`.
|
||||
*/
|
||||
@Input()
|
||||
get enabled(): boolean {
|
||||
return this._isEnabled;
|
||||
}
|
||||
set enabled(val: boolean) {
|
||||
this._isEnabled = isTrueProperty(val);
|
||||
}
|
||||
|
||||
/**
|
||||
* @input {boolean} If the tab button is visible within the
|
||||
* tabbar or not. Defaults to `true`.
|
||||
*/
|
||||
@Input()
|
||||
get show(): boolean {
|
||||
return this._isShown;
|
||||
}
|
||||
set show(val: boolean) {
|
||||
this._isShown = isTrueProperty(val);
|
||||
}
|
||||
|
||||
/**
|
||||
* @output {Tab} Method to call when the current tab is selected
|
||||
*/
|
||||
@Output() select: EventEmitter<Tab> = new EventEmitter();
|
||||
|
||||
constructor(
|
||||
@Inject(forwardRef(() => Tabs)) parentTabs: Tabs,
|
||||
app: IonicApp,
|
||||
config: Config,
|
||||
keyboard: Keyboard,
|
||||
elementRef: ElementRef,
|
||||
zone: NgZone,
|
||||
renderer: Renderer,
|
||||
loader: DynamicComponentLoader,
|
||||
private _cd: ChangeDetectorRef
|
||||
) {
|
||||
// A Tab is a NavController for its child pages
|
||||
super(parentTabs, app, config, keyboard, elementRef, zone, renderer, loader);
|
||||
|
||||
parentTabs.add(this);
|
||||
|
||||
this._panelId = 'tabpanel-' + this.id;
|
||||
this._btnId = 'tab-' + this.id;
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
@ViewChild('viewport', {read: ViewContainerRef})
|
||||
set _vp(val: ViewContainerRef) {
|
||||
this.setViewport(val);
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
ngOnInit() {
|
||||
this.tabBadgeStyle = this.tabBadgeStyle ? this.tabBadgeStyle : 'default';
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
load(opts: NavOptions, done?: Function) {
|
||||
if (!this._loaded && this.root) {
|
||||
this.push(this.root, this.rootParams, opts).then(() => {
|
||||
done();
|
||||
});
|
||||
this._loaded = true;
|
||||
|
||||
} else {
|
||||
done();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
preload(wait: number) {
|
||||
this._loadTmr = setTimeout(() => {
|
||||
if (!this._loaded) {
|
||||
console.debug('Tabs, preload', this.id);
|
||||
this.load({
|
||||
animate: false,
|
||||
preload: true,
|
||||
postLoad: (viewCtrl) => {
|
||||
let navbar = viewCtrl.getNavbar();
|
||||
navbar && navbar.setHidden(true);
|
||||
}
|
||||
}, function(){});
|
||||
}
|
||||
}, wait);
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
loadPage(viewCtrl: ViewController, navbarContainerRef: any, opts: NavOptions, done: Function) {
|
||||
// by default a page's navbar goes into the shared tab's navbar section
|
||||
navbarContainerRef = this.parent.navbarContainerRef;
|
||||
|
||||
let isTabSubPage = (this.parent.subPages && viewCtrl.index > 0);
|
||||
if (isTabSubPage) {
|
||||
// a subpage, that's not the first index
|
||||
// should not use the shared tabs navbar section, but use it's own
|
||||
navbarContainerRef = null;
|
||||
}
|
||||
|
||||
super.loadPage(viewCtrl, navbarContainerRef, opts, () => {
|
||||
if (viewCtrl.instance) {
|
||||
viewCtrl.instance._tabSubPage = isTabSubPage;
|
||||
}
|
||||
done();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
setSelected(isSelected: boolean) {
|
||||
this.isSelected = isSelected;
|
||||
|
||||
if (isSelected) {
|
||||
// this is the selected tab, detect changes
|
||||
this._cd.reattach();
|
||||
|
||||
} else {
|
||||
// this tab is not selected, do not detect changes
|
||||
this._cd.detach();
|
||||
}
|
||||
|
||||
this.hideNavbars(!isSelected);
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
hideNavbars(shouldHideNavbars: boolean) {
|
||||
this._views.forEach(viewCtrl => {
|
||||
let navbar = viewCtrl.getNavbar();
|
||||
navbar && navbar.setHidden(shouldHideNavbars);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
get index(): number {
|
||||
return this.parent.getIndex(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
ngOnDestroy() {
|
||||
clearTimeout(this._loadTmr);
|
||||
super.ngOnDestroy();
|
||||
}
|
||||
|
||||
}
|
||||
140
src/components/tabs/tabs.ios.scss
Normal file
140
src/components/tabs/tabs.ios.scss
Normal file
@@ -0,0 +1,140 @@
|
||||
@import "../../globals.ios";
|
||||
@import "./tabs";
|
||||
|
||||
// iOS Tabs
|
||||
// --------------------------------------------------
|
||||
|
||||
$tabbar-ios-background: $toolbar-ios-background !default;
|
||||
$tabbar-ios-item-padding: 0 10px !default;
|
||||
$tabbar-ios-item-font-size: 10px !default;
|
||||
$tabbar-ios-item-icon-size: 30px !default;
|
||||
$tabbar-ios-height: 49px !default;
|
||||
|
||||
$tab-button-ios-max-width: 240px !default;
|
||||
$tab-button-ios-active-color: $toolbar-ios-active-color !default;
|
||||
$tab-button-ios-inactive-color: $toolbar-ios-inactive-color !default;
|
||||
|
||||
|
||||
tabbar {
|
||||
border-top: 1px solid $toolbar-ios-border-color;
|
||||
background: $tabbar-ios-background;
|
||||
}
|
||||
|
||||
ion-tabs[tabbarPlacement=top] tabbar {
|
||||
border-top: 0;
|
||||
border-bottom: 1px solid $toolbar-ios-border-color;
|
||||
}
|
||||
|
||||
.tab-button {
|
||||
padding: $tabbar-ios-item-padding;
|
||||
|
||||
max-width: $tab-button-ios-max-width;
|
||||
min-height: $tabbar-ios-height;
|
||||
|
||||
color: $tab-button-ios-inactive-color;
|
||||
}
|
||||
|
||||
.tab-button:hover:not(.disable-hover),
|
||||
.tab-button[aria-selected=true] {
|
||||
color: $tab-button-ios-active-color;
|
||||
}
|
||||
|
||||
.tab-button-text {
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
|
||||
min-height: $tabbar-ios-item-font-size + 1;
|
||||
|
||||
font-size: $tabbar-ios-item-font-size;
|
||||
}
|
||||
|
||||
.has-title-only .tab-button-text {
|
||||
font-size: $tabbar-ios-item-font-size + 2;
|
||||
}
|
||||
|
||||
.tab-button-icon {
|
||||
min-width: $tabbar-ios-item-icon-size + 5;
|
||||
height: $tabbar-ios-item-icon-size;
|
||||
|
||||
font-size: $tabbar-ios-item-icon-size;
|
||||
|
||||
&::before {
|
||||
vertical-align: top;
|
||||
}
|
||||
}
|
||||
|
||||
[tabbarLayout=icon-right] .tab-button,
|
||||
[tabbarLayout=icon-left] .tab-button {
|
||||
|
||||
.tab-button-text {
|
||||
font-size: 1.4rem;
|
||||
line-height: 1.1;
|
||||
}
|
||||
|
||||
ion-icon {
|
||||
min-width: 24px;
|
||||
height: 26px;
|
||||
|
||||
font-size: 24px;
|
||||
}
|
||||
}
|
||||
|
||||
[tabbarLayout=icon-hide] .tab-button,
|
||||
.tab-button.has-title-only {
|
||||
min-height: $tabbar-ios-height - 8;
|
||||
|
||||
.tab-button-text {
|
||||
margin: 2px 0;
|
||||
|
||||
font-size: 1.4rem;
|
||||
line-height: 1.1;
|
||||
}
|
||||
}
|
||||
|
||||
[tabbarLayout=title-hide] .tab-button,
|
||||
.tab-button.icon-only {
|
||||
min-height: $tabbar-ios-height - 8;
|
||||
}
|
||||
|
||||
&.hairlines ion-tabs {
|
||||
|
||||
tabbar {
|
||||
border-top-width: $hairlines-width;
|
||||
}
|
||||
|
||||
&[tabbarPlacement="top"] tabbar {
|
||||
border-bottom-width: $hairlines-width;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
// iOS Tabbar Color Mixin
|
||||
// --------------------------------------------------
|
||||
|
||||
@mixin tabbar-ios($color-name, $color-base, $color-contrast) {
|
||||
|
||||
ion-tabs[#{$color-name}] tabbar {
|
||||
border-color: darken($color-base, 10%);
|
||||
background-color: $color-base;
|
||||
|
||||
.tab-button {
|
||||
color: $color-contrast;
|
||||
}
|
||||
|
||||
.tab-button:hover:not(.disable-hover),
|
||||
.tab-button[aria-selected=true] {
|
||||
color: $color-contrast;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
// iOS Tabbar Color Generation
|
||||
// --------------------------------------------------
|
||||
|
||||
@each $color-name, $color-base, $color-contrast in get-colors($colors-ios) {
|
||||
|
||||
@include tabbar-ios($color-name, $color-base, $color-contrast);
|
||||
}
|
||||
129
src/components/tabs/tabs.md.scss
Normal file
129
src/components/tabs/tabs.md.scss
Normal file
@@ -0,0 +1,129 @@
|
||||
@import "../../globals.md";
|
||||
@import "./tabs";
|
||||
|
||||
// Material Design Tabs
|
||||
// --------------------------------------------------
|
||||
|
||||
$tabbar-md-background: $toolbar-md-background !default;
|
||||
$tabbar-md-item-padding: 12px 10px 5px 10px !default;
|
||||
$tabbar-md-item-font-size: 1.4rem !default;
|
||||
$tabbar-md-item-font-weight: 500 !default;
|
||||
$tabbar-md-item-icon-size: 2.4rem !default;
|
||||
$tabbar-md-item-height: 4.8rem !default;
|
||||
|
||||
$tab-button-md-active-color: $toolbar-md-active-color !default;
|
||||
$tab-button-md-inactive-color: $toolbar-md-inactive-color !default;
|
||||
|
||||
|
||||
tabbar {
|
||||
background: $tabbar-md-background;
|
||||
}
|
||||
|
||||
|
||||
.tab-button {
|
||||
padding: $tabbar-md-item-padding;
|
||||
|
||||
min-height: $tabbar-md-item-height;
|
||||
|
||||
border-bottom: 2px solid transparent;
|
||||
border-radius: 0;
|
||||
font-size: $tabbar-md-item-font-size;
|
||||
font-weight: $tabbar-md-item-font-weight;
|
||||
color: $tab-button-md-inactive-color;
|
||||
box-shadow: none;
|
||||
opacity: .7;
|
||||
|
||||
&[aria-selected=true] {
|
||||
color: $tab-button-md-active-color;
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.tab-button-text {
|
||||
margin-top: 5px;
|
||||
margin-bottom: 5px;
|
||||
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.tab-button-icon {
|
||||
min-width: $tabbar-md-item-icon-size + 5;
|
||||
|
||||
font-size: $tabbar-md-item-icon-size;
|
||||
}
|
||||
|
||||
[tabbarLayout=icon-bottom] .tab-button {
|
||||
padding-top: 8px;
|
||||
padding-bottom: 8px;
|
||||
}
|
||||
|
||||
[tabbarLayout=icon-right] .tab-button,
|
||||
[tabbarLayout=icon-left] .tab-button {
|
||||
padding-bottom: 10px;
|
||||
|
||||
ion-icon {
|
||||
min-width: 24px;
|
||||
}
|
||||
}
|
||||
|
||||
[tabbarLayout=icon-hide] .tab-button,
|
||||
[tabbarLayout=title-hide] .tab-button,
|
||||
.tab-button.icon-only,
|
||||
.tab-button.has-title-only {
|
||||
padding: 6px 10px;
|
||||
}
|
||||
|
||||
tab-highlight {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
display: block;
|
||||
|
||||
width: 1px;
|
||||
height: 2px;
|
||||
|
||||
background: $tab-button-md-active-color;
|
||||
transform: translateZ(0);
|
||||
transform-origin: 0 0;
|
||||
|
||||
&.animate {
|
||||
transition-duration: 300ms;
|
||||
}
|
||||
}
|
||||
|
||||
[tabbarPlacement=bottom] tab-highlight {
|
||||
top: 0;
|
||||
}
|
||||
|
||||
|
||||
// Material Design Tabbar Color Mixin
|
||||
// --------------------------------------------------
|
||||
|
||||
@mixin tabbar-md($color-name, $color-base, $color-contrast) {
|
||||
|
||||
ion-tabs[#{$color-name}] tabbar {
|
||||
background-color: $color-base;
|
||||
|
||||
.tab-button {
|
||||
color: $color-contrast;
|
||||
}
|
||||
|
||||
.tab-button:hover:not(.disable-hover),
|
||||
.tab-button[aria-selected=true] {
|
||||
color: $color-contrast;
|
||||
}
|
||||
|
||||
tab-highlight {
|
||||
background: $color-contrast;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
// Material Design Tabbar Color Generation
|
||||
// --------------------------------------------------
|
||||
|
||||
@each $color-name, $color-base, $color-contrast in get-colors($colors-md) {
|
||||
@include tabbar-md($color-name, $color-base, $color-contrast);
|
||||
}
|
||||
194
src/components/tabs/tabs.scss
Normal file
194
src/components/tabs/tabs.scss
Normal file
@@ -0,0 +1,194 @@
|
||||
@import "../../globals.core";
|
||||
|
||||
// Tabs
|
||||
// --------------------------------------------------
|
||||
|
||||
|
||||
ion-tabs {
|
||||
display: flex;
|
||||
overflow: hidden;
|
||||
|
||||
flex-direction: column;
|
||||
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
|
||||
width: 100%;
|
||||
max-width: 100%;
|
||||
height: 100%;
|
||||
max-height: 100%;
|
||||
}
|
||||
|
||||
ion-tab {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
display: none;
|
||||
overflow: hidden;
|
||||
|
||||
flex-direction: column;
|
||||
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
&.show-tab {
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
|
||||
ion-tabs > ion-navbar-section {
|
||||
order: $flex-order-tabbar-navbar;
|
||||
}
|
||||
|
||||
ion-tabbar-section {
|
||||
position: relative;
|
||||
|
||||
order: $flex-order-tabbar-bottom;
|
||||
}
|
||||
|
||||
[tabbarPlacement=top] ion-tabbar-section {
|
||||
order: $flex-order-tabbar-top;
|
||||
}
|
||||
|
||||
tabbar {
|
||||
position: relative;
|
||||
display: flex;
|
||||
overflow: hidden;
|
||||
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.tab-button {
|
||||
@include user-select-none();
|
||||
|
||||
position: relative;
|
||||
z-index: 0;
|
||||
display: flex;
|
||||
overflow: hidden;
|
||||
|
||||
flex: 1;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
align-self: center;
|
||||
justify-content: center;
|
||||
|
||||
margin: 0;
|
||||
|
||||
border: 0;
|
||||
border-radius: 0;
|
||||
|
||||
text-align: center;
|
||||
background: none;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.tab-disabled {
|
||||
pointer-events: none;
|
||||
|
||||
ion-badge,
|
||||
ion-icon,
|
||||
span {
|
||||
opacity: .4;
|
||||
}
|
||||
}
|
||||
|
||||
.tab-hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.tab-button-text {
|
||||
margin-top: 3px;
|
||||
margin-bottom: 2px;
|
||||
}
|
||||
|
||||
.tab-button-text,
|
||||
.tab-button-icon {
|
||||
display: none;
|
||||
overflow: hidden;
|
||||
|
||||
align-self: center;
|
||||
|
||||
min-width: 26px;
|
||||
max-width: 100%;
|
||||
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.has-icon .tab-button-icon,
|
||||
.has-title .tab-button-text {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.has-title-only .tab-button-text {
|
||||
white-space: normal;
|
||||
}
|
||||
|
||||
tab-highlight {
|
||||
display: none;
|
||||
}
|
||||
|
||||
[tabbarLayout=icon-bottom] .tab-button {
|
||||
.tab-button-icon {
|
||||
order: 10;
|
||||
}
|
||||
}
|
||||
|
||||
[tabbarLayout=icon-left] .tab-button {
|
||||
flex-direction: row;
|
||||
|
||||
.tab-button-icon {
|
||||
padding-right: 8px;
|
||||
|
||||
text-align: right;
|
||||
}
|
||||
}
|
||||
|
||||
[tabbarLayout=icon-right] .tab-button {
|
||||
flex-direction: row;
|
||||
|
||||
.tab-button-icon {
|
||||
order: 10;
|
||||
|
||||
padding-left: 8px;
|
||||
|
||||
text-align: left;
|
||||
}
|
||||
}
|
||||
|
||||
[tabbarLayout=icon-hide] .tab-button-icon {
|
||||
display: none;
|
||||
}
|
||||
|
||||
[tabbarLayout=title-hide] .tab-button-text {
|
||||
display: none;
|
||||
}
|
||||
|
||||
// Tab Badges
|
||||
// --------------------------------------------------
|
||||
|
||||
.tab-badge {
|
||||
position: absolute;
|
||||
top: 6%;
|
||||
right: 4%;
|
||||
right: calc(50% - 50px);
|
||||
|
||||
padding: 1px 6px;
|
||||
|
||||
height: auto;
|
||||
|
||||
font-size: 12px;
|
||||
line-height: 16px;
|
||||
}
|
||||
|
||||
.has-icon .tab-badge {
|
||||
right: calc(50% - 30px);
|
||||
}
|
||||
|
||||
[tabbarLayout=icon-bottom] .tab-badge,
|
||||
[tabbarLayout=icon-left] .tab-badge,
|
||||
[tabbarLayout=icon-right] .tab-badge {
|
||||
right: calc(50% - 50px);
|
||||
}
|
||||
495
src/components/tabs/tabs.ts
Normal file
495
src/components/tabs/tabs.ts
Normal file
@@ -0,0 +1,495 @@
|
||||
import {Component, Directive, ElementRef, Optional, Host, forwardRef, ViewContainerRef, ViewChild, ViewChildren, EventEmitter, Output, Input, Renderer, ViewEncapsulation} from '@angular/core';
|
||||
|
||||
import {IonicApp} from '../app/app';
|
||||
import {Config} from '../../config/config';
|
||||
import {Tab} from './tab';
|
||||
import {TabButton} from './tab-button';
|
||||
import {TabHighlight} from './tab-highlight';
|
||||
import {Ion} from '../ion';
|
||||
import {Platform} from '../../platform/platform';
|
||||
import {NavController} from '../nav/nav-controller';
|
||||
import {ViewController} from '../nav/view-controller';
|
||||
import {isBlank, isTrueProperty} from '../../util/util';
|
||||
|
||||
|
||||
/**
|
||||
* @name Tabs
|
||||
* @description
|
||||
* Tabs make it easy to navigate between different pages or functional
|
||||
* aspects of an app. The Tabs component, written as `<ion-tabs>`, is
|
||||
* a container of individual [Tab](../Tab/) components.
|
||||
*
|
||||
* ### Placement
|
||||
*
|
||||
* The position of the tabs relative to the content varies based on
|
||||
* the mode. By default, the tabs are placed at the bottom of the screen
|
||||
* for `ios` mode, and at the top for the `md` and `wp` modes. You can
|
||||
* configure the position using the `tabbarPlacement` property on the
|
||||
* `<ion-tabs>` element, or in your app's [config](../../config/Config/).
|
||||
* See the [Input Properties](#input-properties) below for the available
|
||||
* values of `tabbarPlacement`.
|
||||
*
|
||||
* ### Layout
|
||||
*
|
||||
* The layout for all of the tabs can be defined using the `tabbarLayout`
|
||||
* property. If the individual tab has a title and icon, the icons will
|
||||
* show on top of the title by default. All tabs can be changed by setting
|
||||
* the value of `tabbarLayout` on the `<ion-tabs>` element, or in your
|
||||
* app's [config](../../config/Config/). For example, this is useful if
|
||||
* you want to show tabs with a title only on Android, but show icons
|
||||
* and a title for iOS. See the [Input Properties](#input-properties)
|
||||
* below for the available values of `tabbarLayout`.
|
||||
*
|
||||
* ### Selecting a Tab
|
||||
*
|
||||
* There are different ways you can select a specific tab from the tabs
|
||||
* component. You can use the `selectedIndex` property to set the index
|
||||
* on the `<ion-tabs>` element, or you can call `select()` from the `Tabs`
|
||||
* instance after creation. See [usage](#usage) below for more information.
|
||||
*
|
||||
* @usage
|
||||
*
|
||||
* You can add a basic tabs template to a `@Page` using the following
|
||||
* template:
|
||||
*
|
||||
* ```html
|
||||
* <ion-tabs>
|
||||
* <ion-tab [root]="tab1Root"></ion-tab>
|
||||
* <ion-tab [root]="tab2Root"></ion-tab>
|
||||
* <ion-tab [root]="tab3Root"></ion-tab>
|
||||
* </ion-tabs>
|
||||
* ```
|
||||
*
|
||||
* Where `tab1Root`, `tab2Root`, and `tab3Root` are each a page:
|
||||
*
|
||||
*```ts
|
||||
* @Page({
|
||||
* templateUrl: 'build/pages/tabs/tabs.html'
|
||||
* })
|
||||
* export class TabsPage {
|
||||
* // this tells the tabs component which Pages
|
||||
* // should be each tab's root Page
|
||||
* tab1Root = Page1;
|
||||
* tab2Root = Page2;
|
||||
* tab3Root = Page3;
|
||||
*
|
||||
* constructor() {
|
||||
*
|
||||
* }
|
||||
* }
|
||||
*```
|
||||
*
|
||||
* By default, the first tab will be selected upon navigation to the
|
||||
* Tabs page. We can change the selected tab by using `selectedIndex`
|
||||
* on the `<ion-tabs>` element:
|
||||
*
|
||||
* ```html
|
||||
* <ion-tabs selectedIndex="2">
|
||||
* <ion-tab [root]="tab1Root"></ion-tab>
|
||||
* <ion-tab [root]="tab2Root"></ion-tab>
|
||||
* <ion-tab [root]="tab3Root"></ion-tab>
|
||||
* </ion-tabs>
|
||||
* ```
|
||||
*
|
||||
* Since the index starts at `0`, this will select the 3rd tab which has
|
||||
* root set to `tab3Root`. If you wanted to change it dynamically from
|
||||
* your class, you could use [property binding](https://angular.io/docs/ts/latest/guide/template-syntax.html#!#property-binding).
|
||||
*
|
||||
* Alternatively, you can grab the `Tabs` instance and call the `select()`
|
||||
* method. This requires the `<ion-tabs>` element to have an `id`. For
|
||||
* example, set the value of `id` to `myTabs`:
|
||||
*
|
||||
* ```html
|
||||
* <ion-tabs #myTabs>
|
||||
* <ion-tab [root]="tab1Root"></ion-tab>
|
||||
* <ion-tab [root]="tab2Root"></ion-tab>
|
||||
* <ion-tab [root]="tab3Root"></ion-tab>
|
||||
* </ion-tabs>
|
||||
* ```
|
||||
*
|
||||
* Then in your class you can grab the `Tabs` instance and call `select()`,
|
||||
* passing the index of the tab as the argument. Here we're grabbing the tabs
|
||||
* by using ViewChild.
|
||||
*
|
||||
*```ts
|
||||
* export class TabsPage {
|
||||
*
|
||||
* @ViewChild('myTabs) tabRef: Tabs
|
||||
*
|
||||
* onPageDidEnter() {
|
||||
* this.tabRef.select(2);
|
||||
* }
|
||||
*
|
||||
* }
|
||||
*```
|
||||
*
|
||||
* @demo /docs/v2/demos/tabs/
|
||||
*
|
||||
* @see {@link /docs/v2/components#tabs Tabs Component Docs}
|
||||
* @see {@link ../Tab Tab API Docs}
|
||||
* @see {@link ../../config/Config Config API Docs}
|
||||
*
|
||||
*/
|
||||
@Component({
|
||||
selector: 'ion-tabs',
|
||||
template:
|
||||
'<ion-navbar-section [class.statusbar-padding]="_sbPadding">' +
|
||||
'<template navbar-anchor></template>' +
|
||||
'</ion-navbar-section>' +
|
||||
'<ion-tabbar-section>' +
|
||||
'<tabbar role="tablist">' +
|
||||
'<a *ngFor="let t of _tabs" [tab]="t" class="tab-button" [class.tab-disabled]="!t.enabled" [class.tab-hidden]="!t.show" role="tab">' +
|
||||
'<ion-icon *ngIf="t.tabIcon" [name]="t.tabIcon" [isActive]="t.isSelected" class="tab-button-icon"></ion-icon>' +
|
||||
'<span *ngIf="t.tabTitle" class="tab-button-text">{{t.tabTitle}}</span>' +
|
||||
'<ion-badge *ngIf="t.tabBadge" class="tab-badge" [ngClass]="\'badge-\' + t.tabBadgeStyle">{{t.tabBadge}}</ion-badge>' +
|
||||
'<ion-button-effect></ion-button-effect>' +
|
||||
'</a>' +
|
||||
'<tab-highlight></tab-highlight>' +
|
||||
'</tabbar>' +
|
||||
'</ion-tabbar-section>' +
|
||||
'<ion-content-section>' +
|
||||
'<ng-content></ng-content>' +
|
||||
'</ion-content-section>',
|
||||
directives: [
|
||||
TabButton,
|
||||
TabHighlight,
|
||||
forwardRef(() => TabNavBarAnchor)
|
||||
],
|
||||
encapsulation: ViewEncapsulation.None,
|
||||
})
|
||||
export class Tabs extends Ion {
|
||||
private _ids: number = -1;
|
||||
private _preloadTabs: boolean = null;
|
||||
private _tabs: Array<Tab> = [];
|
||||
private _onReady = null;
|
||||
private _sbPadding: boolean;
|
||||
private _useHighlight: boolean;
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
id: number;
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
navbarContainerRef: ViewContainerRef;
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
subPages: boolean;
|
||||
|
||||
/**
|
||||
* @input {number} The default selected tab index when first loaded. If a selected index isn't provided then it will use `0`, the first tab.
|
||||
*/
|
||||
@Input() selectedIndex: any;
|
||||
|
||||
/**
|
||||
* @input {boolean} Set whether to preload all the tabs: `true`, `false`.
|
||||
*/
|
||||
@Input() preloadTabs: any;
|
||||
|
||||
/**
|
||||
* @input {string} Set the tabbar layout: `icon-top`, `icon-left`, `icon-right`, `icon-bottom`, `icon-hide`, `title-hide`.
|
||||
*/
|
||||
@Input() tabbarLayout: string;
|
||||
|
||||
/**
|
||||
* @input {string} Set position of the tabbar: `top`, `bottom`.
|
||||
*/
|
||||
@Input() tabbarPlacement: string;
|
||||
|
||||
/**
|
||||
* @input {any} Expression to evaluate when the tab changes.
|
||||
*/
|
||||
@Output() change: EventEmitter<Tab> = new EventEmitter();
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
@ViewChild(TabHighlight) private _highlight: TabHighlight;
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
@ViewChildren(TabButton) private _btns;
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
parent: any;
|
||||
|
||||
constructor(
|
||||
@Optional() parent: NavController,
|
||||
@Optional() viewCtrl: ViewController,
|
||||
private _app: IonicApp,
|
||||
private _config: Config,
|
||||
private _elementRef: ElementRef,
|
||||
private _platform: Platform,
|
||||
private _renderer: Renderer
|
||||
) {
|
||||
super(_elementRef);
|
||||
this.parent = parent;
|
||||
this.id = ++tabIds;
|
||||
this.subPages = _config.getBoolean('tabSubPages');
|
||||
this._useHighlight = _config.getBoolean('tabbarHighlight');
|
||||
this._sbPadding = _config.getBoolean('statusbarPadding', false);
|
||||
|
||||
if (parent) {
|
||||
// this Tabs has a parent Nav
|
||||
parent.registerChildNav(this);
|
||||
|
||||
} else if (this._app) {
|
||||
// this is the root navcontroller for the entire app
|
||||
this._app.setRootNav(this);
|
||||
}
|
||||
|
||||
// Tabs may also be an actual ViewController which was navigated to
|
||||
// if Tabs is static and not navigated to within a NavController
|
||||
// then skip this and don't treat it as it's own ViewController
|
||||
if (viewCtrl) {
|
||||
viewCtrl.setContent(this);
|
||||
viewCtrl.setContentRef(_elementRef);
|
||||
|
||||
viewCtrl.onReady = (done) => {
|
||||
this._onReady = done;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
ngAfterViewInit() {
|
||||
this._setConfig('tabbarPlacement', 'bottom');
|
||||
this._setConfig('tabbarLayout', 'icon-top');
|
||||
|
||||
if (this._useHighlight) {
|
||||
this._platform.onResize(() => {
|
||||
this._highlight.select(this.getSelected());
|
||||
});
|
||||
}
|
||||
|
||||
this._btns.toArray().forEach((tabButton: TabButton) => {
|
||||
tabButton.select.subscribe((tab: Tab) => {
|
||||
this.select(tab);
|
||||
});
|
||||
});
|
||||
|
||||
let preloadTabs = (isBlank(this.preloadTabs) ? this._config.getBoolean('preloadTabs') : isTrueProperty(this.preloadTabs));
|
||||
|
||||
// get the selected index
|
||||
let selectedIndex = this.selectedIndex ? parseInt(this.selectedIndex, 10) : 0;
|
||||
|
||||
// ensure the selectedIndex isn't a hidden or disabled tab
|
||||
// also find the first available index incase we need it later
|
||||
let availableIndex = -1;
|
||||
this._tabs.forEach((tab, index) => {
|
||||
if (tab.enabled && tab.show && availableIndex < 0) {
|
||||
// we know this tab index is safe to show
|
||||
availableIndex = index;
|
||||
}
|
||||
|
||||
if (index === selectedIndex && (!tab.enabled || !tab.show)) {
|
||||
// the selectedIndex is not safe to show
|
||||
selectedIndex = -1;
|
||||
}
|
||||
});
|
||||
|
||||
if (selectedIndex < 0) {
|
||||
// the selected index wasn't safe to show
|
||||
// instead use an available index found to be safe to show
|
||||
selectedIndex = availableIndex;
|
||||
}
|
||||
|
||||
this._tabs.forEach((tab, index) => {
|
||||
if (index === selectedIndex) {
|
||||
this.select(tab);
|
||||
|
||||
} else if (preloadTabs) {
|
||||
tab.preload(1000 * index);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
private _setConfig(attrKey, fallback) {
|
||||
var val = this[attrKey];
|
||||
if (isBlank(val)) {
|
||||
val = this._config.get(attrKey, fallback);
|
||||
}
|
||||
this._renderer.setElementAttribute(this._elementRef.nativeElement, attrKey, val);
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
add(tab: Tab) {
|
||||
tab.id = this.id + '-' + (++this._ids);
|
||||
this._tabs.push(tab);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {number} index Index of the tab you want to select
|
||||
*/
|
||||
select(tabOrIndex) {
|
||||
let selectedTab = (typeof tabOrIndex === 'number' ? this.getByIndex(tabOrIndex) : tabOrIndex);
|
||||
if (!selectedTab) {
|
||||
return;
|
||||
}
|
||||
|
||||
let deselectedTab = this.getSelected();
|
||||
|
||||
if (selectedTab === deselectedTab) {
|
||||
// no change
|
||||
return this._touchActive(selectedTab);
|
||||
}
|
||||
|
||||
console.debug('Tabs, select', selectedTab.id);
|
||||
|
||||
let opts = {
|
||||
animate: false
|
||||
};
|
||||
|
||||
let deselectedPage;
|
||||
if (deselectedTab) {
|
||||
deselectedPage = deselectedTab.getActive();
|
||||
deselectedPage && deselectedPage.willLeave();
|
||||
}
|
||||
|
||||
let selectedPage = selectedTab.getActive();
|
||||
selectedPage && selectedPage.willEnter();
|
||||
|
||||
selectedTab.load(opts, () => {
|
||||
|
||||
selectedTab.select.emit(selectedTab);
|
||||
this.change.emit(selectedTab);
|
||||
|
||||
if (selectedTab.root) {
|
||||
// only show the selectedTab if it has a root
|
||||
// it's possible the tab is only for opening modal's or signing out
|
||||
// and doesn't actually have content. In the case there's no content
|
||||
// for a tab then do nothing and leave the current view as is
|
||||
this._tabs.forEach(tab => {
|
||||
tab.setSelected(tab === selectedTab);
|
||||
});
|
||||
|
||||
if (this._useHighlight) {
|
||||
this._highlight.select(selectedTab);
|
||||
}
|
||||
}
|
||||
|
||||
selectedPage && selectedPage.didEnter();
|
||||
deselectedPage && deselectedPage.didLeave();
|
||||
|
||||
if (this._onReady) {
|
||||
this._onReady();
|
||||
this._onReady = null;
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {number} index Index of the tab you want to get
|
||||
* @returns {Tab} Returns the tab who's index matches the one passed
|
||||
*/
|
||||
getByIndex(index: number): Tab {
|
||||
if (index < this._tabs.length && index > -1) {
|
||||
return this._tabs[index];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {Tab} Returns the currently selected tab
|
||||
*/
|
||||
getSelected(): Tab {
|
||||
for (let i = 0; i < this._tabs.length; i++) {
|
||||
if (this._tabs[i].isSelected) {
|
||||
return this._tabs[i];
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
getActiveChildNav() {
|
||||
return this.getSelected();
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
getIndex(tab: Tab): number {
|
||||
return this._tabs.indexOf(tab);
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* "Touch" the active tab, going back to the root view of the tab
|
||||
* or optionally letting the tab handle the event
|
||||
*/
|
||||
private _touchActive(tab: Tab) {
|
||||
let active = tab.getActive();
|
||||
|
||||
if (!active) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
let instance = active.instance;
|
||||
|
||||
// If they have a custom tab selected handler, call it
|
||||
if (instance.tabSelected) {
|
||||
return instance.tabSelected();
|
||||
}
|
||||
|
||||
// If we're a few pages deep, pop to root
|
||||
if (tab.length() > 1) {
|
||||
// Pop to the root view
|
||||
return tab.popToRoot();
|
||||
}
|
||||
|
||||
// Otherwise, if the page we're on is not our real root, reset it to our
|
||||
// default root type
|
||||
if (tab.root !== active.componentType) {
|
||||
return tab.setRoot(tab.root);
|
||||
}
|
||||
|
||||
// And failing all of that, we do something safe and secure
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* Returns the root NavController. Returns `null` if Tabs is not
|
||||
* within a NavController.
|
||||
* @returns {NavController}
|
||||
*/
|
||||
get rootNav(): NavController {
|
||||
let nav = this.parent;
|
||||
while (nav.parent) {
|
||||
nav = nav.parent;
|
||||
}
|
||||
return nav;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
let tabIds = -1;
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
@Directive({selector: 'template[navbar-anchor]'})
|
||||
class TabNavBarAnchor {
|
||||
constructor(@Host() tabs: Tabs, viewContainerRef: ViewContainerRef) {
|
||||
tabs.navbarContainerRef = viewContainerRef;
|
||||
}
|
||||
}
|
||||
119
src/components/tabs/tabs.wp.scss
Normal file
119
src/components/tabs/tabs.wp.scss
Normal file
@@ -0,0 +1,119 @@
|
||||
@import "../../globals.wp";
|
||||
@import "./tabs";
|
||||
|
||||
// Windows Tabs
|
||||
// --------------------------------------------------
|
||||
|
||||
$tabbar-wp-background: $toolbar-wp-background !default;
|
||||
$tabbar-wp-item-padding: 12px 10px 5px 10px !default;
|
||||
$tabbar-wp-item-font-size: 1.2rem !default;
|
||||
$tabbar-wp-item-font-weight: normal !default;
|
||||
$tabbar-wp-item-icon-size: 2.4rem !default;
|
||||
$tabbar-wp-item-height: 4.8rem !default;
|
||||
|
||||
$tab-button-wp-active-color: $toolbar-wp-active-color !default;
|
||||
$tab-button-wp-inactive-color: $toolbar-wp-inactive-color !default;
|
||||
|
||||
$tab-button-wp-background-activated: rgba(0, 0, 0, .1) !default;
|
||||
|
||||
tabbar {
|
||||
background: $tabbar-wp-background;
|
||||
}
|
||||
|
||||
|
||||
.tab-button {
|
||||
padding: $tabbar-wp-item-padding;
|
||||
|
||||
min-height: $tabbar-wp-item-height;
|
||||
|
||||
border-bottom: 2px solid transparent;
|
||||
border-radius: 0;
|
||||
font-size: $tabbar-wp-item-font-size;
|
||||
font-weight: $tabbar-wp-item-font-weight;
|
||||
color: $tab-button-wp-inactive-color;
|
||||
box-shadow: none;
|
||||
opacity: .7;
|
||||
|
||||
&[aria-selected=true] {
|
||||
border-bottom-color: $tab-button-wp-active-color;
|
||||
color: $tab-button-wp-active-color;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
&.activated {
|
||||
background: $tab-button-wp-background-activated;
|
||||
}
|
||||
}
|
||||
|
||||
.tab-button-text {
|
||||
margin-top: 5px;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.tab-button-icon {
|
||||
min-width: $tabbar-wp-item-icon-size;
|
||||
|
||||
font-size: $tabbar-wp-item-icon-size;
|
||||
}
|
||||
|
||||
[tabbarLayout=icon-bottom] .tab-button {
|
||||
padding-top: 8px;
|
||||
padding-bottom: 8px;
|
||||
}
|
||||
|
||||
[tabbarLayout=icon-right] .tab-button,
|
||||
[tabbarLayout=icon-left] .tab-button {
|
||||
padding-bottom: 10px;
|
||||
|
||||
ion-icon {
|
||||
min-width: 24px;
|
||||
}
|
||||
}
|
||||
|
||||
[tabbarLayout=icon-hide] .tab-button,
|
||||
[tabbarLayout=title-hide] .tab-button,
|
||||
.tab-button.icon-only,
|
||||
.tab-button.has-title-only {
|
||||
padding: 6px 10px;
|
||||
}
|
||||
|
||||
[tabbarPlacement=bottom] .tab-button {
|
||||
border-top: 2px solid transparent;
|
||||
border-bottom-width: 0;
|
||||
|
||||
&[aria-selected=true] {
|
||||
border-top-color: $tab-button-wp-active-color;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// Windows Tabbar Color Mixin
|
||||
// --------------------------------------------------
|
||||
|
||||
@mixin tabbar-wp($color-name, $color-base, $color-contrast) {
|
||||
|
||||
ion-tabs[#{$color-name}] tabbar {
|
||||
background-color: $color-base;
|
||||
|
||||
.tab-button {
|
||||
color: $color-contrast;
|
||||
}
|
||||
|
||||
.tab-button:hover:not(.disable-hover),
|
||||
.tab-button[aria-selected=true] {
|
||||
border-color: $color-contrast;
|
||||
color: $color-contrast;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
// Windows Tabbar Color Generation
|
||||
// --------------------------------------------------
|
||||
|
||||
@each $color-name, $color-base, $color-contrast in get-colors($colors-wp) {
|
||||
@include tabbar-wp($color-name, $color-base, $color-contrast);
|
||||
}
|
||||
20
src/components/tabs/test/advanced/e2e.ts
Normal file
20
src/components/tabs/test/advanced/e2e.ts
Normal file
@@ -0,0 +1,20 @@
|
||||
|
||||
// it('should go to Tab1 Page1', function() {
|
||||
// element(by.css('#signIn')).click();
|
||||
// });
|
||||
//
|
||||
// it('should go to Tab1 Page2', function() {
|
||||
// element(by.css('#goToTab1Page2')).click();
|
||||
// });
|
||||
//
|
||||
// it('should go back to Tab1 Page1', function() {
|
||||
// element(by.css('#backToTab1Page1')).click();
|
||||
// });
|
||||
//
|
||||
// it('should go to Tab2 Page1', function() {
|
||||
// element(by.css('.tab-button:nth-of-type(2)')).click();
|
||||
// });
|
||||
//
|
||||
// it('should go back to Tab1 Page1', function() {
|
||||
// element(by.css('.tab-button:nth-of-type(1)')).click();
|
||||
// });
|
||||
419
src/components/tabs/test/advanced/index.ts
Normal file
419
src/components/tabs/test/advanced/index.ts
Normal file
@@ -0,0 +1,419 @@
|
||||
import {ViewChild} from '@angular/core';
|
||||
import {RouteConfig} from '@angular/router';
|
||||
import {Location} from '@angular/common';
|
||||
|
||||
import {App, Page, NavController, NavParams, Modal, ViewController, Tabs} from '../../../../../ionic';
|
||||
|
||||
|
||||
@Page({
|
||||
template: `
|
||||
<ion-navbar *navbar>
|
||||
<ion-title>Sign In</ion-title>
|
||||
</ion-navbar>
|
||||
<ion-content padding>
|
||||
<ion-card>
|
||||
<ion-item>
|
||||
<ion-label>Username:</ion-label>
|
||||
<ion-input></ion-input>
|
||||
</ion-item>
|
||||
<ion-item>
|
||||
<ion-label>Password:</ion-label>
|
||||
<ion-input type="password"></ion-input>
|
||||
</ion-item>
|
||||
<ion-item>
|
||||
<button block id="signIn" (click)="push()">Sign In</button>
|
||||
</ion-item>
|
||||
</ion-card>
|
||||
</ion-content>
|
||||
`
|
||||
})
|
||||
class SignIn {
|
||||
constructor(private nav: NavController) {}
|
||||
|
||||
push() {
|
||||
this.nav.push(TabsPage, {
|
||||
userId: 8675309
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Page({
|
||||
template: `
|
||||
<ion-toolbar>
|
||||
<ion-title>Chat Modal</ion-title>
|
||||
</ion-toolbar>
|
||||
<ion-content padding>
|
||||
<p><button (click)="viewCtrl.dismiss()">Close Modal</button></p>
|
||||
</ion-content>
|
||||
`
|
||||
})
|
||||
class ChatPage {
|
||||
constructor(private viewCtrl: ViewController) {}
|
||||
|
||||
onPageDidLoad() {
|
||||
console.log('ChatPage, onPageDidLoad');
|
||||
}
|
||||
|
||||
onPageDidUnload() {
|
||||
console.log('ChatPage, onPageDidUnload');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Page({
|
||||
templateUrl: './tabs.html'
|
||||
})
|
||||
class TabsPage {
|
||||
tab1Root = Tab1Page1;
|
||||
tab2Root = Tab2Page1;
|
||||
tab3Root = Tab3Page1;
|
||||
@ViewChild(Tabs) tabs: Tabs;
|
||||
|
||||
constructor(private nav: NavController, private params: NavParams) {}
|
||||
|
||||
ngAfterViewInit() {
|
||||
this.tabs.change.subscribe(tab => {
|
||||
console.log('tabs.change.subscribe', tab.index);
|
||||
});
|
||||
}
|
||||
|
||||
onTabChange() {
|
||||
// wired up through the template
|
||||
// <ion-tabs (change)="onTabChange()">
|
||||
console.log('onTabChange');
|
||||
}
|
||||
|
||||
chat() {
|
||||
console.log('Chat clicked!');
|
||||
let modal = Modal.create(ChatPage);
|
||||
this.nav.present(modal);
|
||||
}
|
||||
|
||||
onPageWillEnter() {
|
||||
console.log('TabsPage, onPageWillEnter');
|
||||
}
|
||||
|
||||
onPageDidEnter() {
|
||||
console.log('TabsPage, onPageDidEnter');
|
||||
}
|
||||
|
||||
onPageWillLeave() {
|
||||
console.log('TabsPage, onPageWillLeave');
|
||||
}
|
||||
|
||||
onPageDidLeave() {
|
||||
console.log('TabsPage, onPageDidLeave');
|
||||
}
|
||||
|
||||
onPageDidUnload() {
|
||||
console.log('TabsPage, onPageDidUnload');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// tab 1
|
||||
//
|
||||
@Page({
|
||||
template: '' +
|
||||
'<ion-navbar *navbar>' +
|
||||
'<ion-title>Tabs 1 Page 1</ion-title>' +
|
||||
'</ion-navbar>' +
|
||||
'<ion-content padding>' +
|
||||
'<p><button id="goToTab1Page2" (click)="push()">Go to Tab 1, Page 2</button></p>' +
|
||||
'<p><button (click)="logout()">Logout</button></p>' +
|
||||
'<p><button (click)="favoritesTab()">Favorites Tab</button></p>' +
|
||||
'<p><button (click)="goBack()">Go Back</button></p>' +
|
||||
'<p>UserId: {{userId}}</p>' +
|
||||
'<f></f><f></f><f></f><f></f><f></f><f></f><f></f><f></f><f></f><f></f>' +
|
||||
'<f></f><f></f><f></f><f></f><f></f><f></f><f></f><f></f><f></f><f></f>' +
|
||||
'</ion-content>'
|
||||
})
|
||||
class Tab1Page1 {
|
||||
userId: string;
|
||||
|
||||
constructor(private nav: NavController, private tabs: Tabs, private params: NavParams) {
|
||||
this.userId = params.get('userId');
|
||||
}
|
||||
|
||||
push() {
|
||||
this.nav.push(Tab1Page2)
|
||||
}
|
||||
|
||||
goBack() {
|
||||
console.log('go back begin');
|
||||
this.nav.pop().then((val) => {
|
||||
console.log('go back completed', val);
|
||||
});;
|
||||
}
|
||||
|
||||
favoritesTab() {
|
||||
this.tabs.select(1);
|
||||
}
|
||||
|
||||
logout() {
|
||||
this.nav.rootNav.setRoot(SignIn, null, { animate: true, direction: 'back' });
|
||||
}
|
||||
|
||||
onPageWillEnter() {
|
||||
console.log('Tab1Page1, onPageWillEnter');
|
||||
}
|
||||
|
||||
onPageDidEnter() {
|
||||
console.log('Tab1Page1, onPageDidEnter');
|
||||
}
|
||||
|
||||
onPageWillLeave() {
|
||||
console.log('Tab1Page1, onPageWillLeave');
|
||||
}
|
||||
|
||||
onPageDidLeave() {
|
||||
console.log('Tab1Page1, onPageDidLeave');
|
||||
}
|
||||
|
||||
onPageDidUnload() {
|
||||
console.log('Tab1Page1, onPageDidUnload');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Page({
|
||||
template: '' +
|
||||
'<ion-navbar *navbar primary>' +
|
||||
'<ion-title>Tabs 1 Page 2</ion-title>' +
|
||||
'</ion-navbar>' +
|
||||
'<ion-content padding>' +
|
||||
'<p><button (click)="push()">Go to Tab 1, Page 3</button></p>' +
|
||||
'<p><button id="backToTab1Page1" (click)="nav.pop()">Back to Tab 1, Page 1</button></p>' +
|
||||
'<f></f><f></f><f></f><f></f><f></f><f></f><f></f><f></f><f></f><f></f>' +
|
||||
'<f></f><f></f><f></f><f></f><f></f><f></f><f></f><f></f><f></f><f></f>' +
|
||||
'</ion-content>'
|
||||
})
|
||||
class Tab1Page2 {
|
||||
constructor(private nav: NavController) {}
|
||||
|
||||
push() {
|
||||
this.nav.push(Tab1Page3)
|
||||
}
|
||||
|
||||
onPageWillEnter() {
|
||||
console.log('Tab1Page2, onPageWillEnter');
|
||||
}
|
||||
|
||||
onPageDidEnter() {
|
||||
console.log('Tab1Page2, onPageDidEnter');
|
||||
}
|
||||
|
||||
onPageWillLeave() {
|
||||
console.log('Tab1Page2, onPageWillLeave');
|
||||
}
|
||||
|
||||
onPageDidLeave() {
|
||||
console.log('Tab1Page2, onPageDidLeave');
|
||||
}
|
||||
|
||||
onPageDidUnload() {
|
||||
console.log('Tab1Page2, onPageDidUnload');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Page({
|
||||
template: '' +
|
||||
'<ion-navbar *navbar>' +
|
||||
'<ion-title>Tabs 1 Page 3</ion-title>' +
|
||||
'</ion-navbar>' +
|
||||
'<ion-content padding>' +
|
||||
'<p><button (click)="nav.pop()">Back to Tab 1, Page 2</button></p>' +
|
||||
'<f></f><f></f><f></f><f></f><f></f><f></f><f></f><f></f><f></f><f></f>' +
|
||||
'<f></f><f></f><f></f><f></f><f></f><f></f><f></f><f></f><f></f><f></f>' +
|
||||
'</ion-content>'
|
||||
})
|
||||
class Tab1Page3 {
|
||||
constructor(private nav: NavController) {}
|
||||
|
||||
onPageWillEnter() {
|
||||
console.log('Tab1Page3, onPageWillEnter');
|
||||
}
|
||||
|
||||
onPageDidEnter() {
|
||||
console.log('Tab1Page3, onPageDidEnter');
|
||||
}
|
||||
|
||||
onPageWillLeave() {
|
||||
console.log('Tab1Page3, onPageWillLeave');
|
||||
}
|
||||
|
||||
onPageDidLeave() {
|
||||
console.log('Tab1Page3, onPageDidLeave');
|
||||
}
|
||||
|
||||
onPageDidUnload() {
|
||||
console.log('Tab1Page3, onPageDidUnload');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//
|
||||
// tab 2
|
||||
//
|
||||
@Page({
|
||||
template: '' +
|
||||
'<ion-navbar *navbar>' +
|
||||
'<ion-title>Tabs 2 Page 1</ion-title>' +
|
||||
'</ion-navbar>' +
|
||||
'<ion-content padding>' +
|
||||
'<p><button (click)="push()">Go to Tab 2, Page 2</button></p>' +
|
||||
'<f></f><f></f><f></f><f></f><f></f><f></f><f></f><f></f><f></f><f></f>' +
|
||||
'<f></f><f></f><f></f><f></f><f></f><f></f><f></f><f></f><f></f><f></f>' +
|
||||
'</ion-content>'
|
||||
})
|
||||
class Tab2Page1 {
|
||||
constructor(private nav: NavController) {}
|
||||
|
||||
push() {
|
||||
this.nav.push(Tab2Page2)
|
||||
}
|
||||
|
||||
onPageWillEnter() {
|
||||
console.log('Tab2Page1, onPageWillEnter');
|
||||
}
|
||||
|
||||
onPageDidEnter() {
|
||||
console.log('Tab2Page1, onPageDidEnter');
|
||||
}
|
||||
|
||||
onPageWillLeave() {
|
||||
console.log('Tab2Page1, onPageWillLeave');
|
||||
}
|
||||
|
||||
onPageDidLeave() {
|
||||
console.log('Tab2Page1, onPageDidLeave');
|
||||
}
|
||||
|
||||
onPageDidUnload() {
|
||||
console.log('Tab2Page1, onPageDidUnload');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Page({
|
||||
template: '' +
|
||||
'<ion-navbar *navbar>' +
|
||||
'<ion-title>Tabs 2 Page 2</ion-title>' +
|
||||
'</ion-navbar>' +
|
||||
'<ion-content padding>' +
|
||||
'<p><button (click)="push()">Go to Tab 2, Page 3</button></p>' +
|
||||
'<p><button (click)="nav.pop()">Back to Tab 2, Page 1</button></p>' +
|
||||
'<f></f><f></f><f></f><f></f><f></f><f></f><f></f><f></f><f></f><f></f>' +
|
||||
'<f></f><f></f><f></f><f></f><f></f><f></f><f></f><f></f><f></f><f></f>' +
|
||||
'</ion-content>'
|
||||
})
|
||||
class Tab2Page2 {
|
||||
constructor(private nav: NavController) {}
|
||||
|
||||
push() {
|
||||
this.nav.push(Tab2Page3)
|
||||
}
|
||||
|
||||
onPageWillEnter() {
|
||||
console.log('Tab2Page2, onPageWillEnter');
|
||||
}
|
||||
|
||||
onPageDidEnter() {
|
||||
console.log('Tab2Page2, onPageDidEnter');
|
||||
}
|
||||
|
||||
onPageWillLeave() {
|
||||
console.log('Tab2Page2, onPageWillLeave');
|
||||
}
|
||||
|
||||
onPageDidLeave() {
|
||||
console.log('Tab2Page2, onPageDidLeave');
|
||||
}
|
||||
|
||||
onPageDidUnload() {
|
||||
console.log('Tab2Page2, onPageDidUnload');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Page({
|
||||
template: '' +
|
||||
'<ion-navbar *navbar>' +
|
||||
'<ion-title>Tabs 2 Page 3</ion-title>' +
|
||||
'</ion-navbar>' +
|
||||
'<ion-content padding>' +
|
||||
'<p><button (click)="nav.pop()">Back to Tab 2, Page 2</button></p>' +
|
||||
'<f></f><f></f><f></f><f></f><f></f><f></f><f></f><f></f><f></f><f></f>' +
|
||||
'<f></f><f></f><f></f><f></f><f></f><f></f><f></f><f></f><f></f><f></f>' +
|
||||
'</ion-content>'
|
||||
})
|
||||
class Tab2Page3 {
|
||||
constructor(private nav: NavController) {}
|
||||
|
||||
onPageWillEnter() {
|
||||
console.log('Tab2Page3, onPageWillEnter');
|
||||
}
|
||||
|
||||
onPageDidEnter() {
|
||||
console.log('Tab2Page3, onPageDidEnter');
|
||||
}
|
||||
|
||||
onPageWillLeave() {
|
||||
console.log('Tab2Page3, onPageWillLeave');
|
||||
}
|
||||
|
||||
onPageDidLeave() {
|
||||
console.log('Tab2Page3, onPageDidLeave');
|
||||
}
|
||||
|
||||
onPageDidUnload() {
|
||||
console.log('Tab2Page3, onPageDidUnload');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//
|
||||
// tab 3
|
||||
//
|
||||
@Page({
|
||||
template: '' +
|
||||
'<ion-navbar *navbar>' +
|
||||
'<ion-title>Tabs 3</ion-title>' +
|
||||
'</ion-navbar>' +
|
||||
'<ion-content padding><h2>Tabs 3</h2></ion-content>'
|
||||
})
|
||||
class Tab3Page1 {
|
||||
|
||||
onPageWillEnter() {
|
||||
console.log('Tab3Page1, onPageWillEnter');
|
||||
}
|
||||
|
||||
onPageDidEnter() {
|
||||
console.log('Tab3Page1, onPageDidEnter');
|
||||
}
|
||||
|
||||
onPageWillLeave() {
|
||||
console.log('Tab3Page1, onPageWillLeave');
|
||||
}
|
||||
|
||||
onPageDidLeave() {
|
||||
console.log('Tab3Page1, onPageDidLeave');
|
||||
}
|
||||
|
||||
onPageDidUnload() {
|
||||
console.log('Tab3Page1, onPageDidUnload');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@App()
|
||||
@RouteConfig([
|
||||
{ path: '/', component: SignIn, as: 'Signin' },
|
||||
{ path: '/tabs', component: TabsPage, as: 'Tabs' },
|
||||
])
|
||||
class E2EApp {}
|
||||
7
src/components/tabs/test/advanced/tabs.html
Normal file
7
src/components/tabs/test/advanced/tabs.html
Normal file
@@ -0,0 +1,7 @@
|
||||
|
||||
<ion-tabs preloadTabs="false" (change)="onTabChange()">
|
||||
<ion-tab tabTitle="Recents" tabIcon="call" [root]="tab1Root" [rootParams]="params"></ion-tab>
|
||||
<ion-tab tabTitle="Favorites" tabIcon="star" [root]="tab2Root"></ion-tab>
|
||||
<ion-tab tabTitle="Settings" tabIcon="settings" [root]="tab3Root"></ion-tab>
|
||||
<ion-tab tabTitle="Chat" tabIcon="chatbubbles" (select)="chat()"></ion-tab>
|
||||
</ion-tabs>
|
||||
13
src/components/tabs/test/badges/index.ts
Normal file
13
src/components/tabs/test/badges/index.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
import {App} from '../../../../../ionic';
|
||||
|
||||
|
||||
@App({
|
||||
templateUrl: 'main.html'
|
||||
})
|
||||
class E2EApp {
|
||||
myBadge:number = 55;
|
||||
|
||||
constructor() {}
|
||||
}
|
||||
|
||||
document.body.innerHTML += '<link href="styles.css" rel="stylesheet">'
|
||||
68
src/components/tabs/test/badges/main.html
Normal file
68
src/components/tabs/test/badges/main.html
Normal file
@@ -0,0 +1,68 @@
|
||||
|
||||
<!-- Text -->
|
||||
<ion-tabs no-navbar>
|
||||
<ion-tab tabTitle="Recents"></ion-tab>
|
||||
<ion-tab tabTitle="Favorites" tabBadge="32"></ion-tab>
|
||||
<ion-tab tabTitle="Settings"></ion-tab>
|
||||
</ion-tabs>
|
||||
|
||||
|
||||
<!-- Icons -->
|
||||
<ion-tabs no-navbar>
|
||||
<ion-tab tabIcon="call"></ion-tab>
|
||||
<ion-tab tabIcon="heart"></ion-tab>
|
||||
<ion-tab tabIcon="settings" tabBadge="all" tabBadgeStyle="primary"></ion-tab>
|
||||
</ion-tabs>
|
||||
|
||||
|
||||
<!-- Icons on top of text -->
|
||||
<ion-tabs no-navbar>
|
||||
<ion-tab tabTitle="Location" tabIcon="navigate" tabBadge="11" tabBadgeStyle="secondary"></ion-tab>
|
||||
<ion-tab tabTitle="Favorites" tabIcon="star"></ion-tab>
|
||||
<ion-tab tabTitle="Radio" tabIcon="musical-notes"></ion-tab>
|
||||
</ion-tabs>
|
||||
|
||||
|
||||
<!-- Icons below text -->
|
||||
<ion-tabs tabbarLayout="icon-bottom" no-navbar>
|
||||
<ion-tab tabTitle="Recents" tabIcon="call"></ion-tab>
|
||||
<ion-tab tabTitle="Favorites" tabIcon="heart" tabBadge="577" tabBadgeStyle="dark"></ion-tab>
|
||||
<ion-tab tabTitle="Settings" tabIcon="settings"></ion-tab>
|
||||
</ion-tabs>
|
||||
|
||||
|
||||
<!-- Icons right of text -->
|
||||
<ion-tabs tabbarLayout="icon-right" primary no-navbar>
|
||||
<ion-tab tabTitle="Recents" tabIcon="call"></ion-tab>
|
||||
<ion-tab tabTitle="Favorites" tabIcon="heart"></ion-tab>
|
||||
<ion-tab tabTitle="Settings" tabIcon="settings" tabBadge="1030" tabBadgeStyle="light"></ion-tab>
|
||||
</ion-tabs>
|
||||
|
||||
<!-- Icons left of text -->
|
||||
<ion-tabs tabbarLayout="icon-left" no-navbar>
|
||||
<ion-tab tabTitle="Recents" tabIcon="call" tabBadge="32" tabBadgeStyle="danger"></ion-tab>
|
||||
<ion-tab tabTitle="Favorites" tabIcon="heart"></ion-tab>
|
||||
<ion-tab tabTitle="Settings" tabIcon="settings"></ion-tab>
|
||||
</ion-tabs>
|
||||
|
||||
<!-- No icons -->
|
||||
<ion-tabs no-navbar tabbarLayout="icon-hide">
|
||||
<ion-tab tabTitle="Recents" tabIcon="call" [root]="root"></ion-tab>
|
||||
<ion-tab tabTitle="Favorites" tabIcon="heart" [root]="root" tabBadge="4"></ion-tab>
|
||||
<ion-tab tabTitle="Settings" tabIcon="settings" [root]="root"></ion-tab>
|
||||
</ion-tabs>
|
||||
|
||||
|
||||
<!-- No title -->
|
||||
<ion-tabs tabbarLayout="title-hide" secondary no-navbar>
|
||||
<ion-tab tabTitle="Recents" tabIcon="call" [root]="root" tabBadge="7" tabBadgeStyle="light"></ion-tab>
|
||||
<ion-tab tabTitle="Favorites" tabIcon="heart" [root]="root"></ion-tab>
|
||||
<ion-tab tabTitle="Settings" tabIcon="settings" [root]="root"></ion-tab>
|
||||
</ion-tabs>
|
||||
|
||||
<!-- Dynamic Badge -->
|
||||
<ion-tabs tabbarLayout="icon-left" no-navbar>
|
||||
<ion-tab tabTitle="Recents" tabIcon="call"></ion-tab>
|
||||
<ion-tab tabTitle="Favorites" tabIcon="heart"></ion-tab>
|
||||
<ion-tab tabTitle="Settings" tabIcon="settings" [tabBadge]="myBadge" tabBadgeStyle="primary"></ion-tab>
|
||||
</ion-tabs>
|
||||
12
src/components/tabs/test/badges/styles.css
Normal file
12
src/components/tabs/test/badges/styles.css
Normal file
@@ -0,0 +1,12 @@
|
||||
|
||||
ion-tabs {
|
||||
position: relative;
|
||||
top: auto;
|
||||
height: auto;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
ion-navbar-section,
|
||||
ion-content-section {
|
||||
display: none !important;
|
||||
}
|
||||
1
src/components/tabs/test/basic/e2e.ts
Normal file
1
src/components/tabs/test/basic/e2e.ts
Normal file
@@ -0,0 +1 @@
|
||||
|
||||
192
src/components/tabs/test/basic/index.ts
Normal file
192
src/components/tabs/test/basic/index.ts
Normal file
@@ -0,0 +1,192 @@
|
||||
import {App, Page, NavController, Alert, Modal, ViewController} from '../../../../../ionic';
|
||||
|
||||
//
|
||||
// Modal
|
||||
//
|
||||
@Page({
|
||||
template: `
|
||||
<ion-toolbar>
|
||||
<ion-buttons start>
|
||||
<button (click)="dismiss()">Cancel</button>
|
||||
</ion-buttons>
|
||||
|
||||
<ion-title>
|
||||
Filter Sessions
|
||||
</ion-title>
|
||||
|
||||
<ion-buttons end>
|
||||
<button (click)="dismiss()">Done</button>
|
||||
</ion-buttons>
|
||||
</ion-toolbar>
|
||||
|
||||
<ion-content class="outer-content">
|
||||
<ion-list>
|
||||
<ion-list-header>Tracks</ion-list-header>
|
||||
|
||||
<ion-item *ngFor="let i of items">
|
||||
<ion-label>Toggle {{i}}</ion-label>
|
||||
<ion-toggle secondary></ion-toggle>
|
||||
</ion-item>
|
||||
</ion-list>
|
||||
|
||||
<ion-list>
|
||||
<button ion-item danger detail-none>
|
||||
Reset All Filters
|
||||
</button>
|
||||
</ion-list>
|
||||
</ion-content>
|
||||
`
|
||||
})
|
||||
class MyModal {
|
||||
items: any[] = [];
|
||||
|
||||
constructor(private viewCtrl: ViewController) {
|
||||
for (var i = 1; i <= 10; i++) {
|
||||
this.items.push(i);
|
||||
}
|
||||
}
|
||||
|
||||
dismiss() {
|
||||
// using the injected ViewController this page
|
||||
// can "dismiss" itself and pass back data
|
||||
this.viewCtrl.dismiss();
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Tab 1
|
||||
//
|
||||
@Page({
|
||||
template: `
|
||||
<ion-navbar *navbar>
|
||||
<ion-title>Heart</ion-title>
|
||||
</ion-navbar>
|
||||
<ion-content>
|
||||
<ion-list>
|
||||
<ion-list-header>
|
||||
Tab 1
|
||||
</ion-list-header>
|
||||
<ion-item *ngFor="let i of items">Item {{i}} {{i}} {{i}} {{i}}</ion-item>
|
||||
</ion-list>
|
||||
</ion-content>
|
||||
`
|
||||
})
|
||||
export class Tab1 {
|
||||
items: any[] = [];
|
||||
|
||||
constructor() {
|
||||
for (var i = 1; i <= 250; i++) {
|
||||
this.items.push(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Tab 2
|
||||
//
|
||||
@Page({
|
||||
template: `
|
||||
<ion-navbar *navbar>
|
||||
<ion-title>Schedule</ion-title>
|
||||
</ion-navbar>
|
||||
<ion-content>
|
||||
<ion-list>
|
||||
<ion-item-sliding *ngFor="let session of sessions" #slidingItem>
|
||||
<ion-item>
|
||||
<h3>{{session.name}} {{session.name}} {{session.name}}</h3>
|
||||
<p>{{session.location}} {{session.location}} {{session.location}}</p>
|
||||
</ion-item>
|
||||
<ion-item-options>
|
||||
<button primary>Speaker<br>Info</button>
|
||||
<button secondary>Add to<br>Favorites</button>
|
||||
</ion-item-options>
|
||||
</ion-item-sliding>
|
||||
</ion-list>
|
||||
</ion-content>
|
||||
`
|
||||
})
|
||||
export class Tab2 {
|
||||
sessions: any[] = [];
|
||||
|
||||
constructor() {
|
||||
for (var i = 1; i <= 250; i++) {
|
||||
this.sessions.push({
|
||||
name: 'Name ' + i,
|
||||
location: 'Location: ' + i
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Tab 3
|
||||
//
|
||||
@Page({
|
||||
template: `
|
||||
<ion-navbar *navbar>
|
||||
<button menuToggle>
|
||||
<ion-icon name="menu"></ion-icon>
|
||||
</button>
|
||||
<ion-title>Stopwatch</ion-title>
|
||||
</ion-navbar>
|
||||
<ion-content padding>
|
||||
<h2>Tab 3</h2>
|
||||
<p>
|
||||
<button (click)="presentAlert()">Present Alert</button>
|
||||
<button (click)="presentModal()">Present Modal</button>
|
||||
</p>
|
||||
</ion-content>
|
||||
`
|
||||
})
|
||||
export class Tab3 {
|
||||
constructor(private nav: NavController) {}
|
||||
|
||||
presentAlert() {
|
||||
let alert = Alert.create({
|
||||
title: 'Alert Title!',
|
||||
buttons: ['Dismiss']
|
||||
});
|
||||
this.nav.present(alert);
|
||||
}
|
||||
|
||||
presentModal() {
|
||||
let modal = Modal.create(MyModal);
|
||||
this.nav.present(modal);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Page({
|
||||
template: `
|
||||
<ion-menu [content]="content">
|
||||
<ion-toolbar secondary>
|
||||
<ion-title>Menu</ion-title>
|
||||
</ion-toolbar>
|
||||
<ion-content>
|
||||
<ion-list>
|
||||
<button ion-item menuClose detail-none>
|
||||
Close Menu
|
||||
</button>
|
||||
</ion-list>
|
||||
</ion-content>
|
||||
</ion-menu>
|
||||
|
||||
<ion-tabs #content>
|
||||
<ion-tab tabTitle="Plain List" tabIcon="star" [root]="root1"></ion-tab>
|
||||
<ion-tab tabTitle="Schedule" tabIcon="globe" [root]="root2"></ion-tab>
|
||||
<ion-tab tabTitle="Stopwatch" tabIcon="stopwatch" [root]="root3"></ion-tab>
|
||||
</ion-tabs>
|
||||
`
|
||||
})
|
||||
export class TabsPage {
|
||||
root1 = Tab1;
|
||||
root2 = Tab2;
|
||||
root3 = Tab3;
|
||||
}
|
||||
|
||||
@App({
|
||||
template: `<ion-nav [root]="root"></ion-nav>`
|
||||
})
|
||||
export class e2eApp {
|
||||
root = TabsPage;
|
||||
}
|
||||
1
src/components/tabs/test/colors/e2e.ts
Normal file
1
src/components/tabs/test/colors/e2e.ts
Normal file
@@ -0,0 +1 @@
|
||||
|
||||
17
src/components/tabs/test/colors/index.ts
Normal file
17
src/components/tabs/test/colors/index.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
import {App, Page} from '../../../../../ionic';
|
||||
|
||||
|
||||
@Page({template:'hi'})
|
||||
class E2EPage{}
|
||||
|
||||
|
||||
@App({
|
||||
templateUrl: 'main.html'
|
||||
})
|
||||
class E2EApp {
|
||||
constructor() {
|
||||
this.root = E2EPage;
|
||||
}
|
||||
}
|
||||
|
||||
document.body.innerHTML += '<link href="styles.css" rel="stylesheet">'
|
||||
71
src/components/tabs/test/colors/main.html
Normal file
71
src/components/tabs/test/colors/main.html
Normal file
@@ -0,0 +1,71 @@
|
||||
|
||||
<!-- Default -->
|
||||
<ion-tabs no-navbar>
|
||||
<ion-tab tabTitle="Recents" [root]="root"></ion-tab>
|
||||
<ion-tab tabTitle="Favorites" [root]="root"></ion-tab>
|
||||
<ion-tab tabTitle="Settings" [root]="root"></ion-tab>
|
||||
</ion-tabs>
|
||||
|
||||
|
||||
<!-- Icons -->
|
||||
<ion-tabs no-navbar selectedIndex="1" primary>
|
||||
<ion-tab tabIcon="call" [root]="root"></ion-tab>
|
||||
<ion-tab tabIcon="heart" [root]="root"></ion-tab>
|
||||
<ion-tab tabIcon="settings" [root]="root"></ion-tab>
|
||||
</ion-tabs>
|
||||
|
||||
|
||||
<!-- Icons on top of text -->
|
||||
<ion-tabs no-navbar selectedIndex="2" secondary>
|
||||
<ion-tab tabTitle="Location" tabIcon="navigate" [root]="root"></ion-tab>
|
||||
<ion-tab tabTitle="Favorites" tabIcon="star" [root]="root"></ion-tab>
|
||||
<ion-tab tabTitle="Radio" tabIcon="musical-notes" [root]="root"></ion-tab>
|
||||
</ion-tabs>
|
||||
|
||||
|
||||
<!-- Icons below text -->
|
||||
<ion-tabs tabbarLayout="icon-bottom" no-navbar selectedIndex="1" dark>
|
||||
<ion-tab tabTitle="Recents" tabIcon="call" [root]="root"></ion-tab>
|
||||
<ion-tab tabTitle="Favorites" tabIcon="heart" [root]="root"></ion-tab>
|
||||
<ion-tab tabTitle="Settings" tabIcon="settings" [root]="root"></ion-tab>
|
||||
</ion-tabs>
|
||||
|
||||
|
||||
<!-- Icons right of text -->
|
||||
<ion-tabs tabbarLayout="icon-right" no-navbar selectedIndex="0" danger>
|
||||
<ion-tab tabTitle="Recents" tabIcon="call" [root]="root"></ion-tab>
|
||||
<ion-tab tabTitle="Favorites" tabIcon="heart" [root]="root"></ion-tab>
|
||||
<ion-tab tabTitle="Settings" tabIcon="settings" [root]="root"></ion-tab>
|
||||
</ion-tabs>
|
||||
|
||||
|
||||
<!-- Icons left of text -->
|
||||
<ion-tabs tabbarLayout="icon-left" no-navbar light>
|
||||
<ion-tab tabTitle="Recents" tabIcon="call" [root]="root"></ion-tab>
|
||||
<ion-tab tabTitle="Favorites" tabIcon="heart" [root]="root"></ion-tab>
|
||||
<ion-tab tabTitle="Settings" tabIcon="settings" [root]="root"></ion-tab>
|
||||
</ion-tabs>
|
||||
|
||||
|
||||
<!-- No icons -->
|
||||
<ion-tabs tabbarLayout="icon-hide" no-navbar primary>
|
||||
<ion-tab tabTitle="Recents" tabIcon="call" [root]="root"></ion-tab>
|
||||
<ion-tab tabTitle="Favorites" tabIcon="heart" [root]="root"></ion-tab>
|
||||
<ion-tab tabTitle="Settings" tabIcon="settings" [root]="root"></ion-tab>
|
||||
</ion-tabs>
|
||||
|
||||
|
||||
<!-- No title -->
|
||||
<ion-tabs tabbarLayout="title-hide" no-navbar secondary>
|
||||
<ion-tab tabTitle="Recents" tabIcon="call" [root]="root"></ion-tab>
|
||||
<ion-tab tabTitle="Favorites" tabIcon="heart" [root]="root"></ion-tab>
|
||||
<ion-tab tabTitle="Settings" tabIcon="settings" [root]="root"></ion-tab>
|
||||
</ion-tabs>
|
||||
|
||||
|
||||
<!-- No overflow text -->
|
||||
<ion-tabs no-navbar danger>
|
||||
<ion-tab tabTitle="Indiana Jones and the Raiders of the Lost Ark" [root]="root"></ion-tab>
|
||||
<ion-tab tabTitle="Indiana Jones and the Temple of Doom" [root]="root"></ion-tab>
|
||||
<ion-tab tabTitle="Indiana Jones and the Last Crusade" [root]="root"></ion-tab>
|
||||
</ion-tabs>
|
||||
12
src/components/tabs/test/colors/styles.css
Normal file
12
src/components/tabs/test/colors/styles.css
Normal file
@@ -0,0 +1,12 @@
|
||||
|
||||
ion-tabs {
|
||||
position: relative;
|
||||
top: auto;
|
||||
height: auto;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
ion-navbar-section,
|
||||
ion-content-section {
|
||||
display: none !important;
|
||||
}
|
||||
133
src/components/tabs/test/ghost/index.ts
Normal file
133
src/components/tabs/test/ghost/index.ts
Normal file
@@ -0,0 +1,133 @@
|
||||
import {App, Page, NavController, Tab} from '../../../../../ionic';
|
||||
|
||||
import {ContentChild, QueryList, ViewChildren} from '@angular/core';
|
||||
|
||||
//
|
||||
// Tab 1
|
||||
//
|
||||
@Page({
|
||||
template: `
|
||||
<ion-navbar *navbar>
|
||||
<ion-title>Heart</ion-title>
|
||||
</ion-navbar>
|
||||
<ion-content padding>
|
||||
<h2>Tab 1</h2>
|
||||
</ion-content>
|
||||
`
|
||||
})
|
||||
class Tab1 {
|
||||
constructor(nav: NavController) {
|
||||
this.nav = nav;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Tab 2
|
||||
//
|
||||
@Page({
|
||||
template: `
|
||||
<ion-navbar *navbar>
|
||||
<ion-title>Star</ion-title>
|
||||
</ion-navbar>
|
||||
<ion-content padding>
|
||||
<h2>Tab 2</h2>
|
||||
</ion-content>
|
||||
`
|
||||
})
|
||||
class Tab2 {
|
||||
constructor(nav: NavController) {
|
||||
this.nav = nav;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Tab 3
|
||||
//
|
||||
@Page({
|
||||
template: `
|
||||
<ion-navbar *navbar>
|
||||
<button menuToggle>
|
||||
<ion-icon name="menu"></ion-icon>
|
||||
</button>
|
||||
<ion-title>Stopwatch</ion-title>
|
||||
</ion-navbar>
|
||||
<ion-content padding>
|
||||
<h2>Tab 3</h2>
|
||||
</ion-content>
|
||||
`
|
||||
})
|
||||
class Tab3 {
|
||||
constructor(nav: NavController) {
|
||||
this.nav = nav;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Tab 3
|
||||
//
|
||||
@Page({
|
||||
template: `
|
||||
<ion-navbar *navbar>
|
||||
<button menuToggle>
|
||||
<ion-icon name="menu"></ion-icon>
|
||||
</button>
|
||||
<ion-title>Quesarito</ion-title>
|
||||
</ion-navbar>
|
||||
<ion-content padding>
|
||||
<h2>Quesarito</h2>
|
||||
</ion-content>
|
||||
`
|
||||
})
|
||||
class QuesaritoPage {
|
||||
constructor(nav: NavController) {
|
||||
this.nav = nav;
|
||||
}
|
||||
}
|
||||
|
||||
@App({
|
||||
template: `
|
||||
<ion-menu [content]="content">
|
||||
<ion-toolbar secondary>
|
||||
<ion-title>Secret Menu</ion-title>
|
||||
</ion-toolbar>
|
||||
<ion-content>
|
||||
<ion-list>
|
||||
<button ion-item menuClose detail-none (click)="openPage('quesarito')">
|
||||
Quesarito
|
||||
</button>
|
||||
</ion-list>
|
||||
</ion-content>
|
||||
</ion-menu>
|
||||
|
||||
<ion-tabs #content>
|
||||
<ion-tab tabTitle="Heart" tabIcon="heart" [root]="root1" #tab1></ion-tab>
|
||||
<ion-tab tabTitle="Star" tabIcon="star" [root]="root2"></ion-tab>
|
||||
<ion-tab tabTitle="Stopwatch" tabIcon="stopwatch" [root]="root3"></ion-tab>
|
||||
</ion-tabs>
|
||||
`
|
||||
})
|
||||
export class TabsPage {
|
||||
@ViewChildren(Tab) tab : QueryList<Tab>;
|
||||
|
||||
ngAfterViewInit() {
|
||||
console.log('Tab', this.tab);
|
||||
console.log(this.tab.first.setRoot);
|
||||
}
|
||||
|
||||
openPage(which) {
|
||||
let pages = {
|
||||
'quesarito': QuesaritoPage
|
||||
};
|
||||
|
||||
this.tab.first.setRoot(pages[which])
|
||||
}
|
||||
|
||||
constructor() {
|
||||
|
||||
this.root1 = Tab1;
|
||||
this.root2 = Tab2;
|
||||
this.root3 = Tab3;
|
||||
}
|
||||
ngOnInit() {
|
||||
}
|
||||
}
|
||||
1
src/components/tabs/test/tab-bar-scenarios/e2e.ts
Normal file
1
src/components/tabs/test/tab-bar-scenarios/e2e.ts
Normal file
@@ -0,0 +1 @@
|
||||
|
||||
17
src/components/tabs/test/tab-bar-scenarios/index.ts
Normal file
17
src/components/tabs/test/tab-bar-scenarios/index.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
import {App, Page} from '../../../../../ionic';
|
||||
|
||||
|
||||
@Page({template:'hi'})
|
||||
class E2EPage{}
|
||||
|
||||
|
||||
@App({
|
||||
templateUrl: 'main.html'
|
||||
})
|
||||
class E2EApp {
|
||||
constructor() {
|
||||
this.root = E2EPage;
|
||||
}
|
||||
}
|
||||
|
||||
document.body.innerHTML += '<link href="styles.css" rel="stylesheet">'
|
||||
73
src/components/tabs/test/tab-bar-scenarios/main.html
Normal file
73
src/components/tabs/test/tab-bar-scenarios/main.html
Normal file
@@ -0,0 +1,73 @@
|
||||
|
||||
<!-- Text -->
|
||||
<ion-tabs no-navbar>
|
||||
<ion-tab tabTitle="Recents" [root]="root"></ion-tab>
|
||||
<ion-tab tabTitle="Favorites" [root]="root"></ion-tab>
|
||||
<ion-tab tabTitle="Settings" [root]="root"></ion-tab>
|
||||
</ion-tabs>
|
||||
|
||||
|
||||
<!-- Icons -->
|
||||
<ion-tabs no-navbar selectedIndex="1">
|
||||
<ion-tab tabIcon="call" [root]="root"></ion-tab>
|
||||
<ion-tab tabIcon="heart" [root]="root"></ion-tab>
|
||||
<ion-tab tabIcon="settings" [root]="root"></ion-tab>
|
||||
</ion-tabs>
|
||||
|
||||
|
||||
<!-- Icons on top of text -->
|
||||
<ion-tabs no-navbar selectedIndex="2">
|
||||
<ion-tab tabTitle="Location" tabIcon="navigate" [root]="root"></ion-tab>
|
||||
<ion-tab tabTitle="Favorites" tabIcon="star" [root]="root"></ion-tab>
|
||||
<ion-tab tabTitle="Radio" tabIcon="musical-notes" [root]="root"></ion-tab>
|
||||
</ion-tabs>
|
||||
|
||||
|
||||
<!-- Icons below text -->
|
||||
<ion-tabs tabbarLayout="icon-bottom" no-navbar selectedIndex="1">
|
||||
<ion-tab tabTitle="Recents" tabIcon="call" [root]="root"></ion-tab>
|
||||
<ion-tab tabTitle="Favorites" tabIcon="heart" [root]="root"></ion-tab>
|
||||
<ion-tab tabTitle="Settings" tabIcon="settings" [root]="root"></ion-tab>
|
||||
</ion-tabs>
|
||||
|
||||
|
||||
<!-- Icons right of text -->
|
||||
<ion-tabs tabbarLayout="icon-right" no-navbar selectedIndex="0">
|
||||
<ion-tab tabTitle="Recents" tabIcon="call" [root]="root"></ion-tab>
|
||||
<ion-tab tabTitle="Favorites" tabIcon="heart" [root]="root"></ion-tab>
|
||||
<ion-tab tabTitle="Settings" tabIcon="settings" [root]="root"></ion-tab>
|
||||
</ion-tabs>
|
||||
|
||||
|
||||
<!-- Icons left of text -->
|
||||
<ion-tabs tabbarLayout="icon-left" no-navbar>
|
||||
<ion-tab tabTitle="Recents" tabIcon="call" [root]="root"></ion-tab>
|
||||
<ion-tab tabTitle="Favorites" tabIcon="heart" [root]="root"></ion-tab>
|
||||
<ion-tab tabTitle="Settings" tabIcon="settings" [root]="root"></ion-tab>
|
||||
</ion-tabs>
|
||||
|
||||
|
||||
<!-- No icons -->
|
||||
<ion-tabs tabbarLayout="icon-hide" no-navbar>
|
||||
<ion-tab tabTitle="Recents" tabIcon="call" [root]="root"></ion-tab>
|
||||
<ion-tab tabTitle="Favorites" tabIcon="heart" [root]="root"></ion-tab>
|
||||
<ion-tab tabTitle="Settings" tabIcon="settings" [root]="root"></ion-tab>
|
||||
</ion-tabs>
|
||||
|
||||
|
||||
<!-- No title -->
|
||||
<ion-tabs tabbarLayout="title-hide" secondary no-navbar>
|
||||
<ion-tab tabTitle="Recents" tabIcon="call" [root]="root"></ion-tab>
|
||||
<ion-tab tabTitle="Favorites" tabIcon="heart" [root]="root"></ion-tab>
|
||||
<ion-tab tabTitle="Radio" tabIcon="musical-notes" [root]="root"></ion-tab>
|
||||
<ion-tab tabTitle="Messages" tabIcon="chatboxes" [root]="root"></ion-tab>
|
||||
<ion-tab tabTitle="Settings" tabIcon="settings" [root]="root"></ion-tab>
|
||||
</ion-tabs>
|
||||
|
||||
|
||||
<!-- No overflow text -->
|
||||
<ion-tabs no-navbar>
|
||||
<ion-tab tabTitle="Indiana Jones and the Raiders of the Lost Ark" [root]="root"></ion-tab>
|
||||
<ion-tab tabTitle="Indiana Jones and the Temple of Doom" [root]="root"></ion-tab>
|
||||
<ion-tab tabTitle="Indiana Jones and the Last Crusade" [root]="root"></ion-tab>
|
||||
</ion-tabs>
|
||||
12
src/components/tabs/test/tab-bar-scenarios/styles.css
Normal file
12
src/components/tabs/test/tab-bar-scenarios/styles.css
Normal file
@@ -0,0 +1,12 @@
|
||||
|
||||
ion-tabs {
|
||||
position: relative;
|
||||
top: auto;
|
||||
height: auto;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
ion-navbar-section,
|
||||
ion-content-section {
|
||||
display: none !important;
|
||||
}
|
||||
Reference in New Issue
Block a user