From 3168a215b6538e2e6b388f57161067e65b0d048b Mon Sep 17 00:00:00 2001 From: Bryce Huhtala Date: Tue, 11 Jun 2024 11:47:46 +0200 Subject: [PATCH 01/13] DEV: Add routeType for content header --- .../navigation.gjs | 52 ++++++++++++++++++- 1 file changed, 51 insertions(+), 1 deletion(-) diff --git a/javascripts/discourse/connectors/discovery-navigation-bar-above/navigation.gjs b/javascripts/discourse/connectors/discovery-navigation-bar-above/navigation.gjs index de43d88..1d52555 100644 --- a/javascripts/discourse/connectors/discovery-navigation-bar-above/navigation.gjs +++ b/javascripts/discourse/connectors/discovery-navigation-bar-above/navigation.gjs @@ -1,4 +1,5 @@ import Component from "@glimmer/component"; +import { tracked } from "@glimmer/tracking"; // import { tracked } from "@glimmer/tracking"; // import { concat, get } from "@ember/helper"; // import { action } from "@ember/object"; @@ -18,8 +19,57 @@ export default class Breadcrumbs extends Component { @service router; @service site; + @tracked routeType; + + @action + updateRouteType() { + if (this.router?.currentRoute?.parent?.name === "discovery") { + switch (this.router?.currentRoute?.localName) { + case "latest": + case "hot": + case "top": + case "new": + case "unread": + this.routeType = "home"; + break; + case "category": + case "latestCategory": + case "hotCategory": + case "topCategory": + case "newCategory": + case "unreadCategory": + this.routeType = "category"; + break; + case "categories": + this.routeType = "categories"; + break; + default: + this.routeType = null; + break; + } + } else { + this.routeType = null; + } + } + get isHomepage() { - return this.router.currentRouteName === "discovery.latest"; + this.updateRouteType(); + return this.routeType === "home"; + } + + get isCategoryView() { + this.updateRouteType(); + return this.routeType === "category"; + } + + get isCategoryList() { + this.updateRouteType(); + return this.routeType === "categories"; + } + + get categoryName() { + return this.router?.currentRoute?.attributes?.category?.name || "Category"; + } } } +class TopicFilter extends Component { + @service router; + + @action + filterTopics(event) { + const routeType = this.args.routeType; + const category = this.router?.currentRoute?.attributes?.category; + const categoryRoute = + routeType === "category" ? `/c/${category.slug}/${category.id}/l` : ""; + switch (event.target.value) { + case "latest": + DiscourseURL.routeTo(` ${categoryRoute}/latest`); + break; + } + } + +} From 3d5de8ad1a046f618f88c844af9abe124e8a3b1c Mon Sep 17 00:00:00 2001 From: Bryce Huhtala Date: Tue, 11 Jun 2024 11:49:35 +0200 Subject: [PATCH 04/13] DEV: Category badge theme settings --- settings.yml | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/settings.yml b/settings.yml index 366c9af..45a80ac 100644 --- a/settings.yml +++ b/settings.yml @@ -105,3 +105,21 @@ blocks: default: 1x1 period: type: null +category_badges: + type: objects + default: [] + schema: + name: category_badge + properties: + category: + type: categories + required: true + badge: + type: string + description: a single emoji to use as a badge (copy and paste from https://emojipedia.org/twitter) + max_length: 1 + required: true +default_category_badge: + default: 📁 + description: a single emoji to use as a default category badge (copy and paste from https://emojipedia.org/twitter) + max: 1 \ No newline at end of file From 1e5eeae1a5966a46934e49a866b3804f52912301 Mon Sep 17 00:00:00 2001 From: Bryce Huhtala Date: Tue, 11 Jun 2024 11:50:09 +0200 Subject: [PATCH 05/13] UX: Update styling for content header --- scss/components/navigation.scss | 31 +++++++++++++++++++++++++++---- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/scss/components/navigation.scss b/scss/components/navigation.scss index cfa571a..de83a1e 100644 --- a/scss/components/navigation.scss +++ b/scss/components/navigation.scss @@ -326,6 +326,7 @@ height: 4.5rem; border-bottom: var(--border-outer); + padding: 0 1rem; &__title { @include headline-small; @@ -335,12 +336,34 @@ align-items: center; margin: 0; - padding: 0 1rem; - - &::before { - @include i; + .badge { + &[data-badge-type="icon"]{ + @include i; + } + &[data-badge-type="emoji"]{ + width: 1.25rem; + line-height: 1; + font-size: 1.25rem; + } + &[data-clickable="true"]{ + cursor: pointer; + } + display: flex; + align-items: center; + justify-content: center; + font-size: 24px; padding: 0 0.375rem; } } + &__select { + width: auto; + max-width: 180px; + + margin-left: auto; + margin-bottom: 0; + + border: none; + padding: 0 3px; + } } From b16c08e174169a9a6ef5e9d21a45359b28617f8e Mon Sep 17 00:00:00 2001 From: Bryce Huhtala Date: Tue, 11 Jun 2024 13:00:47 +0200 Subject: [PATCH 06/13] FIX: Remove commented out lines --- .../discovery-navigation-bar-above/navigation.gjs | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/javascripts/discourse/connectors/discovery-navigation-bar-above/navigation.gjs b/javascripts/discourse/connectors/discovery-navigation-bar-above/navigation.gjs index 6f83ef6..f6c73d4 100644 --- a/javascripts/discourse/connectors/discovery-navigation-bar-above/navigation.gjs +++ b/javascripts/discourse/connectors/discovery-navigation-bar-above/navigation.gjs @@ -1,19 +1,8 @@ import Component from "@glimmer/component"; import { tracked } from "@glimmer/tracking"; -// import { tracked } from "@glimmer/tracking"; -// import { concat, get } from "@ember/helper"; import { on } from "@ember/modifier"; import { action } from "@ember/object"; import { service } from "@ember/service"; -// import { htmlSafe } from "@ember/template"; -// import { eq, or } from "truth-helpers"; -// import avatar from "discourse/helpers/avatar"; -// import categoryLink from "discourse/helpers/category-link"; -// import concatClass from "discourse/helpers/concat-class"; -// import number from "discourse/helpers/number"; -// import replaceEmoji from "discourse/helpers/replace-emoji"; -// import { ajax } from "discourse/lib/ajax"; -// import Category from "discourse/models/category"; import DiscourseURL from "discourse/lib/url"; import i18n from "discourse-common/helpers/i18n"; From deeff7aeefe3e6f9a7ef66e3e669bc380b5980d9 Mon Sep 17 00:00:00 2001 From: Bryce Huhtala Date: Wed, 12 Jun 2024 15:27:49 +0200 Subject: [PATCH 07/13] DEV: Add back button to topic content header --- .../discourse/connectors/topic-title/back.hbs | 4 ++++ scss/discourse/topic.scss | 15 ++++++++++++++- 2 files changed, 18 insertions(+), 1 deletion(-) create mode 100644 javascripts/discourse/connectors/topic-title/back.hbs diff --git a/javascripts/discourse/connectors/topic-title/back.hbs b/javascripts/discourse/connectors/topic-title/back.hbs new file mode 100644 index 0000000..67827d7 --- /dev/null +++ b/javascripts/discourse/connectors/topic-title/back.hbs @@ -0,0 +1,4 @@ +{{#unless this.model.isPrivateMessage}} + + +{{/unless}} \ No newline at end of file diff --git a/scss/discourse/topic.scss b/scss/discourse/topic.scss index 657715b..a836068 100644 --- a/scss/discourse/topic.scss +++ b/scss/discourse/topic.scss @@ -1,4 +1,5 @@ #topic-title { + display: flex; border-bottom: var(--border-outer); padding: 1rem; margin: 0; @@ -9,6 +10,18 @@ color: var(--neutral-10); } } + .topic-title-outlet { + padding-top: 8px; + order: -1; + .topic-back-button { + &:before { + @include i; + padding-left: 12px; + padding-right: 16px; + content: "arrow_back"; + } + } + } } .more-topics__container .nav { @@ -187,4 +200,4 @@ } } } -} +} \ No newline at end of file From 951cee6b6fbb5974f43504c9236a6480b9acab63 Mon Sep 17 00:00:00 2001 From: Bryce Huhtala Date: Wed, 12 Jun 2024 15:28:11 +0200 Subject: [PATCH 08/13] UX: Capitalize categories route --- .../discovery-navigation-bar-above/navigation.gjs | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/javascripts/discourse/connectors/discovery-navigation-bar-above/navigation.gjs b/javascripts/discourse/connectors/discovery-navigation-bar-above/navigation.gjs index f6c73d4..990e2e8 100644 --- a/javascripts/discourse/connectors/discovery-navigation-bar-above/navigation.gjs +++ b/javascripts/discourse/connectors/discovery-navigation-bar-above/navigation.gjs @@ -3,9 +3,11 @@ import { tracked } from "@glimmer/tracking"; import { on } from "@ember/modifier"; import { action } from "@ember/object"; import { service } from "@ember/service"; +import { capitalize } from "@ember/string"; import DiscourseURL from "discourse/lib/url"; import i18n from "discourse-common/helpers/i18n"; + export default class Breadcrumbs extends Component { @service router; @service site; @@ -43,6 +45,10 @@ export default class Breadcrumbs extends Component { } } + get shouldShowFilters() { + return this.routerType === "home" || this.routerType === "category"; + } + get isHomepage() { this.updateRouteType(); return this.routeType === "home"; @@ -124,10 +130,12 @@ export default class Breadcrumbs extends Component { > 🗃️ - Categories + {{capitalize (i18n "js.categories.categories_label")}} {{/if}} + {{#if this.shouldShowFilters}} + {{/if}} } @@ -155,6 +163,5 @@ class TopicFilter extends Component { Top - {{@routeType}} } From 8de5a6f450fc6634843c61f37c6186340e467169 Mon Sep 17 00:00:00 2001 From: Bryce Huhtala Date: Thu, 13 Jun 2024 14:23:19 +0200 Subject: [PATCH 09/13] DEV: Add more filter types --- .../navigation.gjs | 41 +++++++++++-------- 1 file changed, 24 insertions(+), 17 deletions(-) diff --git a/javascripts/discourse/connectors/discovery-navigation-bar-above/navigation.gjs b/javascripts/discourse/connectors/discovery-navigation-bar-above/navigation.gjs index 990e2e8..cfab53c 100644 --- a/javascripts/discourse/connectors/discovery-navigation-bar-above/navigation.gjs +++ b/javascripts/discourse/connectors/discovery-navigation-bar-above/navigation.gjs @@ -4,10 +4,8 @@ import { on } from "@ember/modifier"; import { action } from "@ember/object"; import { service } from "@ember/service"; import { capitalize } from "@ember/string"; -import DiscourseURL from "discourse/lib/url"; import i18n from "discourse-common/helpers/i18n"; - export default class Breadcrumbs extends Component { @service router; @service site; @@ -46,7 +44,7 @@ export default class Breadcrumbs extends Component { } get shouldShowFilters() { - return this.routerType === "home" || this.routerType === "category"; + return this.routeType === "home" || this.routeType === "category"; } get isHomepage() { @@ -71,11 +69,10 @@ export default class Breadcrumbs extends Component { get categoryBadge() { const defaultBadge = settings.default_category_badge || "📁"; - const badge = settings.category_badges?.find( - (categoryBadgeSetting) => - categoryBadgeSetting.category[0] === - this.router?.currentRoute?.attributes?.category?.id - )?.badge; + const badge = settings.category_icons?.find( + (category) => + category.id[0] === this.router?.currentRoute?.attributes?.category?.id + )?.emoji; if (!badge) { return defaultBadge; @@ -134,7 +131,7 @@ export default class Breadcrumbs extends Component { {{/if}} {{#if this.shouldShowFilters}} - + {{/if}} @@ -146,21 +143,31 @@ class TopicFilter extends Component { filterTopics(event) { const routeType = this.args.routeType; const category = this.router?.currentRoute?.attributes?.category; - const categoryRoute = - routeType === "category" ? `/c/${category.slug}/${category.id}/l` : ""; - switch (event.target.value) { - case "latest": - DiscourseURL.routeTo(` ${categoryRoute}/latest`); - break; + + if (routeType === "category") { + this.router.transitionTo( + `/c/${category.slug}/${category.id}/l/${event.target.value}` + ); + } else { + this.router.transitionTo(`/${event.target.value}`); } } From 4b5e1d1963f5e80dd6aa3b827fc7477ff582d448 Mon Sep 17 00:00:00 2001 From: Bryce Huhtala Date: Tue, 18 Jun 2024 13:14:57 +0200 Subject: [PATCH 10/13] DEV: Adjust filter to work with site settings --- .../navigation.gjs | 50 +++++++++++-------- settings.yml | 4 +- 2 files changed, 30 insertions(+), 24 deletions(-) diff --git a/javascripts/discourse/connectors/discovery-navigation-bar-above/navigation.gjs b/javascripts/discourse/connectors/discovery-navigation-bar-above/navigation.gjs index cfab53c..5976e52 100644 --- a/javascripts/discourse/connectors/discovery-navigation-bar-above/navigation.gjs +++ b/javascripts/discourse/connectors/discovery-navigation-bar-above/navigation.gjs @@ -4,6 +4,7 @@ import { on } from "@ember/modifier"; import { action } from "@ember/object"; import { service } from "@ember/service"; import { capitalize } from "@ember/string"; +import { eq } from "truth-helpers"; import i18n from "discourse-common/helpers/i18n"; export default class Breadcrumbs extends Component { @@ -43,8 +44,11 @@ export default class Breadcrumbs extends Component { } } - get shouldShowFilters() { - return this.routeType === "home" || this.routeType === "category"; + get filterType() { + if (this.router?.currentRoute?.localName === "categories") { + return "categories"; + } + return this.router?.currentRoute?.attributes?.filterType || ""; } get isHomepage() { @@ -130,21 +134,28 @@ export default class Breadcrumbs extends Component { {{capitalize (i18n "js.categories.categories_label")}} {{/if}} - {{#if this.shouldShowFilters}} - - {{/if}} + } class TopicFilter extends Component { @service router; + @service site; + + @tracked filterOptions; + + constructor() { + super(...arguments); + + this.filterOptions = this.site.siteSettings?.top_menu?.split("|") || []; + } @action filterTopics(event) { const routeType = this.args.routeType; const category = this.router?.currentRoute?.attributes?.category; - if (routeType === "category") { + if (routeType === "category" && event.target.value !== "categories") { this.router.transitionTo( `/c/${category.slug}/${category.id}/l/${event.target.value}` ); @@ -152,23 +163,18 @@ class TopicFilter extends Component { this.router.transitionTo(`/${event.target.value}`); } } + } diff --git a/settings.yml b/settings.yml index c9b238a..ddafa38 100644 --- a/settings.yml +++ b/settings.yml @@ -136,7 +136,7 @@ category_badges: description: a single emoji to use as a badge (copy and paste from https://emojipedia.org/twitter) max_length: 1 required: true -default_category_badge: +default_category_icon: default: 📁 - description: a single emoji to use as a default category badge (copy and paste from https://emojipedia.org/twitter) + description: a single emoji to use as a default category icon (copy and paste from https://emojipedia.org/twitter) max: 1 \ No newline at end of file From 7cbfe0b93a4280153587be2268cf67ac719dc7df Mon Sep 17 00:00:00 2001 From: Bryce Huhtala Date: Tue, 18 Jun 2024 13:15:36 +0200 Subject: [PATCH 11/13] DEV: Add sticky sidebar --- .../discourse/components/sticky-sidebar.hbs | 9 +++ .../discourse/components/sticky-sidebar.js | 64 +++++++++++++++++++ .../connectors/before-main-outlet/blocks.gjs | 39 +++++------ javascripts/discourse/modifiers/scroll.js | 11 ++++ scss/layout.scss | 4 ++ 5 files changed, 109 insertions(+), 18 deletions(-) create mode 100644 javascripts/discourse/components/sticky-sidebar.hbs create mode 100644 javascripts/discourse/components/sticky-sidebar.js create mode 100644 javascripts/discourse/modifiers/scroll.js diff --git a/javascripts/discourse/components/sticky-sidebar.hbs b/javascripts/discourse/components/sticky-sidebar.hbs new file mode 100644 index 0000000..e9739ad --- /dev/null +++ b/javascripts/discourse/components/sticky-sidebar.hbs @@ -0,0 +1,9 @@ + \ No newline at end of file diff --git a/javascripts/discourse/components/sticky-sidebar.js b/javascripts/discourse/components/sticky-sidebar.js new file mode 100644 index 0000000..6ccc103 --- /dev/null +++ b/javascripts/discourse/components/sticky-sidebar.js @@ -0,0 +1,64 @@ +import Component from "@glimmer/component"; +import { tracked } from "@glimmer/tracking"; +import { action } from "@ember/object"; + +export default class StickySidebar extends Component { + @tracked top = 0; + @tracked position = 'relative'; + + offset = 0; + prevScrollTop = 0; + + constructor() { + super(...arguments); + this.offset = 0; + } + + @action + onScroll() { + const scrollY = window.scrollY; + const scrollingUp = scrollY < this.prevScrollTop; + const scrollingDown = scrollY > this.prevScrollTop; + const element = this.element; + const topDist = element.offsetTop; + const stickyTop = 104; + const stickyBot = window.innerHeight - element.getBoundingClientRect().height + 104; + + if (scrollingUp) { + if (isTopInView(element)) { + this.position = 'sticky'; + this.top = stickyTop; + } else if (isBottomInView(element)) { + this.position = 'relative'; + this.top = topDist - this.offset; + } + } else if (scrollingDown) { + if (isTopInView(element)) { + this.position = 'relative'; + this.top = topDist - this.offset; + } else if (isBottomInView(element)) { + this.position = 'sticky'; + this.top = stickyBot - 208; + } + } + + this.prevScrollTop = scrollY; + } + + @action + didInsert(element) { + this.element = element; + this.offset = this.element.offsetTop; + } +} + +function isTopInView(element) { + const rect = element.getBoundingClientRect(); + return rect.top >= 104 && rect.top <= window.innerHeight; +} + +function isBottomInView(element) { + const rect = element.getBoundingClientRect(); + return rect.bottom >= 0 && rect.bottom+104 <= window.innerHeight; +} + diff --git a/javascripts/discourse/connectors/before-main-outlet/blocks.gjs b/javascripts/discourse/connectors/before-main-outlet/blocks.gjs index 2d7bffe..cc2a653 100644 --- a/javascripts/discourse/connectors/before-main-outlet/blocks.gjs +++ b/javascripts/discourse/connectors/before-main-outlet/blocks.gjs @@ -7,6 +7,7 @@ import BlockProfile from "../../components/blocks/profile"; import BlockTime from "../../components/blocks/time"; import BlockTopContributors from "../../components/blocks/top-contributors"; import BlockTopTopics from "../../components/blocks/top-topics"; +import StickySidebarComponent from "../../components/sticky-sidebar"; export default class BlocksComponent extends Component { @service currentUser; @@ -39,24 +40,26 @@ export default class BlocksComponent extends Component { } diff --git a/javascripts/discourse/modifiers/scroll.js b/javascripts/discourse/modifiers/scroll.js new file mode 100644 index 0000000..09a8c22 --- /dev/null +++ b/javascripts/discourse/modifiers/scroll.js @@ -0,0 +1,11 @@ +import { modifier } from 'ember-modifier'; + +export default modifier((element, [callback]) => { + const handleScroll = () => callback(); + + window.addEventListener('scroll', handleScroll); + + return () => { + window.removeEventListener('scroll', handleScroll); + }; +}); diff --git a/scss/layout.scss b/scss/layout.scss index 63b3e05..99dfa63 100644 --- a/scss/layout.scss +++ b/scss/layout.scss @@ -91,6 +91,10 @@ body { padding-left: 0; } + .sticky-sidebar { + display: unset; + } + .blocks { grid-area: right; } From b6e577fbd56b15a5eb8736e0094ceb4129dd60c4 Mon Sep 17 00:00:00 2001 From: Bryce Huhtala Date: Wed, 19 Jun 2024 14:13:02 +0200 Subject: [PATCH 12/13] DEV: Use localized filter titles --- .../discovery-navigation-bar-above/navigation.gjs | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/javascripts/discourse/connectors/discovery-navigation-bar-above/navigation.gjs b/javascripts/discourse/connectors/discovery-navigation-bar-above/navigation.gjs index 5976e52..adc3bbd 100644 --- a/javascripts/discourse/connectors/discovery-navigation-bar-above/navigation.gjs +++ b/javascripts/discourse/connectors/discovery-navigation-bar-above/navigation.gjs @@ -134,7 +134,10 @@ export default class Breadcrumbs extends Component { {{capitalize (i18n "js.categories.categories_label")}} {{/if}} - + } @@ -147,7 +150,10 @@ class TopicFilter extends Component { constructor() { super(...arguments); - this.filterOptions = this.site.siteSettings?.top_menu?.split("|") || []; + this.filterOptions = + this.site.siteSettings?.top_menu?.split("|").map((item) => { + return { name: item, localization: `js.filters.${item}.title` }; + }) || []; } @action @@ -171,8 +177,8 @@ class TopicFilter extends Component { onchange={{this.filterTopics}} > {{#each this.filterOptions as |filterOption|}} - {{/each}} From f117a75b5df87af7395002e7005c322a2148f299 Mon Sep 17 00:00:00 2001 From: Bryce Huhtala Date: Wed, 19 Jun 2024 14:16:51 +0200 Subject: [PATCH 13/13] DEV: Sticky sidebar --- .../discourse/components/sticky-sidebar.hbs | 10 ++- .../discourse/components/sticky-sidebar.js | 62 ++++++++++++------- 2 files changed, 47 insertions(+), 25 deletions(-) diff --git a/javascripts/discourse/components/sticky-sidebar.hbs b/javascripts/discourse/components/sticky-sidebar.hbs index e9739ad..b8105a5 100644 --- a/javascripts/discourse/components/sticky-sidebar.hbs +++ b/javascripts/discourse/components/sticky-sidebar.hbs @@ -2,7 +2,15 @@
{{yield}}
diff --git a/javascripts/discourse/components/sticky-sidebar.js b/javascripts/discourse/components/sticky-sidebar.js index 6ccc103..d9e4241 100644 --- a/javascripts/discourse/components/sticky-sidebar.js +++ b/javascripts/discourse/components/sticky-sidebar.js @@ -4,15 +4,13 @@ import { action } from "@ember/object"; export default class StickySidebar extends Component { @tracked top = 0; - @tracked position = 'relative'; + @tracked bottom = 0; + @tracked position = "relative"; offset = 0; prevScrollTop = 0; - - constructor() { - super(...arguments); - this.offset = 0; - } + yOrigin = 0; + mode = "unset"; @action onScroll() { @@ -20,28 +18,39 @@ export default class StickySidebar extends Component { const scrollingUp = scrollY < this.prevScrollTop; const scrollingDown = scrollY > this.prevScrollTop; const element = this.element; - const topDist = element.offsetTop; - const stickyTop = 104; - const stickyBot = window.innerHeight - element.getBoundingClientRect().height + 104; + if (!this.yOrigin) { + // save the initial vertical position + this.yOrigin = getYOrigin(this.element); + } + const stickyTop = this.yOrigin; if (scrollingUp) { - if (isTopInView(element)) { - this.position = 'sticky'; + if (isTopInView(element, this.yOrigin)) { + this.mode = "top"; + this.position = "fixed"; this.top = stickyTop; - } else if (isBottomInView(element)) { - this.position = 'relative'; - this.top = topDist - this.offset; + this.bottom = "unset"; + } + if (this.mode === "bottom") { + this.mode = "between"; + const top = element.getBoundingClientRect().top; + this.position = "relative"; + this.top = top + scrollY - this.yOrigin; } } else if (scrollingDown) { - if (isTopInView(element)) { - this.position = 'relative'; - this.top = topDist - this.offset; - } else if (isBottomInView(element)) { - this.position = 'sticky'; - this.top = stickyBot - 208; + if (isBottomInView(element, this.yOrigin)) { + this.mode = "bottom"; + this.position = "fixed"; + this.bottom = 0; + this.top = "unset"; + } + if (this.mode === "top") { + this.mode = "between"; + const top = element.getBoundingClientRect().top; + this.position = "relative"; + this.top = top + scrollY - this.yOrigin; } } - this.prevScrollTop = scrollY; } @@ -52,13 +61,18 @@ export default class StickySidebar extends Component { } } -function isTopInView(element) { +function isTopInView(element, yOffset) { const rect = element.getBoundingClientRect(); - return rect.top >= 104 && rect.top <= window.innerHeight; + return rect.top >= yOffset && rect.top <= window.innerHeight; } function isBottomInView(element) { const rect = element.getBoundingClientRect(); - return rect.bottom >= 0 && rect.bottom+104 <= window.innerHeight; + return rect.bottom >= 0 && rect.bottom <= window.innerHeight; } +function getYOrigin(el) { + const rect = el.getBoundingClientRect(); + const scrollTop = window.scrollY || window.pageYOffset; + return rect.top + scrollTop; +}