From 0a7aae28a7eb0270cdcd100933c01850403b66db Mon Sep 17 00:00:00 2001 From: Liam DeBeasi Date: Tue, 29 Oct 2019 14:36:26 -0400 Subject: [PATCH] fix(header): avoid flicker on collapsible header load (#19682) * fix flicker on collapse load * remove old test --- core/src/components/header/header.ios.scss | 4 +-- core/src/components/header/header.tsx | 41 +++++++++++++--------- core/src/components/header/header.utils.ts | 16 ++++----- 3 files changed, 33 insertions(+), 28 deletions(-) diff --git a/core/src/components/header/header.ios.scss b/core/src/components/header/header.ios.scss index 127d05c813..1690e02966 100644 --- a/core/src/components/header/header.ios.scss +++ b/core/src/components/header/header.ios.scss @@ -51,8 +51,8 @@ padding-bottom: 13px; } -ion-toolbar.in-toolbar ion-title, -ion-toolbar.in-toolbar ion-buttons { +.header-collapse-main ion-toolbar.in-toolbar ion-title, +.header-collapse-main ion-toolbar.in-toolbar ion-buttons { transition: all 0.2s ease-in-out; } diff --git a/core/src/components/header/header.tsx b/core/src/components/header/header.tsx index 943427cf9d..23f4c74c6a 100644 --- a/core/src/components/header/header.tsx +++ b/core/src/components/header/header.tsx @@ -2,7 +2,7 @@ import { Component, ComponentInterface, Element, Host, Prop, h, readTask, writeT import { getIonMode } from '../../global/ionic-global'; -import { cloneElement, createHeaderIndex, handleContentScroll, handleToolbarIntersection, setHeaderActive } from './header.utils'; +import { cloneElement, createHeaderIndex, handleContentScroll, handleToolbarIntersection, setHeaderActive, setToolbarBackgroundOpacity } from './header.utils'; /** * @virtualProp {"ios" | "md"} mode - The mode determines which platform styles to use. */ @@ -19,6 +19,7 @@ export class Header implements ComponentInterface { private scrollEl?: HTMLElement; private contentScrollCallback?: any; private intersectionObserver?: any; + private collapsibleMainHeader?: HTMLElement; @Element() el!: HTMLElement; @@ -77,6 +78,11 @@ export class Header implements ComponentInterface { this.scrollEl.removeEventListener('scroll', this.contentScrollCallback); this.contentScrollCallback = undefined; } + + if (this.collapsibleMainHeader) { + this.collapsibleMainHeader.classList.remove('header-collapse-main'); + this.collapsibleMainHeader = undefined; + } } private async setupCollapsibleHeader(contentEl: HTMLIonContentElement | null, pageEl: Element | null) { @@ -84,20 +90,20 @@ export class Header implements ComponentInterface { this.scrollEl = await contentEl.getScrollElement(); + const headers = pageEl.querySelectorAll('ion-header'); + this.collapsibleMainHeader = Array.from(headers).find((header: any) => header.collapse !== 'condense') as HTMLElement | undefined; + + if (!this.collapsibleMainHeader) { return; } + + const mainHeaderIndex = createHeaderIndex(this.collapsibleMainHeader); + const scrollHeaderIndex = createHeaderIndex(this.el); + + if (!mainHeaderIndex || !scrollHeaderIndex) { return; } + + setHeaderActive(mainHeaderIndex, false); + setToolbarBackgroundOpacity(mainHeaderIndex.toolbars[0], 0); + readTask(() => { - const headers = pageEl.querySelectorAll('ion-header'); - const mainHeader = Array.from(headers).find((header: any) => header.collapse !== 'condense') as HTMLElement | undefined; - - if (!mainHeader || !this.scrollEl) { return; } - - const mainHeaderIndex = createHeaderIndex(mainHeader); - const scrollHeaderIndex = createHeaderIndex(this.el); - - if (!mainHeaderIndex || !scrollHeaderIndex) { return; } - - setHeaderActive(mainHeaderIndex, false); - - readTask(() => { const mainHeaderHeight = mainHeaderIndex.el.clientHeight; /** @@ -109,20 +115,21 @@ export class Header implements ComponentInterface { const toolbarIntersection = (ev: any) => { handleToolbarIntersection(ev, mainHeaderIndex, scrollHeaderIndex); }; 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` }); this.intersectionObserver.observe(scrollHeaderIndex.toolbars[0].el); - }); /** * Handle scaling of large iOS titles and * showing/hiding border on last toolbar * in primary header */ - this.contentScrollCallback = () => { handleContentScroll(this.scrollEl!, scrollHeaderIndex); }; - this.scrollEl.addEventListener('scroll', this.contentScrollCallback); + this.contentScrollCallback = () => { handleContentScroll(this.scrollEl!, scrollHeaderIndex); }; + this.scrollEl!.addEventListener('scroll', this.contentScrollCallback); }); writeTask(() => { cloneElement('ion-title'); cloneElement('ion-back-button'); + + this.collapsibleMainHeader!.classList.add('header-collapse-main'); }); this.collapsibleHeaderInitialized = true; diff --git a/core/src/components/header/header.utils.ts b/core/src/components/header/header.utils.ts index 5f06e135c9..9f93299c40 100644 --- a/core/src/components/header/header.utils.ts +++ b/core/src/components/header/header.utils.ts @@ -45,7 +45,7 @@ export const createHeaderIndex = (headerEl: HTMLElement | undefined): HeaderInde innerTitleEl: (ionTitleEl) ? ionTitleEl.shadowRoot!.querySelector('.toolbar-title') : null, ionButtonsEl: Array.from(toolbar.querySelectorAll('ion-buttons')) || [] } as ToolbarIndex; - }) || [[]] + }) || [] } as HeaderIndex; }; @@ -60,7 +60,7 @@ export const handleContentScroll = (scrollEl: HTMLElement, scrollHeaderIndex: He }); }; -const setToolbarBackgroundOpacity = (toolbar: ToolbarIndex, opacity: number | undefined) => { +export const setToolbarBackgroundOpacity = (toolbar: ToolbarIndex, opacity: number | undefined) => { if (opacity === undefined) { toolbar.background.style.removeProperty('--opacity'); } else { @@ -124,13 +124,11 @@ export const handleToolbarIntersection = (ev: any, mainHeaderIndex: HeaderIndex, }; export const setHeaderActive = (headerIndex: HeaderIndex, active = true) => { - writeTask(() => { - if (active) { - headerIndex.el.classList.remove('header-collapse-condense-inactive'); - } else { - headerIndex.el.classList.add('header-collapse-condense-inactive'); - } - }); + if (active) { + headerIndex.el.classList.remove('header-collapse-condense-inactive'); + } else { + headerIndex.el.classList.add('header-collapse-condense-inactive'); + } }; export const scaleLargeTitles = (toolbars: ToolbarIndex[] = [], scale = 1, transition = false) => {