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.
This commit is contained in:
Penar Musaraj 2021-12-29 11:03:21 -05:00 committed by GitHub
parent 108c8302fb
commit 879e35195a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 24 additions and 40 deletions

View File

@ -8,7 +8,7 @@ import Composer from "discourse/models/composer";
import KeyEnterEscape from "discourse/mixins/key-enter-escape"; import KeyEnterEscape from "discourse/mixins/key-enter-escape";
import afterTransition from "discourse/lib/after-transition"; import afterTransition from "discourse/lib/after-transition";
import discourseDebounce from "discourse-common/lib/debounce"; 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"; import positioningWorkaround from "discourse/lib/safari-hacks";
const START_DRAG_EVENTS = ["touchstart", "mousedown"]; const START_DRAG_EVENTS = ["touchstart", "mousedown"];
@ -130,7 +130,7 @@ export default Component.extend(KeyEnterEscape, {
const currentMousePos = mouseYPos(event); const currentMousePos = mouseYPos(event);
let size = this.origComposerSize + (this.lastMousePos - currentMousePos); 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.movePanels(size);
this.element.style.height = size ? `${size}px` : ""; this.element.style.height = size ? `${size}px` : "";
}, },

View File

@ -183,13 +183,13 @@ const SiteHeaderComponent = MountWidget.extend(
} }
const headerRect = header.getBoundingClientRect(); const headerRect = header.getBoundingClientRect();
let headerOffset = headerRect.top + headerRect.height; let headerOffsetCalc = headerRect.top + headerRect.height;
if (window.scrollY < 0) { if (window.scrollY < 0) {
headerOffset += window.scrollY; headerOffsetCalc += window.scrollY;
} }
const newValue = `${headerOffset}px`; const newValue = `${headerOffsetCalc}px`;
if (newValue !== this.currentHeaderOffsetValue) { if (newValue !== this.currentHeaderOffsetValue) {
this.currentHeaderOffsetValue = newValue; this.currentHeaderOffsetValue = newValue;
document.documentElement.style.setProperty("--header-offset", newValue); document.documentElement.style.setProperty("--header-offset", newValue);
@ -389,7 +389,7 @@ const SiteHeaderComponent = MountWidget.extend(
headerCloak.style.display = "block"; headerCloak.style.display = "block";
} }
const menuTop = this.site.mobileView ? headerTop() : headerHeight(); const menuTop = this.site.mobileView ? headerTop() : headerOffset();
const winHeightOffset = 16; const winHeightOffset = 16;
let initialWinHeight = window.innerHeight; let initialWinHeight = window.innerHeight;
@ -438,16 +438,13 @@ export default SiteHeaderComponent.extend({
classNames: ["d-header-wrap"], classNames: ["d-header-wrap"],
}); });
export function headerHeight() { export function headerOffset() {
const header = document.querySelector("header.d-header"); return (
parseInt(
// Header may not exist in tests (e.g. in the user menu component test). document.documentElement.style.getPropertyValue("--header-offset"),
if (!header) { 10
return 0; ) || 0
} );
const headerOffsetTop = header.offsetTop ? header.offsetTop : 0;
return header.offsetHeight + headerOffsetTop - document.body.scrollTop;
} }
export function headerTop() { export function headerTop() {

View File

@ -1,5 +1,6 @@
import Docking from "discourse/mixins/docking"; import Docking from "discourse/mixins/docking";
import MountWidget from "discourse/components/mount-widget"; import MountWidget from "discourse/components/mount-widget";
import { headerOffset } from "discourse/components/site-header";
import { next } from "@ember/runloop"; import { next } from "@ember/runloop";
import { observes } from "discourse-common/utils/decorators"; import { observes } from "discourse-common/utils/decorators";
import optionalService from "discourse/lib/optional-service"; import optionalService from "discourse/lib/optional-service";
@ -50,7 +51,7 @@ export default MountWidget.extend(Docking, {
const timelineHeight = (timeline && timeline.offsetHeight) || 400; const timelineHeight = (timeline && timeline.offsetHeight) || 400;
const prev = this.dockAt; const prev = this.dockAt;
const posTop = this.headerOffset() + window.pageYOffset; const posTop = headerOffset() + window.pageYOffset;
const pos = posTop + timelineHeight; const pos = posTop + timelineHeight;
this.dockBottom = false; this.dockBottom = false;
@ -72,12 +73,6 @@ export default MountWidget.extend(Docking, {
} }
}, },
headerOffset() {
return (
parseInt(document.body.style.getPropertyValue("--header-offset"), 10) || 0
);
},
didInsertElement() { didInsertElement() {
this._super(...arguments); this._super(...arguments);

View File

@ -1,6 +1,7 @@
import { addWidgetCleanCallback } from "discourse/components/mount-widget"; import { addWidgetCleanCallback } from "discourse/components/mount-widget";
import Site from "discourse/models/site"; import Site from "discourse/models/site";
import { bind } from "discourse-common/utils/decorators"; import { bind } from "discourse-common/utils/decorators";
import { headerOffset } from "discourse/components/site-header";
import { schedule } from "@ember/runloop"; import { schedule } from "@ember/runloop";
export default class StickyAvatars { export default class StickyAvatars {
@ -78,11 +79,6 @@ export default class StickyAvatars {
@bind @bind
_initIntersectionObserver() { _initIntersectionObserver() {
schedule("afterRender", () => { schedule("afterRender", () => {
const headerOffset =
parseInt(document.body.style.getPropertyValue("--header-offset"), 10) ||
0;
const headerHeight = Math.max(headerOffset, 0);
this.intersectionObserver = new IntersectionObserver( this.intersectionObserver = new IntersectionObserver(
(entries) => { (entries) => {
entries.forEach((entry) => { entries.forEach((entry) => {
@ -95,13 +91,16 @@ export default class StickyAvatars {
?.clientHeight; ?.clientHeight;
if ( if (
this.direction === "⬆️" || this.direction === "⬆️" ||
postContentHeight > window.innerHeight - headerHeight postContentHeight > window.innerHeight - headerOffset()
) { ) {
entry.target.classList.add(this.stickyClass); 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`,
}
); );
}); });
} }

View File

@ -3,7 +3,7 @@
margin: 0 auto; margin: 0 auto;
padding: 8px; padding: 8px;
box-sizing: border-box; box-sizing: border-box;
height: 100%; height: calc(100% - 11px);
width: 100%; width: 100%;
.submit-panel { .submit-panel {
@ -60,7 +60,6 @@
cursor: row-resize; cursor: row-resize;
padding: 4px 0; padding: 4px 0;
background: var(--tertiary); background: var(--tertiary);
margin-top: -11px;
&:before { &:before {
content: ""; content: "";

View File

@ -1,5 +1,6 @@
import { ajax } from "discourse/lib/ajax"; import { ajax } from "discourse/lib/ajax";
import discourseDebounce from "discourse-common/lib/debounce"; import discourseDebounce from "discourse-common/lib/debounce";
import { headerOffset } from "discourse/components/site-header";
import isElementInViewport from "discourse/lib/is-element-in-viewport"; import isElementInViewport from "discourse/lib/is-element-in-viewport";
import { withPluginApi } from "discourse/lib/plugin-api"; import { withPluginApi } from "discourse/lib/plugin-api";
@ -85,17 +86,10 @@ function initialize(api) {
return; return;
} }
const headerOffset =
parseInt(
getComputedStyle(document.body).getPropertyValue(
"--header-offset"
),
10
) || 0;
const viewportOffset = post.getBoundingClientRect(); const viewportOffset = post.getBoundingClientRect();
window.scrollTo({ window.scrollTo({
top: window.scrollY + viewportOffset.top - headerOffset, top: window.scrollY + viewportOffset.top - headerOffset(),
behavior: "smooth", behavior: "smooth",
}); });
}, },