diff --git a/packages/core/src/components.d.ts b/packages/core/src/components.d.ts
index 0137e730f4..9335a45882 100644
--- a/packages/core/src/components.d.ts
+++ b/packages/core/src/components.d.ts
@@ -2707,36 +2707,6 @@ declare global {
}
-import {
- TabHighlight as IonTabHighlight
-} from './components/tab-highlight/tab-highlight';
-
-declare global {
- interface HTMLIonTabHighlightElement extends IonTabHighlight, HTMLElement {
- }
- var HTMLIonTabHighlightElement: {
- prototype: HTMLIonTabHighlightElement;
- new (): HTMLIonTabHighlightElement;
- };
- interface HTMLElementTagNameMap {
- "ion-tab-highlight": HTMLIonTabHighlightElement;
- }
- interface ElementTagNameMap {
- "ion-tab-highlight": HTMLIonTabHighlightElement;
- }
- namespace JSX {
- interface IntrinsicElements {
- "ion-tab-highlight": JSXElements.IonTabHighlightAttributes;
- }
- }
- namespace JSXElements {
- export interface IonTabHighlightAttributes extends HTMLAttributes {
- selectedTab?: HTMLIonTabElement;
- }
- }
-}
-
-
import {
Tab as IonTab
} from './components/tab/tab';
@@ -2805,6 +2775,7 @@ declare global {
highlight?: boolean;
layout?: string;
placement?: string;
+ scrollable?: Boolean;
selectedTab?: HTMLIonTabElement;
tabs?: HTMLIonTabElement[];
translucent?: boolean;
@@ -2838,6 +2809,7 @@ declare global {
namespace JSXElements {
export interface IonTabsAttributes extends HTMLAttributes {
name?: string;
+ scrollable?: boolean;
tabbarHidden?: boolean;
tabbarHighlight?: boolean;
tabbarLayout?: string;
diff --git a/packages/core/src/components/scroll/scroll.tsx b/packages/core/src/components/scroll/scroll.tsx
index 9c8e81cff0..e5813a0c36 100644
--- a/packages/core/src/components/scroll/scroll.tsx
+++ b/packages/core/src/components/scroll/scroll.tsx
@@ -148,7 +148,7 @@ export class Scroll {
if (easedT < 1) {
// do not use DomController here
// must use nativeRaf in order to fire in the next frame
- this.dom.raf(step);
+ self.dom.raf(step);
} else {
stopScroll = true;
diff --git a/packages/core/src/components/tab-button/readme.md b/packages/core/src/components/tab-button/readme.md
index 53a86e0031..a3e455c10f 100644
--- a/packages/core/src/components/tab-button/readme.md
+++ b/packages/core/src/components/tab-button/readme.md
@@ -31,6 +31,12 @@ any
## Events
+#### ionTabButtonDidLoad
+
+
+#### ionTabButtonDidUnload
+
+
#### ionTabbarClick
diff --git a/packages/core/src/components/tab-button/tab-button.tsx b/packages/core/src/components/tab-button/tab-button.tsx
index 8088f68825..79f06ce7d9 100644
--- a/packages/core/src/components/tab-button/tab-button.tsx
+++ b/packages/core/src/components/tab-button/tab-button.tsx
@@ -1,4 +1,4 @@
-import { Component, Event, EventEmitter, Listen, Prop } from '@stencil/core';
+import {Component, Element, Event, EventEmitter, Listen, Prop} from '@stencil/core';
@Component({
@@ -6,10 +6,22 @@ import { Component, Event, EventEmitter, Listen, Prop } from '@stencil/core';
})
export class TabButton {
+ @Element() el: HTMLElement;
+
@Prop() selected = false;
@Prop() tab: HTMLIonTabElement;
@Event() ionTabbarClick: EventEmitter;
+ @Event() ionTabButtonDidLoad: EventEmitter;
+ @Event() ionTabButtonDidUnload: EventEmitter;
+
+ componentDidLoad() {
+ this.ionTabButtonDidLoad.emit({ button: this });
+ }
+
+ componentDidUnload() {
+ this.ionTabButtonDidUnload.emit({ button: this });
+ }
@Listen('click')
protected onClick(ev: UIEvent) {
@@ -21,7 +33,7 @@ export class TabButton {
const selected = this.selected;
const tab = this.tab;
const hasTitle = !!tab.title;
- const hasIcon = !! tab.icon;
+ const hasIcon = !!tab.icon;
const hasTitleOnly = (hasTitle && !hasIcon);
const hasIconOnly = (hasIcon && !hasTitle);
const hasBadge = !!tab.badge;
diff --git a/packages/core/src/components/tab-highlight/readme.md b/packages/core/src/components/tab-highlight/readme.md
deleted file mode 100644
index 5828817aea..0000000000
--- a/packages/core/src/components/tab-highlight/readme.md
+++ /dev/null
@@ -1,25 +0,0 @@
-# ion-tab-highlight
-
-
-
-
-
-
-## Properties
-
-#### selectedTab
-
-any
-
-
-## Attributes
-
-#### selectedTab
-
-any
-
-
-
-----------------------------------------------
-
-*Built by [StencilJS](https://stenciljs.com/)*
diff --git a/packages/core/src/components/tab-highlight/tab-highlight.tsx b/packages/core/src/components/tab-highlight/tab-highlight.tsx
deleted file mode 100644
index 79a0958b90..0000000000
--- a/packages/core/src/components/tab-highlight/tab-highlight.tsx
+++ /dev/null
@@ -1,64 +0,0 @@
-import { Component, Element, Listen, Prop, PropDidChange, State } from '@stencil/core';
-import { DomController } from '../../index';
-import { getParentElement } from '../../utils/helpers';
-
-
-@Component({
- tag: 'ion-tab-highlight'
-})
-export class TabHighlight {
-
- @Element() private el: HTMLElement;
-
- @State() animated = false;
- @State() transform = '';
-
- @Prop({ context: 'dom' }) dom: DomController;
-
- @Prop() selectedTab: HTMLIonTabElement;
- @PropDidChange('selectedTab')
- selectedTabChanged() {
- this.updateTransform();
- }
-
- @Listen('window:resize')
- onResize() {
- this.updateTransform();
- }
-
- componentDidLoad() {
- this.updateTransform();
- }
-
- protected updateTransform() {
- this.dom.read(() => {
- const btn = this.getSelectedButton();
- this.transform = (btn)
- ? `translate3d(${btn.offsetLeft}px,0,0) scaleX(${btn.offsetWidth})`
- : '';
- if (!this.animated) {
- setTimeout(() => this.animated = true, 80);
- }
- });
- }
-
- private getSelectedButton(): HTMLIonTabButtonElement {
- const parent = getParentElement(this.el) as HTMLElement;
- if (!parent) {
- return null;
- }
- return Array.from(parent.querySelectorAll('ion-tab-button'))
- .find(btn => btn.selected);
- }
-
- hostData() {
- return {
- style: {
- 'transform': this.transform
- },
- class: {
- 'animated': this.animated,
- }
- };
- }
-}
diff --git a/packages/core/src/components/tabbar/readme.md b/packages/core/src/components/tabbar/readme.md
index 0ed636e12e..855fd4da55 100644
--- a/packages/core/src/components/tabbar/readme.md
+++ b/packages/core/src/components/tabbar/readme.md
@@ -22,6 +22,11 @@ string
string
+#### scrollable
+
+any
+
+
#### selectedTab
any
@@ -54,6 +59,11 @@ string
string
+#### scrollable
+
+any
+
+
#### selectedTab
any
diff --git a/packages/core/src/components/tabbar/tabbar.tsx b/packages/core/src/components/tabbar/tabbar.tsx
index 7ce1667ba3..68743ad001 100644
--- a/packages/core/src/components/tabbar/tabbar.tsx
+++ b/packages/core/src/components/tabbar/tabbar.tsx
@@ -1,6 +1,6 @@
-import { Component, Listen, Prop, State } from '@stencil/core';
-import { createThemedClasses } from '../../utils/theme';
-
+import {Component, Element, Listen, Prop, PropDidChange, State} from '@stencil/core';
+import {createThemedClasses} from '../../utils/theme';
+import {DomController} from "../../index";
@Component({
tag: 'ion-tabbar',
@@ -12,11 +12,27 @@ export class Tabbar {
mode: string;
color: string;
+ @Element() el: HTMLElement;
+
+ @State() canScrollLeft: boolean = false;
+ @State() canScrollRight: boolean = false;
+
@State() hidden = false;
+ @Prop({ context: 'dom' }) dom: DomController;
@Prop() placement = 'bottom';
- @Prop() tabs: HTMLIonTabElement[];
@Prop() selectedTab: HTMLIonTabElement;
+ @Prop() scrollable:Boolean;
+ @Prop() tabs: HTMLIonTabElement[];
+
+ private scrollEl: HTMLIonScrollElement;
+
+ @PropDidChange('selectedTab')
+ selectedTabChanged() {
+ this.scrollable && this.scrollToSelectedButton();
+ this.highlight && this.updateHighlight();
+ }
+
@Prop() layout: string = 'icon-top';
@Prop() highlight: boolean = false;
@Prop() translucent: boolean = false;
@@ -33,6 +49,46 @@ export class Tabbar {
}
}
+ @Listen('window:resize')
+ onResize() {
+ this.highlight && this.updateHighlight();
+ }
+
+ @Listen('ionTabButtonDidLoad')
+ @Listen('ionTabButtonDidUnload')
+ onTabButtonLoad() {
+ this.scrollable && this.updateBoundaries();
+ this.highlight && this.updateHighlight()
+ }
+
+ protected analyzeTabs() {
+ const tabs: HTMLIonTabButtonElement[] = Array.from(document.querySelectorAll('ion-tab-button')),
+ scrollLeft: number = this.scrollEl.scrollLeft,
+ tabsWidth: number = this.scrollEl.clientWidth;
+ let previous: {tab: HTMLIonTabButtonElement, amount: number},
+ next: {tab: HTMLIonTabButtonElement, amount: number};
+
+ tabs.forEach((tab: HTMLIonTabButtonElement) => {
+ const left: number = tab.offsetLeft,
+ right: number = left + tab.offsetWidth;
+
+ if (left < scrollLeft) {
+ previous = {tab, amount: left};
+ }
+
+ if (!next && right > (tabsWidth + scrollLeft)) {
+ let amount = right - tabsWidth;
+ next = {tab, amount};
+ }
+ });
+
+ return {previous, next};
+ }
+
+ private getSelectedButton(): HTMLIonTabButtonElement {
+ return Array.from(this.el.querySelectorAll('ion-tab-button'))
+ .find(btn => btn.selected);
+ }
hostData() {
const themedClasses = this.translucent ? createThemedClasses(this.mode, this.color, 'tabbar-translucent') : {};
@@ -43,6 +99,7 @@ export class Tabbar {
const hostClasses = {
...themedClasses,
'tabbar-hidden': this.hidden,
+ 'scrollable': this.scrollable,
[layoutClass]: true,
[placementClass]: true
};
@@ -54,16 +111,89 @@ export class Tabbar {
}
render() {
- const selectedTab = this.selectedTab;
- const dom = this.tabs.map(tab => (
-