From 879e35195ae48814c7f2049159c206e32c5d56d2 Mon Sep 17 00:00:00 2001 From: Penar Musaraj Date: Wed, 29 Dec 2021 11:03:21 -0500 Subject: [PATCH] DEV: Small refactor to header offset (#15421) Centralizes calculations in a helper under the site header component. This also reverts a small CSS change to the composer: since ac79c5ef, the composer height was not including the grippie, which means that the composer height was off by 11 pixels, and the topic progress widget was sometimes being displayed cut off by 11 pixels. --- .../discourse/app/components/composer-body.js | 4 +-- .../discourse/app/components/site-header.js | 25 ++++++++----------- .../app/components/topic-timeline.js | 9 ++----- .../discourse/app/lib/sticky-avatars.js | 13 +++++----- app/assets/stylesheets/desktop/compose.scss | 3 +-- .../initializers/new-user-narrative.js | 10 ++------ 6 files changed, 24 insertions(+), 40 deletions(-) diff --git a/app/assets/javascripts/discourse/app/components/composer-body.js b/app/assets/javascripts/discourse/app/components/composer-body.js index 4be24a8df8d..24e560b67d0 100644 --- a/app/assets/javascripts/discourse/app/components/composer-body.js +++ b/app/assets/javascripts/discourse/app/components/composer-body.js @@ -8,7 +8,7 @@ import Composer from "discourse/models/composer"; import KeyEnterEscape from "discourse/mixins/key-enter-escape"; import afterTransition from "discourse/lib/after-transition"; import discourseDebounce from "discourse-common/lib/debounce"; -import { headerHeight } from "discourse/components/site-header"; +import { headerOffset } from "discourse/components/site-header"; import positioningWorkaround from "discourse/lib/safari-hacks"; const START_DRAG_EVENTS = ["touchstart", "mousedown"]; @@ -130,7 +130,7 @@ export default Component.extend(KeyEnterEscape, { const currentMousePos = mouseYPos(event); let size = this.origComposerSize + (this.lastMousePos - currentMousePos); - size = Math.min(size, window.innerHeight - headerHeight()); + size = Math.min(size, window.innerHeight - headerOffset()); this.movePanels(size); this.element.style.height = size ? `${size}px` : ""; }, diff --git a/app/assets/javascripts/discourse/app/components/site-header.js b/app/assets/javascripts/discourse/app/components/site-header.js index 3130a77b127..febba56a795 100644 --- a/app/assets/javascripts/discourse/app/components/site-header.js +++ b/app/assets/javascripts/discourse/app/components/site-header.js @@ -183,13 +183,13 @@ const SiteHeaderComponent = MountWidget.extend( } const headerRect = header.getBoundingClientRect(); - let headerOffset = headerRect.top + headerRect.height; + let headerOffsetCalc = headerRect.top + headerRect.height; if (window.scrollY < 0) { - headerOffset += window.scrollY; + headerOffsetCalc += window.scrollY; } - const newValue = `${headerOffset}px`; + const newValue = `${headerOffsetCalc}px`; if (newValue !== this.currentHeaderOffsetValue) { this.currentHeaderOffsetValue = newValue; document.documentElement.style.setProperty("--header-offset", newValue); @@ -389,7 +389,7 @@ const SiteHeaderComponent = MountWidget.extend( headerCloak.style.display = "block"; } - const menuTop = this.site.mobileView ? headerTop() : headerHeight(); + const menuTop = this.site.mobileView ? headerTop() : headerOffset(); const winHeightOffset = 16; let initialWinHeight = window.innerHeight; @@ -438,16 +438,13 @@ export default SiteHeaderComponent.extend({ classNames: ["d-header-wrap"], }); -export function headerHeight() { - const header = document.querySelector("header.d-header"); - - // Header may not exist in tests (e.g. in the user menu component test). - if (!header) { - return 0; - } - - const headerOffsetTop = header.offsetTop ? header.offsetTop : 0; - return header.offsetHeight + headerOffsetTop - document.body.scrollTop; +export function headerOffset() { + return ( + parseInt( + document.documentElement.style.getPropertyValue("--header-offset"), + 10 + ) || 0 + ); } export function headerTop() { diff --git a/app/assets/javascripts/discourse/app/components/topic-timeline.js b/app/assets/javascripts/discourse/app/components/topic-timeline.js index 5baa3b75ca4..5a60bc9be27 100644 --- a/app/assets/javascripts/discourse/app/components/topic-timeline.js +++ b/app/assets/javascripts/discourse/app/components/topic-timeline.js @@ -1,5 +1,6 @@ import Docking from "discourse/mixins/docking"; import MountWidget from "discourse/components/mount-widget"; +import { headerOffset } from "discourse/components/site-header"; import { next } from "@ember/runloop"; import { observes } from "discourse-common/utils/decorators"; import optionalService from "discourse/lib/optional-service"; @@ -50,7 +51,7 @@ export default MountWidget.extend(Docking, { const timelineHeight = (timeline && timeline.offsetHeight) || 400; const prev = this.dockAt; - const posTop = this.headerOffset() + window.pageYOffset; + const posTop = headerOffset() + window.pageYOffset; const pos = posTop + timelineHeight; this.dockBottom = false; @@ -72,12 +73,6 @@ export default MountWidget.extend(Docking, { } }, - headerOffset() { - return ( - parseInt(document.body.style.getPropertyValue("--header-offset"), 10) || 0 - ); - }, - didInsertElement() { this._super(...arguments); diff --git a/app/assets/javascripts/discourse/app/lib/sticky-avatars.js b/app/assets/javascripts/discourse/app/lib/sticky-avatars.js index 7e1d319cfb9..0ab533b97a9 100644 --- a/app/assets/javascripts/discourse/app/lib/sticky-avatars.js +++ b/app/assets/javascripts/discourse/app/lib/sticky-avatars.js @@ -1,6 +1,7 @@ import { addWidgetCleanCallback } from "discourse/components/mount-widget"; import Site from "discourse/models/site"; import { bind } from "discourse-common/utils/decorators"; +import { headerOffset } from "discourse/components/site-header"; import { schedule } from "@ember/runloop"; export default class StickyAvatars { @@ -78,11 +79,6 @@ export default class StickyAvatars { @bind _initIntersectionObserver() { schedule("afterRender", () => { - const headerOffset = - parseInt(document.body.style.getPropertyValue("--header-offset"), 10) || - 0; - const headerHeight = Math.max(headerOffset, 0); - this.intersectionObserver = new IntersectionObserver( (entries) => { entries.forEach((entry) => { @@ -95,13 +91,16 @@ export default class StickyAvatars { ?.clientHeight; if ( this.direction === "⬆️" || - postContentHeight > window.innerHeight - headerHeight + postContentHeight > window.innerHeight - headerOffset() ) { entry.target.classList.add(this.stickyClass); } }); }, - { threshold: [0.0, 1.0], rootMargin: `-${headerHeight}px 0px 0px 0px` } + { + threshold: [0.0, 1.0], + rootMargin: `-${headerOffset()}px 0px 0px 0px`, + } ); }); } diff --git a/app/assets/stylesheets/desktop/compose.scss b/app/assets/stylesheets/desktop/compose.scss index f08114e3c63..d7d32ac0497 100644 --- a/app/assets/stylesheets/desktop/compose.scss +++ b/app/assets/stylesheets/desktop/compose.scss @@ -3,7 +3,7 @@ margin: 0 auto; padding: 8px; box-sizing: border-box; - height: 100%; + height: calc(100% - 11px); width: 100%; .submit-panel { @@ -60,7 +60,6 @@ cursor: row-resize; padding: 4px 0; background: var(--tertiary); - margin-top: -11px; &:before { content: ""; diff --git a/plugins/discourse-narrative-bot/assets/javascripts/initializers/new-user-narrative.js b/plugins/discourse-narrative-bot/assets/javascripts/initializers/new-user-narrative.js index 7072e9d4b96..272d4930c3b 100644 --- a/plugins/discourse-narrative-bot/assets/javascripts/initializers/new-user-narrative.js +++ b/plugins/discourse-narrative-bot/assets/javascripts/initializers/new-user-narrative.js @@ -1,5 +1,6 @@ import { ajax } from "discourse/lib/ajax"; import discourseDebounce from "discourse-common/lib/debounce"; +import { headerOffset } from "discourse/components/site-header"; import isElementInViewport from "discourse/lib/is-element-in-viewport"; import { withPluginApi } from "discourse/lib/plugin-api"; @@ -85,17 +86,10 @@ function initialize(api) { return; } - const headerOffset = - parseInt( - getComputedStyle(document.body).getPropertyValue( - "--header-offset" - ), - 10 - ) || 0; const viewportOffset = post.getBoundingClientRect(); window.scrollTo({ - top: window.scrollY + viewportOffset.top - headerOffset, + top: window.scrollY + viewportOffset.top - headerOffset(), behavior: "smooth", }); },