mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-08-19 11:41:20 +08:00
fix(tabs): get the tabbar layout working with shadow DOM (#15113)
- gets the `tabbarLayout` property working - update badge position based on tabs layout - fix the transforms for icon/text and icon size fixes #14611
This commit is contained in:
@ -39,27 +39,3 @@
|
||||
.tab-button-icon::before {
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
.layout-icon-end .tab-button-ios .tab-button-text,
|
||||
.layout-icon-start .tab-button-ios .tab-button-text,
|
||||
.layout-icon-hide .tab-button-ios .tab-button-text {
|
||||
@include margin(2px, 0);
|
||||
|
||||
font-size: 14px;
|
||||
|
||||
line-height: 1.1;
|
||||
}
|
||||
|
||||
.layout-icon-end .tab-button-ios ion-icon,
|
||||
.layout-icon-start .tab-button-ios ion-icon {
|
||||
@include margin(2px, null, 1px, null);
|
||||
|
||||
min-width: 24px;
|
||||
height: 26px;
|
||||
|
||||
font-size: 24px;
|
||||
}
|
||||
|
||||
.layout-label-hide .tab-button-ios ion-icon {
|
||||
@include margin(0);
|
||||
}
|
||||
|
@ -8,6 +8,7 @@
|
||||
--color: #{$tab-button-md-text-color};
|
||||
--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;
|
||||
|
||||
@ -27,6 +28,8 @@
|
||||
@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;
|
||||
|
||||
font-size: $tab-button-md-font-size;
|
||||
@ -35,7 +38,7 @@
|
||||
}
|
||||
|
||||
:host(.tab-selected) .tab-button-text {
|
||||
transform: $tab-button-md-text-transform-active;
|
||||
--label-transform: #{$tab-button-md-text-transform-active};
|
||||
|
||||
transition: $tab-button-md-text-transition;
|
||||
}
|
||||
@ -49,45 +52,10 @@
|
||||
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;
|
||||
}
|
||||
|
||||
// Tab layout: icon-top, icon-only, label-only
|
||||
:host(.tab-selected) .tab-button-icon {
|
||||
@include transform(translate3d($tab-button-md-icon-transform-x-active, $tab-button-md-icon-transform-y-active, $tab-button-md-icon-transform-z-active));
|
||||
}
|
||||
|
||||
|
||||
// Material Design Tab with Icon or Title only
|
||||
// --------------------------------------------------
|
||||
|
||||
// Tab layout: icon-end
|
||||
.layout-icon-end .tab-button-md.tab-selected .tab-button-icon {
|
||||
@include transform(translate3d($tab-button-md-icon-right-transform-x-active, $tab-button-md-icon-right-transform-y-active, $tab-button-md-icon-right-transform-z-active));
|
||||
}
|
||||
|
||||
// Tab layout: icon-bottom
|
||||
.layout-icon-bottom .tab-button-md.tab-selected .tab-button-icon {
|
||||
@include transform(translate3d($tab-button-md-icon-bottom-transform-x-active, $tab-button-md-icon-bottom-transform-y-active, $tab-button-md-icon-bottom-transform-z-active));
|
||||
}
|
||||
|
||||
// Tab layout: icon-start
|
||||
.layout-icon-start .tab-button-md.tab-selected .tab-button-icon {
|
||||
@include transform(translate3d($tab-button-md-icon-left-transform-x-active, $tab-button-md-icon-left-transform-y-active, $tab-button-md-icon-left-transform-z-active));
|
||||
}
|
||||
|
||||
.layout-icon-top .tab-button-md .has-icon .tab-button-text {
|
||||
@include margin(null, null, -2px, null);
|
||||
}
|
||||
|
||||
.layout-icon-bottom .tab-button-md .tab-button-text {
|
||||
@include transform-origin(center, top);
|
||||
@include margin(-2px, null, null, null);
|
||||
}
|
||||
|
||||
.layout-icon-hide .tab-button-md,
|
||||
.layout-label-hide .tab-button-md {
|
||||
justify-content: center;
|
||||
}
|
||||
|
@ -55,49 +55,25 @@ $tab-button-md-text-capitalization: none !default;
|
||||
$tab-button-md-text-transform-active: scale3d($tab-button-md-font-size-active / $tab-button-md-font-size, $tab-button-md-font-size-active / $tab-button-md-font-size, 1) !default;
|
||||
|
||||
/// @prop - Text transition for the tab button text
|
||||
$tab-button-md-text-transition: transform .3s ease-in-out !default;
|
||||
$tab-button-md-text-transition: transform .1s ease-in-out !default;
|
||||
|
||||
/// @prop - Transform x for the active tab button icon when the layout is icon-top, icon-only, or label-only
|
||||
$tab-button-md-icon-transform-x-active: 0 !default;
|
||||
/// @prop - Transform for the active tab button icon when the layout is icon-top, icon-only, or label-only
|
||||
$tab-button-md-icon-transform-active: translate3d(0, -2px, 0) !default;
|
||||
|
||||
/// @prop - Transform y for the active tab button icon when the layout is icon-top, icon-only, or label-only
|
||||
$tab-button-md-icon-transform-y-active: -2px !default;
|
||||
/// @prop - Transform for the active tab button icon when the layout is icon-right
|
||||
$tab-button-md-icon-right-transform-active: translate3d(6px, 0, 0) !default;
|
||||
|
||||
/// @prop - Transform z for the active tab button icon when the layout is icon-top, icon-only, or label-only
|
||||
$tab-button-md-icon-transform-z-active: 0 !default;
|
||||
/// @prop - Transform for the active tab button icon when the layout is icon-bottom
|
||||
$tab-button-md-icon-bottom-transform-active: translate3d(0, 2px, 0) !default;
|
||||
|
||||
/// @prop - Transform x for the active tab button icon when the layout is icon-right
|
||||
$tab-button-md-icon-right-transform-x-active: 2px !default;
|
||||
|
||||
/// @prop - Transform y for the active tab button icon when the layout is icon-right
|
||||
$tab-button-md-icon-right-transform-y-active: 0 !default;
|
||||
|
||||
/// @prop - Transform z for the active tab button icon when the layout is icon-right
|
||||
$tab-button-md-icon-right-transform-z-active: 0 !default;
|
||||
|
||||
/// @prop - Transform x for the active tab button icon when the layout is icon-bottom
|
||||
$tab-button-md-icon-bottom-transform-x-active: 0 !default;
|
||||
|
||||
/// @prop - Transform y for the active tab button icon when the layout is icon-bottom
|
||||
$tab-button-md-icon-bottom-transform-y-active: 2px !default;
|
||||
|
||||
/// @prop - Transform z for the active tab button icon when the layout is icon-bottom
|
||||
$tab-button-md-icon-bottom-transform-z-active: 0 !default;
|
||||
|
||||
/// @prop - Transform x for the active tab button icon when the layout is icon-left
|
||||
$tab-button-md-icon-left-transform-x-active: -2px !default;
|
||||
|
||||
/// @prop - Transform y for the active tab button icon when the layout is icon-left
|
||||
$tab-button-md-icon-left-transform-y-active: 0 !default;
|
||||
|
||||
/// @prop - Transform z for the active tab button icon when the layout is icon-left
|
||||
$tab-button-md-icon-left-transform-z-active: 0 !default;
|
||||
/// @prop - Transform for the active tab button icon when the layout is icon-left
|
||||
$tab-button-md-icon-left-transform-active: translate3d(-6px, 0, 0) !default;
|
||||
|
||||
/// @prop - Text transition for the tab button icon
|
||||
$tab-button-md-icon-transition: transform .3s ease-in-out !default;
|
||||
$tab-button-md-icon-transition: transform .1s ease-in-out !default;
|
||||
|
||||
/// @prop - Size of the tab button icon
|
||||
$tab-button-md-icon-size: 24px !default;
|
||||
$tab-button-md-icon-size: 22px !default;
|
||||
|
||||
/// @prop - Opacity of the inactive tab button
|
||||
$tab-button-md-opacity: .7 !default;
|
||||
|
@ -50,9 +50,9 @@ a {
|
||||
|
||||
display: flex;
|
||||
|
||||
flex-direction: column;
|
||||
flex-direction: var(--flex-direction, column);
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
justify-content: var(--justify-content, flex-start);
|
||||
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
@ -79,10 +79,29 @@ a {
|
||||
opacity: .4;
|
||||
}
|
||||
|
||||
.tab-button-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-button-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-button-text,
|
||||
.tab-button-icon {
|
||||
display: none;
|
||||
|
||||
align-self: center;
|
||||
|
||||
min-width: 26px;
|
||||
@ -96,18 +115,13 @@ a {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
:host(.has-icon) .tab-button-icon,
|
||||
:host(.has-label) .tab-button-text {
|
||||
display: block;
|
||||
}
|
||||
|
||||
:host(.has-label-only) .tab-button-text {
|
||||
white-space: normal;
|
||||
}
|
||||
|
||||
:host(.has-icon-only) .tab-button-native,
|
||||
:host(.has-label-only) .tab-button-native {
|
||||
justify-content: center;
|
||||
--justify-content: center;
|
||||
}
|
||||
|
||||
|
||||
@ -116,7 +130,7 @@ a {
|
||||
|
||||
.tab-badge {
|
||||
@include position(6%, 4%, null, null); // 4% fallback
|
||||
@include position(null, calc(50% - 50px), null, null);
|
||||
@include position(null, var(--badge-end, calc(50% - 30px)), null, null);
|
||||
@include padding(1px, 6px);
|
||||
|
||||
box-sizing: border-box;
|
||||
@ -130,42 +144,14 @@ a {
|
||||
line-height: 16px;
|
||||
}
|
||||
|
||||
:host(.has-icon) .tab-badge {
|
||||
@include position(null, calc(50% - 30px), null, null);
|
||||
:host(.has-label-only) .tab-badge {
|
||||
--badge-end: #{calc(50% - 50px)};
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Tab Badges
|
||||
// --------------------------------------------------
|
||||
|
||||
.layout-icon-start .tab-button {
|
||||
flex-direction: row;
|
||||
:host(.has-icon-only) .tab-badge {
|
||||
--badge-end: #{calc(50% - 30px)};
|
||||
}
|
||||
|
||||
.layout-icon-end .tab-button {
|
||||
flex-direction: row-reverse;
|
||||
}
|
||||
|
||||
.layout-icon-bottom .tab-button {
|
||||
flex-direction: column-reverse;
|
||||
}
|
||||
|
||||
.layout-icon-start .tab-button,
|
||||
.layout-icon-end .tab-button,
|
||||
.layout-icon-hide .tab-button,
|
||||
.layout-label-hide .tab-button {
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.layout-icon-hide .tab-button-icon,
|
||||
.layout-label-hide .tab-button-text {
|
||||
display: none;
|
||||
}
|
||||
|
||||
|
||||
.layout-icon-bottom .tab-badge,
|
||||
.layout-icon-start .tab-badge,
|
||||
.layout-icon-end .tab-badge {
|
||||
@include position(null, calc(50% - 50px), null, null);
|
||||
}
|
||||
:host(.tab-selected) .tab-button-icon {
|
||||
transform: var(--icon-transform-selected);
|
||||
}
|
@ -75,7 +75,7 @@ export class TabButton {
|
||||
{ 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}/> }
|
||||
{ mode === 'md' && <ion-ripple-effect tapClick={true}></ion-ripple-effect> }
|
||||
</a>
|
||||
];
|
||||
}
|
||||
|
@ -32,3 +32,28 @@
|
||||
backdrop-filter: $tabbar-ios-translucent-filter;
|
||||
}
|
||||
|
||||
|
||||
// iOS Tabbar Layout
|
||||
// --------------------------------------------------
|
||||
|
||||
:host(.layout-icon-end) ion-tab-button,
|
||||
:host(.layout-icon-start) ion-tab-button,
|
||||
:host(.layout-icon-hide) ion-tab-button {
|
||||
--label-margin-top: 2px;
|
||||
--label-margin-bottom: 2px;
|
||||
--label-font-size: 14px;
|
||||
--label-line-height: 1.1;
|
||||
}
|
||||
|
||||
:host(.layout-icon-end) ion-tab-button,
|
||||
:host(.layout-icon-start) ion-tab-button {
|
||||
--icon-margin-top: 2px;
|
||||
--icon-margin-bottom: 1px;
|
||||
--icon-min-width: 24px;
|
||||
--icon-height: 26px;
|
||||
--icon-font-size: 24px;
|
||||
}
|
||||
|
||||
:host(.layout-label-hide) ion-tab-button {
|
||||
--icon-margin: 0;
|
||||
}
|
@ -13,9 +13,23 @@
|
||||
contain: strict;
|
||||
}
|
||||
|
||||
// Material Design Tabbar Layout
|
||||
// --------------------------------------------------
|
||||
|
||||
// TODO: REVIEW
|
||||
:host(.placement-top) .tab-button.tab-selected .tab-button-icon,
|
||||
:host(.placement-top) .tab-button.tab-selected .tab-button-text {
|
||||
transform: inherit;
|
||||
:host(.layout-icon-top) ion-tab-button {
|
||||
--label-margin-bottom: -2px;
|
||||
}
|
||||
|
||||
:host(.layout-icon-end) ion-tab-button {
|
||||
--icon-transform-selected: #{$tab-button-md-icon-right-transform-active};
|
||||
}
|
||||
|
||||
:host(.layout-icon-bottom) ion-tab-button {
|
||||
--label-margin-top: -2px;
|
||||
--label-transform: transform-origin(center, top);
|
||||
--icon-transform-selected: #{$tab-button-md-icon-bottom-transform-active};
|
||||
}
|
||||
|
||||
:host(.layout-icon-start) ion-tab-button {
|
||||
--icon-transform-selected: #{$tab-button-md-icon-left-transform-active};
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
@import "../../themes/ionic.globals.md";
|
||||
@import "../tab-button/tab-button.md.vars";
|
||||
|
||||
// Material Design Tabs
|
||||
// --------------------------------------------------
|
||||
|
@ -70,3 +70,45 @@
|
||||
:host(.placement-bottom) .tabbar-highlight {
|
||||
top: 0;
|
||||
}
|
||||
|
||||
|
||||
// Tab Layout
|
||||
// --------------------------------------------------
|
||||
|
||||
:host(.layout-icon-start) ion-tab-button {
|
||||
--flex-direction: row;
|
||||
}
|
||||
|
||||
:host(.layout-icon-end) ion-tab-button {
|
||||
--flex-direction: row-reverse;
|
||||
}
|
||||
|
||||
:host(.layout-icon-bottom) ion-tab-button {
|
||||
--flex-direction: column-reverse;
|
||||
}
|
||||
|
||||
:host(.layout-icon-start) ion-tab-button,
|
||||
:host(.layout-icon-end) ion-tab-button,
|
||||
:host(.layout-icon-hide) ion-tab-button,
|
||||
:host(.layout-label-hide) ion-tab-button {
|
||||
--justify-content: center;
|
||||
}
|
||||
|
||||
:host(.layout-icon-hide) ion-tab-button {
|
||||
--icon-display: none;
|
||||
}
|
||||
|
||||
:host(.layout-label-hide) ion-tab-button {
|
||||
--label-display: none;
|
||||
}
|
||||
|
||||
:host(.layout-icon-top) ion-tab-button,
|
||||
:host(.layout-icon-bottom) ion-tab-button {
|
||||
--badge-end: #{calc(50% - 30px)};
|
||||
}
|
||||
|
||||
:host(.layout-icon-hide) ion-tab-button,
|
||||
:host(.layout-icon-start) ion-tab-button,
|
||||
:host(.layout-icon-end) ion-tab-button {
|
||||
--badge-end: #{calc(50% - 50px)};
|
||||
}
|
||||
|
@ -15,7 +15,7 @@
|
||||
<!-- Default -->
|
||||
<ion-tabs>
|
||||
<ion-tab label="Recents"></ion-tab>
|
||||
<ion-tab label="Favorites"></ion-tab>
|
||||
<ion-tab label="Favorites" badge="6"></ion-tab>
|
||||
<ion-tab label="Settings"></ion-tab>
|
||||
</ion-tabs>
|
||||
|
||||
@ -31,7 +31,7 @@
|
||||
<!-- Icons on top of text -->
|
||||
<ion-tabs selected-index="2" color="secondary">
|
||||
<ion-tab label="Location" icon="navigate"></ion-tab>
|
||||
<ion-tab label="Favorites" icon="star"></ion-tab>
|
||||
<ion-tab label="Favorites" badge="6" icon="heart"></ion-tab>
|
||||
<ion-tab label="Radio" icon="musical-notes"></ion-tab>
|
||||
</ion-tabs>
|
||||
|
||||
@ -39,7 +39,7 @@
|
||||
<!-- Icons below text -->
|
||||
<ion-tabs tabbar-layout="icon-bottom" selected-index="1" color="dark">
|
||||
<ion-tab label="Recents" icon="call"></ion-tab>
|
||||
<ion-tab label="Favorites" icon="heart"></ion-tab>
|
||||
<ion-tab label="Favorites" badge="6" icon="heart"></ion-tab>
|
||||
<ion-tab label="Settings" icon="settings"></ion-tab>
|
||||
</ion-tabs>
|
||||
|
||||
@ -47,7 +47,7 @@
|
||||
<!-- Icons right of text -->
|
||||
<ion-tabs tabbar-layout="icon-end" selected-index="0" color="danger">
|
||||
<ion-tab label="Recents" icon="call"></ion-tab>
|
||||
<ion-tab label="Favorites" icon="heart"></ion-tab>
|
||||
<ion-tab label="Favorites" badge="6" icon="heart"></ion-tab>
|
||||
<ion-tab label="Settings" icon="settings"></ion-tab>
|
||||
</ion-tabs>
|
||||
|
||||
@ -55,7 +55,7 @@
|
||||
<!-- Icons left of text -->
|
||||
<ion-tabs tabbar-layout="icon-start" color="light">
|
||||
<ion-tab label="Recents" icon="call"></ion-tab>
|
||||
<ion-tab label="Favorites" icon="heart"></ion-tab>
|
||||
<ion-tab label="Favorites" badge="6" badge-color="danger" icon="heart"></ion-tab>
|
||||
<ion-tab label="Settings" icon="settings"></ion-tab>
|
||||
</ion-tabs>
|
||||
|
||||
@ -63,7 +63,7 @@
|
||||
<!-- No icons -->
|
||||
<ion-tabs tabbar-layout="icon-hide" color="primary">
|
||||
<ion-tab label="Recents" icon="call"></ion-tab>
|
||||
<ion-tab label="Favorites" icon="heart"></ion-tab>
|
||||
<ion-tab label="Favorites" badge="6" badge-color="danger" icon="heart"></ion-tab>
|
||||
<ion-tab label="Settings" icon="settings"></ion-tab>
|
||||
</ion-tabs>
|
||||
|
||||
@ -71,7 +71,7 @@
|
||||
<!-- No label -->
|
||||
<ion-tabs tabbar-layout="label-hide" color="secondary">
|
||||
<ion-tab label="Recents" icon="call"></ion-tab>
|
||||
<ion-tab label="Favorites" icon="heart"></ion-tab>
|
||||
<ion-tab label="Favorites" badge="6" badge-color="danger" icon="heart"></ion-tab>
|
||||
<ion-tab label="Settings" icon="settings"></ion-tab>
|
||||
</ion-tabs>
|
||||
|
||||
|
Reference in New Issue
Block a user