mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-08-19 19:57:22 +08:00
refactor(tabbar): removes ion-tab-button
This commit is contained in:
@ -46,7 +46,6 @@ exports.config.outputTargets = [
|
|||||||
'ion-router-outlet',
|
'ion-router-outlet',
|
||||||
'ion-anchor',
|
'ion-anchor',
|
||||||
'ion-tabbar',
|
'ion-tabbar',
|
||||||
'ion-tab-button',
|
|
||||||
|
|
||||||
// auxiliar
|
// auxiliar
|
||||||
'ion-picker-column',
|
'ion-picker-column',
|
||||||
|
47
core/src/components.d.ts
vendored
47
core/src/components.d.ts
vendored
@ -2103,7 +2103,7 @@ declare global {
|
|||||||
* The text to display on the ok button. Default: `OK`.
|
* The text to display on the ok button. Default: `OK`.
|
||||||
*/
|
*/
|
||||||
'okText': string;
|
'okText': string;
|
||||||
'open': (ev?: UIEvent | undefined) => Promise<HTMLIonPopoverElement> | Promise<HTMLIonActionSheetElement> | Promise<HTMLIonAlertElement>;
|
'open': (ev?: UIEvent | undefined) => Promise<HTMLIonActionSheetElement> | Promise<HTMLIonAlertElement> | Promise<HTMLIonPopoverElement>;
|
||||||
/**
|
/**
|
||||||
* The text to display when the select is empty.
|
* The text to display when the select is empty.
|
||||||
*/
|
*/
|
||||||
@ -2266,21 +2266,6 @@ declare global {
|
|||||||
'when': string | boolean;
|
'when': string | boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface IonTabButton {
|
|
||||||
'badge': string;
|
|
||||||
'badgeColor': string;
|
|
||||||
'color': Color;
|
|
||||||
'disabled': boolean;
|
|
||||||
'href': string;
|
|
||||||
'icon': string;
|
|
||||||
'label': string;
|
|
||||||
'mode': Mode;
|
|
||||||
/**
|
|
||||||
* If true, the tab button will be selected. Defaults to `false`.
|
|
||||||
*/
|
|
||||||
'selected': boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface IonTab {
|
interface IonTab {
|
||||||
/**
|
/**
|
||||||
* If true, sets the tab as the active tab.
|
* If true, sets the tab as the active tab.
|
||||||
@ -2315,7 +2300,7 @@ declare global {
|
|||||||
*/
|
*/
|
||||||
'getTabId': () => string | null;
|
'getTabId': () => string | null;
|
||||||
/**
|
/**
|
||||||
* The URL which will be used as the `href` within this tab's `<ion-tab-button>` anchor.
|
* The URL which will be used as the `href` within this tab's button anchor.
|
||||||
*/
|
*/
|
||||||
'href': string;
|
'href': string;
|
||||||
/**
|
/**
|
||||||
@ -3384,14 +3369,6 @@ declare global {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
interface HTMLIonTabButtonElement extends StencilComponents.IonTabButton, HTMLStencilElement {}
|
|
||||||
|
|
||||||
var HTMLIonTabButtonElement: {
|
|
||||||
prototype: HTMLIonTabButtonElement;
|
|
||||||
new (): HTMLIonTabButtonElement;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
interface HTMLIonTabElement extends StencilComponents.IonTab, HTMLStencilElement {}
|
interface HTMLIonTabElement extends StencilComponents.IonTab, HTMLStencilElement {}
|
||||||
|
|
||||||
var HTMLIonTabElement: {
|
var HTMLIonTabElement: {
|
||||||
@ -3579,7 +3556,6 @@ declare global {
|
|||||||
'ion-slides': JSXElements.IonSlidesAttributes;
|
'ion-slides': JSXElements.IonSlidesAttributes;
|
||||||
'ion-spinner': JSXElements.IonSpinnerAttributes;
|
'ion-spinner': JSXElements.IonSpinnerAttributes;
|
||||||
'ion-split-pane': JSXElements.IonSplitPaneAttributes;
|
'ion-split-pane': JSXElements.IonSplitPaneAttributes;
|
||||||
'ion-tab-button': JSXElements.IonTabButtonAttributes;
|
|
||||||
'ion-tab': JSXElements.IonTabAttributes;
|
'ion-tab': JSXElements.IonTabAttributes;
|
||||||
'ion-tabbar': JSXElements.IonTabbarAttributes;
|
'ion-tabbar': JSXElements.IonTabbarAttributes;
|
||||||
'ion-tabs': JSXElements.IonTabsAttributes;
|
'ion-tabs': JSXElements.IonTabsAttributes;
|
||||||
@ -5826,21 +5802,6 @@ declare global {
|
|||||||
'when'?: string | boolean;
|
'when'?: string | boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IonTabButtonAttributes extends HTMLAttributes {
|
|
||||||
'badge'?: string;
|
|
||||||
'badgeColor'?: string;
|
|
||||||
'color'?: Color;
|
|
||||||
'disabled'?: boolean;
|
|
||||||
'href'?: string;
|
|
||||||
'icon'?: string;
|
|
||||||
'label'?: string;
|
|
||||||
'mode'?: Mode;
|
|
||||||
/**
|
|
||||||
* If true, the tab button will be selected. Defaults to `false`.
|
|
||||||
*/
|
|
||||||
'selected'?: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface IonTabAttributes extends HTMLAttributes {
|
export interface IonTabAttributes extends HTMLAttributes {
|
||||||
/**
|
/**
|
||||||
* If true, sets the tab as the active tab.
|
* If true, sets the tab as the active tab.
|
||||||
@ -5871,7 +5832,7 @@ declare global {
|
|||||||
*/
|
*/
|
||||||
'disabled'?: boolean;
|
'disabled'?: boolean;
|
||||||
/**
|
/**
|
||||||
* The URL which will be used as the `href` within this tab's `<ion-tab-button>` anchor.
|
* The URL which will be used as the `href` within this tab's button anchor.
|
||||||
*/
|
*/
|
||||||
'href'?: string;
|
'href'?: string;
|
||||||
/**
|
/**
|
||||||
@ -6364,7 +6325,6 @@ declare global {
|
|||||||
'ion-slides': HTMLIonSlidesElement
|
'ion-slides': HTMLIonSlidesElement
|
||||||
'ion-spinner': HTMLIonSpinnerElement
|
'ion-spinner': HTMLIonSpinnerElement
|
||||||
'ion-split-pane': HTMLIonSplitPaneElement
|
'ion-split-pane': HTMLIonSplitPaneElement
|
||||||
'ion-tab-button': HTMLIonTabButtonElement
|
|
||||||
'ion-tab': HTMLIonTabElement
|
'ion-tab': HTMLIonTabElement
|
||||||
'ion-tabbar': HTMLIonTabbarElement
|
'ion-tabbar': HTMLIonTabbarElement
|
||||||
'ion-tabs': HTMLIonTabsElement
|
'ion-tabs': HTMLIonTabsElement
|
||||||
@ -6468,7 +6428,6 @@ declare global {
|
|||||||
'ion-slides': HTMLIonSlidesElement;
|
'ion-slides': HTMLIonSlidesElement;
|
||||||
'ion-spinner': HTMLIonSpinnerElement;
|
'ion-spinner': HTMLIonSpinnerElement;
|
||||||
'ion-split-pane': HTMLIonSplitPaneElement;
|
'ion-split-pane': HTMLIonSplitPaneElement;
|
||||||
'ion-tab-button': HTMLIonTabButtonElement;
|
|
||||||
'ion-tab': HTMLIonTabElement;
|
'ion-tab': HTMLIonTabElement;
|
||||||
'ion-tabbar': HTMLIonTabbarElement;
|
'ion-tabbar': HTMLIonTabbarElement;
|
||||||
'ion-tabs': HTMLIonTabsElement;
|
'ion-tabs': HTMLIonTabsElement;
|
||||||
|
@ -1,26 +0,0 @@
|
|||||||
# ion-tab-button
|
|
||||||
|
|
||||||
TabButton is an internal component for tabs. Please see the [Tab docs](../tab) for more details.
|
|
||||||
|
|
||||||
|
|
||||||
<!-- Auto Generated Below -->
|
|
||||||
|
|
||||||
|
|
||||||
## Properties
|
|
||||||
|
|
||||||
| Property | Attribute | Description | Type |
|
|
||||||
| ------------ | ------------- | -------------------------------------------------------------- | --------- |
|
|
||||||
| `badgeColor` | `badge-color` | | `string` |
|
|
||||||
| `badge` | `badge` | | `string` |
|
|
||||||
| `color` | `color` | | `Color` |
|
|
||||||
| `disabled` | `disabled` | | `boolean` |
|
|
||||||
| `href` | `href` | | `string` |
|
|
||||||
| `icon` | `icon` | | `string` |
|
|
||||||
| `label` | `label` | | `string` |
|
|
||||||
| `mode` | `mode` | | `Mode` |
|
|
||||||
| `selected` | `selected` | If true, the tab button will be selected. Defaults to `false`. | `boolean` |
|
|
||||||
|
|
||||||
|
|
||||||
----------------------------------------------
|
|
||||||
|
|
||||||
*Built with [StencilJS](https://stenciljs.com/)*
|
|
@ -1,82 +0,0 @@
|
|||||||
import { Component, Element, Prop, State } from '@stencil/core';
|
|
||||||
|
|
||||||
import { Color, Mode } from '../../interface';
|
|
||||||
import { createColorClasses } from '../../utils/theme';
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
tag: 'ion-tab-button',
|
|
||||||
styleUrls: {
|
|
||||||
ios: 'tab-button.ios.scss',
|
|
||||||
md: 'tab-button.md.scss'
|
|
||||||
},
|
|
||||||
shadow: true
|
|
||||||
})
|
|
||||||
export class TabButton {
|
|
||||||
|
|
||||||
@Element() el!: HTMLElement;
|
|
||||||
|
|
||||||
@Prop() mode!: Mode;
|
|
||||||
@Prop() color?: Color;
|
|
||||||
|
|
||||||
@State() keyFocus = false;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* If true, the tab button will be selected. Defaults to `false`.
|
|
||||||
*/
|
|
||||||
@Prop() selected = false;
|
|
||||||
@Prop() label?: string;
|
|
||||||
@Prop() icon?: string;
|
|
||||||
@Prop() badge?: string;
|
|
||||||
@Prop() disabled?: boolean;
|
|
||||||
@Prop() badgeColor?: string;
|
|
||||||
@Prop() href?: string;
|
|
||||||
|
|
||||||
private onKeyUp() {
|
|
||||||
this.keyFocus = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private onBlur() {
|
|
||||||
this.keyFocus = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
hostData() {
|
|
||||||
const selected = this.selected;
|
|
||||||
const hasLabel = !!this.label;
|
|
||||||
const hasIcon = !!this.icon;
|
|
||||||
const hasLabelOnly = (hasLabel && !hasIcon);
|
|
||||||
const hasIconOnly = (hasIcon && !hasLabel);
|
|
||||||
const hasBadge = !!this.badge;
|
|
||||||
return {
|
|
||||||
'role': 'tab',
|
|
||||||
'aria-selected': selected ? 'true' : null,
|
|
||||||
class: {
|
|
||||||
...createColorClasses(this.color),
|
|
||||||
'tab-selected': selected,
|
|
||||||
'has-label': hasLabel,
|
|
||||||
'has-icon': hasIcon,
|
|
||||||
'has-label-only': hasLabelOnly,
|
|
||||||
'has-icon-only': hasIconOnly,
|
|
||||||
'has-badge': hasBadge,
|
|
||||||
'tab-button-disabled': this.disabled,
|
|
||||||
'focused': this.keyFocus
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const { icon, label, href, badge, badgeColor, mode } = this;
|
|
||||||
|
|
||||||
return [
|
|
||||||
<a
|
|
||||||
href={href || '#'}
|
|
||||||
class="tab-button-native"
|
|
||||||
onKeyUp={this.onKeyUp.bind(this)}
|
|
||||||
onBlur={this.onBlur.bind(this)}>
|
|
||||||
{ icon && <ion-icon class="tab-button-icon" icon={icon} lazy={false}></ion-icon> }
|
|
||||||
{ label && <span class="tab-button-text">{label}</span> }
|
|
||||||
{ badge && <ion-badge class="tab-badge" color={badgeColor}>{badge}</ion-badge> }
|
|
||||||
{ mode === 'md' && <ion-ripple-effect tapClick={true}></ion-ripple-effect> }
|
|
||||||
</a>
|
|
||||||
];
|
|
||||||
}
|
|
||||||
}
|
|
@ -30,7 +30,7 @@ export class Tab {
|
|||||||
@Prop() label?: string;
|
@Prop() label?: string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The URL which will be used as the `href` within this tab's `<ion-tab-button>` anchor.
|
* The URL which will be used as the `href` within this tab's button anchor.
|
||||||
*/
|
*/
|
||||||
@Prop() href?: string;
|
@Prop() href?: string;
|
||||||
|
|
||||||
|
@ -1,27 +1,20 @@
|
|||||||
@import "./tab-button";
|
@import "./tab-button";
|
||||||
@import "./tab-button.ios.vars";
|
@import "./tab-button.ios.vars";
|
||||||
|
|
||||||
:host {
|
.tab-btn {
|
||||||
--color: #{$tab-button-ios-text-color};
|
@include padding($tab-button-ios-padding-top, $tab-button-ios-padding-end, $tab-button-ios-padding-bottom, $tab-button-ios-padding-start);
|
||||||
--color-selected: #{$tabbar-ios-text-color-active};
|
|
||||||
--background-focused: #{$tabbar-ios-background-color-focused};
|
|
||||||
|
|
||||||
max-width: $tab-button-ios-max-width;
|
max-width: $tab-button-ios-max-width;
|
||||||
|
|
||||||
font-size: $tab-button-ios-font-size;
|
font-size: $tab-button-ios-font-size;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tab-button-native {
|
.tab-btn-text {
|
||||||
@include padding($tab-button-ios-padding-top, $tab-button-ios-padding-end, $tab-button-ios-padding-bottom, $tab-button-ios-padding-start);
|
|
||||||
}
|
|
||||||
|
|
||||||
.tab-button-text {
|
|
||||||
@include margin(0, null, 1px, null);
|
@include margin(0, null, 1px, null);
|
||||||
|
|
||||||
min-height: $tab-button-ios-font-size + 1;
|
min-height: $tab-button-ios-font-size + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
:host(.has-label-only) .tab-button-text {
|
.tab-btn-has-label-only .tab-btn-text {
|
||||||
@include margin(2px, 0);
|
@include margin(2px, 0);
|
||||||
|
|
||||||
font-size: $tab-button-ios-font-size + 2;
|
font-size: $tab-button-ios-font-size + 2;
|
||||||
@ -30,12 +23,12 @@
|
|||||||
line-height: 1.1;
|
line-height: 1.1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tab-button-icon {
|
.tab-btn-icon {
|
||||||
@include margin(4px, null, null, null);
|
@include margin(4px, null, null, null);
|
||||||
|
|
||||||
font-size: $tab-button-ios-icon-size;
|
font-size: $tab-button-ios-icon-size;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tab-button-icon::before {
|
.tab-btn-icon::before {
|
||||||
vertical-align: top;
|
vertical-align: top;
|
||||||
}
|
}
|
@ -4,27 +4,18 @@
|
|||||||
// Material Design Tab Button
|
// Material Design Tab Button
|
||||||
// --------------------------------------------------
|
// --------------------------------------------------
|
||||||
|
|
||||||
:host {
|
.tab-btn {
|
||||||
--color: #{$tab-button-md-text-color};
|
@include padding($tab-button-md-padding-top, $tab-button-md-padding-end, $tab-button-md-padding-bottom, $tab-button-md-padding-start);
|
||||||
--color-selected: #{$tabbar-md-text-color-active};
|
|
||||||
--background-focused: #{$tabbar-md-background-color-focused};
|
|
||||||
--icon-transform-selected: #{$tab-button-md-icon-transform-active};
|
|
||||||
|
|
||||||
max-width: 168px;
|
max-width: 168px;
|
||||||
|
|
||||||
font-weight: $tab-button-md-font-weight;
|
font-weight: $tab-button-md-font-weight;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tab-button-native {
|
|
||||||
@include padding($tab-button-md-padding-top, $tab-button-md-padding-end, $tab-button-md-padding-bottom, $tab-button-md-padding-start);
|
|
||||||
|
|
||||||
display: flex;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Material Design Tab Button Text
|
// Material Design Tab Button Text
|
||||||
// --------------------------------------------------
|
// --------------------------------------------------
|
||||||
|
|
||||||
.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 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);
|
@include transform-origin(center, bottom);
|
||||||
|
|
||||||
@ -37,7 +28,7 @@
|
|||||||
text-transform: $tab-button-md-text-capitalization;
|
text-transform: $tab-button-md-text-capitalization;
|
||||||
}
|
}
|
||||||
|
|
||||||
:host(.tab-selected) .tab-button-text {
|
.tab-btn-selected .tab-btn-text {
|
||||||
--label-transform: #{$tab-button-md-text-transform-active};
|
--label-transform: #{$tab-button-md-text-transform-active};
|
||||||
|
|
||||||
transition: $tab-button-md-text-transition;
|
transition: $tab-button-md-text-transition;
|
||||||
@ -46,7 +37,7 @@
|
|||||||
// Material Design Tab Button Icon
|
// Material Design Tab Button Icon
|
||||||
// --------------------------------------------------
|
// --------------------------------------------------
|
||||||
|
|
||||||
.tab-button-icon {
|
.tab-btn-icon {
|
||||||
@include transform-origin(center, center);
|
@include transform-origin(center, center);
|
||||||
|
|
||||||
width: $tab-button-md-icon-size;
|
width: $tab-button-md-icon-size;
|
@ -1,55 +1,15 @@
|
|||||||
@import "../../themes/ionic.globals";
|
@import "../../themes/ionic.globals";
|
||||||
|
|
||||||
:host {
|
|
||||||
@include border-radius(0);
|
|
||||||
@include margin(0);
|
|
||||||
|
|
||||||
display: block;
|
.tab-btn {
|
||||||
position: relative;
|
@include text-inherit();
|
||||||
|
|
||||||
flex: 1;
|
|
||||||
|
|
||||||
height: 100%;
|
|
||||||
|
|
||||||
border: 0;
|
|
||||||
|
|
||||||
background: var(--background);
|
|
||||||
color: var(--color);
|
|
||||||
|
|
||||||
text-align: center;
|
|
||||||
text-decoration: none;
|
|
||||||
|
|
||||||
overflow: hidden;
|
|
||||||
user-select: none;
|
|
||||||
z-index: 0;
|
|
||||||
box-sizing: border-box;
|
|
||||||
box-sizing: border-box;
|
|
||||||
}
|
|
||||||
|
|
||||||
:host(.focused) {
|
|
||||||
background: var(--background-focused);
|
|
||||||
}
|
|
||||||
|
|
||||||
:host(:hover),
|
|
||||||
:host(.tab-selected) {
|
|
||||||
color: var(--color-selected);
|
|
||||||
}
|
|
||||||
|
|
||||||
:host(.tab-hidden) {
|
|
||||||
/* stylelint-disable-next-line declaration-no-important */
|
|
||||||
display: none !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
a {
|
|
||||||
text-decoration: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tab-button-native {
|
|
||||||
@include margin(0);
|
@include margin(0);
|
||||||
@include padding(0);
|
@include padding(0);
|
||||||
|
|
||||||
display: flex;
|
display: flex;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
flex: 1;
|
||||||
flex-direction: var(--flex-direction, column);
|
flex-direction: var(--flex-direction, column);
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: var(--justify-content, flex-start);
|
justify-content: var(--justify-content, flex-start);
|
||||||
@ -59,27 +19,38 @@ a {
|
|||||||
|
|
||||||
border: 0;
|
border: 0;
|
||||||
|
|
||||||
|
outline: none;
|
||||||
|
|
||||||
background: transparent;
|
background: transparent;
|
||||||
color: inherit;
|
|
||||||
|
text-decoration: none;
|
||||||
|
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
|
-webkit-user-drag: none;
|
||||||
&:active,
|
|
||||||
&:focus {
|
|
||||||
outline: none;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
:host(.tab-button-disabled) {
|
.tab-btn:focus-visible {
|
||||||
|
background: var(--background-focused);
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-btn:hover,
|
||||||
|
.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;
|
pointer-events: none;
|
||||||
}
|
|
||||||
|
|
||||||
:host(.tab-button-disabled) .tab-button-native {
|
|
||||||
opacity: .4;
|
opacity: .4;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tab-button-text {
|
.tab-btn-text {
|
||||||
@include margin(var(--label-margin-top), null, var(--label-margin-bottom), null);
|
@include margin(var(--label-margin-top), null, var(--label-margin-bottom), null);
|
||||||
|
|
||||||
display: var(--label-display, block);
|
display: var(--label-display, block);
|
||||||
@ -89,7 +60,7 @@ a {
|
|||||||
line-height: var(--label-line-height);
|
line-height: var(--label-line-height);
|
||||||
}
|
}
|
||||||
|
|
||||||
.tab-button-icon {
|
.tab-btn-icon {
|
||||||
@include margin(var(--icon-margin-top), null, var(--icon-margin-bottom), null);
|
@include margin(var(--icon-margin-top), null, var(--icon-margin-bottom), null);
|
||||||
|
|
||||||
display: var(--icon-display, block);
|
display: var(--icon-display, block);
|
||||||
@ -100,8 +71,8 @@ a {
|
|||||||
font-size: var(--icon-font-size);
|
font-size: var(--icon-font-size);
|
||||||
}
|
}
|
||||||
|
|
||||||
.tab-button-text,
|
.tab-btn-text,
|
||||||
.tab-button-icon {
|
.tab-btn-icon {
|
||||||
align-self: center;
|
align-self: center;
|
||||||
|
|
||||||
min-width: 26px;
|
min-width: 26px;
|
||||||
@ -115,12 +86,12 @@ a {
|
|||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
}
|
}
|
||||||
|
|
||||||
:host(.has-label-only) .tab-button-text {
|
.tab-btn-has-label-only .tab-btn-text {
|
||||||
white-space: normal;
|
white-space: normal;
|
||||||
}
|
}
|
||||||
|
|
||||||
:host(.has-icon-only) .tab-button-native,
|
.tab-btn-has-icon-only,
|
||||||
:host(.has-label-only) .tab-button-native {
|
.tab-btn-has-label-only {
|
||||||
--justify-content: center;
|
--justify-content: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -128,7 +99,7 @@ a {
|
|||||||
// Tab Badges
|
// Tab Badges
|
||||||
// --------------------------------------------------
|
// --------------------------------------------------
|
||||||
|
|
||||||
.tab-badge {
|
.tab-btn-badge {
|
||||||
@include position(6%, 4%, null, null); // 4% fallback
|
@include position(6%, 4%, null, null); // 4% fallback
|
||||||
@include position(null, var(--badge-end, calc(50% - 30px)), null, null);
|
@include position(null, var(--badge-end, calc(50% - 30px)), null, null);
|
||||||
@include padding(1px, 6px);
|
@include padding(1px, 6px);
|
||||||
@ -144,14 +115,14 @@ a {
|
|||||||
line-height: 16px;
|
line-height: 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
:host(.has-label-only) .tab-badge {
|
.tab-btn-has-label-only .tab-btn-badge {
|
||||||
--badge-end: #{calc(50% - 50px)};
|
--badge-end: #{calc(50% - 50px)};
|
||||||
}
|
}
|
||||||
|
|
||||||
:host(.has-icon-only) .tab-badge {
|
.tab-btn-has-icon-only .tab-btn-badge {
|
||||||
--badge-end: #{calc(50% - 30px)};
|
--badge-end: #{calc(50% - 30px)};
|
||||||
}
|
}
|
||||||
|
|
||||||
:host(.tab-selected) .tab-button-icon {
|
.tab-btn-selected .tab-btn-icon {
|
||||||
transform: var(--icon-transform-selected);
|
transform: var(--icon-transform-selected);
|
||||||
}
|
}
|
@ -1,5 +1,6 @@
|
|||||||
@import "./tabbar";
|
@import "./tabbar";
|
||||||
@import "./tabbar.ios.vars";
|
@import "./tabbar.ios.vars";
|
||||||
|
@import "./tab-button.ios";
|
||||||
|
|
||||||
// iOS Tabs
|
// iOS Tabs
|
||||||
// --------------------------------------------------
|
// --------------------------------------------------
|
||||||
@ -8,7 +9,9 @@
|
|||||||
// default color / background
|
// default color / background
|
||||||
--background: #{$tabbar-ios-background-color};
|
--background: #{$tabbar-ios-background-color};
|
||||||
--background-rgb: var(--ion-tabbar-translucent-background-color-rgb, 248, 248, 248);
|
--background-rgb: var(--ion-tabbar-translucent-background-color-rgb, 248, 248, 248);
|
||||||
--color: #{$tabbar-ios-text-color-active};
|
--color: #{$tab-button-ios-text-color};
|
||||||
|
--color-selected: #{$tabbar-ios-text-color-active};
|
||||||
|
--background-focused: #{$tabbar-ios-background-color-focused};
|
||||||
|
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
|
||||||
@ -36,17 +39,17 @@
|
|||||||
// iOS Tabbar Layout
|
// iOS Tabbar Layout
|
||||||
// --------------------------------------------------
|
// --------------------------------------------------
|
||||||
|
|
||||||
:host(.layout-icon-end) ion-tab-button,
|
:host(.layout-icon-end) .tab-btn,
|
||||||
:host(.layout-icon-start) ion-tab-button,
|
:host(.layout-icon-start) .tab-btn,
|
||||||
:host(.layout-icon-hide) ion-tab-button {
|
:host(.layout-icon-hide) .tab-btn {
|
||||||
--label-margin-top: 2px;
|
--label-margin-top: 2px;
|
||||||
--label-margin-bottom: 2px;
|
--label-margin-bottom: 2px;
|
||||||
--label-font-size: 14px;
|
--label-font-size: 14px;
|
||||||
--label-line-height: 1.1;
|
--label-line-height: 1.1;
|
||||||
}
|
}
|
||||||
|
|
||||||
:host(.layout-icon-end) ion-tab-button,
|
:host(.layout-icon-end) .tab-btn,
|
||||||
:host(.layout-icon-start) ion-tab-button {
|
:host(.layout-icon-start) .tab-btn {
|
||||||
--icon-margin-top: 2px;
|
--icon-margin-top: 2px;
|
||||||
--icon-margin-bottom: 1px;
|
--icon-margin-bottom: 1px;
|
||||||
--icon-min-width: 24px;
|
--icon-min-width: 24px;
|
||||||
@ -54,6 +57,6 @@
|
|||||||
--icon-font-size: 24px;
|
--icon-font-size: 24px;
|
||||||
}
|
}
|
||||||
|
|
||||||
:host(.layout-label-hide) ion-tab-button {
|
:host(.layout-label-hide) .tab-btn {
|
||||||
--icon-margin: 0;
|
--icon-margin: 0;
|
||||||
}
|
}
|
@ -1,10 +1,14 @@
|
|||||||
@import "./tabbar";
|
@import "./tabbar";
|
||||||
@import "./tabbar.md.vars";
|
@import "./tabbar.md.vars";
|
||||||
|
@import "./tab-button.md";
|
||||||
|
|
||||||
:host {
|
:host {
|
||||||
// default color / background
|
// default color / background
|
||||||
|
--color: #{$tab-button-md-text-color};
|
||||||
|
--color-selected: #{$tabbar-md-text-color-active};
|
||||||
--background: #{$tabbar-md-background-color};
|
--background: #{$tabbar-md-background-color};
|
||||||
--color: #{$tabbar-md-text-color-active};
|
--background-focused: #{$tabbar-md-background-color-focused};
|
||||||
|
--icon-transform-selected: #{$tab-button-md-icon-transform-active};
|
||||||
|
|
||||||
height: $tabbar-md-height;
|
height: $tabbar-md-height;
|
||||||
|
|
||||||
@ -16,20 +20,20 @@
|
|||||||
// Material Design Tabbar Layout
|
// Material Design Tabbar Layout
|
||||||
// --------------------------------------------------
|
// --------------------------------------------------
|
||||||
|
|
||||||
:host(.layout-icon-top) ion-tab-button {
|
:host(.layout-icon-top) .tab-btn {
|
||||||
--label-margin-bottom: -2px;
|
--label-margin-bottom: -2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
:host(.layout-icon-end) ion-tab-button {
|
:host(.layout-icon-end) .tab-btn {
|
||||||
--icon-transform-selected: #{$tab-button-md-icon-right-transform-active};
|
--icon-transform-selected: #{$tab-button-md-icon-right-transform-active};
|
||||||
}
|
}
|
||||||
|
|
||||||
:host(.layout-icon-bottom) ion-tab-button {
|
:host(.layout-icon-bottom) .tab-btn {
|
||||||
--label-margin-top: -2px;
|
--label-margin-top: -2px;
|
||||||
--label-transform: transform-origin(center, top);
|
--label-transform: transform-origin(center, top);
|
||||||
--icon-transform-selected: #{$tab-button-md-icon-bottom-transform-active};
|
--icon-transform-selected: #{$tab-button-md-icon-bottom-transform-active};
|
||||||
}
|
}
|
||||||
|
|
||||||
:host(.layout-icon-start) ion-tab-button {
|
:host(.layout-icon-start) .tab-btn {
|
||||||
--icon-transform-selected: #{$tab-button-md-icon-left-transform-active};
|
--icon-transform-selected: #{$tab-button-md-icon-left-transform-active};
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
@import "../../themes/ionic.globals.md";
|
@import "../../themes/ionic.globals.md";
|
||||||
@import "../tab-button/tab-button.md.vars";
|
|
||||||
|
|
||||||
// Material Design Tabs
|
// Material Design Tabs
|
||||||
// --------------------------------------------------
|
// --------------------------------------------------
|
||||||
|
@ -13,11 +13,12 @@
|
|||||||
background: var(--background);
|
background: var(--background);
|
||||||
color: var(--color);
|
color: var(--color);
|
||||||
|
|
||||||
|
user-select: none;
|
||||||
|
|
||||||
z-index: $z-index-toolbar;
|
z-index: $z-index-toolbar;
|
||||||
}
|
}
|
||||||
|
|
||||||
:host(.ion-color),
|
:host(.ion-color) {
|
||||||
:host(.ion-color) ion-tab-button {
|
|
||||||
--background: #{current-color(base)};
|
--background: #{current-color(base)};
|
||||||
--color: #{current-color(contrast, .7)};
|
--color: #{current-color(contrast, .7)};
|
||||||
--color-selected: #{current-color(contrast)};
|
--color-selected: #{current-color(contrast)};
|
||||||
@ -37,7 +38,6 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Tab Highlight
|
// Tab Highlight
|
||||||
// --------------------------------------------------
|
// --------------------------------------------------
|
||||||
|
|
||||||
@ -75,40 +75,40 @@
|
|||||||
// Tab Layout
|
// Tab Layout
|
||||||
// --------------------------------------------------
|
// --------------------------------------------------
|
||||||
|
|
||||||
:host(.layout-icon-start) ion-tab-button {
|
:host(.layout-icon-start) .tab-btn {
|
||||||
--flex-direction: row;
|
--flex-direction: row;
|
||||||
}
|
}
|
||||||
|
|
||||||
:host(.layout-icon-end) ion-tab-button {
|
:host(.layout-icon-end) .tab-btn {
|
||||||
--flex-direction: row-reverse;
|
--flex-direction: row-reverse;
|
||||||
}
|
}
|
||||||
|
|
||||||
:host(.layout-icon-bottom) ion-tab-button {
|
:host(.layout-icon-bottom) .tab-btn {
|
||||||
--flex-direction: column-reverse;
|
--flex-direction: column-reverse;
|
||||||
}
|
}
|
||||||
|
|
||||||
:host(.layout-icon-start) ion-tab-button,
|
:host(.layout-icon-start) .tab-btn,
|
||||||
:host(.layout-icon-end) ion-tab-button,
|
:host(.layout-icon-end) .tab-btn,
|
||||||
:host(.layout-icon-hide) ion-tab-button,
|
:host(.layout-icon-hide) .tab-btn,
|
||||||
:host(.layout-label-hide) ion-tab-button {
|
:host(.layout-label-hide) .tab-btn {
|
||||||
--justify-content: center;
|
--justify-content: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
:host(.layout-icon-hide) ion-tab-button {
|
:host(.layout-icon-hide) .tab-btn {
|
||||||
--icon-display: none;
|
--icon-display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
:host(.layout-label-hide) ion-tab-button {
|
:host(.layout-label-hide) .tab-btn {
|
||||||
--label-display: none;
|
--label-display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
:host(.layout-icon-top) ion-tab-button,
|
:host(.layout-icon-top) .tab-btn,
|
||||||
:host(.layout-icon-bottom) ion-tab-button {
|
:host(.layout-icon-bottom) .tab-btn {
|
||||||
--badge-end: #{calc(50% - 30px)};
|
--badge-end: #{calc(50% - 30px)};
|
||||||
}
|
}
|
||||||
|
|
||||||
:host(.layout-icon-hide) ion-tab-button,
|
:host(.layout-icon-hide) .tab-btn,
|
||||||
:host(.layout-icon-start) ion-tab-button,
|
:host(.layout-icon-start) .tab-btn,
|
||||||
:host(.layout-icon-end) ion-tab-button {
|
:host(.layout-icon-end) .tab-btn {
|
||||||
--badge-end: #{calc(50% - 50px)};
|
--badge-end: #{calc(50% - 50px)};
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { Component, Element, Event, EventEmitter, Listen, Prop, QueueApi, State, Watch } from '@stencil/core';
|
import { Component, Element, Event, EventEmitter, Listen, Prop, QueueApi, State } from '@stencil/core';
|
||||||
|
|
||||||
import { Color, Mode, TabbarLayout, TabbarPlacement } from '../../interface';
|
import { Color, Mode, TabbarLayout, TabbarPlacement } from '../../interface';
|
||||||
import { createColorClasses } from '../../utils/theme';
|
import { createColorClasses } from '../../utils/theme';
|
||||||
@ -41,10 +41,10 @@ export class Tabbar {
|
|||||||
/** The tabs to render */
|
/** The tabs to render */
|
||||||
@Prop() tabs: HTMLIonTabElement[] = [];
|
@Prop() tabs: HTMLIonTabElement[] = [];
|
||||||
|
|
||||||
@Watch('selectedTab')
|
// @Watch('selectedTab')
|
||||||
selectedTabChanged() {
|
// selectedTabChanged() {
|
||||||
this.updateHighlight();
|
// this.updateHighlight();
|
||||||
}
|
// }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If true, show the tab highlight bar under the selected tab.
|
* If true, show the tab highlight bar under the selected tab.
|
||||||
@ -71,32 +71,32 @@ export class Tabbar {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Listen('window:resize')
|
// @Listen('window:resize')
|
||||||
onResize() {
|
// onResize() {
|
||||||
this.updateHighlight();
|
// this.updateHighlight();
|
||||||
}
|
// }
|
||||||
|
|
||||||
componentDidLoad() {
|
// componentDidLoad() {
|
||||||
this.updateHighlight();
|
// this.updateHighlight();
|
||||||
}
|
// }
|
||||||
|
|
||||||
private getSelectedButton(): HTMLIonTabButtonElement | undefined {
|
// private getSelectedButton(): HTMLIonTabButtonElement | undefined {
|
||||||
return Array.from(this.el.querySelectorAll('ion-tab-button'))
|
// return Array.from(this.el.querySelectorAll('ion-tab-button'))
|
||||||
.find(btn => btn.selected);
|
// .find(btn => btn.selected);
|
||||||
}
|
// }
|
||||||
|
|
||||||
private updateHighlight() {
|
// private updateHighlight() {
|
||||||
if (!this.highlight) {
|
// if (!this.highlight) {
|
||||||
return;
|
// return;
|
||||||
}
|
// }
|
||||||
this.queue.read(() => {
|
// this.queue.read(() => {
|
||||||
const btn = this.getSelectedButton();
|
// const btn = this.getSelectedButton();
|
||||||
const highlight = this.el.querySelector('div.tabbar-highlight') as HTMLElement;
|
// const highlight = this.el.querySelector('div.tabbar-highlight') as HTMLElement;
|
||||||
if (btn && highlight) {
|
// if (btn && highlight) {
|
||||||
highlight.style.transform = `translate3d(${btn.offsetLeft}px,0,0) scaleX(${btn.offsetWidth})`;
|
// highlight.style.transform = `translate3d(${btn.offsetLeft}px,0,0) scaleX(${btn.offsetWidth})`;
|
||||||
}
|
// }
|
||||||
});
|
// });
|
||||||
}
|
// }
|
||||||
|
|
||||||
hostData() {
|
hostData() {
|
||||||
const { color, translucent, layout, placement, keyboardVisible } = this;
|
const { color, translucent, layout, placement, keyboardVisible } = this;
|
||||||
@ -115,32 +115,50 @@ export class Tabbar {
|
|||||||
|
|
||||||
render() {
|
render() {
|
||||||
const selectedTab = this.selectedTab;
|
const selectedTab = this.selectedTab;
|
||||||
|
|
||||||
return [
|
return [
|
||||||
this.tabs.map(tab => (
|
this.tabs.map(tab => renderTabButton(tab, tab === selectedTab, this.mode, () => {
|
||||||
<ion-tab-button
|
|
||||||
id={tab.btnId}
|
|
||||||
label={tab.label}
|
|
||||||
icon={tab.icon}
|
|
||||||
badge={tab.badge}
|
|
||||||
disabled={tab.disabled}
|
|
||||||
badgeColor={tab.badgeColor}
|
|
||||||
href={tab.href}
|
|
||||||
selected={selectedTab === tab}
|
|
||||||
mode={this.mode}
|
|
||||||
color={this.color}
|
|
||||||
aria-hidden={ !tab.show ? 'true' : null }
|
|
||||||
class={{ 'tab-hidden': !tab.show }}
|
|
||||||
onClick={ev => {
|
|
||||||
if (!tab.disabled) {
|
|
||||||
this.ionTabbarClick.emit(tab);
|
this.ionTabbarClick.emit(tab);
|
||||||
}
|
})),
|
||||||
ev.stopPropagation();
|
|
||||||
ev.preventDefault();
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
)),
|
|
||||||
this.highlight && <div class="animated tabbar-highlight" />
|
this.highlight && <div class="animated tabbar-highlight" />
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function renderTabButton(tab: HTMLIonTabElement, selected: boolean, mode: string, onClick: () => void) {
|
||||||
|
const { icon, label, disabled, badge, badgeColor, href } = tab;
|
||||||
|
const hasLabel = !!label;
|
||||||
|
const hasIcon = !!icon;
|
||||||
|
const hasLabelOnly = (hasLabel && !hasIcon);
|
||||||
|
const hasIconOnly = (hasIcon && !hasLabel);
|
||||||
|
const hasBadge = !!badge;
|
||||||
|
return (
|
||||||
|
<a
|
||||||
|
role="tab"
|
||||||
|
aria-selected={selected ? 'true' : null}
|
||||||
|
href={href || '#'}
|
||||||
|
ion-activable
|
||||||
|
class={{
|
||||||
|
'tab-btn': true,
|
||||||
|
'tab-btn-selected': selected,
|
||||||
|
'tab-btn-has-label': hasLabel,
|
||||||
|
'tab-btn-has-icon': hasIcon,
|
||||||
|
'tab-btn-has-label-only': hasLabelOnly,
|
||||||
|
'tab-btn-has-icon-only': hasIconOnly,
|
||||||
|
'tab-btn-has-badge': hasBadge,
|
||||||
|
'tab-btn-disabled': disabled,
|
||||||
|
'tab-btn-hidden': !tab.show
|
||||||
|
}}
|
||||||
|
onClick={ev => {
|
||||||
|
if (!tab.disabled) {
|
||||||
|
onClick();
|
||||||
|
}
|
||||||
|
ev.stopPropagation();
|
||||||
|
ev.preventDefault();
|
||||||
|
}}>
|
||||||
|
{ icon && <ion-icon class="tab-btn-icon" icon={icon} lazy={false}></ion-icon> }
|
||||||
|
{ label && <span class="tab-btn-text">{label}</span> }
|
||||||
|
{ badge && <ion-badge class="tab-btn-badge" color={badgeColor}>{badge}</ion-badge> }
|
||||||
|
{ mode === 'md' && <ion-ripple-effect tapClick={true}></ion-ripple-effect> }
|
||||||
|
</a>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
@ -41,7 +41,7 @@ exports.config = {
|
|||||||
{ components: ['ion-slides', 'ion-slide'] },
|
{ components: ['ion-slides', 'ion-slide'] },
|
||||||
{ components: ['ion-spinner'] },
|
{ components: ['ion-spinner'] },
|
||||||
{ components: ['ion-split-pane'] },
|
{ components: ['ion-split-pane'] },
|
||||||
{ components: ['ion-tabs', 'ion-tab', 'ion-tabbar', 'ion-tab-button'] },
|
{ components: ['ion-tabs', 'ion-tab', 'ion-tabbar'] },
|
||||||
{ components: ['ion-text'] },
|
{ components: ['ion-text'] },
|
||||||
{ components: ['ion-toast', 'ion-toast-controller'] },
|
{ components: ['ion-toast', 'ion-toast-controller'] },
|
||||||
{ components: ['ion-toggle'] },
|
{ components: ['ion-toggle'] },
|
||||||
|
Reference in New Issue
Block a user