mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-08-23 22:17:40 +08:00
refactor(tabs): change the material design tabs to act as bottom navigation
Update tabs to reflect the material design bottom navigation spec: https://material.google.com/components/bottom-navigation.html#bottom-nav igation-usage BREAKING CHANGES: Material design mode defaults have changed to the following: ``` tabsHighlight: false, tabsPlacement: 'bottom', tabsHideOnSubPages: false ``` `tabsHighlight` can now be passed as an attribute on the `ion-tabs` element, this allows for tabs to be added in multiple places inside of an app and enable the highlight on some of them. references #7455
This commit is contained in:
@ -5,44 +5,45 @@
|
|||||||
// --------------------------------------------------
|
// --------------------------------------------------
|
||||||
|
|
||||||
$tabbar-md-background: $toolbar-md-background !default;
|
$tabbar-md-background: $toolbar-md-background !default;
|
||||||
$tabbar-md-item-padding: 12px 10px 5px 10px !default;
|
$tabbar-md-item-padding: 8px 0 10px 0 !default;
|
||||||
$tabbar-md-item-font-size: 1.4rem !default;
|
$tabbar-md-item-font-size: 1.4rem !default;
|
||||||
$tabbar-md-item-font-weight: 500 !default;
|
$tabbar-md-item-font-weight: normal !default;
|
||||||
$tabbar-md-item-icon-size: 2.4rem !default;
|
$tabbar-md-item-icon-size: 2.4rem !default;
|
||||||
$tabbar-md-item-height: 4.8rem !default;
|
$tabbar-md-item-height: 5.6rem !default;
|
||||||
|
|
||||||
$tab-button-md-active-color: $toolbar-md-active-color !default;
|
$tab-button-md-active-color: $toolbar-md-active-color !default;
|
||||||
|
$tab-button-md-active-font-size: 1.5rem !default;
|
||||||
|
$tab-button-md-active-padding-top: 6px !default;
|
||||||
$tab-button-md-inactive-opacity: .7 !default;
|
$tab-button-md-inactive-opacity: .7 !default;
|
||||||
$tab-button-md-inactive-color: rgba($toolbar-md-inactive-color, $tab-button-md-inactive-opacity) !default;
|
$tab-button-md-inactive-color: rgba($toolbar-md-inactive-color, $tab-button-md-inactive-opacity) !default;
|
||||||
|
$tab-button-md-text-transform: none !default;
|
||||||
|
$tab-button-md-text-margin: 6px 0 !default;
|
||||||
|
|
||||||
|
|
||||||
ion-tabbar {
|
ion-tabbar {
|
||||||
background: $tabbar-md-background;
|
background: $tabbar-md-background;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
.tab-button {
|
.tab-button {
|
||||||
padding: $tabbar-md-item-padding;
|
padding: $tabbar-md-item-padding;
|
||||||
|
|
||||||
min-height: $tabbar-md-item-height;
|
min-height: $tabbar-md-item-height;
|
||||||
|
|
||||||
border-bottom: 2px solid transparent;
|
|
||||||
border-radius: 0;
|
|
||||||
font-size: $tabbar-md-item-font-size;
|
font-size: $tabbar-md-item-font-size;
|
||||||
font-weight: $tabbar-md-item-font-weight;
|
font-weight: $tabbar-md-item-font-weight;
|
||||||
color: $tab-button-md-inactive-color;
|
color: $tab-button-md-inactive-color;
|
||||||
box-shadow: none;
|
|
||||||
|
|
||||||
&[aria-selected=true] {
|
&[aria-selected=true] {
|
||||||
color: $tab-button-md-active-color;
|
color: $tab-button-md-active-color;
|
||||||
|
font-size: $tab-button-md-active-font-size;
|
||||||
|
padding-top: $tab-button-md-active-padding-top;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.tab-button-text {
|
.tab-button-text {
|
||||||
margin-top: 5px;
|
margin: $tab-button-md-text-margin;
|
||||||
margin-bottom: 5px;
|
|
||||||
|
|
||||||
text-transform: uppercase;
|
text-transform: $tab-button-md-text-transform;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tab-button-icon {
|
.tab-button-icon {
|
||||||
@ -51,9 +52,21 @@ ion-tabbar {
|
|||||||
font-size: $tabbar-md-item-icon-size;
|
font-size: $tabbar-md-item-icon-size;
|
||||||
}
|
}
|
||||||
|
|
||||||
[tabsLayout=icon-bottom] .tab-button {
|
[tabsLayout=icon-top] {
|
||||||
padding-top: 8px;
|
.has-icon .tab-button-text {
|
||||||
padding-bottom: 8px;
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[tabsLayout=icon-bottom] {
|
||||||
|
.tab-button {
|
||||||
|
padding-top: 8px;
|
||||||
|
padding-bottom: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-button-text {
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[tabsLayout=icon-right] .tab-button,
|
[tabsLayout=icon-right] .tab-button,
|
||||||
@ -72,30 +85,37 @@ ion-tabbar {
|
|||||||
padding: 6px 10px;
|
padding: 6px 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
tab-highlight {
|
// Material Design Tab Highlight
|
||||||
position: absolute;
|
// --------------------------------------------------
|
||||||
bottom: 0;
|
|
||||||
left: 0;
|
|
||||||
display: block;
|
|
||||||
|
|
||||||
width: 1px;
|
[tabsHighlight=true] {
|
||||||
height: 2px;
|
|
||||||
|
|
||||||
background: $tab-button-md-active-color;
|
tab-highlight {
|
||||||
transform: translateZ(0);
|
position: absolute;
|
||||||
transform-origin: 0 0;
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
display: block;
|
||||||
|
|
||||||
&.animate {
|
width: 1px;
|
||||||
transition-duration: 300ms;
|
height: 2px;
|
||||||
|
|
||||||
|
background: $tab-button-md-active-color;
|
||||||
|
transform: translateZ(0);
|
||||||
|
transform-origin: 0 0;
|
||||||
|
|
||||||
|
&.animate {
|
||||||
|
transition-duration: 300ms;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&[tabsPlacement=bottom] tab-highlight {
|
||||||
|
top: 0;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
[tabsPlacement=bottom] tab-highlight {
|
|
||||||
top: 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Material Design Tabbar Color Mixin
|
// Material Design Tabs Color Mixin
|
||||||
// --------------------------------------------------
|
// --------------------------------------------------
|
||||||
|
|
||||||
@mixin tabbar-md($color-name, $color-base, $color-contrast) {
|
@mixin tabbar-md($color-name, $color-base, $color-contrast) {
|
||||||
|
@ -160,7 +160,6 @@ export class Tabs extends Ion {
|
|||||||
private _tabs: Tab[] = [];
|
private _tabs: Tab[] = [];
|
||||||
private _onReady: any = null;
|
private _onReady: any = null;
|
||||||
private _sbPadding: boolean;
|
private _sbPadding: boolean;
|
||||||
private _useHighlight: boolean;
|
|
||||||
private _top: number;
|
private _top: number;
|
||||||
private _bottom: number;
|
private _bottom: number;
|
||||||
|
|
||||||
@ -209,6 +208,11 @@ export class Tabs extends Ion {
|
|||||||
*/
|
*/
|
||||||
@Input() tabsPlacement: string;
|
@Input() tabsPlacement: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @input {boolean} Whether to show the tab highlight bar under the selected tab. Default: `false`.
|
||||||
|
*/
|
||||||
|
@Input() tabsHighlight: boolean;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @input {any} Expression to evaluate when the tab changes.
|
* @input {any} Expression to evaluate when the tab changes.
|
||||||
*/
|
*/
|
||||||
@ -249,7 +253,7 @@ export class Tabs extends Ion {
|
|||||||
this.id = 't' + (++tabIds);
|
this.id = 't' + (++tabIds);
|
||||||
this._sbPadding = _config.getBoolean('statusbarPadding');
|
this._sbPadding = _config.getBoolean('statusbarPadding');
|
||||||
this.subPages = _config.getBoolean('tabsHideOnSubPages');
|
this.subPages = _config.getBoolean('tabsHideOnSubPages');
|
||||||
this._useHighlight = _config.getBoolean('tabsHighlight');
|
this.tabsHighlight = _config.getBoolean('tabsHighlight');
|
||||||
|
|
||||||
// TODO deprecated 07-07-2016 beta.11
|
// TODO deprecated 07-07-2016 beta.11
|
||||||
if (_config.get('tabSubPages') !== null) {
|
if (_config.get('tabSubPages') !== null) {
|
||||||
@ -260,7 +264,7 @@ export class Tabs extends Ion {
|
|||||||
// TODO deprecated 07-07-2016 beta.11
|
// TODO deprecated 07-07-2016 beta.11
|
||||||
if (_config.get('tabbarHighlight') !== null) {
|
if (_config.get('tabbarHighlight') !== null) {
|
||||||
console.warn('Config option "tabbarHighlight" has been deprecated. Please use "tabsHighlight" instead.');
|
console.warn('Config option "tabbarHighlight" has been deprecated. Please use "tabsHighlight" instead.');
|
||||||
this._useHighlight = _config.getBoolean('tabbarHighlight');
|
this.tabsHighlight = _config.getBoolean('tabbarHighlight');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.parent) {
|
if (this.parent) {
|
||||||
@ -291,6 +295,7 @@ export class Tabs extends Ion {
|
|||||||
ngAfterViewInit() {
|
ngAfterViewInit() {
|
||||||
this._setConfig('tabsPlacement', 'bottom');
|
this._setConfig('tabsPlacement', 'bottom');
|
||||||
this._setConfig('tabsLayout', 'icon-top');
|
this._setConfig('tabsLayout', 'icon-top');
|
||||||
|
this._setConfig('tabsHighlight', this.tabsHighlight);
|
||||||
|
|
||||||
// TODO deprecated 07-07-2016 beta.11
|
// TODO deprecated 07-07-2016 beta.11
|
||||||
this._setConfig('tabbarPlacement', 'bottom');
|
this._setConfig('tabbarPlacement', 'bottom');
|
||||||
@ -322,7 +327,7 @@ export class Tabs extends Ion {
|
|||||||
this._renderer.setElementAttribute(this._elementRef.nativeElement, 'tabsLayout', this._config.get('tabsLayout'));
|
this._renderer.setElementAttribute(this._elementRef.nativeElement, 'tabsLayout', this._config.get('tabsLayout'));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this._useHighlight) {
|
if (this.tabsHighlight) {
|
||||||
this._platform.onResize(() => {
|
this._platform.onResize(() => {
|
||||||
this._highlight.select(this.getSelected());
|
this._highlight.select(this.getSelected());
|
||||||
});
|
});
|
||||||
@ -428,7 +433,7 @@ export class Tabs extends Ion {
|
|||||||
tab.setSelected(tab === selectedTab);
|
tab.setSelected(tab === selectedTab);
|
||||||
});
|
});
|
||||||
|
|
||||||
if (this._useHighlight) {
|
if (this.tabsHighlight) {
|
||||||
this._highlight.select(selectedTab);
|
this._highlight.select(selectedTab);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -81,9 +81,9 @@ Config.setModeConfig('md', {
|
|||||||
|
|
||||||
spinner: 'crescent',
|
spinner: 'crescent',
|
||||||
|
|
||||||
tabsHighlight: true,
|
tabsHighlight: false,
|
||||||
tabsPlacement: 'top',
|
tabsPlacement: 'bottom',
|
||||||
tabsHideOnSubPages: true,
|
tabsHideOnSubPages: false,
|
||||||
|
|
||||||
toastEnter: 'toast-md-slide-in',
|
toastEnter: 'toast-md-slide-in',
|
||||||
toastLeave: 'toast-md-slide-out',
|
toastLeave: 'toast-md-slide-out',
|
||||||
|
Reference in New Issue
Block a user