Skip to content

Conversation

@paulirish
Copy link
Member

it currently (on master) toggles too late because its setup to flip when the scorescale has cleared the topbar.
now that the scorescale moved... that is wrong.

i changed it to be when the top of the categories clears the topbar.


Also I added a double RAF to remove a forced layout and drop like 50ms of rendering cost. 🎉

@paulirish paulirish requested a review from a team as a code owner October 28, 2021 20:57
@paulirish paulirish requested review from adamraine and removed request for a team October 28, 2021 20:57
@google-cla google-cla bot added the cla: yes label Oct 28, 2021
@connorjclark
Copy link
Collaborator

did you test w/ yarn open-devtools?

@paulirish
Copy link
Member Author

I changed this a bunch and I think all previous comments are mostly irrelevant at this point. Hoping it's more clear whats happening.

Comment on lines 265 to 267
} catch (e) {}

if (!this.stickyHeaderEl) return;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just curious, does sticking return in the catch block narrow the type correctly?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good idea. done. (also moved it a bit)

this.highlightEl = this._dom.createChildOf(this.stickyHeaderEl, 'div', 'lh-highlighter');

// Defer behind rAF to avoid forcing layout
requestAnimationFrame(() => requestAnimationFrame(() => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why double requestAnimationFrame?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

getScrollParent forces layout. and since it currently happens during report creation, we have TWO 50ms blocks of style recalc (one forced and one normal async).

since this code can run a little later without consequence.... i figured deferring it was nice :)
doubleRaf specifically because w/ singleRaf it can still happen in the same frame (and thus still have double the rendering costs).

this would be easier to communicate had i kept the traces when i was doing this.. but alas they gone. :p

const scrollParent = this._getScrollParent(this.stickyHeaderEl);
scrollParent.addEventListener('scroll', e => this._updateStickyHeader(e));
// 'scroll' handler must be Element | Document, but resizeObserve can't be Document.
new window.ResizeObserver(e => this._updateStickyHeader(e))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: Can we bind this._updateStickyHeader instead? Also, looks tike there is no need to pass the e through.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: Can we bind this._updateStickyHeader instead?

we could. these two lines would look like this (or something close):

scrollParent.addEventListener('scroll', this._updateStickyHeader.bind(this));
new window.ResizeObserver(this._updateStickyHeader.bind(this))

i personally dont like the binding style because you create a new function object which has a separate identity from the actual implementation.

so ever since arrow functions have been a thing, i think it makes for a cleaner look without such indirection.

Also, looks tike there is no need to pass the e through.

true! good call. coulda just done a () => this.USH(). thats def better

const showStickyHeader = topbarBottom >= scoreScaleTop;
const categoriesTop = this.categoriesEl.getBoundingClientRect().top;
const showStickyHeader = topbarBottom >= categoriesTop;
console.log('showstickyheader', showStickyHeader, topbarBottom, categoriesTop);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

rm log?

document = window.document;

global.window = global.self = window;
global.window.requestAnimationFrame = fn => fn();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we use the JSDOM implementation?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

they don't have one. :) jsdom/jsdom#1963

};
};


Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit

Suggested change

global.HTMLElement = document.window.HTMLElement;
global.HTMLInputElement = document.window.HTMLInputElement;
global.HTMLInputElement = document.window.HTMLInputElement;

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit

Suggested change

@paulirish paulirish merged commit 68ba77a into master Nov 4, 2021
@paulirish paulirish deleted the stickyheadertoggle branch November 4, 2021 22:43
@brendankenny brendankenny restored the stickyheadertoggle branch November 9, 2021 17:39
@brendankenny brendankenny deleted the stickyheadertoggle branch November 9, 2021 17:40
@brendankenny brendankenny restored the stickyheadertoggle branch November 9, 2021 17:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants