Refactor filter panels and enhance sidebar functionality
- Updated filter panel toggle icons from chevron-up to chevron-down across multiple pages for consistency. - Added 'collapsed' class to filter content divs to manage visibility state. - Enhanced library page button for tidying up media items, replacing the trash icon with a custom SVG broom icon. - Improved CSS styles for sidebar and page header to ensure visibility and proper layout when the sidebar is collapsed. - Introduced JavaScript functionality to manage sidebar width and state, including theme toggle for light/dark mode. - Created a new notification drawer template that adapts based on the compact view state.
This commit is contained in:
@@ -17,7 +17,8 @@
|
||||
const toggleBtn = document.querySelector('[data-action="toggle-sidebar"]');
|
||||
const sidebar = document.querySelector('.ots-sidebar');
|
||||
const closeBtn = document.querySelector('.ots-sidebar-close');
|
||||
const collapseBtn = document.querySelector('.sidebar-collapse-btn');
|
||||
const collapseBtn = document.querySelector('.sidebar-collapse-btn-visible');
|
||||
const expandBtn = document.querySelector('.sidebar-expand-btn');
|
||||
const body = document.body;
|
||||
|
||||
if (!sidebar) return;
|
||||
@@ -42,6 +43,7 @@
|
||||
if (isCollapsed) {
|
||||
sidebar.classList.add('collapsed');
|
||||
body.classList.add('ots-sidebar-collapsed');
|
||||
updateSidebarStateClass();
|
||||
}
|
||||
|
||||
collapseBtn.addEventListener('click', function(e) {
|
||||
@@ -52,6 +54,22 @@
|
||||
localStorage.setItem(STORAGE_KEYS.sidebarCollapsed, nowCollapsed ? 'true' : 'false');
|
||||
// Update measured sidebar width when collapsed state changes
|
||||
updateSidebarWidth();
|
||||
// Recalculate nav offset so items remain below header after collapse
|
||||
updateSidebarNavOffset();
|
||||
updateSidebarStateClass();
|
||||
});
|
||||
}
|
||||
|
||||
if (expandBtn) {
|
||||
expandBtn.addEventListener('click', function(e) {
|
||||
e.preventDefault();
|
||||
sidebar.classList.remove('collapsed');
|
||||
body.classList.remove('ots-sidebar-collapsed');
|
||||
localStorage.setItem(STORAGE_KEYS.sidebarCollapsed, 'false');
|
||||
updateSidebarWidth();
|
||||
// Recalculate nav offset after expanding
|
||||
updateSidebarNavOffset();
|
||||
updateSidebarStateClass();
|
||||
});
|
||||
}
|
||||
|
||||
@@ -79,18 +97,82 @@
|
||||
if (!sidebar) return;
|
||||
// If collapsed, use the known collapsed width; otherwise use measured width
|
||||
const collapsed = sidebar.classList.contains('collapsed');
|
||||
const base = collapsed ? 88 : sidebar.offsetWidth || sidebar.getBoundingClientRect().width || 240;
|
||||
const padding = 5; // user requested ~5px padding
|
||||
const value = Math.max(88, Math.round(base + padding));
|
||||
const base = collapsed ? 64 : sidebar.offsetWidth || sidebar.getBoundingClientRect().width || 256;
|
||||
const padding = 0;
|
||||
const value = Math.max(64, Math.round(base + padding));
|
||||
document.documentElement.style.setProperty('--ots-sidebar-width', `${value}px`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Measure the sidebar header bottom and set the top padding of the nav list
|
||||
* so nav items always begin below the header (logo + buttons).
|
||||
*/
|
||||
function updateSidebarNavOffset() {
|
||||
const sidebar = document.querySelector('.ots-sidebar');
|
||||
if (!sidebar) return;
|
||||
const header = sidebar.querySelector('.sidebar-header');
|
||||
const nav = sidebar.querySelector('.sidebar-nav, .ots-sidebar-nav');
|
||||
if (!nav) return;
|
||||
// Calculate header bottom relative to the sidebar top (so it works with scrolling)
|
||||
const sidebarRect = sidebar.getBoundingClientRect();
|
||||
const headerRect = header ? header.getBoundingClientRect() : null;
|
||||
let offset = 0;
|
||||
if (headerRect) {
|
||||
offset = Math.max(0, Math.ceil(headerRect.bottom - sidebarRect.top));
|
||||
} else if (header) {
|
||||
offset = header.offsetHeight || 0;
|
||||
}
|
||||
// Add a small gap so nav doesn't touch the header edge
|
||||
const gap = 8;
|
||||
const paddingTop = offset > 0 ? offset + gap : '';
|
||||
// apply as inline style to ensure it overrides static CSS rules
|
||||
if (paddingTop) {
|
||||
// Use setProperty with priority so it overrides stylesheet !important rules
|
||||
try {
|
||||
nav.style.setProperty('padding-top', `${paddingTop}px`, 'important');
|
||||
} catch (err) {
|
||||
// fallback
|
||||
nav.style.paddingTop = `${paddingTop}px`;
|
||||
}
|
||||
} else {
|
||||
// remove inline override
|
||||
try {
|
||||
nav.style.removeProperty('padding-top');
|
||||
} catch (err) {
|
||||
nav.style.paddingTop = '';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// simple debounce helper
|
||||
function debounce(fn, wait) {
|
||||
let t;
|
||||
return function () {
|
||||
clearTimeout(t);
|
||||
t = setTimeout(() => fn.apply(this, arguments), wait);
|
||||
};
|
||||
}
|
||||
|
||||
function updateSidebarStateClass() {
|
||||
const sidebar = document.querySelector('.ots-sidebar');
|
||||
if (!sidebar) return;
|
||||
const body = document.body;
|
||||
const isCollapsed = sidebar.classList.contains('collapsed');
|
||||
if (!isCollapsed) {
|
||||
body.classList.add('ots-sidebar-open');
|
||||
} else {
|
||||
body.classList.remove('ots-sidebar-open');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize sidebar section collapse/expand functionality
|
||||
*/
|
||||
function initSidebarSectionToggles() {
|
||||
const groupToggles = document.querySelectorAll('.sidebar-group-toggle');
|
||||
|
||||
syncSidebarActiveStates();
|
||||
|
||||
groupToggles.forEach(toggle => {
|
||||
const group = toggle.closest('.sidebar-group');
|
||||
const submenu = group ? group.querySelector('.sidebar-submenu') : null;
|
||||
@@ -112,6 +194,7 @@
|
||||
group.classList.toggle('is-open', !isOpen);
|
||||
toggle.setAttribute('aria-expanded', (!isOpen).toString());
|
||||
submenu.style.display = isOpen ? 'none' : 'block';
|
||||
syncSidebarActiveStates();
|
||||
});
|
||||
|
||||
if (caret) {
|
||||
@@ -141,9 +224,32 @@
|
||||
group.classList.toggle('is-open', !isOpen);
|
||||
target.setAttribute('aria-expanded', (!isOpen).toString());
|
||||
submenu.style.display = isOpen ? 'none' : 'block';
|
||||
syncSidebarActiveStates();
|
||||
}, true);
|
||||
}
|
||||
|
||||
function syncSidebarActiveStates() {
|
||||
const groups = document.querySelectorAll('.sidebar-group');
|
||||
groups.forEach(group => {
|
||||
const toggle = group.querySelector('.sidebar-group-toggle');
|
||||
if (!toggle) return;
|
||||
|
||||
const hasActiveChild = Boolean(
|
||||
group.querySelector('.sidebar-list.active') ||
|
||||
group.querySelector('.sidebar-list > a.active')
|
||||
);
|
||||
|
||||
toggle.classList.toggle('active', hasActiveChild);
|
||||
|
||||
if (hasActiveChild) {
|
||||
group.classList.add('is-open');
|
||||
const submenu = group.querySelector('.sidebar-submenu');
|
||||
if (submenu) submenu.style.display = 'block';
|
||||
toggle.setAttribute('aria-expanded', 'true');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize dropdown menus
|
||||
*/
|
||||
@@ -462,7 +568,13 @@
|
||||
initChartSafeguard();
|
||||
// Set initial sidebar width variable and keep it updated
|
||||
updateSidebarWidth();
|
||||
window.addEventListener('resize', updateSidebarWidth);
|
||||
// Set initial nav offset and keep it updated on resize
|
||||
updateSidebarNavOffset();
|
||||
const debouncedUpdateNavOffset = debounce(function() {
|
||||
updateSidebarNavOffset();
|
||||
updateSidebarWidth();
|
||||
}, 120);
|
||||
window.addEventListener('resize', debouncedUpdateNavOffset);
|
||||
}
|
||||
|
||||
// Wait for DOM to be ready
|
||||
|
||||
Reference in New Issue
Block a user