discourse/app/assets/javascripts/admin/addon/services/admin-sidebar-state-manager.js
Kris 1afdb5df7b
UX: always close hamburger menu when navigating to admin (#32651)
When we create a custom homepage using the `custom_homepage` modifier we
can hide the sidebar using `{{hideApplicationSidebar}}` in the template
— this forces the hamburger dropdown to appear in the header.

This creates an issue when navigating from the custom homepage to the
admin area, because when the route transitions the hamburger menu isn't
closed... and at this point, it cannot be closed at all. The
`clickOutside` listener from the open menu is calling
`toggleNavigation`, which is now the sidebar... so instead of closing
the hamburger menu, it toggles the sidebar and prevents other elements
from being clicked (because the `clickOuside` listener is only removed
when the hamburger menu is destroyed).


![image](https://github.com/user-attachments/assets/b6893513-6f0e-4f5b-8d47-6b63916c0a29)

This change ensures that when the admin sidebar is forced, the hamburger
menu will be hidden.
2025-05-08 16:08:11 -04:00

78 lines
2 KiB
JavaScript
Vendored

import Service, { service } from "@ember/service";
import KeyValueStore from "discourse/lib/key-value-store";
import { ADMIN_PANEL, MAIN_PANEL } from "discourse/lib/sidebar/panels";
import AdminSearchModal from "admin/components/modal/admin-search";
export default class AdminSidebarStateManager extends Service {
@service sidebarState;
@service header;
STORE_NAMESPACE = "discourse_admin_sidebar_experiment_";
keywords = {};
store = new KeyValueStore(this.STORE_NAMESPACE);
get navConfig() {
return this.store.getObject("navConfig");
}
set navConfig(value) {
this.store.setObject({ key: "navConfig", value });
}
setLinkKeywords(link_name, keywords) {
if (!this.keywords[link_name]) {
this.keywords[link_name] = {
navigation: keywords.map((keyword) => keyword.toLowerCase()),
};
return;
}
this.keywords[link_name].navigation = [
...new Set(
this.keywords[link_name].navigation.concat(
keywords.map((keyword) => keyword.toLowerCase())
)
),
];
}
maybeForceAdminSidebar(opts = {}) {
opts.onlyIfAlreadyActive ??= true;
const isAdminSidebarActive =
this.sidebarState.currentPanel?.key === ADMIN_PANEL;
if (!opts.onlyIfAlreadyActive) {
return this.#forceAdminSidebar();
}
if (isAdminSidebarActive) {
return this.#forceAdminSidebar();
} else {
this.sidebarState.isForcingSidebar = false;
return false;
}
}
stopForcingAdminSidebar() {
this.sidebarState.setPanel(MAIN_PANEL);
this.sidebarState.isForcingSidebar = false;
}
get modals() {
return { adminSearch: AdminSearchModal };
}
#forceAdminSidebar() {
this.sidebarState.setPanel(ADMIN_PANEL);
this.sidebarState.setSeparatedMode();
this.sidebarState.hideSwitchPanelButtons();
this.sidebarState.isForcingSidebar = true;
// we may navigate to admin from the header dropdown
// and when we do, we have to close it
this.header.hamburgerVisible = false;
return true;
}
}