FEATURE: sidebar for narrow desktop screen (#19160)
When desktop screen is narrow like < 1100px, sidebar should behave similarly to mobile version.
This commit is contained in:
parent
20715cd7f0
commit
5b6604f5a7
|
@ -40,6 +40,20 @@ const SiteHeaderComponent = MountWidget.extend(
|
|||
this.queueRerender();
|
||||
},
|
||||
|
||||
@observes("site.narrowDesktopView")
|
||||
narrowDesktopViewChanged() {
|
||||
if (
|
||||
this.siteSettings.enable_experimental_sidebar_hamburger &&
|
||||
(!this.sidebarEnabled || this.site.narrowDesktopView)
|
||||
) {
|
||||
this.appEvents.on(
|
||||
"sidebar-hamburger-dropdown:rendered",
|
||||
this,
|
||||
"_animateMenu"
|
||||
);
|
||||
}
|
||||
},
|
||||
|
||||
_animateOpening(panel) {
|
||||
const headerCloak = document.querySelector(".header-cloak");
|
||||
panel.classList.add("animate");
|
||||
|
@ -219,7 +233,7 @@ const SiteHeaderComponent = MountWidget.extend(
|
|||
|
||||
if (
|
||||
this.siteSettings.enable_experimental_sidebar_hamburger &&
|
||||
!this.sidebarEnabled
|
||||
(!this.sidebarEnabled || this.site.narrowDesktopView)
|
||||
) {
|
||||
this.appEvents.on(
|
||||
"sidebar-hamburger-dropdown:rendered",
|
||||
|
@ -353,14 +367,17 @@ const SiteHeaderComponent = MountWidget.extend(
|
|||
const menuPanels = document.querySelectorAll(".menu-panel");
|
||||
|
||||
if (menuPanels.length === 0) {
|
||||
if (this.site.mobileView) {
|
||||
if (this.site.mobileView || this.site.narrowDesktopView) {
|
||||
this._animate = true;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
const windowWidth = document.body.offsetWidth;
|
||||
const viewMode = this.site.mobileView ? "slide-in" : "drop-down";
|
||||
const viewMode =
|
||||
this.site.mobileView || this.site.narrowDesktopView
|
||||
? "slide-in"
|
||||
: "drop-down";
|
||||
|
||||
menuPanels.forEach((panel) => {
|
||||
const headerCloak = document.querySelector(".header-cloak");
|
||||
|
@ -377,7 +394,7 @@ const SiteHeaderComponent = MountWidget.extend(
|
|||
panel.classList.add(viewMode);
|
||||
if (this._animate || this._panMenuOffset !== 0) {
|
||||
if (
|
||||
this.site.mobileView &&
|
||||
(this.site.mobileView || this.site.narrowDesktopView) &&
|
||||
panel.parentElement.classList.contains(this._leftMenuClass())
|
||||
) {
|
||||
this._panMenuOrigin = "left";
|
||||
|
@ -394,7 +411,7 @@ const SiteHeaderComponent = MountWidget.extend(
|
|||
// We use a mutationObserver to check for style changes, so it's important
|
||||
// we don't set it if it doesn't change. Same goes for the panelBody!
|
||||
|
||||
if (!this.site.mobileView) {
|
||||
if (!this.site.mobileView && !this.site.narrowDesktopView) {
|
||||
const buttonPanel = document.querySelectorAll("header ul.icons");
|
||||
if (buttonPanel.length === 0) {
|
||||
return;
|
||||
|
@ -469,6 +486,8 @@ export default SiteHeaderComponent.extend({
|
|||
didInsertElement() {
|
||||
this._super(...arguments);
|
||||
|
||||
this.appEvents.on("site-header:force-refresh", this, "queueRerender");
|
||||
|
||||
const header = document.querySelector(".d-header-wrap");
|
||||
if (header) {
|
||||
schedule("afterRender", () => {
|
||||
|
@ -499,6 +518,7 @@ export default SiteHeaderComponent.extend({
|
|||
this._super(...arguments);
|
||||
|
||||
this._resizeObserver?.disconnect();
|
||||
this.appEvents.off("site-header:force-refresh", this, "queueRerender");
|
||||
},
|
||||
});
|
||||
|
||||
|
|
|
@ -20,7 +20,9 @@ export default Controller.extend({
|
|||
init() {
|
||||
this._super(...arguments);
|
||||
this.showSidebar =
|
||||
this.canDisplaySidebar && !this.keyValueStore.getItem(HIDE_SIDEBAR_KEY);
|
||||
this.canDisplaySidebar &&
|
||||
!this.keyValueStore.getItem(HIDE_SIDEBAR_KEY) &&
|
||||
!this.site.narrowDesktopView;
|
||||
},
|
||||
|
||||
@discourseComputed
|
||||
|
|
|
@ -0,0 +1,45 @@
|
|||
import NarrowDesktop from "discourse/lib/narrow-desktop";
|
||||
|
||||
export default {
|
||||
name: "narrow-desktop",
|
||||
|
||||
initialize(container) {
|
||||
NarrowDesktop.init();
|
||||
let site;
|
||||
if (!container.isDestroyed) {
|
||||
site = container.lookup("service:site");
|
||||
site.set("narrowDesktopView", NarrowDesktop.narrowDesktopView);
|
||||
}
|
||||
|
||||
if ("ResizeObserver" in window) {
|
||||
this._resizeObserver = new ResizeObserver((entries) => {
|
||||
if (container.isDestroyed) {
|
||||
return;
|
||||
}
|
||||
for (let entry of entries) {
|
||||
const oldNarrowDesktopView = site.narrowDesktopView;
|
||||
const newNarrowDesktopView = NarrowDesktop.isNarrowDesktopView(
|
||||
entry.contentRect.width
|
||||
);
|
||||
if (oldNarrowDesktopView !== newNarrowDesktopView) {
|
||||
const applicationController = container.lookup(
|
||||
"controller:application"
|
||||
);
|
||||
site.set("narrowDesktopView", newNarrowDesktopView);
|
||||
if (newNarrowDesktopView) {
|
||||
applicationController.set("showSidebar", false);
|
||||
}
|
||||
applicationController.appEvents.trigger(
|
||||
"site-header:force-refresh"
|
||||
);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
const bodyElement = document.querySelector("body");
|
||||
if (bodyElement) {
|
||||
this._resizeObserver.observe(bodyElement);
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
|
@ -0,0 +1,16 @@
|
|||
let narrowDesktopForced = false;
|
||||
|
||||
const NarrowDesktop = {
|
||||
narrowDesktopView: false,
|
||||
|
||||
init() {
|
||||
this.narrowDesktopView =
|
||||
narrowDesktopForced || this.isNarrowDesktopView(window.innerWidth);
|
||||
},
|
||||
|
||||
isNarrowDesktopView(width) {
|
||||
return width < 1100;
|
||||
},
|
||||
};
|
||||
|
||||
export default NarrowDesktop;
|
|
@ -476,7 +476,7 @@ export default createWidget("header", {
|
|||
);
|
||||
} else if (state.hamburgerVisible) {
|
||||
if (this.siteSettings.enable_experimental_sidebar_hamburger) {
|
||||
if (!attrs.sidebarEnabled) {
|
||||
if (!attrs.sidebarEnabled || this.site.narrowDesktopView) {
|
||||
panels.push(this.attach("revamped-hamburger-menu-wrapper", {}));
|
||||
}
|
||||
} else {
|
||||
|
@ -501,7 +501,7 @@ export default createWidget("header", {
|
|||
}
|
||||
});
|
||||
|
||||
if (this.site.mobileView) {
|
||||
if (this.site.mobileView || this.site.narrowDesktopView) {
|
||||
panels.push(this.attach("header-cloak"));
|
||||
}
|
||||
|
||||
|
@ -591,7 +591,8 @@ export default createWidget("header", {
|
|||
toggleHamburger() {
|
||||
if (
|
||||
this.siteSettings.enable_experimental_sidebar_hamburger &&
|
||||
this.attrs.sidebarEnabled
|
||||
this.attrs.sidebarEnabled &&
|
||||
!this.site.narrowDesktopView
|
||||
) {
|
||||
this.sendWidgetAction("toggleSidebar");
|
||||
} else {
|
||||
|
@ -601,7 +602,7 @@ export default createWidget("header", {
|
|||
schedule("afterRender", () => {
|
||||
if (this.siteSettings.enable_experimental_sidebar_hamburger) {
|
||||
// Remove focus from hamburger toggle button
|
||||
document.querySelector("#toggle-hamburger-menu").blur();
|
||||
document.querySelector("#toggle-hamburger-menu")?.blur();
|
||||
} else {
|
||||
// auto focus on first link in dropdown
|
||||
document.querySelector(".hamburger-panel .menu-links a")?.focus();
|
||||
|
|
|
@ -11,8 +11,12 @@ export default createWidget("sidebar-toggle", {
|
|||
? "sidebar.hide_sidebar"
|
||||
: "sidebar.show_sidebar",
|
||||
icon: "bars",
|
||||
action: "toggleSidebar",
|
||||
className: "btn btn-flat btn-sidebar-toggle",
|
||||
action: this.site.narrowDesktopView
|
||||
? "toggleHamburger"
|
||||
: "toggleSidebar",
|
||||
className: `btn btn-flat btn-sidebar-toggle ${
|
||||
this.site.narrowDesktopView ? "narrow-desktop" : ""
|
||||
}`,
|
||||
ariaExpanded: attrs.showSidebar ? "true" : "false",
|
||||
ariaControls: "d-sidebar",
|
||||
}),
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
import { test } from "qunit";
|
||||
|
||||
import { click, settled, visit, waitUntil } from "@ember/test-helpers";
|
||||
|
||||
import { acceptance, exists } from "discourse/tests/helpers/qunit-helpers";
|
||||
|
||||
acceptance("Sidebar - Narrow Desktop", function (needs) {
|
||||
needs.user();
|
||||
|
||||
needs.settings({
|
||||
enable_experimental_sidebar_hamburger: true,
|
||||
enable_sidebar: true,
|
||||
});
|
||||
|
||||
test("wide sidebar is changed to cloak when resize to narrow screen", async function (assert) {
|
||||
await visit("/");
|
||||
await settled();
|
||||
assert.ok(exists("#d-sidebar"), "wide sidebar is displayed");
|
||||
|
||||
await click(".header-sidebar-toggle .btn");
|
||||
|
||||
assert.ok(!exists("#d-sidebar"), "widge sidebar is collapsed");
|
||||
|
||||
const bodyElement = document.querySelector("body");
|
||||
bodyElement.style.width = "1000px";
|
||||
|
||||
await waitUntil(
|
||||
() => document.querySelector(".btn-sidebar-toggle.narrow-desktop"),
|
||||
{
|
||||
timeout: 5000,
|
||||
}
|
||||
);
|
||||
await click(".btn-sidebar-toggle");
|
||||
|
||||
assert.ok(
|
||||
exists(".sidebar-hamburger-dropdown"),
|
||||
"cloak sidebar is displayed"
|
||||
);
|
||||
|
||||
await click("#main-outlet");
|
||||
assert.ok(
|
||||
!exists(".sidebar-hamburger-dropdown"),
|
||||
"cloak sidebar is collapsed"
|
||||
);
|
||||
bodyElement.style.width = null;
|
||||
});
|
||||
});
|
|
@ -660,3 +660,50 @@ div.menu-links-header {
|
|||
color: var(--primary-med-or-secondary-med);
|
||||
}
|
||||
}
|
||||
|
||||
.hamburger-panel .menu-panel.slide-in {
|
||||
left: 0;
|
||||
|
||||
.panel-body {
|
||||
display: block;
|
||||
}
|
||||
.panel-body-contents {
|
||||
max-height: unset;
|
||||
min-height: 100%;
|
||||
}
|
||||
}
|
||||
.header-cloak {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
position: fixed;
|
||||
background-color: black;
|
||||
--opacity: 0.5;
|
||||
opacity: var(--opacity);
|
||||
top: 0;
|
||||
left: 0;
|
||||
display: none;
|
||||
touch-action: pan-y pinch-zoom;
|
||||
|
||||
@media (prefers-reduced-motion: no-preference) {
|
||||
&.animate {
|
||||
transition: opacity 0.1s linear;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.menu-panel.slide-in {
|
||||
transform: translateX(var(--offset));
|
||||
@media (prefers-reduced-motion: no-preference) {
|
||||
&.animate {
|
||||
transition: transform 0.1s linear;
|
||||
}
|
||||
}
|
||||
&.moving,
|
||||
&.animate {
|
||||
// PERF: only render first 20 items in a list to allow for smooth
|
||||
// pan events
|
||||
li:nth-child(n + 20) {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,50 +1,3 @@
|
|||
.hamburger-panel .menu-panel.slide-in {
|
||||
left: 0;
|
||||
|
||||
.panel-body {
|
||||
display: block;
|
||||
}
|
||||
.panel-body-contents {
|
||||
max-height: unset;
|
||||
min-height: 100%;
|
||||
}
|
||||
}
|
||||
.header-cloak {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
position: fixed;
|
||||
background-color: black;
|
||||
--opacity: 0.5;
|
||||
opacity: var(--opacity);
|
||||
top: 0;
|
||||
left: 0;
|
||||
display: none;
|
||||
touch-action: pan-y pinch-zoom;
|
||||
|
||||
@media (prefers-reduced-motion: no-preference) {
|
||||
&.animate {
|
||||
transition: opacity 0.1s linear;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.menu-panel.slide-in {
|
||||
transform: translateX(var(--offset));
|
||||
@media (prefers-reduced-motion: no-preference) {
|
||||
&.animate {
|
||||
transition: transform 0.1s linear;
|
||||
}
|
||||
}
|
||||
&.moving,
|
||||
&.animate {
|
||||
// PERF: only render first 20 items in a list to allow for smooth
|
||||
// pan events
|
||||
li:nth-child(n + 20) {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.user-menu .quick-access-panel.quick-access-profile li:not(.show-all) {
|
||||
border-bottom: 1px solid var(--primary-low);
|
||||
|
||||
|
|
Loading…
Reference in New Issue