fix(ios): large title transition works properly in tabbed applications (#20555)

fixes #20482
This commit is contained in:
Liam DeBeasi
2020-02-24 11:38:50 -05:00
committed by GitHub
parent 6b2a929cd7
commit 71875417f2
3 changed files with 175 additions and 3 deletions

View File

@ -0,0 +1,10 @@
import { newE2EPage } from '@stencil/core/testing';
test('router: tabs', async () => {
const page = await newE2EPage({
url: '/src/components/router/test/tabs?ionic:_testing=true'
});
const compare = await page.compareScreenshot();
expect(compare).toMatchScreenshot();
});

View File

@ -0,0 +1,147 @@
<!DOCTYPE html>
<html dir="ltr">
<head>
<meta charset="UTF-8">
<title>Nav</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no">
<link href="../../../../../css/ionic.bundle.css" rel="stylesheet">
<link href="../../../../../scripts/testing/styles.css" rel="stylesheet">
<script src="../../../../../scripts/testing/scripts.js"></script>
<script nomodule src="../../../../../dist/ionic/ionic.js"></script>
<script type="module" src="../../../../../dist/ionic/ionic.esm.js"></script>
<script>
class PageTabOne extends HTMLElement {
connectedCallback() {
this.innerHTML = `
<ion-header>
<ion-toolbar>
<ion-title>Tab One</ion-title>
</ion-toolbar>
</ion-header>
<ion-content>
<ion-header collapse="condense">
<ion-toolbar>
<ion-title size="large">Tab One</ion-title>
</ion-toolbar>
</ion-header>
<div class="ion-padding">
<ion-button href="#/second-page">Go to Child</ion-button>
</div>
</ion-content>`;
}
}
class PageTabTwo extends HTMLElement {
connectedCallback() {
this.innerHTML = `
<ion-header>
<ion-toolbar>
<ion-title>Tab Two</ion-title>
</ion-toolbar>
</ion-header>
<ion-content>
<ion-header collapse="condense">
<ion-toolbar>
<ion-title size="large">Tab Two</ion-title>
</ion-toolbar>
</ion-header>
<div class="ion-padding">
<ion-button href="#/second-page">Go to Child</ion-button>
</div>
</ion-content>`;
}
}
class PageTwo extends HTMLElement {
connectedCallback() {
this.innerHTML = `
<ion-header>
<ion-toolbar>
<ion-buttons>
<ion-back-button></ion-back-button>
</ion-buttons>
<ion-title>Child</ion-title>
</ion-toolbar>
</ion-header>
<ion-content>
<ion-header collapse="condense">
<ion-toolbar>
<ion-title size="large">Child</ion-title>
</ion-toolbar>
</ion-header>
</ion-content>`;
}
}
class TabOne extends HTMLElement {
connectedCallback() {
this.innerHTML = `<ion-nav></ion-nav>`;
}
}
class TabTwo extends HTMLElement {
connectedCallback() {
this.innerHTML = `<ion-nav></ion-nav>`;
}
}
class TabsPage extends HTMLElement {
connectedCallback() {
this.innerHTML = `
<ion-tabs>
<ion-tab tab="tab-one" component="tab-one"></ion-tab>
<ion-tab tab="tab-two" component="tab-two"></ion-tab>
<ion-tab-bar slot="bottom">
<ion-tab-button tab="tab-one">
<ion-label>Tab One</ion-label>
<ion-icon name="star"></ion-icon>
</ion-tab-button>
<ion-tab-button tab="tab-two">
<ion-label>Tab Two</ion-label>
<ion-icon name="globe"></ion-icon>
</ion-tab-button>
</ion-tab-bar>
</ion-tabs>
`;
}
}
customElements.define('page-tab-one', PageTabOne);
customElements.define('page-tab-two', PageTabTwo);
customElements.define('page-two', PageTwo);
customElements.define('tabs-page', TabsPage);
customElements.define('tab-one', TabOne);
customElements.define('tab-two', TabTwo);
</script>
</head>
<body>
<ion-app>
<ion-router>
<ion-route url="/" component="tabs-page">
<ion-route url="/one" component="tab-one">
<ion-route component="page-tab-one"></ion-route>
</ion-route>
<ion-route url="/two" component="tab-two">
<ion-route component="page-tab-two"></ion-route>
</ion-route>
</ion-route>
<ion-route url="/second-page" component="page-two"></ion-route>
</ion-router>
<ion-nav></ion-nav>
</ion-app>
</body>
</html>

View File

@ -13,11 +13,27 @@ export const shadow = <T extends Element>(el: T): ShadowRoot | T => {
};
const getLargeTitle = (refEl: any) => {
return refEl.querySelector('ion-header:not(.header-collapse-condense-inactive) ion-title[size=large]');
const tabs = (refEl.tagName === 'ION-TABS') ? refEl : refEl.querySelector('ion-tabs');
const query = 'ion-header:not(.header-collapse-condense-inactive) ion-title[size=large]';
if (tabs != null) {
const activeTab = tabs.querySelector('ion-tab:not(.tab-hidden), .ion-page:not(.ion-page-hidden)');
return activeTab.querySelector(query);
}
return refEl.querySelector(query);
};
const getBackButton = (refEl: any, backDirection: boolean) => {
const buttonsList = refEl.querySelectorAll('ion-buttons');
const tabs = (refEl.tagName === 'ION-TABS') ? refEl : refEl.querySelector('ion-tabs');
let buttonsList = [];
if (tabs != null) {
const activeTab = tabs.querySelector('ion-tab:not(.tab-hidden), .ion-page:not(.ion-page-hidden)');
buttonsList = activeTab.querySelectorAll('ion-buttons');
} else {
buttonsList = refEl.querySelectorAll('ion-buttons');
}
for (const buttons of buttonsList) {
const parentHeader = buttons.closest('ion-header');
@ -277,7 +293,6 @@ export const iosTransitionAnimation = (navEl: HTMLElement, opts: TransitionOptio
const enteringContentHasLargeTitle = enteringEl.querySelector('ion-header.header-collapse-condense');
const { forward, backward } = createLargeTitleTransition(rootAnimation, isRTL, backDirection, enteringEl, leavingEl);
enteringToolBarEls.forEach(enteringToolBarEl => {
const enteringToolBar = createAnimation();
enteringToolBar.addElement(enteringToolBarEl);