mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2026-03-13 10:22:08 +08:00
feat(md): tab ripple and highlight line
This commit is contained in:
@@ -7,7 +7,7 @@
|
||||
.md .nav .navbar-title {
|
||||
color: #FDFEFE;
|
||||
}
|
||||
#tabs .tab-bar:before {
|
||||
#tabs tab-bar:before {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: auto;
|
||||
|
||||
@@ -60,11 +60,11 @@ export class Ion {
|
||||
}
|
||||
|
||||
width() {
|
||||
return this.getDimensions().w;
|
||||
return dom.getDimensions(this).width;
|
||||
}
|
||||
|
||||
height() {
|
||||
return this.getDimensions().h;
|
||||
return dom.getDimensions(this).height;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -8,11 +8,11 @@ $tab-bar-ios-item-icon-size: 32px !default;
|
||||
$tab-bar-ios-height: 49px !default;
|
||||
|
||||
|
||||
.tab-bar {
|
||||
tab-bar {
|
||||
border-top: 1px solid $toolbar-ios-border-color;
|
||||
}
|
||||
|
||||
.tabs[tab-bar-placement=top] .tab-bar {
|
||||
ion-tabs[tab-bar-placement=top] tab-bar {
|
||||
border-top: none;
|
||||
border-bottom: 1px solid $toolbar-ios-border-color;
|
||||
}
|
||||
@@ -72,13 +72,13 @@ $tab-bar-ios-height: 49px !default;
|
||||
min-height: $tab-bar-ios-height - 8;
|
||||
}
|
||||
|
||||
&.hairlines .tabs {
|
||||
&.hairlines ion-tabs {
|
||||
|
||||
.tab-bar {
|
||||
tab-bar {
|
||||
border-top-width: 0.5px;
|
||||
}
|
||||
|
||||
&[tab-bar-placement="top"] .tab-bar {
|
||||
&[tab-bar-placement="top"] tab-bar {
|
||||
border-bottom-width: 0.55px;
|
||||
}
|
||||
|
||||
|
||||
@@ -20,10 +20,6 @@ $tab-bar-md-item-height: 4.8rem !default;
|
||||
border-bottom: 2px solid transparent;
|
||||
}
|
||||
|
||||
.tab-button[aria-selected=true] {
|
||||
border-bottom-color: $tab-button-text-active;
|
||||
}
|
||||
|
||||
.tab-button-text {
|
||||
margin-top: 5px;
|
||||
margin-bottom: 5px;
|
||||
@@ -53,3 +49,18 @@ $tab-bar-md-item-height: 4.8rem !default;
|
||||
.tab-button.has-title-only {
|
||||
padding: 6px 10px 6px 10px;
|
||||
}
|
||||
|
||||
tab-highlight {
|
||||
position: absolute;
|
||||
display: block;
|
||||
height: 2px;
|
||||
width: 1px;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
background: $tab-button-active-color;
|
||||
transform-origin: 0 0;
|
||||
|
||||
&.animate {
|
||||
transition-duration: 300ms;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,7 +27,6 @@ import {Tabs} from './tabs';
|
||||
'[attr.id]': 'panelId',
|
||||
'[attr.aria-labelledby]': 'labeledBy',
|
||||
'[attr.aria-hidden]': 'isNotSelected',
|
||||
'[class.tab-selected]': 'isSelected',
|
||||
'role': 'tabpanel'
|
||||
}
|
||||
})
|
||||
|
||||
@@ -2,13 +2,14 @@
|
||||
// Tabs
|
||||
// --------------------------------------------------
|
||||
|
||||
$tab-bar-background-color: $toolbar-background-color !default;
|
||||
$tab-bar-background-color: $toolbar-background-color !default;
|
||||
|
||||
$tab-button-text-active: $toolbar-active-color !default;
|
||||
$tab-button-text-inactive: $toolbar-inactive-color !default;
|
||||
$tab-button-padding: 10px !default;
|
||||
$tab-button-min-width: 80px !default;
|
||||
$tab-button-max-width: 160px !default;
|
||||
$tab-button-text-color: $toolbar-text-color !default;
|
||||
$tab-button-active-color: $toolbar-active-color !default;
|
||||
$tab-button-inactive-color: $toolbar-inactive-color !default;
|
||||
$tab-button-padding: 10px !default;
|
||||
$tab-button-min-width: 80px !default;
|
||||
$tab-button-max-width: 240px !default;
|
||||
|
||||
|
||||
ion-tabs {
|
||||
@@ -50,7 +51,8 @@ ion-tab {
|
||||
order: $flex-order-tab-bar-top;
|
||||
}
|
||||
|
||||
.tab-bar {
|
||||
tab-bar {
|
||||
position: relative;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
overflow: hidden;
|
||||
@@ -58,6 +60,9 @@ ion-tab {
|
||||
}
|
||||
|
||||
.tab-button {
|
||||
position: relative;
|
||||
z-index: 0;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
@@ -74,13 +79,13 @@ ion-tab {
|
||||
cursor: pointer;
|
||||
@include user-select-none();
|
||||
|
||||
color: $tab-button-text-inactive;
|
||||
color: $tab-button-inactive-color;
|
||||
border: 0;
|
||||
border-radius: 0;
|
||||
background: none;
|
||||
|
||||
&:hover:not(.disable-hover) {
|
||||
color: $tab-button-text-inactive;
|
||||
color: $tab-button-active-color;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -138,5 +143,9 @@ ion-tab {
|
||||
}
|
||||
|
||||
.tab-button[aria-selected=true] {
|
||||
color: $toolbar-active-color;
|
||||
color: $tab-button-active-color;
|
||||
}
|
||||
|
||||
tab-highlight {
|
||||
display: none;
|
||||
}
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
import {Component, Directive, View, Injector, NgFor, ElementRef, Optional, Host, forwardRef, NgZone} from 'angular2/angular2';
|
||||
|
||||
import {Ion} from '../ion';
|
||||
import {IonicApp} from '../app/app';
|
||||
import {NavController} from '../nav/nav-controller';
|
||||
import {ViewController} from '../nav/view-controller';
|
||||
import {IonicComponent, IonicView} from '../../config/decorators';
|
||||
import {IonicConfig} from '../../config/config';
|
||||
import * as dom from 'ionic/util/dom';
|
||||
|
||||
|
||||
/**
|
||||
@@ -24,9 +26,9 @@ import {IonicConfig} from '../../config/config';
|
||||
* @usage
|
||||
* ```html
|
||||
* <ion-tabs>
|
||||
* <ion-tab tab-title="Heart" tab-icon="ion-ios-heart-outline" [root]="root1"></ion-tab>
|
||||
* <ion-tab tab-title="Star" tab-icon="ion-ios-star-outline" [root]="root2"></ion-tab>
|
||||
* <ion-tab tab-title="Stopwatch" tab-icon="ion-ios-stopwatch-outline" [root]="root3"></ion-tab>
|
||||
* <ion-tab tab-title="Heart" tab-icon="heart-" [root]="root1"></ion-tab>
|
||||
* <ion-tab tab-title="Star" tab-icon="star" [root]="root2"></ion-tab>
|
||||
* <ion-tab tab-title="Stopwatch" tab-icon="stopwatch" [root]="root3"></ion-tab>
|
||||
* </ion-tabs>
|
||||
* ```
|
||||
*
|
||||
@@ -41,17 +43,18 @@ import {IonicConfig} from '../../config/config';
|
||||
@IonicView({
|
||||
template: '' +
|
||||
'<nav class="tab-bar-container">' +
|
||||
'<div class="tab-bar" role="tablist">' +
|
||||
'<tab-bar role="tablist">' +
|
||||
'<a *ng-for="#t of tabs" [tab]="t" class="tab-button" role="tab">' +
|
||||
'<icon [name]="t.tabIcon" [is-active]="t.isSelected" class="tab-button-icon"></icon>' +
|
||||
'<span class="tab-button-text">{{t.tabTitle}}</span>' +
|
||||
'</a>' +
|
||||
'</div>' +
|
||||
'<tab-highlight></tab-highlight>' +
|
||||
'</tab-bar>' +
|
||||
'</nav>' +
|
||||
'<section class="content-container">' +
|
||||
'<ng-content></ng-content>' +
|
||||
'</section>',
|
||||
directives: [forwardRef(() => TabButton)]
|
||||
directives: [forwardRef(() => TabButton), forwardRef(() => TabHighlight)]
|
||||
})
|
||||
export class Tabs extends NavController {
|
||||
/**
|
||||
@@ -138,6 +141,7 @@ export class Tabs extends NavController {
|
||||
leavingView.shouldCache = true;
|
||||
|
||||
this.transition(enteringView, leavingView, opts, () => {
|
||||
this.highlight && this.highlight.select(tab);
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
@@ -168,8 +172,9 @@ export class Tabs extends NavController {
|
||||
'(click)': 'onClick($event)',
|
||||
}
|
||||
})
|
||||
class TabButton {
|
||||
class TabButton extends Ion {
|
||||
constructor(@Host() tabs: Tabs, config: IonicConfig, elementRef: ElementRef) {
|
||||
super(elementRef, config);
|
||||
this.tabs = tabs;
|
||||
|
||||
if (config.setting('hoverCSS') === false) {
|
||||
@@ -178,6 +183,7 @@ class TabButton {
|
||||
}
|
||||
|
||||
onInit() {
|
||||
this.tab.btn = this;
|
||||
let id = this.tab.viewCtrl.id;
|
||||
this.btnId = 'tab-button-' + id;
|
||||
this.panelId = 'tab-panel-' + id;
|
||||
@@ -194,3 +200,32 @@ class TabButton {
|
||||
this.tabs.select(this.tab);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Directive({
|
||||
selector: 'tab-highlight'
|
||||
})
|
||||
class TabHighlight {
|
||||
constructor(@Host() tabs: Tabs, config: IonicConfig, elementRef: ElementRef) {
|
||||
if (config.setting('mode') === 'md') {
|
||||
tabs.highlight = this;
|
||||
this.elementRef = elementRef;
|
||||
}
|
||||
}
|
||||
|
||||
select(tab) {
|
||||
setTimeout(() => {
|
||||
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;
|
||||
setTimeout(() => {
|
||||
ele.classList.add('animate');
|
||||
}, 64)
|
||||
}
|
||||
}, 32);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -242,8 +242,10 @@ export function getDimensions(ion) {
|
||||
if (!dimensions) {
|
||||
let ele = ion.getNativeElement();
|
||||
dimensions = dimensionCache[ion._dimId] = {
|
||||
w: ele.offsetWidth,
|
||||
h: ele.offsetHeight
|
||||
width: ele.offsetWidth,
|
||||
height: ele.offsetHeight,
|
||||
left: ele.offsetLeft,
|
||||
top: ele.offsetTop
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user