diff --git a/cypress/integration/custom_buttons.js b/cypress/integration/custom_buttons.js
index ddbd19731a..fd93613900 100644
--- a/cypress/integration/custom_buttons.js
+++ b/cypress/integration/custom_buttons.js
@@ -41,6 +41,8 @@ describe(
before(() => {
cy.login();
cy.visit(`/app/note/new`);
+ // close the sidebar cause default is expanded
+ cy.get(".body-sidebar .collapse-sidebar-link").click();
});
test_button_names.forEach((button_name) => {
diff --git a/frappe/public/icons/timeless/icons.svg b/frappe/public/icons/timeless/icons.svg
index 3cf8477143..d6c409aada 100644
--- a/frappe/public/icons/timeless/icons.svg
+++ b/frappe/public/icons/timeless/icons.svg
@@ -417,8 +417,7 @@ Tip: use lucide.svg in /icons for all downloaded icons
-
+
@@ -545,8 +544,7 @@ Tip: use lucide.svg in /icons for all downloaded icons
-
+
@@ -876,7 +874,6 @@ Tip: use lucide.svg in /icons for all downloaded icons
-
diff --git a/frappe/public/js/frappe/ui/apps_switcher.js b/frappe/public/js/frappe/ui/apps_switcher.js
index adb22a6982..0f346cc3db 100644
--- a/frappe/public/js/frappe/ui/apps_switcher.js
+++ b/frappe/public/js/frappe/ui/apps_switcher.js
@@ -3,22 +3,17 @@ frappe.ui.AppsSwitcher = class AppsSwitcher {
this.drop_down_state = false;
this.sidebar_wrapper = sidebar.wrapper;
this.sidebar = sidebar;
+ this.app_switcher = $(sidebar.app_switcher_dropdown[0]);
this.setup_app_switcher();
+ this.set_hover();
}
setup_app_switcher() {
this.app_switcher_menu = $(".app-switcher-menu");
$(".app-switcher-dropdown").on("click", () => {
+ this.set_active();
this.app_switcher_menu.toggleClass("hidden");
});
-
- // hover out of the sidebar move this to sidebar.js
- this.sidebar_wrapper.find(".body-sidebar").on("mouseleave", () => {
- this.app_switcher_menu.addClass("hidden");
-
- // hide any expanded menus as they leave a blank space in the sidebar
- this.sidebar_wrapper.find(".drop-icon[data-state='opened'").click();
- });
}
create_app_data_map() {
frappe.boot.app_data_map = {};
@@ -152,4 +147,23 @@ frappe.ui.AppsSwitcher = class AppsSwitcher {
// re-render the sidebar
frappe.app.sidebar.make_sidebar();
}
+ set_hover() {
+ this.app_switcher.on("mouseover", function (event) {
+ if ($(this).hasClass("active-sidebar")) return;
+ $(this).addClass("hover");
+ if (!this.sidebar.sidebar_expanded) {
+ $(this).removeClass("hover");
+ }
+ });
+
+ this.app_switcher.on("mouseleave", function () {
+ $(this).removeClass("hover");
+ });
+ }
+ set_active() {
+ this.app_switcher.toggleClass("active-sidebar");
+ if (!this.sidebar.sidebar_expanded) {
+ this.app_switcher.removeClass("active-sidebar");
+ }
+ }
};
diff --git a/frappe/public/js/frappe/ui/sidebar.js b/frappe/public/js/frappe/ui/sidebar.js
index 6d2303e2a7..b2c0e3a332 100644
--- a/frappe/public/js/frappe/ui/sidebar.js
+++ b/frappe/public/js/frappe/ui/sidebar.js
@@ -1,6 +1,7 @@
frappe.ui.Sidebar = class Sidebar {
constructor() {
this.items = {};
+ this.child_items = [];
this.sidebar_expanded = false;
if (!frappe.boot.setup_complete) {
@@ -79,16 +80,65 @@ frappe.ui.Sidebar = class Sidebar {
}
set_active_workspace_item() {
- if (this.is_route_in_sidebar(decodeURIComponent(window.location.pathname))) {
+ if (!frappe.get_route()) return;
+ if (frappe.get_route()[0] == "") return;
+ let current_route = frappe.get_route();
+ let doctype = frappe.get_route()[1];
+ let current_item = doctype;
+ if (current_route[0] != "Workspaces") {
+ let meta_info = frappe.get_meta(doctype);
+ if (meta_info) {
+ let active_workspace = meta_info.module;
+ if (meta_info.__workspaces) {
+ active_workspace = meta_info.__workspaces[0];
+ }
+ current_item = active_workspace;
+ }
+ }
+ if (this.is_route_in_sidebar(current_item)) {
this.active_item.addClass("active-sidebar");
}
+ if (this.active_item) {
+ if (this.is_nested_item(this.active_item.parent())) {
+ let current_item = this.active_item.parent();
+ this.expand_parent_item(current_item);
+ }
+ }
+ }
+ expand_parent_item(item) {
+ let parent_title = item.attr("item-parent");
+ if (!parent_title) return;
+
+ let parent = this.get_sidebar_item(parent_title);
+ $($(parent).children()[1]).removeClass("hidden");
+ if (parent) {
+ if (this.is_nested_item($(parent))) {
+ this.expand_parent_item($(parent));
+ }
+ }
+ }
+ is_nested_item(item) {
+ if (item.attr("item-parent")) {
+ return true;
+ } else {
+ return false;
+ }
}
- is_route_in_sidebar(route_name) {
+ get_sidebar_item(name) {
+ let sidebar_item = "";
+ $(".sidebar-item-container").each(function () {
+ if ($(this).attr("item-name") == name) {
+ sidebar_item = this;
+ }
+ });
+ return sidebar_item;
+ }
+ is_route_in_sidebar(active_module) {
let match = false;
const that = this;
$(".item-anchor").each(function () {
- if ($(this).attr("href") == route_name) {
+ if ($(this).attr("title") == active_module) {
match = true;
if (that.active_item) that.active_item.removeClass("active-sidebar");
that.active_item = $(this).parent();
@@ -126,12 +176,19 @@ frappe.ui.Sidebar = class Sidebar {
this.make_sidebar();
}
this.set_hover();
+ this.set_sidebar_state();
+ if (!this.sidebar_expanded) this.close_children_item();
+ }
+ set_sidebar_state() {
+ this.sidebar_expanded = true;
if (localStorage.getItem("sidebar-expanded") !== null) {
this.sidebar_expanded = JSON.parse(localStorage.getItem("sidebar-expanded"));
- this.expand_sidebar();
}
+ if (frappe.is_mobile()) {
+ this.sidebar_expanded = false;
+ }
+ this.expand_sidebar();
}
-
make_sidebar() {
if (this.wrapper.find(".standard-sidebar-section")[0]) {
this.wrapper.find(".standard-sidebar-section").remove();
@@ -242,6 +299,7 @@ frappe.ui.Sidebar = class Sidebar {
let child_container = $item_container.find(".sidebar-child-item");
child_container.addClass("hidden");
this.prepare_sidebar(child_items, child_container, $item_container);
+ this.child_items.push(child_container);
}
$item_container.appendTo(container);
@@ -394,10 +452,18 @@ frappe.ui.Sidebar = class Sidebar {
close_sidebar() {
this.sidebar_expanded = false;
this.expand_sidebar();
+ this.close_children_item();
}
open_sidebar() {
this.sidebar_expanded = true;
this.expand_sidebar();
+ this.set_active_workspace_item();
+ }
+
+ close_children_item() {
+ this.child_items.forEach((i) => {
+ i.addClass("hidden");
+ });
}
reload() {
@@ -406,4 +472,9 @@ frappe.ui.Sidebar = class Sidebar {
this.setup_pages();
});
}
+ set_height() {
+ $(".body-sidebar").css("height", window.innerHeight + "px");
+ $(".overlay").css("height", window.innerHeight + "px");
+ document.body.style.overflow = "hidden";
+ }
};
diff --git a/frappe/public/js/frappe/ui/toolbar/toolbar.js b/frappe/public/js/frappe/ui/toolbar/toolbar.js
index 9a96f1ed21..ba1c163fc7 100644
--- a/frappe/public/js/frappe/ui/toolbar/toolbar.js
+++ b/frappe/public/js/frappe/ui/toolbar/toolbar.js
@@ -29,6 +29,7 @@ frappe.ui.toolbar.Toolbar = class {
this.bind_events();
$(document).trigger("toolbar_setup");
$(".navbar-brand .app-logo").on("click", () => {
+ frappe.app.sidebar.set_height();
frappe.app.sidebar.toggle_sidebar();
});
}
diff --git a/frappe/public/scss/common/icons.scss b/frappe/public/scss/common/icons.scss
index bef46bd625..878c9590c1 100644
--- a/frappe/public/scss/common/icons.scss
+++ b/frappe/public/scss/common/icons.scss
@@ -9,7 +9,9 @@
background-position: 50% 50%;
fill: var(--icon-fill);
stroke: var(--icon-stroke);
- stroke-width: 1.25px;
+ stroke-width: 1.5px;
+ stroke-linecap: round;
+ stroke-linejoin: round;
}
.es-icon {
diff --git a/frappe/public/scss/desk/sidebar.scss b/frappe/public/scss/desk/sidebar.scss
index 5390aa9f83..a667979871 100644
--- a/frappe/public/scss/desk/sidebar.scss
+++ b/frappe/public/scss/desk/sidebar.scss
@@ -6,6 +6,7 @@
--surface-modal: rgba(255, 255, 255, 1);
--divider-color: rgba(237, 237, 237, 1);
--sidebar-width: 220px;
+ --left-sidebar-width: 240px;
}
[data-theme="dark"] {
--sidebar-hover-color: rgba(43, 43, 43, 1);
@@ -122,7 +123,7 @@ body {
}
.sidebar-items {
- width: 204px;
+ width: 224px;
padding-left: 1px;
padding-right: 1px;
width: 100%;
@@ -172,7 +173,7 @@ body {
}
svg {
- margin: -1px;
+ margin: -2px;
}
}
@@ -248,17 +249,17 @@ body {
.body-sidebar {
// make it an overlay on hover
position: absolute;
- width: var(--sidebar-width);
+ width: var(--left-sidebar-width);
.app-switcher-dropdown {
- width: 204px;
+ width: 224px;
left: 0px;
- padding: 2px 0px 2px 3px;
+ padding: 3px;
}
.body-sidebar-top {
- width: 204px;
+ width: 224px;
overflow-y: hidden;
.app-switcher-dropdown {
- width: 204px;
+ width: 224px;
}
}
.sidebar-item-container {
@@ -279,7 +280,7 @@ body {
visibility: visible;
}
.body-sidebar-bottom {
- width: var(--sidebar-width);
+ width: 224px;
position: static;
}
}
@@ -287,7 +288,7 @@ body {
// show placeholder so that main section remains static
.body-sidebar-placeholder {
display: flex;
- width: var(--sidebar-width);
+ width: var(--left-sidebar-width);
}
}
@@ -310,7 +311,7 @@ body {
position: relative;
.body-sidebar {
padding: 8px 8px 10px 8px;
- width: var(--sidebar-width);
+ width: var(--left-sidebar-width);
height: 100%;
position: absolute;
bottom: 0;
@@ -319,10 +320,10 @@ body {
.overlay {
display: block;
position: absolute;
- width: 100vw;
+ width: calc(100vw - 240px);
height: 100%;
z-index: 1021;
- left: var(--sidebar-width);
+ left: var(--left-sidebar-width);
overflow: auto;
background-color: rgba(128, 128, 128, 0.5);
}
@@ -347,15 +348,15 @@ body {
text-decoration: none;
width: 38px;
height: 38px;
- left: -2px;
padding: 3px;
+ margin-left: -2px;
.standard-sidebar-item {
padding-top: 1px;
padding-bottom: 1px;
.d-flex {
width: 161px;
}
- gap: 8px;
+ gap: 30px;
}
.sidebar-item-control {
margin: 2px;
@@ -365,15 +366,13 @@ body {
.app-switcher-menu {
position: absolute;
- top: 44px;
- left: 7px;
- width: 205px;
+ top: 50px;
+ left: 9px;
+ width: 220px;
padding: 6px;
border-radius: var(--border-radius-lg);
background: var(--surface-modal);
- box-shadow: 0px 10px 24px -3px rgba(0, 0, 0, 0.1);
- // box-shadow: 0px 1px 3px 0px rgba(0, 0, 0, 0.05);
- // box-shadow: 0px 0px 1px 0px rgba(0, 0, 0, 0.2);
+ box-shadow: var(--shadow-xl);
z-index: 1;
}
@@ -421,7 +420,7 @@ body {
.active-sidebar {
background: var(--sidebar-active-color);
- box-shadow: 0px 1px 2px 0px rgba(0, 0, 0, 0.1);
+ box-shadow: var(--shadow-sm);
border-radius: 8px;
}
.overlay {