Skip to content

Commit 4853909

Browse files
committed
fix(header): collapsible header works in tabs (#19658)
fixes #19640
1 parent 1535e95 commit 4853909

File tree

2 files changed

+23
-28
lines changed

2 files changed

+23
-28
lines changed

core/src/components/header/header.tsx

Lines changed: 11 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -57,14 +57,10 @@ export class Header implements ComponentInterface {
5757
// Determine if the header can collapse
5858
const hasCollapse = this.collapse === 'condense';
5959
const canCollapse = (hasCollapse && getIonMode(this) === 'ios') ? hasCollapse : false;
60-
6160
if (!canCollapse && this.collapsibleHeaderInitialized) {
6261
this.destroyCollapsibleHeader();
6362
} else if (canCollapse && !this.collapsibleHeaderInitialized) {
64-
const tabs = this.el.closest('ion-tabs');
65-
const page = this.el.closest('ion-app,ion-page,.ion-page,page-inner');
66-
67-
const pageEl = (tabs) ? tabs : (page) ? page : null;
63+
const pageEl = this.el.closest('ion-app,ion-page,.ion-page,page-inner');
6864
const contentEl = (pageEl) ? pageEl.querySelector('ion-content') : null;
6965

7066
await this.setupCollapsibleHeader(contentEl, pageEl);
@@ -101,21 +97,17 @@ export class Header implements ComponentInterface {
10197

10298
setHeaderActive(mainHeaderIndex, false);
10399

104-
// TODO: Find a better way to do this
105-
let remainingHeight = 0;
106-
for (let i = 1; i <= scrollHeaderIndex.toolbars.length - 1; i++) {
107-
remainingHeight += scrollHeaderIndex.toolbars[i].el.clientHeight;
108-
}
109-
110-
/**
111-
* Handle interaction between toolbar collapse and
112-
* showing/hiding content in the primary ion-header
113-
*/
114-
const toolbarIntersection = (ev: any) => { handleToolbarIntersection(ev, mainHeaderIndex, scrollHeaderIndex); };
115-
116100
readTask(() => {
117101
const mainHeaderHeight = mainHeaderIndex.el.clientHeight;
118-
this.intersectionObserver = new IntersectionObserver(toolbarIntersection, { threshold: 0.25, rootMargin: `-${mainHeaderHeight}px 0px 0px 0px` });
102+
103+
/**
104+
* Handle interaction between toolbar collapse and
105+
* showing/hiding content in the primary ion-header
106+
* as well as progressively showing/hiding the main header
107+
* border as the top-most toolbar collapses or expands.
108+
*/
109+
const toolbarIntersection = (ev: any) => { handleToolbarIntersection(ev, mainHeaderIndex, scrollHeaderIndex); };
110+
this.intersectionObserver = new IntersectionObserver(toolbarIntersection, { threshold: [0.25, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1], rootMargin: `-${mainHeaderHeight}px 0px 0px 0px` });
119111
this.intersectionObserver.observe(scrollHeaderIndex.toolbars[0].el);
120112
});
121113

@@ -124,7 +116,7 @@ export class Header implements ComponentInterface {
124116
* showing/hiding border on last toolbar
125117
* in primary header
126118
*/
127-
this.contentScrollCallback = () => { handleContentScroll(this.scrollEl!, mainHeaderIndex, scrollHeaderIndex, remainingHeight); };
119+
this.contentScrollCallback = () => { handleContentScroll(this.scrollEl!, scrollHeaderIndex); };
128120
this.scrollEl.addEventListener('scroll', this.contentScrollCallback);
129121
});
130122

core/src/components/header/header.utils.ts

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -49,20 +49,13 @@ export const createHeaderIndex = (headerEl: HTMLElement | undefined): HeaderInde
4949
} as HeaderIndex;
5050
};
5151

52-
export const handleContentScroll = (scrollEl: HTMLElement, mainHeaderIndex: HeaderIndex, scrollHeaderIndex: HeaderIndex, remainingHeight = 0) => {
52+
export const handleContentScroll = (scrollEl: HTMLElement, scrollHeaderIndex: HeaderIndex) => {
5353
readTask(() => {
5454
const scrollTop = scrollEl.scrollTop;
55-
const lastMainToolbar = mainHeaderIndex.toolbars[mainHeaderIndex.toolbars.length - 1];
56-
5755
const scale = clamp(1, 1 + (-scrollTop / 500), 1.1);
5856

59-
const borderOpacity = clamp(0, (scrollTop - remainingHeight) / lastMainToolbar.el.clientHeight, 1);
60-
const maxOpacity = 1;
61-
const scaledOpacity = borderOpacity * maxOpacity;
62-
6357
writeTask(() => {
6458
scaleLargeTitles(scrollHeaderIndex.toolbars, scale);
65-
setToolbarBackgroundOpacity(mainHeaderIndex.toolbars[0], (scaledOpacity === 1) ? undefined : scaledOpacity);
6659
});
6760
});
6861
};
@@ -75,14 +68,24 @@ const setToolbarBackgroundOpacity = (toolbar: ToolbarIndex, opacity: number | un
7568
}
7669
};
7770

71+
const handleToolbarBorderIntersection = (ev: any, mainHeaderIndex: HeaderIndex) => {
72+
if (!ev[0].isIntersecting) { return; }
73+
74+
const scale = ((1 - ev[0].intersectionRatio) * 100) / 75;
75+
setToolbarBackgroundOpacity(mainHeaderIndex.toolbars[0], (scale === 1) ? undefined : scale);
76+
};
77+
7878
/**
7979
* If toolbars are intersecting, hide the scrollable toolbar content
8080
* and show the primary toolbar content. If the toolbars are not intersecting,
8181
* hide the primary toolbar content and show the scrollable toolbar content
8282
*/
8383
export const handleToolbarIntersection = (ev: any, mainHeaderIndex: HeaderIndex, scrollHeaderIndex: HeaderIndex) => {
8484
writeTask(() => {
85+
handleToolbarBorderIntersection(ev, mainHeaderIndex);
86+
8587
const event = ev[0];
88+
8689
const intersection = event.intersectionRect;
8790
const intersectionArea = intersection.width * intersection.height;
8891
const rootArea = event.rootBounds.width * event.rootBounds.height;
@@ -114,6 +117,7 @@ export const handleToolbarIntersection = (ev: any, mainHeaderIndex: HeaderIndex,
114117
if (hasValidIntersection) {
115118
setHeaderActive(mainHeaderIndex);
116119
setHeaderActive(scrollHeaderIndex, false);
120+
setToolbarBackgroundOpacity(mainHeaderIndex.toolbars[0], 1);
117121
}
118122
}
119123
});
@@ -126,7 +130,6 @@ export const setHeaderActive = (headerIndex: HeaderIndex, active = true) => {
126130
} else {
127131
headerIndex.el.classList.add('header-collapse-condense-inactive');
128132
}
129-
setToolbarBackgroundOpacity(headerIndex.toolbars[0], (active) ? undefined : 0);
130133
});
131134
};
132135

0 commit comments

Comments
 (0)