chore(header): finalize collapse API (#19276)

* make requested changes

* add e2e

* add RTL support

* fix typo

* add info on how to make collapsable title

* add usage examples

* fix typo

* fix another typo

* fix typos

* update usage

* fix alpha order

* update api

* add class to collapse buttons

* merge

* update

* change back to collapse

* remove platform specific class

* update docs

* run build

* update api again

* run build
This commit is contained in:
Liam DeBeasi
2019-09-24 18:00:03 +01:00
committed by GitHub
parent 1e081c0a22
commit e90e960294
26 changed files with 873 additions and 157 deletions

View File

@ -400,7 +400,7 @@ ion-grid,css-prop,--ion-grid-width-xl
ion-grid,css-prop,--ion-grid-width-xs
ion-header,none
ion-header,prop,collapse,boolean,false,false,false
ion-header,prop,collapse,"condense" | undefined,undefined,false,false
ion-header,prop,mode,"ios" | "md",undefined,false,false
ion-header,prop,translucent,boolean,false,false,false

View File

@ -391,7 +391,7 @@ export namespace Components {
}
interface IonButtons {
/**
* If true, buttons will disappear when its parent toolbar has fully collapsed if the toolbar is not the first toolbar. If the toolbar is the first toolbar, the buttons will be hidden and will only be shown once all toolbars have fully collapsed. Only applies in `ios` mode with `collapse` set to `true` on `ion-header`
* If true, buttons will disappear when its parent toolbar has fully collapsed if the toolbar is not the first toolbar. If the toolbar is the first toolbar, the buttons will be hidden and will only be shown once all toolbars have fully collapsed. Only applies in `ios` mode with `collapse` set to `true` on `ion-header`. Typically used for [Collapsible Large Titles](https://ionicframework.com/docs/api/title#collapsible-large-titles)
*/
'collapse': boolean;
}
@ -871,9 +871,9 @@ export namespace Components {
}
interface IonHeader {
/**
* If `true`, the header will collapse on scroll of the content. Only applies in `ios` mode.
* Describes the scroll effect that will be applied to the header `condense` only applies in iOS mode. Typically used for [Collapsible Large Titles](https://ionicframework.com/docs/api/title#collapsible-large-titles)
*/
'collapse': boolean;
'collapse'?: 'condense';
/**
* The mode determines which platform styles to use.
*/
@ -3898,7 +3898,7 @@ declare namespace LocalJSX {
}
interface IonButtons extends JSXBase.HTMLAttributes<HTMLIonButtonsElement> {
/**
* If true, buttons will disappear when its parent toolbar has fully collapsed if the toolbar is not the first toolbar. If the toolbar is the first toolbar, the buttons will be hidden and will only be shown once all toolbars have fully collapsed. Only applies in `ios` mode with `collapse` set to `true` on `ion-header`
* If true, buttons will disappear when its parent toolbar has fully collapsed if the toolbar is not the first toolbar. If the toolbar is the first toolbar, the buttons will be hidden and will only be shown once all toolbars have fully collapsed. Only applies in `ios` mode with `collapse` set to `true` on `ion-header`. Typically used for [Collapsible Large Titles](https://ionicframework.com/docs/api/title#collapsible-large-titles)
*/
'collapse'?: boolean;
}
@ -4390,9 +4390,9 @@ declare namespace LocalJSX {
}
interface IonHeader extends JSXBase.HTMLAttributes<HTMLIonHeaderElement> {
/**
* If `true`, the header will collapse on scroll of the content. Only applies in `ios` mode.
* Describes the scroll effect that will be applied to the header `condense` only applies in iOS mode. Typically used for [Collapsible Large Titles](https://ionicframework.com/docs/api/title#collapsible-large-titles)
*/
'collapse'?: boolean;
'collapse'?: 'condense';
/**
* The mode determines which platform styles to use.
*/

View File

@ -20,13 +20,21 @@ export class Buttons implements ComponentInterface {
* only be shown once all toolbars have fully collapsed.
*
* Only applies in `ios` mode with `collapse` set to
* `true` on `ion-header`
* `true` on `ion-header`.
*
* Typically used for [Collapsible Large Titles](https://ionicframework.com/docs/api/title#collapsible-large-titles)
*/
@Prop() collapse = false;
render() {
const mode = getIonMode(this);
return (
<Host class={getIonMode(this)}>
<Host
class={{
[mode]: true,
['buttons-collapse']: this.collapse
}}
>
</Host>
);
}

View File

@ -55,6 +55,15 @@ The `<ion-buttons>` element can be positioned inside of the toolbar using a name
<ion-menu-button autoHide="false"></ion-menu-button>
</ion-buttons>
</ion-toolbar>
<ion-toolbar>
<ion-buttons collapse="true">
<ion-button>
<ion-icon slot="icon-only" name="star"></ion-icon>
</ion-button>
</ion-buttons>
<ion-title>Collapsible Buttons</ion-title>
</ion-toolbar>
```
@ -100,6 +109,15 @@ The `<ion-buttons>` element can be positioned inside of the toolbar using a name
</ion-menu-toggle>
</ion-buttons>
</ion-toolbar>
<ion-toolbar>
<ion-buttons collapse="true">
<ion-button>
<ion-icon slot="icon-only" name="star"></ion-icon>
</ion-button>
</ion-buttons>
<ion-title>Collapsible Buttons</ion-title>
</ion-toolbar>
```
@ -155,6 +173,15 @@ export const ButtonsExample: React.FC = () => (
<IonMenuButton autoHide={false} />
</IonButtons>
</IonToolbar>
<IonToolbar>
<IonButtons collapse="true">
<IonButton>
<IonIcon slot="icon-only" name="star" />
</IonButton>
</IonButtons>
<IonTitle>Collapsible Buttons</IonTitle>
</IonToolbar>
</IonContent>
);
```
@ -199,6 +226,15 @@ export const ButtonsExample: React.FC = () => (
<ion-menu-button autoHide="false"></ion-menu-button>
</ion-buttons>
</ion-toolbar>
<ion-toolbar>
<ion-buttons collapse="true">
<ion-button>
<ion-icon slot="icon-only" name="star"></ion-icon>
</ion-button>
</ion-buttons>
<ion-title>Collapsible Buttons</ion-title>
</ion-toolbar>
</template>
```
@ -206,9 +242,9 @@ export const ButtonsExample: React.FC = () => (
## Properties
| Property | Attribute | Description | Type | Default |
| ---------- | ---------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------- | ------- |
| `collapse` | `collapse` | If true, buttons will disappear when its parent toolbar has fully collapsed if the toolbar is not the first toolbar. If the toolbar is the first toolbar, the buttons will be hidden and will only be shown once all toolbars have fully collapsed. Only applies in `ios` mode with `collapse` set to `true` on `ion-header` | `boolean` | `false` |
| Property | Attribute | Description | Type | Default |
| ---------- | ---------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------- | ------- |
| `collapse` | `collapse` | If true, buttons will disappear when its parent toolbar has fully collapsed if the toolbar is not the first toolbar. If the toolbar is the first toolbar, the buttons will be hidden and will only be shown once all toolbars have fully collapsed. Only applies in `ios` mode with `collapse` set to `true` on `ion-header`. Typically used for [Collapsible Large Titles](https://ionicframework.com/docs/api/title#collapsible-large-titles) | `boolean` | `false` |
----------------------------------------------

View File

@ -34,4 +34,13 @@
<ion-menu-button autoHide="false"></ion-menu-button>
</ion-buttons>
</ion-toolbar>
<ion-toolbar>
<ion-buttons collapse="true">
<ion-button>
<ion-icon slot="icon-only" name="star"></ion-icon>
</ion-button>
</ion-buttons>
<ion-title>Collapsible Buttons</ion-title>
</ion-toolbar>
```

View File

@ -38,4 +38,13 @@
</ion-menu-toggle>
</ion-buttons>
</ion-toolbar>
<ion-toolbar>
<ion-buttons collapse="true">
<ion-button>
<ion-icon slot="icon-only" name="star"></ion-icon>
</ion-button>
</ion-buttons>
<ion-title>Collapsible Buttons</ion-title>
</ion-toolbar>
```

View File

@ -48,6 +48,15 @@ export const ButtonsExample: React.FC = () => (
<IonMenuButton autoHide={false} />
</IonButtons>
</IonToolbar>
<IonToolbar>
<IonButtons collapse="true">
<IonButton>
<IonIcon slot="icon-only" name="star" />
</IonButton>
</IonButtons>
<IonTitle>Collapsible Buttons</IonTitle>
</IonToolbar>
</IonContent>
);
```

View File

@ -35,5 +35,14 @@
<ion-menu-button autoHide="false"></ion-menu-button>
</ion-buttons>
</ion-toolbar>
<ion-toolbar>
<ion-buttons collapse="true">
<ion-button>
<ion-icon slot="icon-only" name="star"></ion-icon>
</ion-button>
</ion-buttons>
<ion-title>Collapsible Buttons</ion-title>
</ion-toolbar>
</template>
```

View File

@ -25,26 +25,26 @@
// iOS Header - Collapse
// --------------------------------------------------
.header-collapse-ios {
.header-collapse-condense {
z-index: 9;
}
.header-collapse-ios ion-toolbar {
.header-collapse-condense ion-toolbar {
position: sticky;
top: 0;
}
.header-collapse-ios ion-toolbar:first-child {
.header-collapse-condense ion-toolbar:first-child {
padding-top: 7px;
z-index: 1;
}
.header-collapse-ios ion-toolbar {
.header-collapse-condense ion-toolbar {
z-index: 0;
}
.header-collapse-ios ion-toolbar ion-searchbar {
.header-collapse-condense ion-toolbar ion-searchbar {
height: 48px;
padding-top: 0px;
@ -61,13 +61,13 @@ ion-toolbar.in-toolbar ion-buttons {
* on an element in a scrollable container while scrolling
* causes the scroll position to jump to the top
*/
.header-collapse-ios ion-toolbar ion-title,
.header-collapse-ios ion-toolbar ion-buttons {
.header-collapse-condense ion-toolbar ion-title,
.header-collapse-condense ion-toolbar ion-buttons {
transition: none;
}
.header-collapse-ios-inactive ion-toolbar.in-toolbar ion-title,
.header-collapse-ios-inactive ion-toolbar.in-toolbar ion-buttons[collapse] {
.header-collapse-condense-inactive ion-toolbar.in-toolbar ion-title,
.header-collapse-condense-inactive ion-toolbar.in-toolbar ion-buttons.buttons-collapse {
opacity: 0;
pointer-events: none;
}

View File

@ -26,6 +26,6 @@
display: none;
}
.header-collapse-md {
.header-collapse-condense {
display: none;
}

View File

@ -15,16 +15,20 @@ import { cloneElement, createHeaderIndex, handleContentScroll, handleToolbarInte
})
export class Header implements ComponentInterface {
private collapsibleHeaderInitialized = false;
private scrollEl?: HTMLElement;
private contentScrollCallback?: any;
private intersectionObserver?: any;
@Element() el!: HTMLElement;
/**
* If `true`, the header will collapse on scroll of the content.
* Only applies in `ios` mode.
* Describes the scroll effect that will be applied to the header
* `condense` only applies in iOS mode.
*
* Typically used for [Collapsible Large Titles](https://ionicframework.com/docs/api/title#collapsible-large-titles)
*/
@Prop() collapse = false;
@Prop() collapse?: 'condense';
/**
* If `true`, the header will be translucent.
@ -37,32 +41,56 @@ export class Header implements ComponentInterface {
@Prop() translucent = false;
async componentDidLoad() {
// Determine if the header can collapse
const canCollapse = (this.collapse && getIonMode(this) === 'ios') ? this.collapse : false;
await this.checkCollapsibleHeader();
}
const tabs = this.el.closest('ion-tabs');
const page = this.el.closest('ion-app,ion-page,.ion-page,page-inner');
const contentEl = tabs ? tabs.querySelector('ion-content') : page!.querySelector('ion-content');
if (canCollapse) {
await this.setupCollapsableHeader(contentEl, (tabs) ? tabs : page!);
}
async componentDidUpdate() {
await this.checkCollapsibleHeader();
}
componentDidUnload() {
if (this.scrollEl && this.contentScrollCallback) {
this.scrollEl.removeEventListener('scroll', this.contentScrollCallback);
this.destroyCollapsibleHeader();
}
private async checkCollapsibleHeader() {
// Determine if the header can collapse
const hasCollapse = this.collapse === 'condense';
const canCollapse = (hasCollapse && getIonMode(this) === 'ios') ? hasCollapse : false;
if (!canCollapse && this.collapsibleHeaderInitialized) {
this.destroyCollapsibleHeader();
} else if (canCollapse && !this.collapsibleHeaderInitialized) {
const tabs = this.el.closest('ion-tabs');
const page = this.el.closest('ion-app,ion-page,.ion-page,page-inner');
const pageEl = (tabs) ? tabs : (page) ? page : null;
const contentEl = (pageEl) ? pageEl.querySelector('ion-content') : null;
await this.setupCollapsibleHeader(contentEl, pageEl);
}
}
private async setupCollapsableHeader(contentEl: HTMLIonContentElement | null, pageEl: Element) {
if (!contentEl) { console.error('ion-header requires a content to collapse, make sure there is an ion-content.'); }
private destroyCollapsibleHeader() {
if (this.intersectionObserver) {
this.intersectionObserver.disconnect();
this.intersectionObserver = undefined;
}
this.scrollEl = await contentEl!.getScrollElement();
if (this.scrollEl && this.contentScrollCallback) {
this.scrollEl.removeEventListener('scroll', this.contentScrollCallback);
this.contentScrollCallback = undefined;
}
}
private async setupCollapsibleHeader(contentEl: HTMLIonContentElement | null, pageEl: Element | null) {
if (!contentEl || !pageEl) { console.error('ion-header requires a content to collapse, make sure there is an ion-content.'); return; }
this.scrollEl = await contentEl.getScrollElement();
readTask(() => {
const headers = pageEl.querySelectorAll('ion-header');
const mainHeader = Array.from(headers).find((header: any) => !header.collapse) as HTMLElement | undefined;
const mainHeader = Array.from(headers).find((header: any) => header.collapse !== 'condense') as HTMLElement | undefined;
if (!mainHeader || !this.scrollEl) { return; }
@ -87,8 +115,8 @@ export class Header implements ComponentInterface {
readTask(() => {
const mainHeaderHeight = mainHeaderIndex.el.clientHeight;
const intersectionObserver = new IntersectionObserver(toolbarIntersection, { threshold: 0.25, rootMargin: `-${mainHeaderHeight}px 0px 0px 0px` });
intersectionObserver.observe(scrollHeaderIndex.toolbars[0].el);
this.intersectionObserver = new IntersectionObserver(toolbarIntersection, { threshold: 0.25, rootMargin: `-${mainHeaderHeight}px 0px 0px 0px` });
this.intersectionObserver.observe(scrollHeaderIndex.toolbars[0].el);
});
/**
@ -104,10 +132,13 @@ export class Header implements ComponentInterface {
cloneElement('ion-title');
cloneElement('ion-back-button');
});
this.collapsibleHeaderInitialized = true;
}
render() {
const mode = getIonMode(this);
const collapse = this.collapse || 'none';
return (
<Host
role="banner"
@ -118,7 +149,7 @@ export class Header implements ComponentInterface {
[`header-${mode}`]: true,
[`header-translucent`]: this.translucent,
[`header-collapse-${mode}`]: this.collapse,
[`header-collapse-${collapse}`]: true,
[`header-translucent-${mode}`]: this.translucent,
}}
>

View File

@ -81,7 +81,6 @@ const setToolbarBackgroundOpacity = (toolbar: ToolbarIndex, opacity: number | un
* hide the primary toolbar content and show the scrollable toolbar content
*/
export const handleToolbarIntersection = (ev: any, mainHeaderIndex: HeaderIndex, scrollHeaderIndex: HeaderIndex) => {
console.log(ev);
writeTask(() => {
const event = ev[0];
const intersection = event.intersectionRect;
@ -121,9 +120,9 @@ export const handleToolbarIntersection = (ev: any, mainHeaderIndex: HeaderIndex,
export const setHeaderActive = (headerIndex: HeaderIndex, active = true) => {
writeTask(() => {
if (active) {
headerIndex.el.classList.remove('header-collapse-ios-inactive');
headerIndex.el.classList.remove('header-collapse-condense-inactive');
} else {
headerIndex.el.classList.add('header-collapse-ios-inactive');
headerIndex.el.classList.add('header-collapse-condense-inactive');
}
setToolbarBackgroundOpacity(headerIndex.toolbars[0], (active) ? undefined : 0);
});

View File

@ -10,7 +10,7 @@ It's important to note that ion-header needs to be the one of the three root ele
## Usage
### Javascript
### Angular / javascript
```html
<ion-header>
@ -26,7 +26,13 @@ It's important to note that ion-header needs to be the one of the three root ele
</ion-toolbar>
</ion-header>
<ion-content></ion-content>
<ion-content>
<ion-header collapse="condense">
<ion-toolbar>
<ion-title size="large">My Navigation Bar</ion-title>
</ion-toolbar>
</ion-header>
</ion-content>
```
@ -45,26 +51,60 @@ export const HeaderExample: React.FC = () => (
</IonButtons>
<IonTitle>My Navigation Bar</IonTitle>
</IonToolbar>
<IonToolbar>
<IonTitle>Subheader</IonTitle>
</IonToolbar>
</IonHeader>
<IonContent />
<IonContent>
<IonHeader collapse="condense">
<IonToolbar>
<IonTitle size="large">My Navigation Bar</IonTitle>
</IonToolbar>
</IonHeader>
</IonContent>
</>
);
```
### Vue
```html
<template>
<ion-header>
<ion-toolbar>
<ion-buttons slot="start">
<ion-back-button></ion-back-button>
</ion-buttons>
<ion-title>My Navigation Bar</ion-title>
</ion-toolbar>
<ion-toolbar>
<ion-title>Subheader</ion-title>
</ion-toolbar>
</ion-header>
<ion-content>
<ion-header collapse="condense">
<ion-toolbar>
<ion-title size="large">My Navigation Bar</ion-title>
</ion-toolbar>
</ion-header>
</ion-content>
</template>
```
## Properties
| Property | Attribute | Description | Type | Default |
| ------------- | ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------- | ----------- |
| `collapse` | `collapse` | If `true`, the header will collapse on scroll of the content. Only applies in `ios` mode. | `boolean` | `false` |
| `mode` | `mode` | The mode determines which platform styles to use. | `"ios" \| "md"` | `undefined` |
| `translucent` | `translucent` | If `true`, the header will be translucent. Only applies when the mode is `"ios"` and the device supports [`backdrop-filter`](https://developer.mozilla.org/en-US/docs/Web/CSS/backdrop-filter#Browser_compatibility). Note: In order to scroll content behind the header, the `fullscreen` attribute needs to be set on the content. | `boolean` | `false` |
| Property | Attribute | Description | Type | Default |
| ------------- | ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------- | ----------- |
| `collapse` | `collapse` | Describes the scroll effect that will be applied to the header `condense` only applies in iOS mode. Typically used for [Collapsible Large Titles](https://ionicframework.com/docs/api/title#collapsible-large-titles) | `"condense" \| undefined` | `undefined` |
| `mode` | `mode` | The mode determines which platform styles to use. | `"ios" \| "md"` | `undefined` |
| `translucent` | `translucent` | If `true`, the header will be translucent. Only applies when the mode is `"ios"` and the device supports [`backdrop-filter`](https://developer.mozilla.org/en-US/docs/Web/CSS/backdrop-filter#Browser_compatibility). Note: In order to scroll content behind the header, the `fullscreen` attribute needs to be set on the content. | `boolean` | `false` |
----------------------------------------------

View File

@ -0,0 +1,22 @@
```html
<ion-header>
<ion-toolbar>
<ion-buttons slot="start">
<ion-back-button></ion-back-button>
</ion-buttons>
<ion-title>My Navigation Bar</ion-title>
</ion-toolbar>
<ion-toolbar>
<ion-title>Subheader</ion-title>
</ion-toolbar>
</ion-header>
<ion-content>
<ion-header collapse="condense">
<ion-toolbar>
<ion-title size="large">My Navigation Bar</ion-title>
</ion-toolbar>
</ion-header>
</ion-content>
```

View File

@ -12,5 +12,11 @@
</ion-toolbar>
</ion-header>
<ion-content></ion-content>
<ion-content>
<ion-header collapse="condense">
<ion-toolbar>
<ion-title size="large">My Navigation Bar</ion-title>
</ion-toolbar>
</ion-header>
</ion-content>
```

View File

@ -11,13 +11,19 @@ export const HeaderExample: React.FC = () => (
</IonButtons>
<IonTitle>My Navigation Bar</IonTitle>
</IonToolbar>
<IonToolbar>
<IonTitle>Subheader</IonTitle>
</IonToolbar>
</IonHeader>
<IonContent />
<IonContent>
<IonHeader collapse="condense">
<IonToolbar>
<IonTitle size="large">My Navigation Bar</IonTitle>
</IonToolbar>
</IonHeader>
</IonContent>
</>
);
```

View File

@ -0,0 +1,24 @@
```html
<template>
<ion-header>
<ion-toolbar>
<ion-buttons slot="start">
<ion-back-button></ion-back-button>
</ion-buttons>
<ion-title>My Navigation Bar</ion-title>
</ion-toolbar>
<ion-toolbar>
<ion-title>Subheader</ion-title>
</ion-toolbar>
</ion-header>
<ion-content>
<ion-header collapse="condense">
<ion-toolbar>
<ion-title size="large">My Navigation Bar</ion-title>
</ion-toolbar>
</ion-header>
</ion-content>
</template>
```

View File

@ -2,8 +2,6 @@
`ion-title` is a component that sets the title of the `Toolbar`.
<!-- Auto Generated Below -->
@ -24,50 +22,281 @@
<ion-toolbar>
<ion-title>Default Title</ion-title>
</ion-toolbar>
<!-- Large title -->
<ion-toolbar>
<ion-title size="large">Large Title</ion-title>
</ion-toolbar>
```
### Collapsible Large Titles
Ionic provides a way to create the collapsible titles that exist on stock iOS apps. Getting this setup requires configuring your `ion-title`, `ion-header`, and (optionally) `ion-buttons` elements.
```html
<ion-header>
<ion-toolbar>
<ion-title>Settings</ion-title>
</ion-toolbar>
</ion-header>
<ion-content>
<ion-header collapse="condense">
<ion-toolbar>
<ion-title size="large">Settings</ion-title>
</ion-toolbar>
<ion-toolbar>
<ion-searchbar></ion-searchbar>
</ion-toolbar>
</ion-header>
...
</ion-content>
```
In the example above, notice there are two `ion-header` elements. The first `ion-header` represents the "collapsed" state of your collapsible header, and the second `ion-header` represents the "expanded" state of your collapsible header. Notice that the second `ion-header` must have `collapse="condense"` and must exist within `ion-content`. Additionally, in order to get the large title styling, `ion-title` must have `size="large"`.
```html
<ion-header>
<ion-toolbar>
<ion-buttons collapse="true">
<ion-button>Click Me</ion-button>
</ion-buttons>
<ion-title>Settings</ion-title>
</ion-toolbar>
</ion-header>
<ion-content>
<ion-header collapse="condense">
<ion-toolbar>
<ion-buttons collapse="true">
<ion-button>Click Me</ion-button>
</ion-buttons>
<ion-title size="large">Settings</ion-title>
</ion-toolbar>
<ion-toolbar>
<ion-searchbar></ion-searchbar>
</ion-toolbar>
</ion-header>
...
</ion-content>
```
In this example, notice that we have added two sets of `ion-buttons` both with `collapse="true"`. When the secondary header collapses, the buttons in the secondary header will hide, and the buttons in the primary header will show. This is useful for ensuring that your header buttons always appear next to an `ion-title` element.
`ion-buttons` elements that do not have `collapse` set will always be visible, regardless of collapsed state.
### React
```tsx
import React from 'react';
import {
IonToolbar,
IonTitle
IonTitle,
IonToolbar
} from '@ionic/react';
export const ToolbarExample: React.FC = () => (
{/*-- Default title --*/}
<IonToolbar>
<IonTitle>Default Title</IonTitle>
</IonToolbar>
{/*-- Small title --*/}
<IonToolbar>
<IonTitle size="small">Small Title above a Default Title</IonTitle>
</IonToolbar>
<IonToolbar>
<IonTitle>Default Title</IonTitle>
</IonToolbar>
{/*-- Large title --*/}
<IonToolbar>
<IonTitle size="large">Large Title</IonTitle>
</IonToolbar>
);
```
### Collapsible Large Titles
Ionic provides a way to create the collapsible titles that exist on stock iOS apps. Getting this setup requires configuring your `IonTitle`, `IonHeader`, and (optionally) `IonButtons` elements.
```tsx
import React from 'react';
import {
IonContent,
IonHeader,
IonSearchbar,
IonTitle,
IonToolbar
} from '@ionic/react';
export const LargeTitleExample: React.FC = () => (
<>
<IonHeader>
<IonToolbar>
<IonTitle>Settings</IonTitle>
</IonToolbar>
</IonHeader>
<IonContent>
<IonHeader collapse="condense">
<IonToolbar>
<IonTitle size="large">Settings</IonTitle>
</IonToolbar>
<IonToolbar>
<IonSearchbar></IonSearchbar>
</IonToolbar>
</IonHeader>
...
</IonContent>
</>
);
```
In the example above, notice there are two `IonHeader` elements. The first `IonHeader` represents the "collapsed" state of your collapsible header, and the second `IonHeader` represents the "expanded" state of your collapsible header. Notice that the second `IonHeader` must have `collapse="condense"` and must exist within `IonContent`. Additionally, in order to get the large title styling, `IonTitle` must have `size="large"`.
```tsx
import React from 'react';
import {
IonButton,
IonButtons,
IonContent,
IonHeader,
IonSearchbar,
IonTitle,
IonToolbar
} from '@ionic/react';
export const LargeTitleExample: React.FC = () => (
<>
<IonHeader>
<IonToolbar>
<IonButtons collapse="true">
<IonButton>Click Me</IonButton>
</IonButtons>
<IonTitle>Settings</IonTitle>
</IonToolbar>
</IonHeader>
<IonContent>
<IonHeader collapse="condense">
<IonToolbar>
<IonButtons collapse="true">
<IonButton>Click Me</IonButton>
</IonButtons>
<IonTitle size="large">Settings</IonTitle>
</IonToolbar>
<IonToolbar>
<IonSearchbar></IonSearchbar>
</IonToolbar>
</IonHeader>
...
</IonContent>
</>
);
```
In this example, notice that we have added two sets of `IonButtons` both with `collapse="true"`. When the secondary header collapses, the buttons in the secondary header will hide, and the buttons in the primary header will show. This is useful for ensuring that your header buttons always appear next to an `IonTitle` element.
`IonButtons` elements that do not have `collapse` set will always be visible, regardless of collapsed state.
### Vue
```html
<template>
<!-- Default title -->
<ion-toolbar>
<ion-title>Default Title</ion-title>
</ion-toolbar>
<!-- Small title -->
<ion-toolbar>
<ion-title size="small">Small Title above a Default Title</ion-title>
</ion-toolbar>
<ion-toolbar>
<ion-title>Default Title</ion-title>
</ion-toolbar>
<!-- Large title -->
<ion-toolbar>
<ion-title size="large">Large Title</ion-title>
</ion-toolbar>
</template>
```
### Collapsible Large Titles
Ionic provides a way to create the collapsible titles that exist on stock iOS apps. Getting this setup requires configuring your `ion-title`, `ion-header`, and (optionally) `ion-buttons` elements.
```html
<template>
<ion-header>
<ion-toolbar>
<ion-title>Settings</ion-title>
</ion-toolbar>
</ion-header>
<ion-content>
<ion-header collapse="condense">
<ion-toolbar>
<ion-title size="large">Settings</ion-title>
</ion-toolbar>
<ion-toolbar>
<ion-searchbar></ion-searchbar>
</ion-toolbar>
</ion-header>
...
</ion-content>
</template>
```
In the example above, notice there are two `ion-header` elements. The first `ion-header` represents the "collapsed" state of your collapsible header, and the second `ion-header` represents the "expanded" state of your collapsible header. Notice that the second `ion-header` must have `collapse="condense"` and must exist within `ion-content`. Additionally, in order to get the large title styling, `ion-title` must have `size="large"`.
```html
<template>
<ion-header>
<ion-toolbar>
<ion-buttons collapse="true">
<ion-button>Click Me</ion-button>
</ion-buttons>
<ion-title>Settings</ion-title>
</ion-toolbar>
</ion-header>
<ion-content>
<ion-header collapse="condense">
<ion-toolbar>
<ion-buttons collapse="true">
<ion-button>Click Me</ion-button>
</ion-buttons>
<ion-title size="large">Settings</ion-title>
</ion-toolbar>
<ion-toolbar>
<ion-searchbar></ion-searchbar>
</ion-toolbar>
</ion-header>
...
</ion-content>
</template>
```
In this example, notice that we have added two sets of `ion-buttons` both with `collapse="true"`. When the secondary header collapses, the buttons in the secondary header will hide, and the buttons in the primary header will show. This is useful for ensuring that your header buttons always appear next to an `ion-title` element.
`ion-buttons` elements that do not have `collapse` set will always be visible, regardless of collapsed state.
## Properties

View File

@ -111,5 +111,5 @@
font-size: 34px;
font-weight: 700;
text-align: left;
text-align: start;
}

View File

@ -11,4 +11,69 @@
<ion-toolbar>
<ion-title>Default Title</ion-title>
</ion-toolbar>
<!-- Large title -->
<ion-toolbar>
<ion-title size="large">Large Title</ion-title>
</ion-toolbar>
```
### Collapsible Large Titles
Ionic provides a way to create the collapsible titles that exist on stock iOS apps. Getting this setup requires configuring your `ion-title`, `ion-header`, and (optionally) `ion-buttons` elements.
```html
<ion-header>
<ion-toolbar>
<ion-title>Settings</ion-title>
</ion-toolbar>
</ion-header>
<ion-content>
<ion-header collapse="condense">
<ion-toolbar>
<ion-title size="large">Settings</ion-title>
</ion-toolbar>
<ion-toolbar>
<ion-searchbar></ion-searchbar>
</ion-toolbar>
</ion-header>
...
</ion-content>
```
In the example above, notice there are two `ion-header` elements. The first `ion-header` represents the "collapsed" state of your collapsible header, and the second `ion-header` represents the "expanded" state of your collapsible header. Notice that the second `ion-header` must have `collapse="condense"` and must exist within `ion-content`. Additionally, in order to get the large title styling, `ion-title` must have `size="large"`.
```html
<ion-header>
<ion-toolbar>
<ion-buttons collapse="true">
<ion-button>Click Me</ion-button>
</ion-buttons>
<ion-title>Settings</ion-title>
</ion-toolbar>
</ion-header>
<ion-content>
<ion-header collapse="condense">
<ion-toolbar>
<ion-buttons collapse="true">
<ion-button>Click Me</ion-button>
</ion-buttons>
<ion-title size="large">Settings</ion-title>
</ion-toolbar>
<ion-toolbar>
<ion-searchbar></ion-searchbar>
</ion-toolbar>
</ion-header>
...
</ion-content>
```
In this example, notice that we have added two sets of `ion-buttons` both with `collapse="true"`. When the secondary header collapses, the buttons in the secondary header will hide, and the buttons in the primary header will show. This is useful for ensuring that your header buttons always appear next to an `ion-title` element.
`ion-buttons` elements that do not have `collapse` set will always be visible, regardless of collapsed state.

View File

@ -11,4 +11,69 @@
<ion-toolbar>
<ion-title>Default Title</ion-title>
</ion-toolbar>
<!-- Large title -->
<ion-toolbar>
<ion-title size="large">Large Title</ion-title>
</ion-toolbar>
```
### Collapsible Large Titles
Ionic provides a way to create the collapsible titles that exist on stock iOS apps. Getting this setup requires configuring your `ion-title`, `ion-header`, and (optionally) `ion-buttons` elements.
```html
<ion-header>
<ion-toolbar>
<ion-title>Settings</ion-title>
</ion-toolbar>
</ion-header>
<ion-content>
<ion-header collapse="condense">
<ion-toolbar>
<ion-title size="large">Settings</ion-title>
</ion-toolbar>
<ion-toolbar>
<ion-searchbar></ion-searchbar>
</ion-toolbar>
</ion-header>
...
</ion-content>
```
In the example above, notice there are two `ion-header` elements. The first `ion-header` represents the "collapsed" state of your collapsible header, and the second `ion-header` represents the "expanded" state of your collapsible header. Notice that the second `ion-header` must have `collapse="condense"` and must exist within `ion-content`. Additionally, in order to get the large title styling, `ion-title` must have `size="large"`.
```html
<ion-header>
<ion-toolbar>
<ion-buttons collapse="true">
<ion-button>Click Me</ion-button>
</ion-buttons>
<ion-title>Settings</ion-title>
</ion-toolbar>
</ion-header>
<ion-content>
<ion-header collapse="condense">
<ion-toolbar>
<ion-buttons collapse="true">
<ion-button>Click Me</ion-button>
</ion-buttons>
<ion-title size="large">Settings</ion-title>
</ion-toolbar>
<ion-toolbar>
<ion-searchbar></ion-searchbar>
</ion-toolbar>
</ion-header>
...
</ion-content>
```
In this example, notice that we have added two sets of `ion-buttons` both with `collapse="true"`. When the secondary header collapses, the buttons in the secondary header will hide, and the buttons in the primary header will show. This is useful for ensuring that your header buttons always appear next to an `ion-title` element.
`ion-buttons` elements that do not have `collapse` set will always be visible, regardless of collapsed state.

View File

@ -1,20 +1,115 @@
```tsx
import React from 'react';
import {
IonToolbar,
IonTitle
IonTitle,
IonToolbar
} from '@ionic/react';
export const ToolbarExample: React.FC = () => (
{/*-- Default title --*/}
<IonToolbar>
<IonTitle>Default Title</IonTitle>
</IonToolbar>
{/*-- Small title --*/}
<IonToolbar>
<IonTitle size="small">Small Title above a Default Title</IonTitle>
</IonToolbar>
<IonToolbar>
<IonTitle>Default Title</IonTitle>
</IonToolbar>
{/*-- Large title --*/}
<IonToolbar>
<IonTitle size="large">Large Title</IonTitle>
</IonToolbar>
);
```
### Collapsible Large Titles
Ionic provides a way to create the collapsible titles that exist on stock iOS apps. Getting this setup requires configuring your `IonTitle`, `IonHeader`, and (optionally) `IonButtons` elements.
```tsx
import React from 'react';
import {
IonContent,
IonHeader,
IonSearchbar,
IonTitle,
IonToolbar
} from '@ionic/react';
export const LargeTitleExample: React.FC = () => (
<>
<IonHeader>
<IonToolbar>
<IonTitle>Settings</IonTitle>
</IonToolbar>
</IonHeader>
<IonContent>
<IonHeader collapse="condense">
<IonToolbar>
<IonTitle size="large">Settings</IonTitle>
</IonToolbar>
<IonToolbar>
<IonSearchbar></IonSearchbar>
</IonToolbar>
</IonHeader>
...
</IonContent>
</>
);
```
In the example above, notice there are two `IonHeader` elements. The first `IonHeader` represents the "collapsed" state of your collapsible header, and the second `IonHeader` represents the "expanded" state of your collapsible header. Notice that the second `IonHeader` must have `collapse="condense"` and must exist within `IonContent`. Additionally, in order to get the large title styling, `IonTitle` must have `size="large"`.
```tsx
import React from 'react';
import {
IonButton,
IonButtons,
IonContent,
IonHeader,
IonSearchbar,
IonTitle,
IonToolbar
} from '@ionic/react';
export const LargeTitleExample: React.FC = () => (
<>
<IonHeader>
<IonToolbar>
<IonButtons collapse="true">
<IonButton>Click Me</IonButton>
</IonButtons>
<IonTitle>Settings</IonTitle>
</IonToolbar>
</IonHeader>
<IonContent>
<IonHeader collapse="condense">
<IonToolbar>
<IonButtons collapse="true">
<IonButton>Click Me</IonButton>
</IonButtons>
<IonTitle size="large">Settings</IonTitle>
</IonToolbar>
<IonToolbar>
<IonSearchbar></IonSearchbar>
</IonToolbar>
</IonHeader>
...
</IonContent>
</>
);
```
In this example, notice that we have added two sets of `IonButtons` both with `collapse="true"`. When the secondary header collapses, the buttons in the secondary header will hide, and the buttons in the primary header will show. This is useful for ensuring that your header buttons always appear next to an `IonTitle` element.
`IonButtons` elements that do not have `collapse` set will always be visible, regardless of collapsed state.

View File

@ -1,14 +1,85 @@
```html
<template>
<!-- Default title -->
<ion-toolbar>
<ion-title>Default Title</ion-title>
</ion-toolbar>
<!-- Small title -->
<ion-toolbar>
<ion-title size="small">Small Title above a Default Title</ion-title>
</ion-toolbar>
<ion-toolbar>
<ion-title>Default Title</ion-title>
</ion-toolbar>
<!-- Large title -->
<ion-toolbar>
<ion-title size="large">Large Title</ion-title>
</ion-toolbar>
</template>
```
```
### Collapsible Large Titles
Ionic provides a way to create the collapsible titles that exist on stock iOS apps. Getting this setup requires configuring your `ion-title`, `ion-header`, and (optionally) `ion-buttons` elements.
```html
<template>
<ion-header>
<ion-toolbar>
<ion-title>Settings</ion-title>
</ion-toolbar>
</ion-header>
<ion-content>
<ion-header collapse="condense">
<ion-toolbar>
<ion-title size="large">Settings</ion-title>
</ion-toolbar>
<ion-toolbar>
<ion-searchbar></ion-searchbar>
</ion-toolbar>
</ion-header>
...
</ion-content>
</template>
```
In the example above, notice there are two `ion-header` elements. The first `ion-header` represents the "collapsed" state of your collapsible header, and the second `ion-header` represents the "expanded" state of your collapsible header. Notice that the second `ion-header` must have `collapse="condense"` and must exist within `ion-content`. Additionally, in order to get the large title styling, `ion-title` must have `size="large"`.
```html
<template>
<ion-header>
<ion-toolbar>
<ion-buttons collapse="true">
<ion-button>Click Me</ion-button>
</ion-buttons>
<ion-title>Settings</ion-title>
</ion-toolbar>
</ion-header>
<ion-content>
<ion-header collapse="condense">
<ion-toolbar>
<ion-buttons collapse="true">
<ion-button>Click Me</ion-button>
</ion-buttons>
<ion-title size="large">Settings</ion-title>
</ion-toolbar>
<ion-toolbar>
<ion-searchbar></ion-searchbar>
</ion-toolbar>
</ion-header>
...
</ion-content>
</template>
```
In this example, notice that we have added two sets of `ion-buttons` both with `collapse="true"`. When the secondary header collapses, the buttons in the secondary header will hide, and the buttons in the primary header will show. This is useful for ensuring that your header buttons always appear next to an `ion-title` element.
`ion-buttons` elements that do not have `collapse` set will always be visible, regardless of collapsed state.

View File

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

View File

@ -30,27 +30,9 @@
.create ion-icon {
transform: scale(0.9);
}
/*
ion-toolbar {
--background: red;
--border-color: #dfe1e0;
}
.main-content {
--background: #f1f2f6;
}
*/
</style>
</head>
<!--<ion-button slot="icon-only" class="more">
<ion-icon name="ios-more"></ion-icon>
</ion-button>
<ion-button slot="icon-only" class="create">
<ion-icon name="ios-create"></ion-icon>
</ion-button>-->
<body>
<ion-app>
<ion-nav root="page-one"></ion-nav>
@ -71,7 +53,7 @@
</style>
<script>
class PageTwo extends HTMLElement {
class PageOne extends HTMLElement {
generateList() {
let html = '';
for (let i = 0; i < 100; i++) {
@ -108,7 +90,7 @@
</ion-header>
<ion-content id="content" class="main-content">
<ion-header collapse>
<ion-header collapse="condense">
<ion-toolbar>
<ion-title size="large">Page Two</ion-title>
</ion-toolbar>
@ -122,48 +104,21 @@
`;
}
}
class PageOne extends HTMLElement {
connectedCallback() {
this.innerHTML = `
<ion-header>
<ion-toolbar>
<ion-buttons slot="start">
<ion-back-button text="Settings"></ion-back-button>
</ion-buttons>
<ion-title>Page main</ion-title>
</ion-toolbar>
</ion-header>
<ion-content class="ion-padding">
<h1>Page One</h1>
<ion-nav-link component="page-two">
<ion-item button>
<ion-label>Go to Page Two</ion-label>
</ion-item>
</ion-nav-link>
</ion-content>
`;
}
}
class PageThree extends HTMLElement {
generateList() {
let html = '';
for (let i = 0; i < 100; i++) {
html += `
<ion-nav-link component="page-two">
<ion-item button color="dark">
<ion-badge slot="start" class="item-badge ion-align-self-start">&nbsp;</ion-badge>
<ion-label>
<h2>Heading ${i}</h2>
<h3>Smaller heading ${i}</h2>
<p>Paragraph ${i}</p>
</ion-label>
</ion-item>
</ion-nav-link>
<ion-item button color="dark">
<ion-badge slot="start" class="item-badge ion-align-self-start">&nbsp;</ion-badge>
<ion-label>
<h2>Heading ${i}</h2>
<h3>Smaller heading ${i}</h2>
<p>Paragraph ${i}</p>
</ion-label>
</ion-item>
`;
}
return html;
@ -184,7 +139,7 @@
</ion-header>
<ion-content id="content" class="three-content" fullscreen color="dark">
<ion-header collapse color="dark">
<ion-header collapse="condense" color="dark">
<ion-toolbar color="dark">
<ion-title size="large">Page Three</ion-title>
</ion-toolbar>
@ -196,7 +151,6 @@
}
}
customElements.define('page-one', PageOne);
customElements.define('page-two', PageTwo);
customElements.define('page-three', PageThree);
</script>
</body>

View File

@ -16,7 +16,7 @@ export const shadow = <T extends Element>(el: T): ShadowRoot | T => {
};
const getLargeTitle = (refEl: any) => {
return refEl.querySelector('ion-header:not(.header-collapse-ios-inactive) ion-title[size=large]');
return refEl.querySelector('ion-header:not(.header-collapse-condense-inactive) ion-title[size=large]');
};
const getBackButton = (refEl: any, backDirection: boolean) => {
@ -24,10 +24,11 @@ const getBackButton = (refEl: any, backDirection: boolean) => {
for (const buttons of buttonsList) {
const parentHeader = buttons.closest('ion-header');
const activeHeader = parentHeader && !parentHeader.classList.contains('header-collapse-ios-inactive');
const activeHeader = parentHeader && !parentHeader.classList.contains('header-collapse-condense-inactive');
const backButton = buttons.querySelector('ion-back-button');
const buttonsCollapse = buttons.classList.contains('buttons-collapse');
if (backButton !== null && ((buttons.collapse && activeHeader && backDirection) || !buttons.collapse)) {
if (backButton !== null && ((buttonsCollapse && activeHeader && backDirection) || !buttonsCollapse)) {
return backButton;
}
}
@ -60,26 +61,33 @@ const createLargeTitleTransition = (rootAnimation: IonicAnimation, rtl: boolean,
};
const animateBackButton = (rootAnimation: IonicAnimation, rtl: boolean, backDirection: boolean, backButtonEl: any) => {
console.log(rtl);
const START_TEXT_TRANSLATE = (rtl) ? '7px' : '-7px';
const END_TEXT_TRANSLATE = (rtl) ? '-4px' : '4px';
const ICON_TRANSLATE = (rtl) ? '-4px' : '4px';
const TEXT_TRANSFORM_ORIGIN_X = (rtl) ? 'right' : 'left';
const ICON_TRANSFORM_ORIGIN_X = (rtl) ? 'left' : 'right';
const FORWARD_TEXT_KEYFRAMES = [
{ offset: 0, opacity: 0, transform: `translate(-7px, ${addSafeArea(8)}) scale(2.1)` },
{ offset: 1, opacity: 1, transform: `translate(4px, ${addSafeArea(-40)}) scale(1)` }
{ offset: 0, opacity: 0, transform: `translate(${START_TEXT_TRANSLATE}, ${addSafeArea(8)}) scale(2.1)` },
{ offset: 1, opacity: 1, transform: `translate(${END_TEXT_TRANSLATE}, ${addSafeArea(-40)}) scale(1)` }
];
const BACKWARD_TEXT_KEYFRAMES = [
{ offset: 0, opacity: 1, transform: `translate(4px, ${addSafeArea(-40)}) scale(1)` },
{ offset: 0, opacity: 1, transform: `translate(${END_TEXT_TRANSLATE}, ${addSafeArea(-40)}) scale(1)` },
{ offset: 0.6, opacity: 0 },
{ offset: 1, opacity: 0, transform: `translate(-7px, ${addSafeArea(8)}) scale(2.1)` }
{ offset: 1, opacity: 0, transform: `translate(${START_TEXT_TRANSLATE}, ${addSafeArea(8)}) scale(2.1)` }
];
const TEXT_KEYFRAMES = (backDirection) ? BACKWARD_TEXT_KEYFRAMES : FORWARD_TEXT_KEYFRAMES;
const FORWARD_ICON_KEYFRAMES = [
{ offset: 0, opacity: 0, transform: `translate3d(4px, ${addSafeArea(-35)}, 0) scale(0.6)` },
{ offset: 1, opacity: 1, transform: `translate3d(4px, ${addSafeArea(-40)}, 0) scale(1)` }
{ offset: 0, opacity: 0, transform: `translate3d(${ICON_TRANSLATE}, ${addSafeArea(-35)}, 0) scale(0.6)` },
{ offset: 1, opacity: 1, transform: `translate3d(${ICON_TRANSLATE}, ${addSafeArea(-40)}, 0) scale(1)` }
];
const BACKWARD_ICON_KEYFRAMES = [
{ offset: 0, opacity: 1, transform: `translate(4px, ${addSafeArea(-40)}) scale(1)` },
{ offset: 0.2, opacity: 0, transform: `translate(4px, ${addSafeArea(-35)}) scale(0.6)` },
{ offset: 1, opacity: 0, transform: `translate(4px, ${addSafeArea(-35)}) scale(0.6)` }
{ offset: 0, opacity: 1, transform: `translate(${ICON_TRANSLATE}, ${addSafeArea(-40)}) scale(1)` },
{ offset: 0.2, opacity: 0, transform: `translate(${ICON_TRANSLATE}, ${addSafeArea(-35)}) scale(0.6)` },
{ offset: 1, opacity: 0, transform: `translate(${ICON_TRANSLATE}, ${addSafeArea(-35)}) scale(0.6)` }
];
const ICON_KEYFRAMES = (backDirection) ? BACKWARD_ICON_KEYFRAMES : FORWARD_ICON_KEYFRAMES;
@ -105,7 +113,7 @@ const animateBackButton = (rootAnimation: IonicAnimation, rtl: boolean, backDire
enteringBackButtonTextAnimation
.beforeStyles({
'transform-origin': 'left center'
'transform-origin': `${TEXT_TRANSFORM_ORIGIN_X} center`
})
.beforeAddWrite(() => {
backButtonEl.style.setProperty('display', 'none');
@ -118,7 +126,7 @@ const animateBackButton = (rootAnimation: IonicAnimation, rtl: boolean, backDire
enteringBackButtonIconAnimation
.beforeStyles({
'transform-origin': 'right center'
'transform-origin': `${ICON_TRANSFORM_ORIGIN_X} center`
})
.keyframes(ICON_KEYFRAMES);
@ -126,16 +134,18 @@ const animateBackButton = (rootAnimation: IonicAnimation, rtl: boolean, backDire
};
const animateLargeTitle = (rootAnimation: IonicAnimation, rtl: boolean, backDirection: boolean, largeTitleEl: any) => {
const TRANSLATE = (rtl) ? '-18px' : '18px';
const START_TRANSLATE = (rtl) ? '-18px' : '18px';
const TRANSFORM_ORIGIN_X = (rtl) ? 'right' : 'left';
const BACKWARDS_KEYFRAMES = [
{ offset: 0, opacity: 0, transform: `translate(${TRANSLATE}, ${addSafeArea(0)}) scale(0.49)` },
{ offset: 0, opacity: 0, transform: `translate(${START_TRANSLATE}, ${addSafeArea(0)}) scale(0.49)` },
{ offset: 0.1, opacity: 0 },
{ offset: 1, opacity: 1, transform: `translate(0, ${addSafeArea(49)}) scale(1)` }
];
const FORWARDS_KEYFRAMES = [
{ offset: 0, opacity: 0.99, transform: `translate(0, ${addSafeArea(49)}) scale(1)` },
{ offset: 0.6, opacity: 0 },
{ offset: 1, opacity: 0, transform: `translate(${TRANSLATE}, ${addSafeArea(0)}) scale(0.5)` }
{ offset: 1, opacity: 0, transform: `translate(${START_TRANSLATE}, ${addSafeArea(0)}) scale(0.5)` }
];
const KEYFRAMES = (backDirection) ? BACKWARDS_KEYFRAMES : FORWARDS_KEYFRAMES;
@ -150,7 +160,7 @@ const animateLargeTitle = (rootAnimation: IonicAnimation, rtl: boolean, backDire
clonedLargeTitleAnimation
.beforeStyles({
'transform-origin': 'left center',
'transform-origin': `${TRANSFORM_ORIGIN_X} center`,
'height': '46px',
'display': '',
'position': 'relative'
@ -254,7 +264,7 @@ export const iosTransitionAnimation = (navEl: HTMLElement, opts: TransitionOptio
}
}
const enteringContentHasLargeTitle = enteringEl.querySelector('ion-header.header-collapse-ios');
const enteringContentHasLargeTitle = enteringEl.querySelector('ion-header.header-collapse-condense');
const { forward, backward } = createLargeTitleTransition(rootAnimation, isRTL, backDirection, enteringEl, leavingEl);
@ -270,16 +280,16 @@ export const iosTransitionAnimation = (navEl: HTMLElement, opts: TransitionOptio
const buttons = Array.from(enteringToolBarEl.querySelectorAll('ion-buttons,[menuToggle]'));
const parentHeader = enteringToolBarEl.closest('ion-header');
const inactiveHeader = parentHeader && parentHeader.classList.contains('header-collapse-ios-inactive');
const inactiveHeader = parentHeader && parentHeader.classList.contains('header-collapse-condense-inactive');
let buttonsToAnimate;
if (backDirection) {
buttonsToAnimate = buttons.filter(button => {
const isCollapseButton = (button as any).collapse;
const isCollapseButton = button.classList.contains('buttons-collapse');
return (isCollapseButton && !inactiveHeader) || !isCollapseButton;
});
} else {
buttonsToAnimate = buttons.filter(button => !(button as any).collapse);
buttonsToAnimate = buttons.filter(button => !button.classList.contains('buttons-collapse'));
}
enteringToolBarButtons.addElement(buttonsToAnimate);
@ -409,10 +419,10 @@ export const iosTransitionAnimation = (navEl: HTMLElement, opts: TransitionOptio
const buttons = leavingToolBarEl.querySelectorAll('ion-buttons,[menuToggle]');
const parentHeader = leavingToolBarEl.closest('ion-header');
const inactiveHeader = parentHeader && parentHeader.classList.contains('header-collapse-ios-inactive');
const inactiveHeader = parentHeader && parentHeader.classList.contains('header-collapse-condense-inactive');
const buttonsToAnimate = Array.from(buttons).filter(button => {
const isCollapseButton = (button as any).collapse;
const isCollapseButton = button.classList.contains('buttons-collapse');
return (isCollapseButton && !inactiveHeader) || !isCollapseButton;
});