bug fixes and qol changes

This commit is contained in:
Ali 2026-04-16 09:49:27 +00:00
parent 7486c80656
commit bae6c16a6b
2 changed files with 351 additions and 5 deletions

View File

@ -253,7 +253,8 @@ input.list-header-checkbox:checked::after {
Sidebar Full Width button
========================================================================== */
.jey-fullwidth-link {
.jey-fullwidth-link,
.jey-theme-switch-link {
text-decoration: none;
font-size: var(--text-sm);
display: flex;
@ -262,18 +263,28 @@ input.list-header-checkbox:checked::after {
margin-bottom: 8px;
}
.jey-fullwidth-link svg {
.jey-fullwidth-link svg,
.jey-theme-switch-link svg {
margin: 0;
flex: 0 0 auto;
}
.jey-fullwidth-link span {
.jey-fullwidth-link span,
.jey-theme-switch-link span {
margin-left: 10px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
/* Hide dropdown items now surfaced as sidebar buttons */
.dropdown-menu-item[onclick*="toggle_full_width"],
.dropdown-menu-item[onclick*="ThemeSwitcher"],
.dropdown-menu-item[data-name="website"],
.dropdown-menu-item.jey-hidden-item {
display: none !important;
}
/* ==========================================================================
Desktop Icons Shared base (all themes)
@ -467,7 +478,14 @@ input.list-header-checkbox:checked::after {
transition: transform 0.3s cubic-bezier(0.22, 1, 0.36, 1),
box-shadow 0.35s ease;
position: relative;
overflow: hidden;
}
/* Allow dropdown menus (card actions) to escape the widget box.
Without this, .widget-control .dropdown-menu is clipped/hidden behind
the widget because Popper renders it as a sibling inside the box. */
.ce-block .links-widget-box .widget-control .dropdown-menu,
.ce-block .number-widget-box .widget-control .dropdown-menu {
z-index: 1050;
}
/* Stagger delays */
@ -503,7 +521,7 @@ input.list-header-checkbox:checked::after {
}
to {
opacity: 1;
transform: translateY(0) scale(1);
transform: none;
}
}
@ -535,6 +553,18 @@ input.list-header-checkbox:checked::after {
0 2px 6px rgba(0, 0, 0, 0.04);
}
/* Lift widget above its siblings while hovered or while its card-actions
dropdown is open, so the dropdown menu (which lives inside the widget's
own stacking context due to transform) is not covered by neighbours. */
.ce-block .links-widget-box:hover,
.ce-block .number-widget-box:hover,
.ce-block .links-widget-box:focus-within,
.ce-block .number-widget-box:focus-within,
.ce-block .links-widget-box:has(.dropdown-menu.show),
.ce-block .number-widget-box:has(.dropdown-menu.show) {
z-index: 100;
}
/* Link items: colored left accent bar slides in */
.links-widget-box .link-item {
@ -604,6 +634,90 @@ input.list-header-checkbox:checked::after {
background-position: center;
}
/* ==========================================================================
Notification Bell Top-right position
========================================================================== */
/* Hide original notification button in sidebar */
.sidebar-notification {
display: none !important;
}
/* Fixed wrapper */
.jey-topright-wrapper {
position: fixed;
top: 16px;
right: 24px;
z-index: 1039;
}
/* Bell button */
.jey-topright-bell {
position: relative;
width: 36px;
height: 36px;
border-radius: 50%;
background: var(--card-bg, #fff);
border: 1px solid var(--border-color, #e2e2e2);
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
box-shadow: 0 1px 4px rgba(0,0,0,0.08);
transition: box-shadow 0.2s, background 0.2s;
color: var(--text-muted, #74808b);
padding: 0;
}
.jey-topright-bell:hover {
background: var(--subtle-fg, #f5f5f5);
box-shadow: 0 2px 8px rgba(0,0,0,0.12);
color: var(--text-color, #333);
}
/* Unread count badge */
.jey-notif-badge {
position: absolute;
top: -4px;
right: -4px;
background: var(--red-500, #e53e3e);
color: #fff;
font-size: 10px;
font-weight: 600;
min-width: 16px;
height: 16px;
line-height: 16px;
border-radius: 8px;
text-align: center;
padding: 0 4px;
pointer-events: none;
}
/* Notification dropdown panel */
.jey-topright-wrapper .dropdown-notifications {
display: block;
position: absolute;
top: 44px;
right: 0;
width: 360px;
border-radius: 12px;
box-shadow: 0 8px 24px rgba(0,0,0,0.12), 0 2px 6px rgba(0,0,0,0.04);
background: var(--card-bg, #fff);
border: 1px solid var(--border-color, #e2e2e2);
max-height: 70vh;
overflow-y: auto;
}
.jey-topright-wrapper .dropdown-notifications.hidden {
display: none !important;
}
@media (max-width: 400px) {
.jey-topright-wrapper .dropdown-notifications {
width: calc(100vw - 32px);
}
}
/* ==========================================================================
Hide "Getting Started" onboarding panels
========================================================================== */

View File

@ -677,6 +677,238 @@
$(document).on("page-change", addFullWidthButton);
})();
/* ==========================================================================
Toggle Theme button in sidebar (above Collapse)
========================================================================== */
(function () {
"use strict";
function addThemeSwitchButton() {
var collapse = document.querySelector(".collapse-sidebar-link");
if (!collapse || document.querySelector(".jey-theme-switch-link")) return;
var link = document.createElement("a");
link.className = "jey-theme-switch-link";
link.innerHTML =
frappe.utils.icon("palette", "sm", "", "", "text-ink-gray-7 current-color", true) +
"<span>" + __("Switch Theme") + "</span>";
link.addEventListener("click", function () {
new frappe.ui.ThemeSwitcher().show();
});
collapse.parentNode.insertBefore(link, collapse);
}
$(document).ready(addThemeSwitchButton);
$(document).on("page-change", addThemeSwitchButton);
})();
/* ==========================================================================
Hide "Website" item from sidebar user dropdown
========================================================================== */
(function () {
"use strict";
function tagWebsiteItem() {
var label = __("Website");
document.querySelectorAll(".dropdown-menu-item:not(.jey-hidden-item)").forEach(function (el) {
var title = el.querySelector(".menu-item-title");
if (title && title.textContent.trim() === label) {
el.classList.add("jey-hidden-item");
}
});
}
$(document).ready(tagWebsiteItem);
var observer = new MutationObserver(tagWebsiteItem);
observer.observe(document.body, { childList: true, subtree: true });
})();
/* ==========================================================================
Reload button next to Notifications in sidebar
========================================================================== */
(function () {
"use strict";
function addReloadButton() {
var notif = document.querySelector(".sidebar-notification");
if (!notif || document.querySelector(".jey-reload-btn")) return;
var btn = notif.cloneNode(true);
btn.classList.remove("sidebar-notification");
btn.classList.remove("hidden");
btn.classList.add("jey-reload-btn");
btn.removeAttribute("id");
btn.setAttribute("title", __("Reload"));
var iconWrap = btn.querySelector(".sidebar-item-icon");
if (iconWrap) {
iconWrap.setAttribute("item-icon", "rotate-ccw");
iconWrap.innerHTML = frappe.utils.icon(
"rotate-ccw", "sm", "", "", "text-ink-gray-7 current-color", true
);
}
var label = btn.querySelector(".sidebar-item-label");
if (label) label.textContent = __("Reload");
btn.addEventListener("click", function (e) {
e.preventDefault();
e.stopPropagation();
frappe.ui.toolbar.clear_cache();
});
notif.parentNode.insertBefore(btn, notif.nextSibling);
}
$(document).ready(function () {
addReloadButton();
var tries = 0;
var poll = setInterval(function () {
addReloadButton();
if (++tries > 30 || document.querySelector(".jey-reload-btn")) {
clearInterval(poll);
}
}, 300);
});
$(document).on("page-change", addReloadButton);
})();
/* ==========================================================================
Notification Bell Move to top-right corner
========================================================================== */
(function () {
"use strict";
function moveNotifications() {
var dropdown = document.querySelector(".standard-items-sections .dropdown-notifications, .body-sidebar .dropdown-notifications:not(.jey-moved)");
var wrapper = document.querySelector(".jey-topright-wrapper");
// A new dropdown appeared after page rebuild — move it into existing wrapper
if (dropdown && wrapper) {
dropdown.classList.add("jey-moved", "hidden");
dropdown.parentNode.removeChild(dropdown);
var old = wrapper.querySelector(".dropdown-notifications");
if (old) old.remove();
wrapper.appendChild(dropdown);
return;
}
if (wrapper) return; // already set up
if (!dropdown) return; // nothing to move yet
// --- First-time setup ---
wrapper = document.createElement("div");
wrapper.className = "jey-topright-wrapper";
var bell = document.createElement("button");
bell.className = "jey-topright-bell btn-reset";
bell.setAttribute("title", __("Notifications"));
bell.innerHTML =
'<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" ' +
'fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">' +
'<path d="M18 8A6 6 0 0 0 6 8c0 7-3 9-3 9h18s-3-2-3-9"/>' +
'<path d="M13.73 21a2 2 0 0 1-3.46 0"/>' +
'</svg>';
wrapper.appendChild(bell);
dropdown.classList.add("jey-moved", "hidden");
dropdown.parentNode.removeChild(dropdown);
wrapper.appendChild(dropdown);
document.body.appendChild(wrapper);
function updateBadge() {
var dd = wrapper.querySelector(".dropdown-notifications");
if (!dd) return;
var unread = dd.querySelectorAll(".notification-item.unread").length;
var badge = bell.querySelector(".jey-notif-badge");
if (unread > 0) {
if (!badge) {
badge = document.createElement("span");
badge.className = "jey-notif-badge";
bell.appendChild(badge);
}
badge.textContent = unread > 9 ? "9+" : unread;
} else if (badge) {
badge.remove();
}
}
bell.addEventListener("click", function (e) {
e.preventDefault();
e.stopPropagation();
var dd = wrapper.querySelector(".dropdown-notifications");
if (dd) dd.classList.toggle("hidden");
updateBadge();
});
document.addEventListener("click", function (e) {
if (!wrapper.contains(e.target)) {
var dd = wrapper.querySelector(".dropdown-notifications");
if (dd) dd.classList.add("hidden");
}
});
wrapper.addEventListener("click", function (e) {
if (e.target.closest(".close-notification-dialogue")) {
var dd = wrapper.querySelector(".dropdown-notifications");
if (dd) dd.classList.add("hidden");
}
});
updateBadge();
var obs = new MutationObserver(updateBadge);
obs.observe(dropdown, { childList: true, subtree: true, attributes: true, attributeFilter: ["class"] });
}
$(document).ready(function () {
moveNotifications();
var tries = 0;
var poll = setInterval(function () {
moveNotifications();
if (++tries > 30) clearInterval(poll);
}, 300);
});
$(document).on("page-change", moveNotifications);
})();
/* ==========================================================================
Fix: nested menus left orphaned when parent menu is toggled closed
(sidebar-header app-switcher Workspaces submenu stays on screen)
========================================================================== */
(function () {
"use strict";
function patchMenuHide() {
if (!window.frappe || !frappe.ui || !frappe.ui.menu) return false;
var proto = frappe.ui.menu.prototype;
if (proto.__jeyHidePatched) return true;
var origHide = proto.hide;
proto.hide = function () {
if (this.nested_menus && this.nested_menus.length) {
this.nested_menus.forEach(function (m) { m && m.hide && m.hide(); });
}
this.current_menu = null;
return origHide.apply(this, arguments);
};
proto.__jeyHidePatched = true;
return true;
}
if (!patchMenuHide()) {
var tries = 0;
var poll = setInterval(function () {
if (patchMenuHide() || ++tries > 50) clearInterval(poll);
}, 200);
}
})();
/* ==========================================================================
Override Frappe Theme Switcher Jey themes
========================================================================== */