diff --git a/angular/src/directives/navigation/router-controller.ts b/angular/src/directives/navigation/router-controller.ts
index 5ebf41f9f6..4156408df2 100644
--- a/angular/src/directives/navigation/router-controller.ts
+++ b/angular/src/directives/navigation/router-controller.ts
@@ -21,7 +21,7 @@ export class StackController {
ref: enteringRef,
element: (enteringRef && enteringRef.location && enteringRef.location.nativeElement) as HTMLElement,
url: this.getUrl(route),
- fullpath: document.location.pathname,
+ fullpath: document.location!.pathname,
deactivatedId: -1
};
}
diff --git a/angular/src/directives/navigation/tabs-delegate.ts b/angular/src/directives/navigation/tabs-delegate.ts
index e89dd4f2ce..121241d615 100644
--- a/angular/src/directives/navigation/tabs-delegate.ts
+++ b/angular/src/directives/navigation/tabs-delegate.ts
@@ -15,7 +15,7 @@ export class TabsDelegate {
}
}
- @HostListener('ionTabbarClick', ['$event'])
+ @HostListener('ionTabButtonClick', ['$event'])
onTabbarClick(ev: UIEvent) {
const tabElm: HTMLIonTabElement = ev.detail as any;
if (this.router && tabElm && tabElm.href) {
diff --git a/angular/src/directives/proxies-list.txt b/angular/src/directives/proxies-list.txt
index 2e713a7b2b..827390d133 100644
--- a/angular/src/directives/proxies-list.txt
+++ b/angular/src/directives/proxies-list.txt
@@ -72,7 +72,8 @@ export const DIRECTIVES = [
d.Spinner,
d.SplitPane,
d.Tab,
- d.Tabbar,
+ d.TabBar,
+ d.TabButton,
d.Tabs,
d.Text,
d.Textarea,
diff --git a/angular/src/directives/proxies.ts b/angular/src/directives/proxies.ts
index 75aa5f1d82..703cd42d4b 100644
--- a/angular/src/directives/proxies.ts
+++ b/angular/src/directives/proxies.ts
@@ -813,33 +813,42 @@ export class SplitPane {
}
export declare interface Tab extends StencilComponents<'IonTab'> {}
-@Component({ selector: 'ion-tab', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, template: '', inputs: ['active', 'btnId', 'delegate', 'label', 'href', 'icon', 'badge', 'badgeColor', 'component', 'name', 'disabled', 'selected', 'show', 'tabsHideOnSubPages'] })
+@Component({ selector: 'ion-tab', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, template: '', inputs: ['active', 'delegate', 'tab', 'component'] })
export class Tab {
- ionSelect: EventEmitter;
- ionTabMutated: EventEmitter;
constructor(r: ElementRef) {
const el = r.nativeElement;
proxyMethods(this, el, ['setActive']);
- proxyInputs(this, el, ['active', 'btnId', 'delegate', 'label', 'href', 'icon', 'badge', 'badgeColor', 'component', 'name', 'disabled', 'selected', 'show', 'tabsHideOnSubPages']);
- proxyOutputs(this, el, ['ionSelect', 'ionTabMutated']);
+ proxyInputs(this, el, ['active', 'delegate', 'tab', 'component']);
}
}
-export declare interface Tabbar extends StencilComponents<'IonTabbar'> {}
-@Component({ selector: 'ion-tabbar', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, template: '', inputs: ['mode', 'color', 'layout', 'placement', 'selectedTab', 'tabs', 'highlight', 'translucent'] })
-export class Tabbar {
- ionTabbarClick: EventEmitter;
+export declare interface TabBar extends StencilComponents<'IonTabBar'> {}
+@Component({ selector: 'ion-tab-bar', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, template: '', inputs: ['mode', 'color', 'layout', 'placement', 'selectedTab', 'translucent'] })
+export class TabBar {
+ ionTabBarChanged: EventEmitter;
constructor(r: ElementRef) {
const el = r.nativeElement;
- proxyInputs(this, el, ['mode', 'color', 'layout', 'placement', 'selectedTab', 'tabs', 'highlight', 'translucent']);
- proxyOutputs(this, el, ['ionTabbarClick']);
+ proxyInputs(this, el, ['mode', 'color', 'layout', 'placement', 'selectedTab', 'translucent']);
+ proxyOutputs(this, el, ['ionTabBarChanged']);
+ }
+}
+
+export declare interface TabButton extends StencilComponents<'IonTabButton'> {}
+@Component({ selector: 'ion-tab-button', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, template: '', inputs: ['mode', 'color', 'layout', 'href', 'tab', 'disabled'] })
+export class TabButton {
+ ionTabButtonClick: EventEmitter;
+
+ constructor(r: ElementRef) {
+ const el = r.nativeElement;
+ proxyInputs(this, el, ['mode', 'color', 'layout', 'href', 'tab', 'disabled']);
+ proxyOutputs(this, el, ['ionTabButtonClick']);
}
}
export declare interface Tabs extends StencilComponents<'IonTabs'> {}
-@Component({ selector: 'ion-tabs', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, template: '', inputs: ['name', 'tabbarHidden', 'useRouter'] })
+@Component({ selector: 'ion-tabs', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, template: '', inputs: ['name'] })
export class Tabs {
ionChange: EventEmitter;
ionNavWillLoad: EventEmitter;
@@ -849,7 +858,7 @@ export class Tabs {
constructor(r: ElementRef) {
const el = r.nativeElement;
proxyMethods(this, el, ['select', 'setRouteId', 'getRouteId', 'getTab', 'getSelected']);
- proxyInputs(this, el, ['name', 'tabbarHidden', 'useRouter']);
+ proxyInputs(this, el, ['name']);
proxyOutputs(this, el, ['ionChange', 'ionNavWillLoad', 'ionNavWillChange', 'ionNavDidChange']);
}
}
diff --git a/angular/src/ionic-module.ts b/angular/src/ionic-module.ts
index 1c46f29db7..8f3f28ba05 100644
--- a/angular/src/ionic-module.ts
+++ b/angular/src/ionic-module.ts
@@ -81,7 +81,8 @@ const DECLARATIONS = [
d.Spinner,
d.SplitPane,
d.Tab,
- d.Tabbar,
+ d.TabBar,
+ d.TabButton,
d.Tabs,
d.Text,
d.Textarea,
diff --git a/core/src/components.d.ts b/core/src/components.d.ts
index 2cb1f51421..4c04bdccb2 100644
--- a/core/src/components.d.ts
+++ b/core/src/components.d.ts
@@ -55,6 +55,8 @@ import {
Side,
SpinnerTypes,
StyleEvent,
+ TabbarChangedDetail,
+ TabbarClickDetail,
TabbarLayout,
TabbarPlacement,
TextFieldTypes,
@@ -3704,7 +3706,7 @@ export namespace Components {
interface IonRoute {
/**
- * Name of the component to load/select in the navigation outlet (`ion-tabs`, `ion-nav`) when the route matches. The value of this property is not always the tagname of the component to load, in ion-tabs it actually refers to the name of the `ion-tab` to select.
+ * Name of the component to load/select in the navigation outlet (`ion-tabs`, `ion-nav`) when the route matches. The value of this property is not always the tagname of the component to load, in `ion-tabs` it actually refers to the name of the `ion-tab` to select.
*/
'component': string;
/**
@@ -3718,7 +3720,7 @@ export namespace Components {
}
interface IonRouteAttributes extends StencilHTMLAttributes {
/**
- * Name of the component to load/select in the navigation outlet (`ion-tabs`, `ion-nav`) when the route matches. The value of this property is not always the tagname of the component to load, in ion-tabs it actually refers to the name of the `ion-tab` to select.
+ * Name of the component to load/select in the navigation outlet (`ion-tabs`, `ion-nav`) when the route matches. The value of this property is not always the tagname of the component to load, in `ion-tabs` it actually refers to the name of the `ion-tab` to select.
*/
'component'?: string;
/**
@@ -4538,146 +4540,13 @@ export namespace Components {
'when'?: string | boolean;
}
- interface IonTab {
- /**
- * If `true`, sets the tab as the active tab.
- */
- 'active': boolean;
- /**
- * The badge for the tab.
- */
- 'badge'?: string;
- /**
- * The badge color for the tab button.
- */
- 'badgeColor'?: Color;
- /**
- * hidden
- */
- 'btnId'?: string;
- /**
- * The component to display inside of the tab.
- */
- 'component'?: ComponentRef;
- /**
- * hidden
- */
- 'delegate'?: FrameworkDelegate;
- /**
- * If `true`, the user cannot interact with the tab. Defaults to `false`.
- */
- 'disabled': boolean;
- /**
- * The URL which will be used as the `href` within this tab's button anchor.
- */
- 'href'?: string;
- /**
- * The icon for the tab.
- */
- 'icon'?: string;
- /**
- * The label of the tab.
- */
- 'label'?: string;
- /**
- * The name of the tab.
- */
- 'name'?: string;
- /**
- * If `true`, the tab will be selected. Defaults to `false`.
- */
- 'selected': boolean;
- /**
- * Set the active component for the tab
- */
- 'setActive': () => Promise;
- /**
- * If `true`, the tab button is visible within the tabbar. Defaults to `true`.
- */
- 'show': boolean;
- /**
- * If `true`, hide the tabs on child pages.
- */
- 'tabsHideOnSubPages': boolean;
- }
- interface IonTabAttributes extends StencilHTMLAttributes {
- /**
- * If `true`, sets the tab as the active tab.
- */
- 'active'?: boolean;
- /**
- * The badge for the tab.
- */
- 'badge'?: string;
- /**
- * The badge color for the tab button.
- */
- 'badgeColor'?: Color;
- /**
- * hidden
- */
- 'btnId'?: string;
- /**
- * The component to display inside of the tab.
- */
- 'component'?: ComponentRef;
- /**
- * hidden
- */
- 'delegate'?: FrameworkDelegate;
- /**
- * If `true`, the user cannot interact with the tab. Defaults to `false`.
- */
- 'disabled'?: boolean;
- /**
- * The URL which will be used as the `href` within this tab's button anchor.
- */
- 'href'?: string;
- /**
- * The icon for the tab.
- */
- 'icon'?: string;
- /**
- * The label of the tab.
- */
- 'label'?: string;
- /**
- * The name of the tab.
- */
- 'name'?: string;
- /**
- * Emitted when the current tab is selected.
- */
- 'onIonSelect'?: (event: CustomEvent) => void;
- /**
- * Emitted when the tab props mutates. Used internally.
- */
- 'onIonTabMutated'?: (event: CustomEvent) => void;
- /**
- * If `true`, the tab will be selected. Defaults to `false`.
- */
- 'selected'?: boolean;
- /**
- * If `true`, the tab button is visible within the tabbar. Defaults to `true`.
- */
- 'show'?: boolean;
- /**
- * If `true`, hide the tabs on child pages.
- */
- 'tabsHideOnSubPages'?: boolean;
- }
-
- interface IonTabbar {
+ interface IonTabBar {
/**
* The color to use from your application's color palette. Default options are: `"primary"`, `"secondary"`, `"tertiary"`, `"success"`, `"warning"`, `"danger"`, `"light"`, `"medium"`, and `"dark"`. For more information on colors, see [theming](/docs/theming/basics).
*/
'color'?: Color;
/**
- * If `true`, show the tab highlight bar under the selected tab.
- */
- 'highlight': boolean;
- /**
- * Set the layout of the text and icon in the tabbar. Available options: `"icon-top"`, `"icon-start"`, `"icon-end"`, `"icon-bottom"`, `"icon-hide"`, `"label-hide"`.
+ * Set the layout of the text and icon in the tabbar.
*/
'layout': TabbarLayout;
/**
@@ -4685,33 +4554,87 @@ export namespace Components {
*/
'mode': Mode;
/**
- * Set the position of the tabbar, relative to the content. Available options: `"top"`, `"bottom"`.
+ * Set the position of the tabbar, relative to the content.
*/
'placement': TabbarPlacement;
/**
* The selected tab component
*/
- 'selectedTab'?: HTMLIonTabElement;
+ 'selectedTab'?: string;
/**
- * The tabs to render
- */
- 'tabs': HTMLIonTabElement[];
- /**
- * If `true`, the tabbar will be translucent. Defaults to `false`.
+ * If `true`, the tab bar will be translucent. Defaults to `false`.
*/
'translucent': boolean;
}
- interface IonTabbarAttributes extends StencilHTMLAttributes {
+ interface IonTabBarAttributes extends StencilHTMLAttributes {
/**
* The color to use from your application's color palette. Default options are: `"primary"`, `"secondary"`, `"tertiary"`, `"success"`, `"warning"`, `"danger"`, `"light"`, `"medium"`, and `"dark"`. For more information on colors, see [theming](/docs/theming/basics).
*/
'color'?: Color;
/**
- * If `true`, show the tab highlight bar under the selected tab.
+ * Set the layout of the text and icon in the tabbar.
*/
- 'highlight'?: boolean;
+ 'layout'?: TabbarLayout;
/**
- * Set the layout of the text and icon in the tabbar. Available options: `"icon-top"`, `"icon-start"`, `"icon-end"`, `"icon-bottom"`, `"icon-hide"`, `"label-hide"`.
+ * The mode determines which platform styles to use. Possible values are: `"ios"` or `"md"`.
+ */
+ 'mode'?: Mode;
+ 'onIonTabBarChanged'?: (event: CustomEvent) => void;
+ /**
+ * Set the position of the tabbar, relative to the content.
+ */
+ 'placement'?: TabbarPlacement;
+ /**
+ * The selected tab component
+ */
+ 'selectedTab'?: string;
+ /**
+ * If `true`, the tab bar will be translucent. Defaults to `false`.
+ */
+ 'translucent'?: boolean;
+ }
+
+ interface IonTabButton {
+ /**
+ * The color to use from your application's color palette. Default options are: `"primary"`, `"secondary"`, `"tertiary"`, `"success"`, `"warning"`, `"danger"`, `"light"`, `"medium"`, and `"dark"`. For more information on colors, see [theming](/docs/theming/basics).
+ */
+ 'color'?: Color;
+ /**
+ * The selected tab component
+ */
+ 'disabled': boolean;
+ /**
+ * The URL which will be used as the `href` within this tab's button anchor.
+ */
+ 'href'?: string;
+ /**
+ * Set the layout of the text and icon in the tabbar.
+ */
+ 'layout': TabbarLayout;
+ /**
+ * The mode determines which platform styles to use. Possible values are: `"ios"` or `"md"`.
+ */
+ 'mode': Mode;
+ /**
+ * A tab id must be provided for each `ion-tab`. It's used internally to reference the selected tab or by the router to switch between them.
+ */
+ 'tab'?: string;
+ }
+ interface IonTabButtonAttributes extends StencilHTMLAttributes {
+ /**
+ * The color to use from your application's color palette. Default options are: `"primary"`, `"secondary"`, `"tertiary"`, `"success"`, `"warning"`, `"danger"`, `"light"`, `"medium"`, and `"dark"`. For more information on colors, see [theming](/docs/theming/basics).
+ */
+ 'color'?: Color;
+ /**
+ * The selected tab component
+ */
+ 'disabled'?: boolean;
+ /**
+ * The URL which will be used as the `href` within this tab's button anchor.
+ */
+ 'href'?: string;
+ /**
+ * Set the layout of the text and icon in the tabbar.
*/
'layout'?: TabbarLayout;
/**
@@ -4721,23 +4644,40 @@ export namespace Components {
/**
* Emitted when the tab bar is clicked
*/
- 'onIonTabbarClick'?: (event: CustomEvent) => void;
+ 'onIonTabButtonClick'?: (event: CustomEvent) => void;
/**
- * Set the position of the tabbar, relative to the content. Available options: `"top"`, `"bottom"`.
+ * A tab id must be provided for each `ion-tab`. It's used internally to reference the selected tab or by the router to switch between them.
*/
- 'placement'?: TabbarPlacement;
+ 'tab'?: string;
+ }
+
+ interface IonTab {
+ 'active': boolean;
/**
- * The selected tab component
+ * The component to display inside of the tab.
*/
- 'selectedTab'?: HTMLIonTabElement;
+ 'component'?: ComponentRef;
+ 'delegate'?: FrameworkDelegate;
/**
- * The tabs to render
+ * Set the active component for the tab
*/
- 'tabs'?: HTMLIonTabElement[];
+ 'setActive': () => Promise;
/**
- * If `true`, the tabbar will be translucent. Defaults to `false`.
+ * A tab id must be provided for each `ion-tab`. It's used internally to reference the selected tab or by the router to switch between them.
*/
- 'translucent'?: boolean;
+ 'tab'?: string;
+ }
+ interface IonTabAttributes extends StencilHTMLAttributes {
+ 'active'?: boolean;
+ /**
+ * The component to display inside of the tab.
+ */
+ 'component'?: ComponentRef;
+ 'delegate'?: FrameworkDelegate;
+ /**
+ * A tab id must be provided for each `ion-tab`. It's used internally to reference the selected tab or by the router to switch between them.
+ */
+ 'tab'?: string;
}
interface IonTabs {
@@ -4749,7 +4689,7 @@ export namespace Components {
/**
* Get the tab at the given index
*/
- 'getTab': (tabOrIndex: string | number | HTMLIonTabElement) => Promise;
+ 'getTab': (tab: string | HTMLIonTabElement) => Promise;
/**
* A unique name for the tabs.
*/
@@ -4757,16 +4697,8 @@ export namespace Components {
/**
* Index or the Tab instance, of the tab to select.
*/
- 'select': (tabOrIndex: number | HTMLIonTabElement) => Promise;
+ 'select': (tab: string | HTMLIonTabElement) => Promise;
'setRouteId': (id: string) => Promise;
- /**
- * If `true`, the tabbar will be hidden. Defaults to `false`.
- */
- 'tabbarHidden': boolean;
- /**
- * If `true`, the tabs will use the router and `selectedTab` will not do anything.
- */
- 'useRouter': boolean;
}
interface IonTabsAttributes extends StencilHTMLAttributes {
/**
@@ -4789,14 +4721,6 @@ export namespace Components {
* Emitted when the navigation will load a component.
*/
'onIonNavWillLoad'?: (event: CustomEvent) => void;
- /**
- * If `true`, the tabbar will be hidden. Defaults to `false`.
- */
- 'tabbarHidden'?: boolean;
- /**
- * If `true`, the tabs will use the router and `selectedTab` will not do anything.
- */
- 'useRouter'?: boolean;
}
interface IonText {
@@ -5456,8 +5380,9 @@ declare global {
'IonSlides': Components.IonSlides;
'IonSpinner': Components.IonSpinner;
'IonSplitPane': Components.IonSplitPane;
+ 'IonTabBar': Components.IonTabBar;
+ 'IonTabButton': Components.IonTabButton;
'IonTab': Components.IonTab;
- 'IonTabbar': Components.IonTabbar;
'IonTabs': Components.IonTabs;
'IonText': Components.IonText;
'IonTextarea': Components.IonTextarea;
@@ -5559,8 +5484,9 @@ declare global {
'ion-slides': Components.IonSlidesAttributes;
'ion-spinner': Components.IonSpinnerAttributes;
'ion-split-pane': Components.IonSplitPaneAttributes;
+ 'ion-tab-bar': Components.IonTabBarAttributes;
+ 'ion-tab-button': Components.IonTabButtonAttributes;
'ion-tab': Components.IonTabAttributes;
- 'ion-tabbar': Components.IonTabbarAttributes;
'ion-tabs': Components.IonTabsAttributes;
'ion-text': Components.IonTextAttributes;
'ion-textarea': Components.IonTextareaAttributes;
@@ -6102,18 +6028,24 @@ declare global {
new (): HTMLIonSplitPaneElement;
};
+ interface HTMLIonTabBarElement extends Components.IonTabBar, HTMLStencilElement {}
+ var HTMLIonTabBarElement: {
+ prototype: HTMLIonTabBarElement;
+ new (): HTMLIonTabBarElement;
+ };
+
+ interface HTMLIonTabButtonElement extends Components.IonTabButton, HTMLStencilElement {}
+ var HTMLIonTabButtonElement: {
+ prototype: HTMLIonTabButtonElement;
+ new (): HTMLIonTabButtonElement;
+ };
+
interface HTMLIonTabElement extends Components.IonTab, HTMLStencilElement {}
var HTMLIonTabElement: {
prototype: HTMLIonTabElement;
new (): HTMLIonTabElement;
};
- interface HTMLIonTabbarElement extends Components.IonTabbar, HTMLStencilElement {}
- var HTMLIonTabbarElement: {
- prototype: HTMLIonTabbarElement;
- new (): HTMLIonTabbarElement;
- };
-
interface HTMLIonTabsElement extends Components.IonTabs, HTMLStencilElement {}
var HTMLIonTabsElement: {
prototype: HTMLIonTabsElement;
@@ -6263,8 +6195,9 @@ declare global {
'ion-slides': HTMLIonSlidesElement
'ion-spinner': HTMLIonSpinnerElement
'ion-split-pane': HTMLIonSplitPaneElement
+ 'ion-tab-bar': HTMLIonTabBarElement
+ 'ion-tab-button': HTMLIonTabButtonElement
'ion-tab': HTMLIonTabElement
- 'ion-tabbar': HTMLIonTabbarElement
'ion-tabs': HTMLIonTabsElement
'ion-text': HTMLIonTextElement
'ion-textarea': HTMLIonTextareaElement
@@ -6366,8 +6299,9 @@ declare global {
'ion-slides': HTMLIonSlidesElement;
'ion-spinner': HTMLIonSpinnerElement;
'ion-split-pane': HTMLIonSplitPaneElement;
+ 'ion-tab-bar': HTMLIonTabBarElement;
+ 'ion-tab-button': HTMLIonTabButtonElement;
'ion-tab': HTMLIonTabElement;
- 'ion-tabbar': HTMLIonTabbarElement;
'ion-tabs': HTMLIonTabsElement;
'ion-text': HTMLIonTextElement;
'ion-textarea': HTMLIonTextareaElement;
diff --git a/core/src/components/animation-controller/animation-controller.tsx b/core/src/components/animation-controller/animation-controller.tsx
index af645292bb..35e3abb5d5 100644
--- a/core/src/components/animation-controller/animation-controller.tsx
+++ b/core/src/components/animation-controller/animation-controller.tsx
@@ -4,7 +4,7 @@ import { Animation, AnimationBuilder, AnimationController, Config } from '../../
import { Animator } from './animator';
-/** @hidden */
+/** @internal */
@Component({
tag: 'ion-animation-controller'
})
diff --git a/core/src/components/button/button.tsx b/core/src/components/button/button.tsx
index 3677baefe1..34a5327d7c 100644
--- a/core/src/components/button/button.tsx
+++ b/core/src/components/button/button.tsx
@@ -132,7 +132,6 @@ export class Button implements ComponentInterface {
const form = this.el.closest('form');
if (form) {
ev.preventDefault();
- ev.stopPropagation();
const fakeButton = document.createElement('button');
fakeButton.type = this.type;
diff --git a/core/src/components/item-divider/item-divider.tsx b/core/src/components/item-divider/item-divider.tsx
index 75315f4ac3..0903396e27 100644
--- a/core/src/components/item-divider/item-divider.tsx
+++ b/core/src/components/item-divider/item-divider.tsx
@@ -40,7 +40,10 @@ export class ItemDivider implements ComponentInterface {
hostData() {
return {
- class: createColorClasses(this.color)
+ class: {
+ ...createColorClasses(this.color),
+ 'item': true,
+ }
};
}
diff --git a/core/src/components/item-group/item-group.tsx b/core/src/components/item-group/item-group.tsx
index 446f19d7a1..571ae027bf 100644
--- a/core/src/components/item-group/item-group.tsx
+++ b/core/src/components/item-group/item-group.tsx
@@ -16,7 +16,10 @@ export class ItemGroup implements ComponentInterface {
hostData() {
return {
- class: createThemedClasses(this.mode, 'item-group')
+ class: {
+ ...createThemedClasses(this.mode, 'item-group'),
+ 'item': true,
+ }
};
}
}
diff --git a/core/src/components/label/label.ios.scss b/core/src/components/label/label.ios.scss
index 4e699ece43..3c40090a8b 100644
--- a/core/src/components/label/label.ios.scss
+++ b/core/src/components/label/label.ios.scss
@@ -4,7 +4,7 @@
// iOS Label
// --------------------------------------------------
-:host {
+:host-context(.item) {
@include margin($label-ios-margin-top, $label-ios-margin-end, $label-ios-margin-bottom, $label-ios-margin-start);
}
diff --git a/core/src/components/label/label.md.scss b/core/src/components/label/label.md.scss
index 6206c64d7c..8afbdc5310 100644
--- a/core/src/components/label/label.md.scss
+++ b/core/src/components/label/label.md.scss
@@ -4,7 +4,7 @@
// Material Design Label
// --------------------------------------------------
-:host {
+:host-context(.item) {
@include margin($label-md-margin-top, $label-md-margin-end, $label-md-margin-bottom, $label-md-margin-start);
}
diff --git a/core/src/components/label/label.scss b/core/src/components/label/label.scss
index 0e6cf2ce1c..b147cc45b6 100644
--- a/core/src/components/label/label.scss
+++ b/core/src/components/label/label.scss
@@ -4,7 +4,7 @@
// Label
// --------------------------------------------------
-:host {
+:host-context(.item) {
/**
* @prop --color: Color of the label
*/
diff --git a/core/src/components/picker-column/picker-column.tsx b/core/src/components/picker-column/picker-column.tsx
index 40aa7e4e5b..d4b090cacc 100644
--- a/core/src/components/picker-column/picker-column.tsx
+++ b/core/src/components/picker-column/picker-column.tsx
@@ -4,7 +4,6 @@ import { Gesture, GestureDetail, Mode, PickerColumn } from '../../interface';
import { hapticSelectionChanged } from '../../utils';
import { clamp } from '../../utils/helpers';
-/** @hidden */
@Component({
tag: 'ion-picker-column'
})
diff --git a/core/src/components/picker-controller/picker-controller.tsx b/core/src/components/picker-controller/picker-controller.tsx
index bb83b24136..4d6548cb6b 100644
--- a/core/src/components/picker-controller/picker-controller.tsx
+++ b/core/src/components/picker-controller/picker-controller.tsx
@@ -3,7 +3,7 @@ import { Component, ComponentInterface, Method, Prop } from '@stencil/core';
import { OverlayController, PickerOptions } from '../../interface';
import { createOverlay, dismissOverlay, getOverlay } from '../../utils/overlays';
-/** @hidden */
+/** @internal */
@Component({
tag: 'ion-picker-controller'
})
diff --git a/core/src/components/route/readme.md b/core/src/components/route/readme.md
index dc4913f20d..865d6bfbf4 100644
--- a/core/src/components/route/readme.md
+++ b/core/src/components/route/readme.md
@@ -9,11 +9,11 @@ Router is a component that can take a component, and render it when the Browser
## Properties
-| Property | Attribute | Description | Type |
-| ---------------- | ----------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------- |
-| `componentProps` | -- | A key value `{ 'red': true, 'blue': 'white'}` containing props that should be passed to the defined component when rendered. | `undefined \| { [key: string]: any; }` |
-| `component` | `component` | Name of the component to load/select in the navigation outlet (`ion-tabs`, `ion-nav`) when the route matches. The value of this property is not always the tagname of the component to load, in ion-tabs it actually refers to the name of the `ion-tab` to select. | `string` |
-| `url` | `url` | Relative path that needs to match in order for this route to apply. Accepts paths similar to expressjs so that you can define parameters in the url /foo/:bar where bar would be available in incoming props. | `string` |
+| Property | Attribute | Description | Type |
+| ---------------- | ----------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------- |
+| `componentProps` | -- | A key value `{ 'red': true, 'blue': 'white'}` containing props that should be passed to the defined component when rendered. | `undefined \| { [key: string]: any; }` |
+| `component` | `component` | Name of the component to load/select in the navigation outlet (`ion-tabs`, `ion-nav`) when the route matches. The value of this property is not always the tagname of the component to load, in `ion-tabs` it actually refers to the name of the `ion-tab` to select. | `string` |
+| `url` | `url` | Relative path that needs to match in order for this route to apply. Accepts paths similar to expressjs so that you can define parameters in the url /foo/:bar where bar would be available in incoming props. | `string` |
## Events
diff --git a/core/src/components/route/route.tsx b/core/src/components/route/route.tsx
index 56d9685451..efb9fe5f39 100644
--- a/core/src/components/route/route.tsx
+++ b/core/src/components/route/route.tsx
@@ -18,7 +18,7 @@ export class Route implements ComponentInterface {
* when the route matches.
*
* The value of this property is not always the tagname of the component to load,
- * in ion-tabs it actually refers to the name of the `ion-tab` to select.
+ * in `ion-tabs` it actually refers to the name of the `ion-tab` to select.
*/
@Prop() component!: string;
diff --git a/core/src/components/router/test/basic/index.html b/core/src/components/router/test/basic/index.html
index 3598c0aa52..0a405f1016 100644
--- a/core/src/components/router/test/basic/index.html
+++ b/core/src/components/router/test/basic/index.html
@@ -105,26 +105,38 @@
class TabsPage extends HTMLElement {
connectedCallback() {
this.innerHTML = `
-
-
+
-
+
+
+
+
+ inline tab 4
+
-
+
-
- inline tab 4
-
+
+ Plain List
+
+
+
+
+ Schedule
+
+
+
+
+ Stopwatch
+
+
+
+
+ Messages
+
+
+
+
`;
}
@@ -194,8 +206,8 @@
-
-
+
+
diff --git a/core/src/components/tab-bar/readme.md b/core/src/components/tab-bar/readme.md
new file mode 100644
index 0000000000..c5fca1c7e2
--- /dev/null
+++ b/core/src/components/tab-bar/readme.md
@@ -0,0 +1,42 @@
+# ion-tab-bar
+
+Tab bar is the UI component that implements the array of button of `ion-tabs`. It's provided by default when `ion-tabs` is used, though, this "implicit" tab bar can not be customized.
+
+In order to have a custom tabbar, it should be provided in user's markup as direct children of `ion-tabs`:
+
+```html
+
+
+
+
+
+
+
+
+
+
+```
+
+
+
+
+
+## Properties
+
+| Property | Attribute | Description | Type |
+| ------------- | -------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------ |
+| `color` | `color` | The color to use from your application's color palette. Default options are: `"primary"`, `"secondary"`, `"tertiary"`, `"success"`, `"warning"`, `"danger"`, `"light"`, `"medium"`, and `"dark"`. For more information on colors, see [theming](/docs/theming/basics). | `string \| undefined` |
+| `layout` | `layout` | Set the layout of the text and icon in the tabbar. | `"icon-bottom" \| "icon-end" \| "icon-hide" \| "icon-start" \| "icon-top" \| "label-hide"` |
+| `mode` | `mode` | The mode determines which platform styles to use. Possible values are: `"ios"` or `"md"`. | `"ios" \| "md"` |
+| `placement` | `placement` | Set the position of the tabbar, relative to the content. | `"bottom" \| "top"` |
+| `selectedTab` | `selected-tab` | The selected tab component | `string \| undefined` |
+| `translucent` | `translucent` | If `true`, the tab bar will be translucent. Defaults to `false`. | `boolean` |
+
+
+----------------------------------------------
+
+*Built with [StencilJS](https://stenciljs.com/)*
diff --git a/core/src/components/tabbar/tabbar-interface.ts b/core/src/components/tab-bar/tab-bar-interface.ts
similarity index 54%
rename from core/src/components/tabbar/tabbar-interface.ts
rename to core/src/components/tab-bar/tab-bar-interface.ts
index fb61458253..875e1ab132 100644
--- a/core/src/components/tabbar/tabbar-interface.ts
+++ b/core/src/components/tab-bar/tab-bar-interface.ts
@@ -1,2 +1,11 @@
export type TabbarLayout = 'icon-top' | 'icon-start' | 'icon-end' | 'icon-bottom' | 'icon-hide' | 'label-hide';
export type TabbarPlacement = 'top' | 'bottom';
+
+export interface TabbarChangedDetail {
+ tab?: string;
+}
+
+export interface TabbarClickDetail {
+ tab?: string;
+ href?: string;
+}
diff --git a/core/src/components/tab-bar/tab-bar.ios.scss b/core/src/components/tab-bar/tab-bar.ios.scss
new file mode 100644
index 0000000000..4179ce9bba
--- /dev/null
+++ b/core/src/components/tab-bar/tab-bar.ios.scss
@@ -0,0 +1,21 @@
+@import "./tab-bar";
+@import "../../themes/ionic.globals.ios";
+
+// iOS Tabs
+// --------------------------------------------------
+
+:host {
+ // default color / background
+ --background: #{$tabbar-ios-background};
+ --border: #{$hairlines-width solid $tabbar-ios-border-color};
+
+ height: 50px;
+}
+
+// iOS Translucent Tabbar
+// --------------------------------------------------
+
+:host(.tabbar-translucent) {
+ background-color: #{current-color(base, .8)};
+ backdrop-filter: saturate(210%) blur(20px);
+}
diff --git a/core/src/components/tab-bar/tab-bar.md.scss b/core/src/components/tab-bar/tab-bar.md.scss
new file mode 100644
index 0000000000..95833e78f8
--- /dev/null
+++ b/core/src/components/tab-bar/tab-bar.md.scss
@@ -0,0 +1,10 @@
+@import "./tab-bar";
+@import "../../themes/ionic.globals.md";
+
+:host {
+ // default color / background
+ --background: #{$tabbar-md-background};
+ --border: #{1px solid $tabbar-md-border-color};
+
+ height: 56px;
+}
diff --git a/core/src/components/tab-bar/tab-bar.scss b/core/src/components/tab-bar/tab-bar.scss
new file mode 100644
index 0000000000..b1880738c1
--- /dev/null
+++ b/core/src/components/tab-bar/tab-bar.scss
@@ -0,0 +1,51 @@
+@import "../../themes/ionic.globals";
+
+:host {
+ @include padding-horizontal(
+ var(--ion-safe-area-left),
+ var(--ion-safe-area-right)
+ );
+
+ display: flex;
+
+ align-items: center;
+ justify-content: center;
+ order: 1;
+
+ width: auto;
+
+ background: var(--background);
+ color: var(--color);
+
+ contain: strict;
+ user-select: none;
+ z-index: $z-index-toolbar;
+ box-sizing: content-box;
+}
+
+:host(.ion-color) {
+ --background: #{current-color(base)};
+}
+
+:host(.ion-color) ::slotted(ion-tab-button) {
+ --color: #{current-color(contrast, .7)};
+ --color-selected: #{current-color(contrast)};
+ --background-focused: #{current-color(shade)};
+}
+
+:host(.placement-top) {
+ order: -1;
+
+ border-bottom: var(--border);
+}
+
+:host(.placement-bottom) {
+ padding-bottom: var(--ion-safe-area-bottom, 0);
+
+ border-top: var(--border);
+}
+
+:host(.tabbar-hidden) {
+ /* stylelint-disable-next-line declaration-no-important */
+ display: none !important;
+}
diff --git a/core/src/components/tab-bar/tab-bar.tsx b/core/src/components/tab-bar/tab-bar.tsx
new file mode 100644
index 0000000000..7186fbb165
--- /dev/null
+++ b/core/src/components/tab-bar/tab-bar.tsx
@@ -0,0 +1,101 @@
+import { Component, ComponentInterface, Element, Event, EventEmitter, Listen, Prop, QueueApi, State, Watch } from '@stencil/core';
+
+import { Color, Mode, TabbarChangedDetail, TabbarLayout, TabbarPlacement } from '../../interface';
+import { createColorClasses } from '../../utils/theme';
+
+@Component({
+ tag: 'ion-tab-bar',
+ styleUrls: {
+ ios: 'tab-bar.ios.scss',
+ md: 'tab-bar.md.scss'
+ },
+ shadow: true
+})
+export class TabBar implements ComponentInterface {
+
+ @Element() el!: HTMLElement;
+
+ @Prop({ context: 'queue' }) queue!: QueueApi;
+ @Prop({ context: 'document' }) doc!: Document;
+
+ @State() keyboardVisible = false;
+
+ /**
+ * The mode determines which platform styles to use.
+ * Possible values are: `"ios"` or `"md"`.
+ */
+ @Prop() mode!: Mode;
+
+ /**
+ * The color to use from your application's color palette.
+ * Default options are: `"primary"`, `"secondary"`, `"tertiary"`, `"success"`, `"warning"`, `"danger"`, `"light"`, `"medium"`, and `"dark"`.
+ * For more information on colors, see [theming](/docs/theming/basics).
+ */
+ @Prop() color?: Color;
+
+ /**
+ * Set the layout of the text and icon in the tabbar.
+ */
+ @Prop() layout: TabbarLayout = 'icon-top';
+
+ /**
+ * Set the position of the tabbar, relative to the content.
+ */
+ @Prop() placement: TabbarPlacement = 'bottom';
+
+ /**
+ * The selected tab component
+ */
+ @Prop() selectedTab?: string;
+ @Watch('selectedTab')
+ selectedTabChanged() {
+ this.ionTabBarChanged.emit({
+ tab: this.selectedTab
+ });
+ }
+
+ /**
+ * If `true`, the tab bar will be translucent. Defaults to `false`.
+ */
+ @Prop() translucent = false;
+
+ /** @internal */
+ @Event() ionTabBarChanged!: EventEmitter;
+
+ @Listen('body:keyboardWillHide')
+ protected onKeyboardWillHide() {
+ setTimeout(() => this.keyboardVisible = false, 50);
+ }
+
+ @Listen('body:keyboardWillShow')
+ protected onKeyboardWillShow() {
+ if (this.placement === 'bottom') {
+ this.keyboardVisible = true;
+ }
+ }
+
+ componentWillLoad() {
+ this.selectedTabChanged();
+ }
+
+ hostData() {
+ const { color, translucent, placement, keyboardVisible } = this;
+ return {
+ role: 'tablist',
+ 'aria-hidden': keyboardVisible ? 'true' : null,
+ 'slot': 'tabbar',
+ class: {
+ ...createColorClasses(color),
+ 'tabbar-translucent': translucent,
+ [`placement-${placement}`]: true,
+ 'tabbar-hidden': keyboardVisible,
+ }
+ };
+ }
+
+ render() {
+ return (
+
+ );
+ }
+}
diff --git a/core/src/components/tab-bar/test/scenarios/e2e.ts b/core/src/components/tab-bar/test/scenarios/e2e.ts
new file mode 100644
index 0000000000..d60ee190fa
--- /dev/null
+++ b/core/src/components/tab-bar/test/scenarios/e2e.ts
@@ -0,0 +1,10 @@
+import { newE2EPage } from '@stencil/core/testing';
+
+it('tab-bar: scenarios', async () => {
+ const page = await newE2EPage({
+ url: '/src/components/tab-bar/test/scenarios?ionic:_testing=true'
+ });
+
+ const compare = await page.compareScreenshot();
+ expect(compare).toMatchScreenshot();
+});
diff --git a/core/src/components/tab-bar/test/scenarios/index.html b/core/src/components/tab-bar/test/scenarios/index.html
new file mode 100644
index 0000000000..03d472cdf3
--- /dev/null
+++ b/core/src/components/tab-bar/test/scenarios/index.html
@@ -0,0 +1,194 @@
+
+
+
+
+
+ Tab - Colors
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Recents
+
+
+
+ Favorites
+ 6
+
+
+
+ Settings
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Location
+
+
+
+
+ 6
+
+
+
+
+ Radio
+
+
+
+
+
+
+
+
+
+
+ Recents
+
+
+
+
+ 6
+ Favorites
+
+
+
+
+ Settings
+
+
+
+
+
+
+
+
+
+ Recents
+
+
+
+
+ Favorites
+
+ 6
+
+
+
+ Settings
+
+
+
+
+
+
+
+
+
+ Recents
+
+
+
+
+ Favorites
+
+ 6
+
+
+
+ Settings
+
+
+
+
+
+
+
+
+
+ Recents
+
+
+
+
+ Favorites
+
+ 6
+
+
+
+ Settings
+
+
+
+
+
+
+
+
+ Recents
+
+ 6
+
+
+
+ Favorites
+
+ 6
+
+
+
+ Settings
+
+
+
+
+
+
+
+
+ Indiana Jones and the Raiders of the Lost Ark
+
+
+
+ Indiana Jones and the Temple of Doom
+
+
+
+ Indiana Jones and the Last Crusade
+
+
+
+
+
+
+
+
diff --git a/core/src/components/tab-button/readme.md b/core/src/components/tab-button/readme.md
new file mode 100644
index 0000000000..f4a6e34e02
--- /dev/null
+++ b/core/src/components/tab-button/readme.md
@@ -0,0 +1,42 @@
+# ion-tab-bar
+
+Tab bar is the UI component that implements the array of button of `ion-tabs`. It's provided by default when `ion-tabs` is used, though, this "implicit" tab bar can not be customized.
+
+In order to have a custom tab bar, it should be provided in user's markup as direct children of `ion-tabs`:
+
+```html
+
+
+
+
+
+
+
+
+
+
+```
+
+
+
+
+
+## Properties
+
+| Property | Attribute | Description | Type |
+| ---------- | ---------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------ |
+| `color` | `color` | The color to use from your application's color palette. Default options are: `"primary"`, `"secondary"`, `"tertiary"`, `"success"`, `"warning"`, `"danger"`, `"light"`, `"medium"`, and `"dark"`. For more information on colors, see [theming](/docs/theming/basics). | `string \| undefined` |
+| `disabled` | `disabled` | The selected tab component | `boolean` |
+| `href` | `href` | The URL which will be used as the `href` within this tab's button anchor. | `string \| undefined` |
+| `layout` | `layout` | Set the layout of the text and icon in the tabbar. | `"icon-bottom" \| "icon-end" \| "icon-hide" \| "icon-start" \| "icon-top" \| "label-hide"` |
+| `mode` | `mode` | The mode determines which platform styles to use. Possible values are: `"ios"` or `"md"`. | `"ios" \| "md"` |
+| `tab` | `tab` | A tab id must be provided for each `ion-tab`. It's used internally to reference the selected tab or by the router to switch between them. | `string \| undefined` |
+
+
+----------------------------------------------
+
+*Built with [StencilJS](https://stenciljs.com/)*
diff --git a/core/src/components/tab-button/tab-button.ios.scss b/core/src/components/tab-button/tab-button.ios.scss
new file mode 100644
index 0000000000..59c0c8384c
--- /dev/null
+++ b/core/src/components/tab-button/tab-button.ios.scss
@@ -0,0 +1,72 @@
+@import "./tab-button";
+@import "./tab-button.ios.vars";
+
+:host {
+ --padding-top: #{$tab-button-ios-padding-top};
+ --padding-end: #{$tab-button-ios-padding-end};
+ --padding-bottom: #{$tab-button-ios-padding-bottom};
+ --padding-start: #{$tab-button-ios-padding-start};
+ --color: #{$tab-button-ios-text-color};
+ --color-selected: #{$tabbar-ios-color-activated};
+ --background: transparent;
+ --background-focused: #{$tabbar-ios-background-focused};
+
+ max-width: $tab-button-ios-max-width;
+
+ font-size: $tab-button-ios-font-size;
+}
+
+:host(.tab-has-label-only) ::slotted(ion-label) {
+ @include margin(2px, 0);
+
+ font-size: $tab-button-ios-font-size + 2;
+ font-size: 14px;
+
+ line-height: 1.1;
+}
+
+::slotted(ion-label) {
+ @include margin(0, null, 1px, null);
+
+ min-height: $tab-button-ios-font-size + 1;
+}
+
+::slotted(ion-icon) {
+ @include margin(4px, null, null, null);
+
+ font-size: $tab-button-ios-icon-size;
+}
+
+::slotted(ion-icon::before) {
+ vertical-align: top;
+}
+
+
+// iOS TabButton Layout
+// --------------------------------------------------
+
+:host(.tab-layout-icon-end) ::slotted(ion-label),
+:host(.tab-layout-icon-start) ::slotted(ion-label),
+:host(.tab-layout-icon-hide) ::slotted(ion-label) {
+ margin-top: 2px;
+ margin-bottom: 2px;
+
+ font-size: 14px;
+
+ line-height: 1.1;
+}
+
+:host(.tab-layout-icon-end) ::slotted(ion-icon),
+:host(.tab-layout-icon-start) ::slotted(ion-icon) {
+ min-width: 24px;
+ height: 26px;
+
+ margin-top: 2px;
+ margin-bottom: 1px;
+
+ font-size: 24px;
+}
+
+:host(.tab-layout-label-hide) ::slotted(ion-icon) {
+ @include margin(0);
+}
\ No newline at end of file
diff --git a/core/src/components/tabbar/tab-button.ios.vars.scss b/core/src/components/tab-button/tab-button.ios.vars.scss
similarity index 100%
rename from core/src/components/tabbar/tab-button.ios.vars.scss
rename to core/src/components/tab-button/tab-button.ios.vars.scss
diff --git a/core/src/components/tab-button/tab-button.md.scss b/core/src/components/tab-button/tab-button.md.scss
new file mode 100644
index 0000000000..0824e9ed03
--- /dev/null
+++ b/core/src/components/tab-button/tab-button.md.scss
@@ -0,0 +1,88 @@
+@import "./tab-button";
+@import "./tab-button.md.vars";
+
+// Material Design Tab Button
+// --------------------------------------------------
+
+:host {
+ --padding-top: #{$tab-button-md-padding-top};
+ --padding-end: #{$tab-button-md-padding-end};
+ --padding-bottom: #{$tab-button-md-padding-bottom};
+ --padding-start: #{$tab-button-md-padding-start};
+ --color: #{$tab-button-md-text-color};
+ --color-selected: #{$tabbar-md-color-activated};
+ --background: transparent;
+ --background-focused: #{$tabbar-md-background-focused};
+
+ max-width: 168px;
+
+ font-size: $tab-button-md-font-size;
+ font-weight: $tab-button-md-font-weight;
+}
+
+
+// Material Design Tab Button Text
+// --------------------------------------------------
+
+::slotted(ion-label) {
+ @include margin($tab-button-md-text-margin-top, $tab-button-md-text-margin-end, $tab-button-md-text-margin-bottom, $tab-button-md-text-margin-start);
+ @include transform-origin(center, bottom);
+
+ transition: $tab-button-md-text-transition;
+
+ text-transform: $tab-button-md-text-capitalization;
+}
+
+::slotted(.tab-selected) ::slotted(ion-label) {
+ transform: #{$tab-button-md-text-transform-active};
+
+ transition: $tab-button-md-text-transition;
+}
+
+// Material Design Tab Button Icon
+// --------------------------------------------------
+
+::slotted(ion-icon) {
+ @include transform-origin(center, center);
+
+ width: $tab-button-md-icon-size;
+ height: $tab-button-md-icon-size;
+
+ transition: $tab-button-md-icon-transition;
+
+ font-size: $tab-button-md-icon-size;
+}
+
+
+
+// Material Design TabButton Layout
+// --------------------------------------------------
+
+:host(.tab-layout-icon-top) ::slotted(ion-label) {
+ margin-bottom: -2px;
+}
+
+:host(.tab-layout-icon-bottom) ::slotted(ion-label) {
+ margin-top: -2px;
+ // --label-transform: transform-origin(center, top);
+}
+
+:host(.tab-selected) ::slotted(ion-label) {
+ transform: #{$tab-button-md-text-transform-active};
+}
+
+:host(.tab-selected) ::slotted(ion-icon) {
+ transform: #{$tab-button-md-icon-transform-active};
+}
+
+:host(.tab-layout-icon-end.tab-selected) ::slotted(ion-icon) {
+ transform: #{$tab-button-md-icon-right-transform-active};
+}
+
+:host(.tab-layout-icon-bottom.tab-selected) ::slotted(ion-icon) {
+ transform: #{$tab-button-md-icon-bottom-transform-active};
+}
+
+:host(.tab-layout-icon-start.tab-selected) ::slotted(ion-icon) {
+ transform: #{$tab-button-md-icon-left-transform-active};
+}
diff --git a/core/src/components/tabbar/tab-button.md.vars.scss b/core/src/components/tab-button/tab-button.md.vars.scss
similarity index 100%
rename from core/src/components/tabbar/tab-button.md.vars.scss
rename to core/src/components/tab-button/tab-button.md.vars.scss
diff --git a/core/src/components/tab-button/tab-button.scss b/core/src/components/tab-button/tab-button.scss
new file mode 100644
index 0000000000..5fce5acd79
--- /dev/null
+++ b/core/src/components/tab-button/tab-button.scss
@@ -0,0 +1,169 @@
+@import "../../themes/ionic.globals";
+
+:host {
+ --badge-end: 4%;
+
+ flex: 1;
+
+ height: 100%;
+
+ color: var(--color);
+}
+
+a {
+ @include text-inherit();
+ @include margin(0);
+ @include padding(
+ var(--padding-top),
+ var(--padding-end),
+ var(--padding-bottom),
+ var(--padding-start),
+ );
+
+ display: flex;
+ position: relative;
+
+ flex-direction: column;
+ align-items: center;
+ justify-content: flex-start;
+
+ width: 100%;
+ height: 100%;
+
+ border: 0;
+
+ outline: none;
+
+ background: var(--background);
+
+ text-decoration: none;
+
+ cursor: pointer;
+ overflow: hidden;
+ box-sizing: border-box;
+ -webkit-user-drag: none;
+}
+
+a:focus-visible {
+ background: var(--background-focused);
+}
+
+@media (any-hover: hover) {
+ a:hover {
+ color: var(--color-selected);
+ }
+}
+
+:host(.tab-selected) {
+ color: var(--color-selected);
+}
+
+:host(.tab-hidden) {
+ /* stylelint-disable-next-line declaration-no-important */
+ display: none !important;
+}
+
+:host(.tab-disabled) {
+ pointer-events: none;
+
+ opacity: .4;
+}
+
+::slotted(ion-label) {
+ order: 0;
+}
+
+::slotted(ion-icon) {
+ order: -1;
+
+ height: 1em;
+}
+
+::slotted(ion-label),
+::slotted(ion-icon) {
+ display: block;
+
+ align-self: center;
+
+ min-width: 26px;
+ max-width: 100%;
+
+ text-overflow: ellipsis;
+
+ white-space: nowrap;
+
+ overflow: hidden;
+ box-sizing: border-box;
+}
+
+:host(.tab-has-label-only) ::slotted(ion-label) {
+ white-space: normal;
+}
+
+
+
+// Tab Badges
+// --------------------------------------------------
+
+::slotted(ion-badge) {
+ @include position(null, var(--badge-end), null, null);
+ @include padding(1px, 6px);
+
+ box-sizing: border-box;
+
+ position: absolute;
+
+ height: auto;
+
+ font-size: 12px;
+
+ line-height: 16px;
+}
+
+
+// Tab Button Layout
+// --------------------------------------------------
+
+:host(.tab-layout-icon-start) a {
+ flex-direction: row;
+}
+
+:host(.tab-layout-icon-end) a {
+ flex-direction: row-reverse;
+}
+
+:host(.tab-layout-icon-bottom) a {
+ flex-direction: column-reverse;
+}
+
+:host(.tab-layout-icon-start) a,
+:host(.tab-layout-icon-end) a,
+:host(.tab-layout-icon-hide) a,
+:host(.tab-layout-label-hide) a,
+:host(.tab-has-icon-only) a,
+:host(.tab-has-label-only) a {
+ justify-content: center;
+}
+
+:host(.tab-layout-icon-hide) ::slotted(ion-icon) {
+ display: none;
+}
+
+:host(.tab-layout-label-hide) ::slotted(ion-label) {
+ display: none;
+}
+
+:host(.tab-layout-icon-top),
+:host(.tab-layout-icon-bottom),
+:host(.tab-layout-icon-only),
+:host(.tab-layout-label-hide),
+:host(.tab-has-icon-only) {
+ --badge-end: #{calc(50% - 30px)};
+}
+
+:host(.tab-layout-icon-hide),
+:host(.tab-layout-icon-start),
+:host(.tab-layout-icon-end),
+:host(.tab-has-label-only) {
+ --badge-end: #{calc(50% - 50px)};
+}
diff --git a/core/src/components/tab-button/tab-button.tsx b/core/src/components/tab-button/tab-button.tsx
new file mode 100644
index 0000000000..b1b3774e06
--- /dev/null
+++ b/core/src/components/tab-button/tab-button.tsx
@@ -0,0 +1,128 @@
+import { Component, ComponentInterface, Element, Event, EventEmitter, Listen, Prop, QueueApi, State } from '@stencil/core';
+
+import { Color, Mode, TabbarClickDetail, TabbarLayout } from '../../interface';
+import { createColorClasses } from '../../utils/theme';
+import { TabbarChangedDetail } from '../tab-bar/tab-bar-interface';
+
+@Component({
+ tag: 'ion-tab-button',
+ styleUrls: {
+ ios: 'tab-button.ios.scss',
+ md: 'tab-button.md.scss'
+ },
+ shadow: true
+})
+export class TabButton implements ComponentInterface {
+
+ @Element() el!: HTMLElement;
+
+ @Prop({ context: 'queue' }) queue!: QueueApi;
+ @Prop({ context: 'document' }) doc!: Document;
+
+ /**
+ * The selected tab component
+ */
+ @State() selected = false;
+
+ /**
+ * The mode determines which platform styles to use.
+ * Possible values are: `"ios"` or `"md"`.
+ */
+ @Prop() mode!: Mode;
+
+ /**
+ * The color to use from your application's color palette.
+ * Default options are: `"primary"`, `"secondary"`, `"tertiary"`, `"success"`, `"warning"`, `"danger"`, `"light"`, `"medium"`, and `"dark"`.
+ * For more information on colors, see [theming](/docs/theming/basics).
+ */
+ @Prop() color?: Color;
+
+ /**
+ * Set the layout of the text and icon in the tabbar.
+ */
+ @Prop() layout: TabbarLayout = 'icon-top';
+
+ /**
+ * The URL which will be used as the `href` within this tab's button anchor.
+ */
+ @Prop() href?: string;
+
+ /**
+ * A tab id must be provided for each `ion-tab`. It's used internally to reference
+ * the selected tab or by the router to switch between them.
+ */
+ @Prop() tab?: string;
+
+ /**
+ * The selected tab component
+ */
+ @Prop() disabled = false;
+
+ /**
+ * Emitted when the tab bar is clicked
+ * @internal
+ */
+ @Event() ionTabButtonClick!: EventEmitter;
+
+ @Listen('parent:ionTabBarChanged')
+ onTabbarChanged(ev: CustomEvent) {
+ this.selected = this.tab === ev.detail.tab;
+ }
+
+ @Listen('click')
+ onClick(ev: Event) {
+ if (!this.disabled) {
+ this.ionTabButtonClick.emit({
+ tab: this.tab,
+ href: this.href
+ });
+ }
+ ev.preventDefault();
+ }
+
+ componentWillLoad() {
+ if (this.tab === undefined) {
+ console.warn('ion-tab-button needs a tab, so it can be selected');
+ }
+ }
+
+ private get hasLabel() {
+ return !!this.el.querySelector('ion-label');
+ }
+
+ private get hasIcon() {
+ return !!this.el.querySelector('ion-icon');
+ }
+
+ hostData() {
+ const { color, tab, selected, layout, disabled, hasLabel, hasIcon } = this;
+ return {
+ 'role': 'tab',
+ 'ion-activatable': true,
+ 'aria-selected': selected ? 'true' : null,
+ 'id': `tab-button-${tab}`,
+ 'aria-controls': `tab-view-${tab}`,
+ class: {
+ ...createColorClasses(color),
+
+ 'tab-selected': selected,
+ 'tab-disabled': disabled,
+ 'tab-has-label': hasLabel,
+ 'tab-has-icon': hasIcon,
+ 'tab-has-label-only': hasLabel && !hasIcon,
+ 'tab-has-icon-only': hasIcon && !hasLabel,
+ [`tab-layout-${layout}`]: true,
+ }
+ };
+ }
+
+ render() {
+ const { mode, href } = this;
+ return (
+
+
+ {mode === 'md' && }
+
+ );
+ }
+}
diff --git a/core/src/components/tab/readme.md b/core/src/components/tab/readme.md
index 757f51e5fd..4c41e79d60 100644
--- a/core/src/components/tab/readme.md
+++ b/core/src/components/tab/readme.md
@@ -12,30 +12,12 @@ See the [Tabs API Docs](../Tabs/) for more details on configuring Tabs.
## Properties
-| Property | Attribute | Description | Type |
-| -------------------- | ------------------------ | --------------------------------------------------------------------------- | -------------------------------------------------------- |
-| `active` | `active` | If `true`, sets the tab as the active tab. | `boolean` |
-| `badgeColor` | `badge-color` | The badge color for the tab button. | `string \| undefined` |
-| `badge` | `badge` | The badge for the tab. | `string \| undefined` |
-| `btnId` | `btn-id` | hidden | `string \| undefined` |
-| `component` | `component` | The component to display inside of the tab. | `Function \| HTMLElement \| null \| string \| undefined` |
-| `delegate` | -- | hidden | `FrameworkDelegate \| undefined` |
-| `disabled` | `disabled` | If `true`, the user cannot interact with the tab. Defaults to `false`. | `boolean` |
-| `href` | `href` | The URL which will be used as the `href` within this tab's button anchor. | `string \| undefined` |
-| `icon` | `icon` | The icon for the tab. | `string \| undefined` |
-| `label` | `label` | The label of the tab. | `string \| undefined` |
-| `name` | `name` | The name of the tab. | `string \| undefined` |
-| `selected` | `selected` | If `true`, the tab will be selected. Defaults to `false`. | `boolean` |
-| `show` | `show` | If `true`, the tab button is visible within the tabbar. Defaults to `true`. | `boolean` |
-| `tabsHideOnSubPages` | `tabs-hide-on-sub-pages` | If `true`, hide the tabs on child pages. | `boolean` |
-
-
-## Events
-
-| Event | Detail | Description |
-| --------------- | ------ | ---------------------------------------------------- |
-| `ionSelect` | | Emitted when the current tab is selected. |
-| `ionTabMutated` | | Emitted when the tab props mutates. Used internally. |
+| Property | Attribute | Description | Type |
+| ----------- | ----------- | ----------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------- |
+| `active` | `active` | | `boolean` |
+| `component` | `component` | The component to display inside of the tab. | `Function \| HTMLElement \| null \| string \| undefined` |
+| `delegate` | -- | | `FrameworkDelegate \| undefined` |
+| `tab` | `tab` | A tab id must be provided for each `ion-tab`. It's used internally to reference the selected tab or by the router to switch between them. | `string \| undefined` |
## Methods
diff --git a/core/src/components/tab/tab.tsx b/core/src/components/tab/tab.tsx
index 8a7f43f274..99cd748d8f 100644
--- a/core/src/components/tab/tab.tsx
+++ b/core/src/components/tab/tab.tsx
@@ -1,6 +1,6 @@
-import { Build, Component, ComponentInterface, Element, Event, EventEmitter, Method, Prop, Watch } from '@stencil/core';
+import { Build, Component, ComponentInterface, Element, Method, Prop } from '@stencil/core';
-import { Color, ComponentRef, FrameworkDelegate } from '../../interface';
+import { ComponentRef, FrameworkDelegate } from '../../interface';
import { attachComponent } from '../../utils/framework-delegate';
@Component({
@@ -13,94 +13,24 @@ export class Tab implements ComponentInterface {
private loaded = false;
@Element() el!: HTMLIonTabElement;
- /**
- * If `true`, sets the tab as the active tab.
- */
+ /** @internal */
@Prop({ mutable: true }) active = false;
- /** hidden */
- @Prop() btnId?: string;
-
- /** hidden */
+ /** @internal */
@Prop() delegate?: FrameworkDelegate;
/**
- * The label of the tab.
+ * A tab id must be provided for each `ion-tab`. It's used internally to reference
+ * the selected tab or by the router to switch between them.
*/
- @Prop() label?: string;
-
- /**
- * The URL which will be used as the `href` within this tab's button anchor.
- */
- @Prop() href?: string;
-
- /**
- * The icon for the tab.
- */
- @Prop() icon?: string;
-
- /**
- * The badge for the tab.
- */
- @Prop() badge?: string;
-
- /**
- * The badge color for the tab button.
- */
- @Prop() badgeColor?: Color;
+ @Prop() tab?: string;
/**
* The component to display inside of the tab.
*/
@Prop() component?: ComponentRef;
- /**
- * The name of the tab.
- */
- @Prop({ mutable: true }) name?: string;
-
- /**
- * If `true`, the user cannot interact with the tab. Defaults to `false`.
- */
- @Prop() disabled = false;
-
- /**
- * If `true`, the tab will be selected. Defaults to `false`.
- */
- @Prop() selected = false;
-
- @Watch('selected')
- selectedChanged(selected: boolean) {
- if (selected) {
- this.ionSelect.emit();
- }
- }
-
- /**
- * If `true`, the tab button is visible within the tabbar. Defaults to `true`.
- */
- @Prop() show = true;
-
- /**
- * If `true`, hide the tabs on child pages.
- */
- @Prop() tabsHideOnSubPages = false;
-
- /**
- * Emitted when the current tab is selected.
- */
- @Event() ionSelect!: EventEmitter;
-
- /**
- * Emitted when the tab props mutates. Used internally.
- */
- @Event() ionTabMutated!: EventEmitter;
-
componentWillLoad() {
- // Set default name
- if (this.name === undefined && typeof this.component === 'string') {
- this.name = this.component;
- }
if (Build.isDev) {
if (this.component !== undefined && this.el.childElementCount > 0) {
@@ -109,18 +39,12 @@ export class Tab implements ComponentInterface {
` or` +
`- Remove the embedded content inside the ion-tab: `);
}
- }
- }
- @Watch('label')
- @Watch('href')
- @Watch('show')
- @Watch('disabled')
- @Watch('badge')
- @Watch('badgeColor')
- @Watch('icon')
- onPropChanged() {
- this.ionTabMutated.emit();
+ if (this.tab === undefined) {
+ console.error(`Tab views need to have an unique id attribute:
+ `);
+ }
+ }
}
/** Set the active component for the tab */
@@ -139,11 +63,12 @@ export class Tab implements ComponentInterface {
}
hostData() {
- const { btnId, active, component } = this;
+ const { tab, active, component } = this;
return {
- 'aria-labelledby': btnId,
- 'aria-hidden': !active ? 'true' : null,
'role': 'tabpanel',
+ 'aria-hidden': !active ? 'true' : null,
+ 'aria-labelledby': `tab-button-${tab}`,
+ 'id': `tab-view-${tab}`,
'class': {
'ion-page': component === undefined,
'tab-hidden': !active
diff --git a/core/src/components/tabbar/readme.md b/core/src/components/tabbar/readme.md
deleted file mode 100644
index 47befc233f..0000000000
--- a/core/src/components/tabbar/readme.md
+++ /dev/null
@@ -1,51 +0,0 @@
-# ion-tabbar
-
-Tabbar is the UI component that implements the array of button of `ion-tabs`. It's provided by default when `ion-tabs` is used, though, this "implicit" tabbar can not be customized.
-
-In order to have a custom tabbar, it should be provided in user's markup as direct children of `ion-tabs`:
-
-```html
-
-
-
-
-
-
-
-
-
-
-```
-
-
-
-
-
-## Properties
-
-| Property | Attribute | Description | Type |
-| ------------- | ------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------ |
-| `color` | `color` | The color to use from your application's color palette. Default options are: `"primary"`, `"secondary"`, `"tertiary"`, `"success"`, `"warning"`, `"danger"`, `"light"`, `"medium"`, and `"dark"`. For more information on colors, see [theming](/docs/theming/basics). | `string \| undefined` |
-| `highlight` | `highlight` | If `true`, show the tab highlight bar under the selected tab. | `boolean` |
-| `layout` | `layout` | Set the layout of the text and icon in the tabbar. Available options: `"icon-top"`, `"icon-start"`, `"icon-end"`, `"icon-bottom"`, `"icon-hide"`, `"label-hide"`. | `"icon-bottom" \| "icon-end" \| "icon-hide" \| "icon-start" \| "icon-top" \| "label-hide"` |
-| `mode` | `mode` | The mode determines which platform styles to use. Possible values are: `"ios"` or `"md"`. | `"ios" \| "md"` |
-| `placement` | `placement` | Set the position of the tabbar, relative to the content. Available options: `"top"`, `"bottom"`. | `"bottom" \| "top"` |
-| `selectedTab` | -- | The selected tab component | `HTMLIonTabElement \| undefined` |
-| `tabs` | -- | The tabs to render | `HTMLIonTabElement[]` |
-| `translucent` | `translucent` | If `true`, the tabbar will be translucent. Defaults to `false`. | `boolean` |
-
-
-## Events
-
-| Event | Detail | Description |
-| ---------------- | ----------------- | ----------------------------------- |
-| `ionTabbarClick` | HTMLIonTabElement | Emitted when the tab bar is clicked |
-
-
-----------------------------------------------
-
-*Built with [StencilJS](https://stenciljs.com/)*
diff --git a/core/src/components/tabbar/tab-button.ios.scss b/core/src/components/tabbar/tab-button.ios.scss
deleted file mode 100644
index f4e44e7ba2..0000000000
--- a/core/src/components/tabbar/tab-button.ios.scss
+++ /dev/null
@@ -1,32 +0,0 @@
-@import "./tab-button";
-@import "./tab-button.ios.vars";
-
-.tab-btn {
- @include padding($tab-button-ios-padding-top, $tab-button-ios-padding-end, $tab-button-ios-padding-bottom, $tab-button-ios-padding-start);
- max-width: $tab-button-ios-max-width;
-}
-
-.tab-btn-text {
- @include margin(0, null, 1px, null);
-
- min-height: $tab-button-ios-font-size + 1;
-}
-
-.tab-btn-has-label-only .tab-btn-text {
- @include margin(2px, 0);
-
- font-size: $tab-button-ios-font-size + 2;
- font-size: 14px;
-
- line-height: 1.1;
-}
-
-.tab-btn-icon {
- @include margin(4px, null, null, null);
-
- font-size: $tab-button-ios-icon-size;
-}
-
-.tab-btn-icon::before {
- vertical-align: top;
-}
diff --git a/core/src/components/tabbar/tab-button.md.scss b/core/src/components/tabbar/tab-button.md.scss
deleted file mode 100644
index 35f5432ae3..0000000000
--- a/core/src/components/tabbar/tab-button.md.scss
+++ /dev/null
@@ -1,48 +0,0 @@
-@import "./tab-button";
-@import "./tab-button.md.vars";
-
-// Material Design Tab Button
-// --------------------------------------------------
-
-.tab-btn {
- @include padding($tab-button-md-padding-top, $tab-button-md-padding-end, $tab-button-md-padding-bottom, $tab-button-md-padding-start);
-
- max-width: 168px;
-}
-
-// Material Design Tab Button Text
-// --------------------------------------------------
-
-.tab-btn-text {
- @include margin($tab-button-md-text-margin-top, $tab-button-md-text-margin-end, $tab-button-md-text-margin-bottom, $tab-button-md-text-margin-start);
- @include transform-origin(center, bottom);
-
- transform: var(--label-transform);
-
- transition: $tab-button-md-text-transition;
-
- text-transform: $tab-button-md-text-capitalization;
-}
-
-.tab-btn-selected .tab-btn-text {
- transform: #{$tab-button-md-text-transform-active};
-
- transition: $tab-button-md-text-transition;
-}
-
-// Material Design Tab Button Icon
-// --------------------------------------------------
-
-.tab-btn-icon {
- @include transform-origin(center, center);
-
- width: $tab-button-md-icon-size;
- height: $tab-button-md-icon-size;
-
- transform: var(--icon-transform);
-
- transition: $tab-button-md-icon-transition;
-
- font-size: $tab-button-md-icon-size;
-}
-
diff --git a/core/src/components/tabbar/tab-button.scss b/core/src/components/tabbar/tab-button.scss
deleted file mode 100644
index e4ba2e317a..0000000000
--- a/core/src/components/tabbar/tab-button.scss
+++ /dev/null
@@ -1,134 +0,0 @@
-@import "../../themes/ionic.globals";
-
-
-.tab-btn {
- @include text-inherit();
- @include margin(0);
- @include padding(0);
-
- display: flex;
- position: relative;
-
- flex: 1;
- flex-direction: column;
- align-items: center;
- justify-content: flex-start;
-
- width: 100%;
- height: 100%;
-
- border: 0;
-
- outline: none;
-
- background: transparent;
-
- text-decoration: none;
-
- cursor: pointer;
- overflow: hidden;
- box-sizing: border-box;
- -webkit-user-drag: none;
-}
-
-.tab-btn:focus-visible {
- background: var(--background-focused);
-}
-
-@media (any-hover: hover) {
- .tab-btn:hover {
- color: var(--color-selected);
- }
-}
-
-.tab-btn-selected {
- color: var(--color-selected);
-}
-
-.tab-btn-hidden {
- /* stylelint-disable-next-line declaration-no-important */
- display: none !important;
-}
-
-.tab-btn-disabled {
- pointer-events: none;
-
- opacity: .4;
-}
-
-.tab-btn-text {
- @include margin(var(--label-margin-top), null, var(--label-margin-bottom), null);
-
- display: var(--label-display, block);
-
- font-size: var(--label-font-size);
-
- line-height: var(--label-line-height);
-}
-
-.tab-btn-icon {
- @include margin(var(--icon-margin-top), null, var(--icon-margin-bottom), null);
-
- display: var(--icon-display, block);
-
- min-width: var(--icon-min-width);
- height: var(--icon-height, 1em);
-
- font-size: var(--icon-font-size);
-}
-
-.tab-btn-text,
-.tab-btn-icon {
- align-self: center;
-
- min-width: 26px;
- max-width: 100%;
-
- text-overflow: ellipsis;
-
- white-space: nowrap;
-
- overflow: hidden;
- box-sizing: border-box;
-}
-
-.tab-btn-has-label-only .tab-btn-text {
- white-space: normal;
-}
-
-.tab-btn-has-icon-only,
-.tab-btn-has-label-only {
- justify-content: center;
-}
-
-
-// Tab Badges
-// --------------------------------------------------
-
-.tab-btn-badge {
- @include position(6%, 4%, null, null); // 4% fallback
- @include position(null, calc(50% - 30px), null, null);
- @include padding(1px, 6px);
-
- box-sizing: border-box;
-
- position: absolute;
-
- height: auto;
-
- font-size: 12px;
-
- line-height: 16px;
-}
-
-.tab-btn-has-label-only .tab-btn-badge {
- @include position-horizontal(null, #{calc(50% - 50px)});
-}
-
-.tab-btn-has-icon-only .tab-btn-badge {
- @include position-horizontal(null, #{calc(50% - 30px)});
-}
-
-.tab-btn-selected .tab-btn-icon {
- transform: var(--icon-transform-selected);
-}
diff --git a/core/src/components/tabbar/tabbar.ios.scss b/core/src/components/tabbar/tabbar.ios.scss
deleted file mode 100644
index da5ef10c60..0000000000
--- a/core/src/components/tabbar/tabbar.ios.scss
+++ /dev/null
@@ -1,63 +0,0 @@
-@import "./tabbar";
-@import "./tabbar.ios.vars";
-@import "./tab-button.ios";
-
-// iOS Tabs
-// --------------------------------------------------
-
-:host {
- // default color / background
- --background: #{$tabbar-ios-background};
- --color: #{$tab-button-ios-text-color};
- --color-selected: #{$tabbar-ios-color-activated};
- --background-focused: #{$tabbar-ios-background-focused};
-
- justify-content: center;
-
- height: $tabbar-ios-height;
-
- border-top: $tabbar-ios-border;
-
- font-size: $tab-button-ios-font-size;
-
- contain: strict;
-}
-
-:host(.placement-top) {
- border-top: 0;
- border-bottom: $tabbar-ios-border;
-}
-
-// iOS Translucent Tabbar
-// --------------------------------------------------
-
-:host(.tabbar-translucent) {
- background-color: #{current-color(base, .8)};
- backdrop-filter: $tabbar-ios-translucent-filter;
-}
-
-
-// iOS Tabbar Layout
-// --------------------------------------------------
-
-:host(.layout-icon-end),
-:host(.layout-icon-start),
-:host(.layout-icon-hide) {
- --label-margin-top: 2px;
- --label-margin-bottom: 2px;
- --label-font-size: 14px;
- --label-line-height: 1.1;
-}
-
-:host(.layout-icon-end),
-:host(.layout-icon-start) {
- --icon-margin-top: 2px;
- --icon-margin-bottom: 1px;
- --icon-min-width: 24px;
- --icon-height: 26px;
- --icon-font-size: 24px;
-}
-
-:host(.layout-label-hide) {
- --icon-margin: 0;
-}
\ No newline at end of file
diff --git a/core/src/components/tabbar/tabbar.ios.vars.scss b/core/src/components/tabbar/tabbar.ios.vars.scss
deleted file mode 100644
index c4d441705d..0000000000
--- a/core/src/components/tabbar/tabbar.ios.vars.scss
+++ /dev/null
@@ -1,13 +0,0 @@
-@import "../../themes/ionic.globals.ios";
-
-// iOS Tabs
-// --------------------------------------------------
-
-/// @prop - Height of the tabbar
-$tabbar-ios-height: 50px !default;
-
-/// @prop - Border on the tabbar (border-top when [tabsPlacement=bottom] and border-bottom when [tabsPlacement=top])
-$tabbar-ios-border: $hairlines-width solid $tabbar-ios-border-color !default;
-
-/// @prop - Filter of the translucent tabbar
-$tabbar-ios-translucent-filter: saturate(210%) blur(20px) !default;
diff --git a/core/src/components/tabbar/tabbar.md.scss b/core/src/components/tabbar/tabbar.md.scss
deleted file mode 100644
index b5399c8c08..0000000000
--- a/core/src/components/tabbar/tabbar.md.scss
+++ /dev/null
@@ -1,42 +0,0 @@
-@import "./tabbar";
-@import "./tabbar.md.vars";
-@import "./tab-button.md";
-
-:host {
- // default color / background
- --color: #{$tab-button-md-text-color};
- --color-selected: #{$tabbar-md-color-activated};
- --background: #{$tabbar-md-background};
- --background-focused: #{$tabbar-md-background-focused};
- --icon-transform-selected: #{$tab-button-md-icon-transform-active};
-
- height: $tabbar-md-height;
-
- border-top: $tabbar-md-border;
-
- font-size: $tab-button-md-font-size;
- font-weight: $tab-button-md-font-weight;
-
- contain: strict;
-}
-
-// Material Design Tabbar Layout
-// --------------------------------------------------
-
-:host(.layout-icon-top) {
- --label-margin-bottom: -2px;
-}
-
-:host(.layout-icon-end) {
- --icon-transform-selected: #{$tab-button-md-icon-right-transform-active};
-}
-
-:host(.layout-icon-bottom) {
- --label-margin-top: -2px;
- --label-transform: transform-origin(center, top);
- --icon-transform-selected: #{$tab-button-md-icon-bottom-transform-active};
-}
-
-:host(.layout-icon-start) {
- --icon-transform-selected: #{$tab-button-md-icon-left-transform-active};
-}
diff --git a/core/src/components/tabbar/tabbar.md.vars.scss b/core/src/components/tabbar/tabbar.md.vars.scss
deleted file mode 100644
index a4aad29697..0000000000
--- a/core/src/components/tabbar/tabbar.md.vars.scss
+++ /dev/null
@@ -1,10 +0,0 @@
-@import "../../themes/ionic.globals.md";
-
-// Material Design Tabs
-// --------------------------------------------------
-
-/// @prop - Minimum height of the tabbar
-$tabbar-md-height: 56px !default;
-
-/// @prop - Border on the tabbar
-$tabbar-md-border: 1px solid $tabbar-md-border-color !default;
diff --git a/core/src/components/tabbar/tabbar.scss b/core/src/components/tabbar/tabbar.scss
deleted file mode 100644
index 596636de85..0000000000
--- a/core/src/components/tabbar/tabbar.scss
+++ /dev/null
@@ -1,119 +0,0 @@
-@import "../../themes/ionic.globals";
-
-:host {
- @include padding-horizontal(
- var(--ion-safe-area-left),
- var(--ion-safe-area-right)
- );
-
- display: flex;
-
- align-items: center;
- justify-content: center;
- order: 1;
-
- width: auto;
-
- background: var(--background);
- color: var(--color);
-
- user-select: none;
-
- z-index: $z-index-toolbar;
- box-sizing: content-box;
-}
-
-:host(.ion-color) {
- --background: #{current-color(base)};
- --color: #{current-color(contrast, .7)};
- --color-selected: #{current-color(contrast)};
-}
-
-:host(.tabbar-hidden) {
- /* stylelint-disable-next-line declaration-no-important */
- display: none !important;
-}
-
-:host(.placement-top) {
- order: -1;
-}
-
-:host(.placement-bottom) {
- padding-bottom: var(--ion-safe-area-bottom, 0);
-}
-
-
-// Tab Highlight
-// --------------------------------------------------
-
-.tabbar-highlight {
- @include position(null, null, 0, 0);
- @include transform-origin(0, 0);
-
- display: block;
- position: absolute;
-
- width: 1px;
- height: 2px;
-
- transform: translateZ(0);
-
- background: currentColor;
-
- &.animated {
- transition-duration: 300ms;
- transition-property: transform;
- transition-timing-function: cubic-bezier(.4, 0, .2, 1);
- will-change: transform;
- }
-}
-
-:host(.placement-top) .tabbar-highlight {
- bottom: 0;
-}
-
-:host(.placement-bottom) .tabbar-highlight {
- top: 0;
-}
-
-
-// Tab Layout
-// --------------------------------------------------
-
-:host(.layout-icon-start) .tab-btn {
- flex-direction: row;
-}
-
-:host(.layout-icon-end) .tab-btn {
- flex-direction: row-reverse;
-}
-
-:host(.layout-icon-bottom) .tab-btn {
- flex-direction: column-reverse;
-}
-
-:host(.layout-icon-start) .tab-btn,
-:host(.layout-icon-end) .tab-btn,
-:host(.layout-icon-hide) .tab-btn,
-:host(.layout-label-hide) .tab-btn {
- justify-content: center;
-}
-
-:host(.layout-icon-hide) {
- --icon-display: none;
-}
-
-:host(.layout-label-hide) {
- --label-display: none;
-}
-
-:host(.layout-icon-top) .tab-btn,
-:host(.layout-icon-bottom) .tab-btn {
- --badge-end: #{calc(50% - 30px)};
-}
-
-:host(.layout-icon-hide) .tab-btn,
-:host(.layout-icon-start) .tab-btn,
-:host(.layout-icon-end) .tab-btn {
- --badge-end: #{calc(50% - 50px)};
-}
diff --git a/core/src/components/tabbar/tabbar.tsx b/core/src/components/tabbar/tabbar.tsx
deleted file mode 100644
index cd89a6bc78..0000000000
--- a/core/src/components/tabbar/tabbar.tsx
+++ /dev/null
@@ -1,163 +0,0 @@
-import { Component, ComponentInterface, Element, Event, EventEmitter, Listen, Prop, QueueApi, State, Watch } from '@stencil/core';
-
-import { Color, Mode, TabbarLayout, TabbarPlacement } from '../../interface';
-import { createColorClasses } from '../../utils/theme';
-
-@Component({
- tag: 'ion-tabbar',
- styleUrls: {
- ios: 'tabbar.ios.scss',
- md: 'tabbar.md.scss'
- },
- scoped: true
-})
-export class Tabbar implements ComponentInterface {
-
- /**
- * The mode determines which platform styles to use.
- * Possible values are: `"ios"` or `"md"`.
- */
- @Prop() mode!: Mode;
-
- /**
- * The color to use from your application's color palette.
- * Default options are: `"primary"`, `"secondary"`, `"tertiary"`, `"success"`, `"warning"`, `"danger"`, `"light"`, `"medium"`, and `"dark"`.
- * For more information on colors, see [theming](/docs/theming/basics).
- */
- @Prop() color?: Color;
-
- @Element() el!: HTMLElement;
-
- @Prop({ context: 'queue' }) queue!: QueueApi;
- @Prop({ context: 'document' }) doc!: Document;
-
- @State() canScrollLeft = false;
- @State() canScrollRight = false;
- @State() keyboardVisible = false;
-
- /**
- * Set the layout of the text and icon in the tabbar. Available options: `"icon-top"`, `"icon-start"`, `"icon-end"`, `"icon-bottom"`, `"icon-hide"`, `"label-hide"`.
- */
- @Prop() layout: TabbarLayout = 'icon-top';
-
- /**
- * Set the position of the tabbar, relative to the content. Available options: `"top"`, `"bottom"`.
- */
- @Prop() placement: TabbarPlacement = 'bottom';
-
- /**
- * The selected tab component
- */
- @Prop() selectedTab?: HTMLIonTabElement;
-
- /**
- * The tabs to render
- */
- @Prop() tabs: HTMLIonTabElement[] = [];
-
- /**
- * If `true`, show the tab highlight bar under the selected tab.
- */
- @Prop() highlight = false;
-
- /**
- * If `true`, the tabbar will be translucent. Defaults to `false`.
- */
- @Prop() translucent = false;
-
- /**
- * Emitted when the tab bar is clicked
- */
- @Event() ionTabbarClick!: EventEmitter;
-
- @Listen('body:keyboardWillHide')
- protected onKeyboardWillHide() {
- setTimeout(() => this.keyboardVisible = false, 50);
- }
-
- @Listen('body:keyboardWillShow')
- protected onKeyboardWillShow() {
- if (this.placement === 'bottom') {
- this.keyboardVisible = true;
- }
- }
-
- componentDidLoad() {
- this.updateHighlight();
- }
-
- @Watch('selectedTab')
- @Listen('window:resize')
- private updateHighlight() {
- if (!this.highlight) {
- return;
- }
- this.queue.read(() => {
- const btn = this.el.shadowRoot!.querySelector('.tab-btn-selected') as HTMLElement | null;
- const highlight = this.el.shadowRoot!.querySelector('.tabbar-highlight') as HTMLElement;
- if (btn && highlight) {
- highlight.style.transform = `translate3d(${btn.offsetLeft}px,0,0) scaleX(${btn.offsetWidth})`;
- }
- });
- }
-
- hostData() {
- const { color, translucent, layout, placement, keyboardVisible } = this;
- return {
- role: 'tablist',
- 'aria-hidden': keyboardVisible ? 'true' : null,
- 'slot': 'tabbar',
- class: {
- ...createColorClasses(color),
- 'tabbar-translucent': translucent,
- [`layout-${layout}`]: true,
- [`placement-${placement}`]: true,
- 'tabbar-hidden': keyboardVisible,
- }
- };
- }
-
- renderTabButton(tab: HTMLIonTabElement) {
- const { icon, label, disabled, badge, badgeColor, href } = tab;
- const selected = tab === this.selectedTab;
- const hasLabel = label !== undefined;
- const hasIcon = icon !== undefined;
- return (
- {
- if (!tab.disabled) {
- this.ionTabbarClick.emit(tab);
- }
- ev.preventDefault();
- }}
- >
- {icon && }
- {label && {label}}
- {badge && {badge}}
- {this.mode === 'md' && }
-
- );
- }
-
- render() {
- return [
- this.tabs.map(tab => this.renderTabButton(tab)),
- this.highlight &&
- ];
- }
-}
diff --git a/core/src/components/tabs/readme.md b/core/src/components/tabs/readme.md
index 64b19af625..533ff6b701 100644
--- a/core/src/components/tabs/readme.md
+++ b/core/src/components/tabs/readme.md
@@ -4,23 +4,29 @@ Tabs are a top level navigation component for created multiple stacked navs.
The component is a container of individual [Tab](../Tab/) components.
`ion-tabs` is a styleless component that works as a router outlet in
-order to handle navigation. When the user does not provide a `ion-tabbar` in their markup, `ion-tabs`, by default provides one. Notice that `ion-tabbar` is the UI component that can be used to switch between tabs.
+order to handle navigation. When the user does not provide a `ion-tab-bar` in their markup, `ion-tabs`, by default provides one. Notice that `ion-tab-bar` is the UI component that can be used to switch between tabs.
-In order to customize the style of the `ion-tabbar`, it should be included in the user's markup as
+In order to customize the style of the `ion-tab-bar`, it should be included in the user's markup as
direct children of `ion-tabs`, like this:
```html
-
-
-
-
+ Home Content
+ Settings Content
-
+
+
+
+ Home
+
+
+
+
+ Settings
+
+
+
+
```
@@ -29,11 +35,9 @@ direct children of `ion-tabs`, like this:
## Properties
-| Property | Attribute | Description | Type |
-| -------------- | --------------- | ------------------------------------------------------------------------------- | --------------------- |
-| `name` | `name` | A unique name for the tabs. | `string \| undefined` |
-| `tabbarHidden` | `tabbar-hidden` | If `true`, the tabbar will be hidden. Defaults to `false`. | `boolean` |
-| `useRouter` | `use-router` | If `true`, the tabs will use the router and `selectedTab` will not do anything. | `boolean` |
+| Property | Attribute | Description | Type |
+| -------- | --------- | --------------------------- | --------------------- |
+| `name` | `name` | A unique name for the tabs. | `string \| undefined` |
## Events
@@ -68,15 +72,15 @@ Type: `Promise`
-### `getTab(tabOrIndex: string | number | HTMLIonTabElement) => Promise`
+### `getTab(tab: string | HTMLIonTabElement) => Promise`
Get the tab at the given index
#### Parameters
-| Name | Type | Description |
-| ------------ | --------------------------------------- | ----------- |
-| `tabOrIndex` | `HTMLIonTabElement \| number \| string` | |
+| Name | Type | Description |
+| ----- | ----------------------------- | ----------- |
+| `tab` | `HTMLIonTabElement \| string` | |
#### Returns
@@ -84,15 +88,15 @@ Type: `Promise`
-### `select(tabOrIndex: number | HTMLIonTabElement) => Promise`
+### `select(tab: string | HTMLIonTabElement) => Promise`
Index or the Tab instance, of the tab to select.
#### Parameters
-| Name | Type | Description |
-| ------------ | ----------------------------- | ----------- |
-| `tabOrIndex` | `HTMLIonTabElement \| number` | |
+| Name | Type | Description |
+| ----- | ----------------------------- | ----------- |
+| `tab` | `HTMLIonTabElement \| string` | |
#### Returns
diff --git a/core/src/components/tabs/tabs.scss b/core/src/components/tabs/tabs.scss
index 3f075deac2..969f283f51 100644
--- a/core/src/components/tabs/tabs.scss
+++ b/core/src/components/tabs/tabs.scss
@@ -22,8 +22,3 @@
contain: layout size style;
}
-
-:host(.tabbar-hidden) ion-tabbar,
-:host(.tabbar-hidden)::slotted(ion-tabbar) {
- display: none;
-}
diff --git a/core/src/components/tabs/tabs.tsx b/core/src/components/tabs/tabs.tsx
index d39046e4ac..683e37febb 100644
--- a/core/src/components/tabs/tabs.tsx
+++ b/core/src/components/tabs/tabs.tsx
@@ -1,6 +1,6 @@
-import { Build, Component, Element, Event, EventEmitter, Listen, Method, Prop, State } from '@stencil/core';
+import { Component, Element, Event, EventEmitter, Listen, Method, Prop, State } from '@stencil/core';
-import { Config, NavOutlet, RouteID, RouteWrite } from '../../interface';
+import { Config, NavOutlet, RouteID, RouteWrite, TabbarClickDetail } from '../../interface';
@Component({
tag: 'ion-tabs',
@@ -9,11 +9,9 @@ import { Config, NavOutlet, RouteID, RouteWrite } from '../../interface';
})
export class Tabs implements NavOutlet {
- private ids = -1;
private transitioning = false;
- private tabsId = (++tabIds);
private leavingTab?: HTMLIonTabElement;
- private userTabbarEl?: HTMLIonTabbarElement;
+ private useRouter = false;
@Element() el!: HTMLStencilElement;
@@ -28,16 +26,6 @@ export class Tabs implements NavOutlet {
*/
@Prop() name?: string;
- /**
- * If `true`, the tabbar will be hidden. Defaults to `false`.
- */
- @Prop() tabbarHidden = false;
-
- /**
- * If `true`, the tabs will use the router and `selectedTab` will not do anything.
- */
- @Prop({ mutable: true }) useRouter = false;
-
/**
* Emitted when the tab changes.
*/
@@ -59,13 +47,8 @@ export class Tabs implements NavOutlet {
@Event() ionNavDidChange!: EventEmitter;
async componentWillLoad() {
- if (!this.useRouter) {
- this.useRouter = !!this.doc.querySelector('ion-router') && !this.el.closest('[no-router]');
- }
- this.userTabbarEl = this.el.querySelector('ion-tabbar') || undefined;
-
- this.initTabs();
-
+ this.useRouter = !!this.doc.querySelector('ion-router') && !this.el.closest('[no-router]');
+ this.tabs = Array.from(this.el.querySelectorAll('ion-tab'));
this.ionNavWillLoad.emit();
this.componentWillUpdate();
}
@@ -80,28 +63,23 @@ export class Tabs implements NavOutlet {
}
componentWillUpdate() {
- const tabbarEl = this.userTabbarEl;
- if (tabbarEl) {
- tabbarEl.tabs = this.tabs.slice();
- tabbarEl.selectedTab = this.selectedTab;
+ const tabbar = this.el.querySelector('ion-tab-bar');
+ if (tabbar) {
+ const tab = this.selectedTab ? this.selectedTab.tab : undefined;
+ tabbar.selectedTab = tab;
}
}
- @Listen('ionTabMutated')
- protected onTabMutated() {
- this.el.forceUpdate();
- }
-
- @Listen('ionTabbarClick')
- protected onTabClicked(ev: CustomEvent) {
- const selectedTab = ev.detail;
- const href = selectedTab.href as string | undefined;
+ @Listen('ionTabButtonClick')
+ protected onTabClicked(ev: CustomEvent) {
+ const { href, tab } = ev.detail;
+ const selectedTab = this.tabs.find(t => t.tab === tab);
if (this.useRouter && href !== undefined) {
const router = this.doc.querySelector('ion-router');
if (router) {
router.push(href);
}
- } else {
+ } else if (selectedTab) {
this.select(selectedTab);
}
}
@@ -110,8 +88,8 @@ export class Tabs implements NavOutlet {
* Index or the Tab instance, of the tab to select.
*/
@Method()
- async select(tabOrIndex: number | HTMLIonTabElement): Promise {
- const selectedTab = await this.getTab(tabOrIndex);
+ async select(tab: string | HTMLIonTabElement): Promise {
+ const selectedTab = await this.getTab(tab);
if (!this.shouldSwitch(selectedTab)) {
return false;
}
@@ -141,20 +119,21 @@ export class Tabs implements NavOutlet {
/** @internal */
@Method()
async getRouteId(): Promise {
- const id = this.selectedTab && this.selectedTab.name;
- return id !== undefined ? { id, element: this.selectedTab } : undefined;
+ const tabId = this.selectedTab && this.selectedTab.tab;
+ return tabId !== undefined ? { id: tabId, element: this.selectedTab } : undefined;
}
/** Get the tab at the given index */
@Method()
- async getTab(tabOrIndex: string | number | HTMLIonTabElement): Promise {
- if (typeof tabOrIndex === 'string') {
- return this.tabs.find(tab => tab.name === tabOrIndex);
+ async getTab(tab: string | HTMLIonTabElement): Promise {
+ const tabEl = (typeof tab === 'string')
+ ? this.tabs.find(t => t.tab === tab)
+ : tab;
+
+ if (!tabEl) {
+ console.error(`tab with id: "${tabEl}" does not exist`);
}
- if (typeof tabOrIndex === 'number') {
- return this.tabs[tabOrIndex];
- }
- return tabOrIndex;
+ return tabEl;
}
/**
@@ -165,47 +144,13 @@ export class Tabs implements NavOutlet {
return Promise.resolve(this.selectedTab);
}
- private initTabs() {
- const tabs = this.tabs = Array.from(this.el.querySelectorAll('ion-tab'));
- tabs.forEach(tab => {
- const id = `t-${this.tabsId}-${++this.ids}`;
- tab.btnId = 'tab-' + id;
- tab.id = 'tabpanel-' + id;
- });
- }
-
private async initSelect(): Promise {
- const tabs = this.tabs;
- // wait for all tabs to be ready
- await Promise.all(tabs.map(tab => tab.componentOnReady()));
if (this.useRouter) {
- if (Build.isDev) {
- const tab = tabs.find(t => t.selected);
- if (tab) {
- console.warn('When using a router (ion-router) makes no difference' +
- 'Define routes properly the define which tab is selected');
- }
- }
return;
}
- // find pre-selected tabs
- const selectedTab = tabs.find(t => t.selected) ||
- tabs.find(t => t.show && !t.disabled);
-
- // reset all tabs none is selected
- for (const tab of tabs) {
- if (tab !== selectedTab) {
- tab.selected = false;
- }
- }
- if (selectedTab) {
- await selectedTab.setActive();
- }
- this.selectedTab = selectedTab;
- if (selectedTab) {
- selectedTab.selected = true;
- selectedTab.active = true;
- }
+ // wait for all tabs to be ready
+ await Promise.all(this.tabs.map(tab => tab.componentOnReady()));
+ await this.select(this.tabs[0]);
}
private setActive(selectedTab: HTMLIonTabElement): Promise {
@@ -213,13 +158,6 @@ export class Tabs implements NavOutlet {
return Promise.reject('transitioning already happening');
}
- // Reset rest of tabs
- for (const tab of this.tabs) {
- if (selectedTab !== tab) {
- tab.selected = false;
- }
- }
-
this.transitioning = true;
this.leavingTab = this.selectedTab;
this.selectedTab = selectedTab;
@@ -237,7 +175,6 @@ export class Tabs implements NavOutlet {
return;
}
- selectedTab.selected = true;
if (leavingTab !== selectedTab) {
if (leavingTab) {
leavingTab.active = false;
@@ -262,28 +199,12 @@ export class Tabs implements NavOutlet {
return selectedTab !== undefined && selectedTab !== leavingTab && !this.transitioning;
}
- hostData() {
- return {
- class: {
- 'tabbar-hidden': this.tabbarHidden
- }
- };
- }
-
render() {
return [
,
-
-
-
-
+
];
}
}
-
-let tabIds = -1;
diff --git a/core/src/components/tabs/test/basic/e2e.js b/core/src/components/tabs/test/basic/e2e.js
deleted file mode 100644
index b6c656dc2d..0000000000
--- a/core/src/components/tabs/test/basic/e2e.js
+++ /dev/null
@@ -1,34 +0,0 @@
-'use strict';
-
-const { register, Page, platforms } = require('../../../../../scripts/e2e');
-const { getElement, waitAndGetElementById, waitForTransition } = require('../../../../../scripts/e2e/utils');
-
-class E2ETestPage extends Page {
- constructor(driver, platform) {
- super(driver, `http://localhost:3333/src/components/tabs/test/basic?ionic:mode=${platform}`);
- }
-}
-
-platforms.forEach(platform => {
- describe('tabs/basic', () => {
- register('should init', driver => {
- const page = new E2ETestPage(driver, platform);
- return page.navigate();
- });
-
- // register('should check each tab', async (driver, testContext) => {
- // testContext.timeout(60000);
- // const page = new E2ETestPage(driver, platform);
-
- // await waitForTransition(300);
-
- // const tabTwoButton = await waitAndGetElementById(driver, 'tab-t-0-1');
- // tabTwoButton.click();
- // await waitForTransition(600);
-
- // const tabThreeButton = await waitAndGetElementById(driver, 'tab-t-0-2');
- // tabThreeButton.click();
- // await waitForTransition(600);
- // });
- });
-});
diff --git a/core/src/components/tabs/test/basic/e2e.ts b/core/src/components/tabs/test/basic/e2e.ts
new file mode 100644
index 0000000000..ba03f6f8dc
--- /dev/null
+++ b/core/src/components/tabs/test/basic/e2e.ts
@@ -0,0 +1,25 @@
+import { newE2EPage } from '@stencil/core/testing';
+
+it('tab-group: basic', async () => {
+ const page = await newE2EPage({
+ url: '/src/components/tab-group/test/basic?ionic:_testing=true'
+ });
+
+ let compare = await page.compareScreenshot();
+ expect(compare).toMatchScreenshot();
+
+ const button2 = await page.find('.e2eTabTwoButton');
+ await button2.click();
+ compare = await page.compareScreenshot();
+ expect(compare).toMatchScreenshot();
+
+ const button3 = await page.find('.e2eTabThreeButton');
+ await button3.click();
+ compare = await page.compareScreenshot();
+ expect(compare).toMatchScreenshot();
+
+ const button4 = await page.find('.e2eTabFourButton');
+ await button4.click();
+ compare = await page.compareScreenshot();
+ expect(compare).toMatchScreenshot();
+});
diff --git a/core/src/components/tabs/test/basic/index.html b/core/src/components/tabs/test/basic/index.html
index dd063848a7..9a3fd23ce4 100644
--- a/core/src/components/tabs/test/basic/index.html
+++ b/core/src/components/tabs/test/basic/index.html
@@ -14,7 +14,8 @@
-
+
+
Tab One
@@ -22,13 +23,12 @@
Tab One
-
Update Badge Count
Update Badge Color
-
+
Tab Two
@@ -39,7 +39,7 @@
-
+
Tab Three
@@ -50,7 +50,7 @@
-
+
Hidden Tab
@@ -61,25 +61,58 @@
-
-
+
-
+
+
+ Plain List
+
+
+
+
+ Schedule
+
+ 6
+
+
+
+ Stopwatch
+
+ 6
+
+
+
+ Hidden
+
+
+
+
+ Messages
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/core/src/components/tabs/test/colors/e2e.js b/core/src/components/tabs/test/colors/e2e.js
deleted file mode 100644
index 7c10f08c89..0000000000
--- a/core/src/components/tabs/test/colors/e2e.js
+++ /dev/null
@@ -1,34 +0,0 @@
-'use strict';
-
-const { register, Page, platforms } = require('../../../../../scripts/e2e');
-const { getElement, waitAndGetElementById, waitForTransition } = require('../../../../../scripts/e2e/utils');
-
-class E2ETestPage extends Page {
- constructor(driver, platform) {
- super(driver, `http://localhost:3333/src/components/tabs/test/colors?ionic:mode=${platform}`);
- }
-}
-
-platforms.forEach(platform => {
- describe('tabs/colors', () => {
- register('should init', driver => {
- const page = new E2ETestPage(driver, platform);
- return page.navigate();
- });
-
- // register('should check each tab', async (driver, testContext) => {
- // testContext.timeout(60000);
- // const page = new E2ETestPage(driver, platform);
-
- // await waitForTransition(300);
-
- // const tabTwoButton = await waitAndGetElementById(driver, 'tab-t-0-1');
- // tabTwoButton.click();
- // await waitForTransition(600);
-
- // const tabThreeButton = await waitAndGetElementById(driver, 'tab-t-0-2');
- // tabThreeButton.click();
- // await waitForTransition(600);
- // });
- });
-});
diff --git a/core/src/components/tabs/test/colors/index.html b/core/src/components/tabs/test/colors/index.html
deleted file mode 100644
index 0a925fad67..0000000000
--- a/core/src/components/tabs/test/colors/index.html
+++ /dev/null
@@ -1,114 +0,0 @@
-
-
-
-