-
Notifications
You must be signed in to change notification settings - Fork 11
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* DEV: Add routeType for content header * DEV: Make conent header dynamic * DEV: Add topic filter to content header * DEV: Category badge theme settings * UX: Update styling for content header * FIX: Remove commented out lines * DEV: Add back button to topic content header * UX: Capitalize categories route * DEV: Add more filter types * DEV: Adjust filter to work with site settings * DEV: Add sticky sidebar * DEV: Use localized filter titles * DEV: Sticky sidebar
- Loading branch information
Showing
10 changed files
with
360 additions
and
37 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
<div class="sticky-sidebar"> | ||
<div | ||
{{did-insert this.didInsert}} | ||
{{scroll this.onScroll}} | ||
style={{concat | ||
"position: " | ||
this.position | ||
"; top: " | ||
this.top | ||
"px; bottom: " | ||
this.bottom | ||
"px" | ||
}} | ||
> | ||
{{yield}} | ||
</div> | ||
</div> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
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 bottom = 0; | ||
@tracked position = "relative"; | ||
|
||
offset = 0; | ||
prevScrollTop = 0; | ||
yOrigin = 0; | ||
mode = "unset"; | ||
|
||
@action | ||
onScroll() { | ||
const scrollY = window.scrollY; | ||
const scrollingUp = scrollY < this.prevScrollTop; | ||
const scrollingDown = scrollY > this.prevScrollTop; | ||
const element = this.element; | ||
if (!this.yOrigin) { | ||
// save the initial vertical position | ||
this.yOrigin = getYOrigin(this.element); | ||
} | ||
const stickyTop = this.yOrigin; | ||
|
||
if (scrollingUp) { | ||
if (isTopInView(element, this.yOrigin)) { | ||
this.mode = "top"; | ||
this.position = "fixed"; | ||
this.top = stickyTop; | ||
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 (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; | ||
} | ||
|
||
@action | ||
didInsert(element) { | ||
this.element = element; | ||
this.offset = this.element.offsetTop; | ||
} | ||
} | ||
|
||
function isTopInView(element, yOffset) { | ||
const rect = element.getBoundingClientRect(); | ||
return rect.top >= yOffset && rect.top <= window.innerHeight; | ||
} | ||
|
||
function isBottomInView(element) { | ||
const rect = element.getBoundingClientRect(); | ||
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; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
180 changes: 166 additions & 14 deletions
180
javascripts/discourse/connectors/discovery-navigation-bar-above/navigation.gjs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,34 +1,186 @@ | ||
import Component from "@glimmer/component"; | ||
// import { tracked } from "@glimmer/tracking"; | ||
// import { concat, get } from "@ember/helper"; | ||
// import { action } from "@ember/object"; | ||
import { tracked } from "@glimmer/tracking"; | ||
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 { capitalize } from "@ember/string"; | ||
import { eq } from "truth-helpers"; | ||
import i18n from "discourse-common/helpers/i18n"; | ||
|
||
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 filterType() { | ||
if (this.router?.currentRoute?.localName === "categories") { | ||
return "categories"; | ||
} | ||
return this.router?.currentRoute?.attributes?.filterType || ""; | ||
} | ||
|
||
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"; | ||
} | ||
|
||
get categoryBadge() { | ||
const defaultBadge = settings.default_category_badge || "📁"; | ||
|
||
const badge = settings.category_icons?.find( | ||
(category) => | ||
category.id[0] === this.router?.currentRoute?.attributes?.category?.id | ||
)?.emoji; | ||
|
||
if (!badge) { | ||
return defaultBadge; | ||
} | ||
|
||
try { | ||
// check for valid emoji | ||
const regex = /\p{Emoji}/u; | ||
if (regex.test(badge)) { | ||
return badge; | ||
} | ||
return defaultBadge; | ||
} catch (e) { | ||
// \p{Emoji} not supported -> skip validation | ||
return badge; | ||
} | ||
} | ||
|
||
@action | ||
home() { | ||
this.router.transitionTo("/"); | ||
} | ||
|
||
<template> | ||
<div class="breadcrumbs"> | ||
{{#if this.isHomepage}} | ||
<h2 data-name="home" class="breadcrumbs__title"> | ||
<h2 class="breadcrumbs__title"> | ||
<div data-badge-type="icon" class="badge"> | ||
home | ||
</div> | ||
{{i18n "js.home"}} | ||
</h2> | ||
{{else if this.isCategoryView}} | ||
<h2 class="breadcrumbs__title"> | ||
<div | ||
data-badge-type="emoji" | ||
data-clickable="true" | ||
class="badge" | ||
{{on "click" this.home}} | ||
> | ||
{{this.categoryBadge}} | ||
</div> | ||
{{this.categoryName}} | ||
</h2> | ||
{{else if this.isCategoryList}} | ||
<h2 class="breadcrumbs__title"> | ||
<div | ||
data-badge-type="emoji" | ||
data-clickable="true" | ||
class="badge" | ||
{{on "click" this.home}} | ||
> | ||
🗃️ | ||
</div> | ||
{{capitalize (i18n "js.categories.categories_label")}} | ||
</h2> | ||
{{/if}} | ||
<TopicFilter | ||
@filterType={{this.filterType}} | ||
@routeType={{this.routeType}} | ||
/> | ||
</div> | ||
</template> | ||
} | ||
class TopicFilter extends Component { | ||
@service router; | ||
@service site; | ||
|
||
@tracked filterOptions; | ||
|
||
constructor() { | ||
super(...arguments); | ||
|
||
this.filterOptions = | ||
this.site.siteSettings?.top_menu?.split("|").map((item) => { | ||
return { name: item, localization: `js.filters.${item}.title` }; | ||
}) || []; | ||
} | ||
|
||
@action | ||
filterTopics(event) { | ||
const routeType = this.args.routeType; | ||
const category = this.router?.currentRoute?.attributes?.category; | ||
|
||
if (routeType === "category" && event.target.value !== "categories") { | ||
this.router.transitionTo( | ||
`/c/${category.slug}/${category.id}/l/${event.target.value}` | ||
); | ||
} else { | ||
this.router.transitionTo(`/${event.target.value}`); | ||
} | ||
} | ||
|
||
<template> | ||
<select | ||
class="breadcrumbs__select" | ||
value={{@filterType}} | ||
onchange={{this.filterTopics}} | ||
> | ||
{{#each this.filterOptions as |filterOption|}} | ||
<option value={{filterOption.name}} selected={{eq filterOption.name @filterType}}> | ||
{{i18n filterOption.localization}} | ||
</option> | ||
{{/each}} | ||
</select> | ||
</template> | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
{{#unless this.model.isPrivateMessage}} | ||
<a href={{this.model.category.url}} role="button" class="topic-back-button"> | ||
</a> | ||
{{/unless}} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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); | ||
}; | ||
}); |
Oops, something went wrong.