mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-08-19 11:41:20 +08:00
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:
@ -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
|
||||
|
||||
|
12
core/src/components.d.ts
vendored
12
core/src/components.d.ts
vendored
@ -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.
|
||||
*/
|
||||
|
@ -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>
|
||||
);
|
||||
}
|
||||
|
@ -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` |
|
||||
|
||||
|
||||
----------------------------------------------
|
||||
|
@ -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>
|
||||
```
|
@ -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>
|
||||
```
|
@ -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>
|
||||
);
|
||||
```
|
@ -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>
|
||||
```
|
@ -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;
|
||||
}
|
@ -26,6 +26,6 @@
|
||||
display: none;
|
||||
}
|
||||
|
||||
.header-collapse-md {
|
||||
.header-collapse-condense {
|
||||
display: none;
|
||||
}
|
@ -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,
|
||||
}}
|
||||
>
|
||||
|
@ -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);
|
||||
});
|
||||
|
@ -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` |
|
||||
|
||||
|
||||
----------------------------------------------
|
||||
|
22
core/src/components/header/usage/angular.md
Normal file
22
core/src/components/header/usage/angular.md
Normal 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>
|
||||
```
|
@ -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>
|
||||
```
|
||||
|
@ -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>
|
||||
</>
|
||||
);
|
||||
```
|
24
core/src/components/header/usage/vue.md
Normal file
24
core/src/components/header/usage/vue.md
Normal 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>
|
||||
```
|
@ -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
|
||||
|
@ -111,5 +111,5 @@
|
||||
font-size: 34px;
|
||||
font-weight: 700;
|
||||
|
||||
text-align: left;
|
||||
text-align: start;
|
||||
}
|
||||
|
@ -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.
|
@ -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.
|
@ -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.
|
||||
|
@ -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.
|
||||
|
19
core/src/components/toolbar/test/title/e2e.ts
Normal file
19
core/src/components/toolbar/test/title/e2e.ts
Normal 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();
|
||||
});
|
@ -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"> </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"> </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>
|
||||
|
@ -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;
|
||||
});
|
||||
|
||||
|
Reference in New Issue
Block a user