mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-08-16 18:17:31 +08:00
fix(tabs): use slot instead of placement
This commit is contained in:
@ -865,14 +865,14 @@ export class Tab {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export declare interface TabBar extends StencilComponents<'IonTabBar'> {}
|
export declare interface TabBar extends StencilComponents<'IonTabBar'> {}
|
||||||
@Component({ selector: 'ion-tab-bar', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, template: '<ng-content></ng-content>', inputs: ['mode', 'color', 'layout', 'placement', 'selectedTab', 'translucent'] })
|
@Component({ selector: 'ion-tab-bar', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, template: '<ng-content></ng-content>', inputs: ['mode', 'color', 'layout', 'selectedTab', 'translucent'] })
|
||||||
export class TabBar {
|
export class TabBar {
|
||||||
ionTabBarChanged: EventEmitter<CustomEvent>;
|
ionTabBarChanged: EventEmitter<CustomEvent>;
|
||||||
|
|
||||||
constructor(c: ChangeDetectorRef, r: ElementRef) {
|
constructor(c: ChangeDetectorRef, r: ElementRef) {
|
||||||
c.detach();
|
c.detach();
|
||||||
const el = r.nativeElement;
|
const el = r.nativeElement;
|
||||||
proxyInputs(this, el, ['mode', 'color', 'layout', 'placement', 'selectedTab', 'translucent']);
|
proxyInputs(this, el, ['mode', 'color', 'layout', 'selectedTab', 'translucent']);
|
||||||
proxyOutputs(this, el, ['ionTabBarChanged']);
|
proxyOutputs(this, el, ['ionTabBarChanged']);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -30,7 +30,7 @@
|
|||||||
"ionicons": "4.4.6"
|
"ionicons": "4.4.6"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@stencil/core": "0.15.2-2",
|
"@stencil/core": "0.15.2",
|
||||||
"@stencil/sass": "0.1.1",
|
"@stencil/sass": "0.1.1",
|
||||||
"@stencil/utils": "latest",
|
"@stencil/utils": "latest",
|
||||||
"@types/jest": "^23.3.1",
|
"@types/jest": "^23.3.1",
|
||||||
|
13
core/src/components.d.ts
vendored
13
core/src/components.d.ts
vendored
@ -59,7 +59,6 @@ import {
|
|||||||
TabbarChangedDetail,
|
TabbarChangedDetail,
|
||||||
TabbarClickDetail,
|
TabbarClickDetail,
|
||||||
TabbarLayout,
|
TabbarLayout,
|
||||||
TabbarPlacement,
|
|
||||||
TextFieldTypes,
|
TextFieldTypes,
|
||||||
TextInputChangeEvent,
|
TextInputChangeEvent,
|
||||||
ToastOptions,
|
ToastOptions,
|
||||||
@ -4441,7 +4440,7 @@ export namespace Components {
|
|||||||
*/
|
*/
|
||||||
'color'?: Color;
|
'color'?: Color;
|
||||||
/**
|
/**
|
||||||
* Set the layout of the text and icon in the tabbar.
|
* Set the layout of the text and icon in the tab bar.
|
||||||
*/
|
*/
|
||||||
'layout': TabbarLayout;
|
'layout': TabbarLayout;
|
||||||
/**
|
/**
|
||||||
@ -4449,10 +4448,6 @@ export namespace Components {
|
|||||||
*/
|
*/
|
||||||
'mode': Mode;
|
'mode': Mode;
|
||||||
/**
|
/**
|
||||||
* Set the position of the tabbar, relative to the content.
|
|
||||||
*/
|
|
||||||
'placement': TabbarPlacement;
|
|
||||||
/**
|
|
||||||
* The selected tab component
|
* The selected tab component
|
||||||
*/
|
*/
|
||||||
'selectedTab'?: string;
|
'selectedTab'?: string;
|
||||||
@ -4467,7 +4462,7 @@ export namespace Components {
|
|||||||
*/
|
*/
|
||||||
'color'?: Color;
|
'color'?: Color;
|
||||||
/**
|
/**
|
||||||
* Set the layout of the text and icon in the tabbar.
|
* Set the layout of the text and icon in the tab bar.
|
||||||
*/
|
*/
|
||||||
'layout'?: TabbarLayout;
|
'layout'?: TabbarLayout;
|
||||||
/**
|
/**
|
||||||
@ -4476,10 +4471,6 @@ export namespace Components {
|
|||||||
'mode'?: Mode;
|
'mode'?: Mode;
|
||||||
'onIonTabBarChanged'?: (event: CustomEvent<TabbarChangedDetail>) => void;
|
'onIonTabBarChanged'?: (event: CustomEvent<TabbarChangedDetail>) => void;
|
||||||
/**
|
/**
|
||||||
* Set the position of the tabbar, relative to the content.
|
|
||||||
*/
|
|
||||||
'placement'?: TabbarPlacement;
|
|
||||||
/**
|
|
||||||
* The selected tab component
|
* The selected tab component
|
||||||
*/
|
*/
|
||||||
'selectedTab'?: string;
|
'selectedTab'?: string;
|
||||||
|
@ -114,7 +114,7 @@
|
|||||||
inline tab 4
|
inline tab 4
|
||||||
</ion-tab>
|
</ion-tab>
|
||||||
|
|
||||||
<ion-tab-bar>
|
<ion-tab-bar slot="bottom">
|
||||||
|
|
||||||
<ion-tab-button tab="tab-one">
|
<ion-tab-button tab="tab-one">
|
||||||
<ion-label>Plain List</ion-label>
|
<ion-label>Plain List</ion-label>
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
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.
|
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`:
|
In order to have a custom tab bar, it should be provided in user's markup as direct children of `ion-tabs`:
|
||||||
|
|
||||||
```html
|
```html
|
||||||
<style>
|
<style>
|
||||||
@ -17,7 +17,7 @@ In order to have a custom tabbar, it should be provided in user's markup as dire
|
|||||||
<ion-tab></ion-tab>
|
<ion-tab></ion-tab>
|
||||||
|
|
||||||
<!-- User provided ion-tab-bar that can be customized -->
|
<!-- User provided ion-tab-bar that can be customized -->
|
||||||
<ion-tab-bar color="dark" layout="icon-only">
|
<ion-tab-bar slot="bottom" color="dark" layout="icon-only">
|
||||||
</ion-tabs>
|
</ion-tabs>
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -30,9 +30,8 @@ In order to have a custom tabbar, it should be provided in user's markup as dire
|
|||||||
| Property | Attribute | Description | Type |
|
| 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` |
|
| `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"` |
|
| `layout` | `layout` | Set the layout of the text and icon in the tab bar. | `"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"` |
|
| `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` |
|
| `selectedTab` | `selected-tab` | The selected tab component | `string \| undefined` |
|
||||||
| `translucent` | `translucent` | If `true`, the tab bar will be translucent. Defaults to `false`. | `boolean` |
|
| `translucent` | `translucent` | If `true`, the tab bar will be translucent. Defaults to `false`. | `boolean` |
|
||||||
|
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
export type TabbarLayout = 'icon-top' | 'icon-start' | 'icon-end' | 'icon-bottom' | 'icon-hide' | 'label-hide';
|
export type TabbarLayout = 'icon-top' | 'icon-start' | 'icon-end' | 'icon-bottom' | 'icon-hide' | 'label-hide';
|
||||||
export type TabbarPlacement = 'top' | 'bottom';
|
|
||||||
|
|
||||||
export interface TabbarChangedDetail {
|
export interface TabbarChangedDetail {
|
||||||
tab?: string;
|
tab?: string;
|
||||||
|
@ -10,7 +10,6 @@
|
|||||||
|
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
order: 1;
|
|
||||||
|
|
||||||
width: auto;
|
width: auto;
|
||||||
|
|
||||||
@ -37,13 +36,11 @@
|
|||||||
--background-focused: #{current-color(shade)};
|
--background-focused: #{current-color(shade)};
|
||||||
}
|
}
|
||||||
|
|
||||||
:host(.placement-top) {
|
:host([slot="top"]) {
|
||||||
order: -1;
|
|
||||||
|
|
||||||
border-bottom: var(--border);
|
border-bottom: var(--border);
|
||||||
}
|
}
|
||||||
|
|
||||||
:host(.placement-bottom) {
|
:host([slot="bottom"]) {
|
||||||
padding-bottom: var(--ion-safe-area-bottom, 0);
|
padding-bottom: var(--ion-safe-area-bottom, 0);
|
||||||
|
|
||||||
border-top: var(--border);
|
border-top: var(--border);
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { Component, ComponentInterface, Element, Event, EventEmitter, Listen, Prop, QueueApi, State, Watch } from '@stencil/core';
|
import { Component, ComponentInterface, Element, Event, EventEmitter, Listen, Prop, QueueApi, State, Watch } from '@stencil/core';
|
||||||
|
|
||||||
import { Color, Mode, TabbarChangedDetail, TabbarLayout, TabbarPlacement } from '../../interface';
|
import { Color, Mode, TabbarChangedDetail, TabbarLayout } from '../../interface';
|
||||||
import { createColorClasses } from '../../utils/theme';
|
import { createColorClasses } from '../../utils/theme';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
@ -34,15 +34,10 @@ export class TabBar implements ComponentInterface {
|
|||||||
@Prop() color?: Color;
|
@Prop() color?: Color;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the layout of the text and icon in the tabbar.
|
* Set the layout of the text and icon in the tab bar.
|
||||||
*/
|
*/
|
||||||
@Prop() layout: TabbarLayout = 'icon-top';
|
@Prop() layout: TabbarLayout = 'icon-top';
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the position of the tabbar, relative to the content.
|
|
||||||
*/
|
|
||||||
@Prop() placement: TabbarPlacement = 'bottom';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The selected tab component
|
* The selected tab component
|
||||||
*/
|
*/
|
||||||
@ -69,7 +64,7 @@ export class TabBar implements ComponentInterface {
|
|||||||
|
|
||||||
@Listen('body:keyboardWillShow')
|
@Listen('body:keyboardWillShow')
|
||||||
protected onKeyboardWillShow() {
|
protected onKeyboardWillShow() {
|
||||||
if (this.placement === 'bottom') {
|
if (this.el.getAttribute('slot') === 'bottom') {
|
||||||
this.keyboardVisible = true;
|
this.keyboardVisible = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -79,15 +74,13 @@ export class TabBar implements ComponentInterface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
hostData() {
|
hostData() {
|
||||||
const { color, translucent, placement, keyboardVisible } = this;
|
const { color, translucent, keyboardVisible } = this;
|
||||||
return {
|
return {
|
||||||
role: 'tablist',
|
'role': 'tablist',
|
||||||
'aria-hidden': keyboardVisible ? 'true' : null,
|
'aria-hidden': keyboardVisible ? 'true' : null,
|
||||||
'slot': 'tabbar',
|
|
||||||
class: {
|
class: {
|
||||||
...createColorClasses(color),
|
...createColorClasses(color),
|
||||||
'tabbar-translucent': translucent,
|
'tabbar-translucent': translucent,
|
||||||
[`placement-${placement}`]: true,
|
|
||||||
'tabbar-hidden': keyboardVisible,
|
'tabbar-hidden': keyboardVisible,
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
```html
|
```html
|
||||||
<ion-tabs>
|
<ion-tabs>
|
||||||
|
|
||||||
<ion-tab-bar>
|
<ion-tab-bar slot="bottom">
|
||||||
<ion-tab-button tab="schedule" href="/app/tabs/(schedule:schedule)">
|
<ion-tab-button tab="schedule" href="/app/tabs/(schedule:schedule)">
|
||||||
<ion-icon name="calendar"></ion-icon>
|
<ion-icon name="calendar"></ion-icon>
|
||||||
<ion-label>Schedule</ion-label>
|
<ion-label>Schedule</ion-label>
|
||||||
|
@ -12,7 +12,7 @@ In order to do so, an `ion-tab-bar` should be provided as a direct child of `ion
|
|||||||
<ion-tab tab="home">Home Content</ion-tab>
|
<ion-tab tab="home">Home Content</ion-tab>
|
||||||
<ion-tab tab="settings">Settings Content</ion-tab>
|
<ion-tab tab="settings">Settings Content</ion-tab>
|
||||||
|
|
||||||
<ion-tab-bar>
|
<ion-tab-bar slot="bottom">
|
||||||
|
|
||||||
<ion-tab-button tab="home">
|
<ion-tab-button tab="home">
|
||||||
<ion-label>Home</ion-label>
|
<ion-label>Home</ion-label>
|
||||||
@ -30,6 +30,8 @@ In order to do so, an `ion-tab-bar` should be provided as a direct child of `ion
|
|||||||
|
|
||||||
Note that both `ion-tabs` and `ion-tab-bar` can be used as standalone elements. They don’t depend on each other to work, but they are usually used together in order to implement a tab-based navigation that feels like a native app.
|
Note that both `ion-tabs` and `ion-tab-bar` can be used as standalone elements. They don’t depend on each other to work, but they are usually used together in order to implement a tab-based navigation that feels like a native app.
|
||||||
|
|
||||||
|
`ion-tab-bar` always needs `slot="bottom"` in order to be projected into `ion-tabs` at the right place.
|
||||||
|
|
||||||
## The "tab" property
|
## The "tab" property
|
||||||
|
|
||||||
Each `ion-tab-button` will activate one of the tabs when tapped.
|
Each `ion-tab-button` will activate one of the tabs when tapped.
|
||||||
@ -68,7 +70,7 @@ Using tabs with Angular's router is fairly straight forward. The only additional
|
|||||||
```html
|
```html
|
||||||
|
|
||||||
<ion-tabs>
|
<ion-tabs>
|
||||||
<ion-tab-bar>
|
<ion-tab-bar slot="bottom">
|
||||||
<ion-tab-button tab="schedule" href="/app/tabs/(schedule:schedule)">
|
<ion-tab-button tab="schedule" href="/app/tabs/(schedule:schedule)">
|
||||||
<ion-icon name="calendar"></ion-icon>
|
<ion-icon name="calendar"></ion-icon>
|
||||||
<ion-label>Schedule</ion-label>
|
<ion-label>Schedule</ion-label>
|
||||||
|
@ -196,10 +196,11 @@ export class Tabs implements NavOutlet {
|
|||||||
|
|
||||||
render() {
|
render() {
|
||||||
return [
|
return [
|
||||||
|
<slot name="top"></slot>,
|
||||||
<div class="tabs-inner">
|
<div class="tabs-inner">
|
||||||
<slot></slot>
|
<slot></slot>
|
||||||
</div>,
|
</div>,
|
||||||
<slot name="tabbar"></slot>
|
<slot name="bottom"></slot>
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -69,7 +69,7 @@
|
|||||||
|
|
||||||
<ion-tab tab="tab-four" component="page-one"></ion-tab>
|
<ion-tab tab="tab-four" component="page-one"></ion-tab>
|
||||||
|
|
||||||
<ion-tab-bar>
|
<ion-tab-bar slot="bottom">
|
||||||
<ion-tab-button href="" tab="tab-one" class="e2eTabOneButton">
|
<ion-tab-button href="" tab="tab-one" class="e2eTabOneButton">
|
||||||
<ion-label>Tab One</ion-label>
|
<ion-label>Tab One</ion-label>
|
||||||
<ion-icon name="star"></ion-icon>
|
<ion-icon name="star"></ion-icon>
|
||||||
|
@ -55,7 +55,7 @@
|
|||||||
|
|
||||||
<ion-tab tab="page-one" disabled icon="chatboxes" component="page-one"></ion-tab>
|
<ion-tab tab="page-one" disabled icon="chatboxes" component="page-one"></ion-tab>
|
||||||
|
|
||||||
<ion-tab-bar placement="top">
|
<ion-tab-bar slot="top">
|
||||||
<ion-tab-button tab="star-tab">
|
<ion-tab-button tab="star-tab">
|
||||||
<ion-icon name="star"></ion-icon>
|
<ion-icon name="star"></ion-icon>
|
||||||
</ion-tab-button>
|
</ion-tab-button>
|
||||||
|
@ -54,7 +54,7 @@
|
|||||||
|
|
||||||
<ion-tab tab="tab-four" component="page-one"></ion-tab>
|
<ion-tab tab="tab-four" component="page-one"></ion-tab>
|
||||||
|
|
||||||
<ion-tab-bar>
|
<ion-tab-bar slot="bottom">
|
||||||
<ion-tab-button tab="tab-one">
|
<ion-tab-button tab="tab-one">
|
||||||
<ion-label>Plain List</ion-label>
|
<ion-label>Plain List</ion-label>
|
||||||
<ion-icon name="star"></ion-icon>
|
<ion-icon name="star"></ion-icon>
|
||||||
|
@ -23,7 +23,7 @@
|
|||||||
<div class="div-two" slot="not-initialized">Div Two</div>
|
<div class="div-two" slot="not-initialized">Div Two</div>
|
||||||
</ion-tab>
|
</ion-tab>
|
||||||
|
|
||||||
<ion-tab-bar>
|
<ion-tab-bar slot="bottom">
|
||||||
<ion-tab-button tab="tab-one">
|
<ion-tab-button tab="tab-one">
|
||||||
<ion-label>Tab One</ion-label>
|
<ion-label>Tab One</ion-label>
|
||||||
<ion-icon name="star"></ion-icon>
|
<ion-icon name="star"></ion-icon>
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
```html
|
```html
|
||||||
<ion-tabs>
|
<ion-tabs>
|
||||||
|
|
||||||
<ion-tab-bar>
|
<ion-tab-bar slot="bottom">
|
||||||
<ion-tab-button tab="schedule" href="/app/tabs/(schedule:schedule)">
|
<ion-tab-button tab="schedule" href="/app/tabs/(schedule:schedule)">
|
||||||
<ion-icon name="calendar"></ion-icon>
|
<ion-icon name="calendar"></ion-icon>
|
||||||
<ion-label>Schedule</ion-label>
|
<ion-label>Schedule</ion-label>
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
<ion-tab tab="tab-map" component="page-map"></ion-tab>
|
<ion-tab tab="tab-map" component="page-map"></ion-tab>
|
||||||
<ion-tab tab="tab-about" component="page-about"></ion-tab>
|
<ion-tab tab="tab-about" component="page-about"></ion-tab>
|
||||||
|
|
||||||
<ion-tab-bar>
|
<ion-tab-bar slot="bottom">
|
||||||
<ion-tab-button tab="tab-schedule">
|
<ion-tab-button tab="tab-schedule">
|
||||||
<ion-icon name="calendar"></ion-icon>
|
<ion-icon name="calendar"></ion-icon>
|
||||||
<ion-label>Schedule</ion-label>
|
<ion-label>Schedule</ion-label>
|
||||||
|
Reference in New Issue
Block a user