feat: Enhance OTS Signage theme with improved sidebar, dropdowns, and UI interactions
- Updated sidebar functionality to include a close button and improved mobile responsiveness. - Introduced dropdown menus for user actions and enhanced search functionality in the topbar. - Refined page interactions for folder and media item selections. - Modernized sidebar navigation with icons and improved layout for better user experience. - Enhanced media and display pages with updated layouts and statistics display. - Improved overall styling and responsiveness across various components.
This commit is contained in:
@@ -1,14 +1,13 @@
|
||||
/**
|
||||
* OTS Signage Modern Theme - Client-Side Utilities
|
||||
* Sidebar toggle, theme persistence, and UI interactions
|
||||
* Sidebar toggle, dropdown menus, and UI interactions
|
||||
*/
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
const STORAGE_KEYS = {
|
||||
sidebarCollapsed: 'otsTheme:sidebarCollapsed',
|
||||
themeMode: 'otsTheme:mode'
|
||||
sidebarCollapsed: 'otsTheme:sidebarCollapsed'
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -16,37 +15,140 @@
|
||||
*/
|
||||
function initSidebarToggle() {
|
||||
const toggleBtn = document.querySelector('[data-action="toggle-sidebar"]');
|
||||
const shell = document.querySelector('.ots-shell');
|
||||
const sidebar = document.querySelector('.ots-sidebar');
|
||||
|
||||
if (!toggleBtn || !shell) return;
|
||||
if (!toggleBtn || !sidebar) return;
|
||||
|
||||
const isCollapsed = localStorage.getItem(STORAGE_KEYS.sidebarCollapsed) === 'true';
|
||||
if (isCollapsed) {
|
||||
shell.classList.add('ots-sidebar-collapsed');
|
||||
}
|
||||
toggleBtn.addEventListener('click', function(e) {
|
||||
e.preventDefault();
|
||||
sidebar.classList.toggle('active');
|
||||
});
|
||||
|
||||
toggleBtn.addEventListener('click', function() {
|
||||
shell.classList.toggle('ots-sidebar-collapsed');
|
||||
const collapsed = shell.classList.contains('ots-sidebar-collapsed');
|
||||
localStorage.setItem(STORAGE_KEYS.sidebarCollapsed, collapsed);
|
||||
// Close sidebar when clicking outside on mobile
|
||||
document.addEventListener('click', function(e) {
|
||||
if (window.innerWidth <= 768) {
|
||||
const isClickInsideSidebar = sidebar.contains(e.target);
|
||||
const isClickOnToggle = toggleBtn.contains(e.target);
|
||||
|
||||
if (!isClickInsideSidebar && !isClickOnToggle && sidebar.classList.contains('active')) {
|
||||
sidebar.classList.remove('active');
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize theme toggle (light/dark mode)
|
||||
* Initialize dropdown menus
|
||||
*/
|
||||
function initThemeToggle() {
|
||||
const themeBtn = document.querySelector('[data-action="toggle-theme"]');
|
||||
const html = document.documentElement;
|
||||
function initDropdowns() {
|
||||
const dropdowns = document.querySelectorAll('.dropdown');
|
||||
|
||||
dropdowns.forEach(dropdown => {
|
||||
const button = dropdown.querySelector('.dropdown-menu');
|
||||
|
||||
if (!button) return;
|
||||
|
||||
const menu = dropdown.querySelector('.dropdown-menu');
|
||||
|
||||
// Toggle menu on button click
|
||||
dropdown.addEventListener('click', function(e) {
|
||||
if (e.target.closest('.user-btn') || e.target.closest('[aria-label="User menu"]')) {
|
||||
e.preventDefault();
|
||||
dropdown.classList.toggle('active');
|
||||
}
|
||||
});
|
||||
|
||||
// Close menu when clicking outside
|
||||
document.addEventListener('click', function(e) {
|
||||
if (!dropdown.contains(e.target)) {
|
||||
dropdown.classList.remove('active');
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
if (!themeBtn) return;
|
||||
/**
|
||||
* Initialize search functionality
|
||||
*/
|
||||
function initSearch() {
|
||||
const searchForm = document.querySelector('.topbar-search');
|
||||
if (!searchForm) return;
|
||||
|
||||
// Restore theme preference
|
||||
const savedTheme = localStorage.getItem(STORAGE_KEYS.themeMode);
|
||||
if (savedTheme) {
|
||||
html.setAttribute('data-theme', savedTheme);
|
||||
themeBtn.setAttribute('aria-pressed', savedTheme === 'dark');
|
||||
const input = searchForm.querySelector('.search-input');
|
||||
if (input) {
|
||||
input.addEventListener('focus', function() {
|
||||
searchForm.style.borderColor = 'var(--color-primary)';
|
||||
});
|
||||
input.addEventListener('blur', function() {
|
||||
searchForm.style.borderColor = 'var(--color-border)';
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize page specific interactions
|
||||
*/
|
||||
function initPageInteractions() {
|
||||
// Displays page - folder selection
|
||||
const folderItems = document.querySelectorAll('.folder-item');
|
||||
folderItems.forEach(item => {
|
||||
item.addEventListener('click', function() {
|
||||
folderItems.forEach(f => f.classList.remove('active'));
|
||||
this.classList.add('active');
|
||||
});
|
||||
});
|
||||
|
||||
// Media page - item selection
|
||||
const mediaItems = document.querySelectorAll('.media-item');
|
||||
mediaItems.forEach(item => {
|
||||
item.addEventListener('click', function() {
|
||||
this.style.opacity = '0.7';
|
||||
setTimeout(() => this.style.opacity = '1', 200);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Make sidebar responsive
|
||||
*/
|
||||
function makeResponsive() {
|
||||
const sidebar = document.querySelector('.ots-sidebar');
|
||||
const main = document.querySelector('.ots-main');
|
||||
|
||||
if (!sidebar) return;
|
||||
|
||||
// Add toggle button for mobile
|
||||
if (window.innerWidth <= 768) {
|
||||
sidebar.classList.add('mobile');
|
||||
}
|
||||
|
||||
window.addEventListener('resize', function() {
|
||||
if (window.innerWidth > 768) {
|
||||
sidebar.classList.remove('mobile', 'active');
|
||||
} else {
|
||||
sidebar.classList.add('mobile');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize all features when DOM is ready
|
||||
*/
|
||||
function init() {
|
||||
initSidebarToggle();
|
||||
initDropdowns();
|
||||
initSearch();
|
||||
initPageInteractions();
|
||||
makeResponsive();
|
||||
}
|
||||
|
||||
// Wait for DOM to be ready
|
||||
if (document.readyState === 'loading') {
|
||||
document.addEventListener('DOMContentLoaded', init);
|
||||
} else {
|
||||
init();
|
||||
}
|
||||
})();
|
||||
|
||||
themeBtn.addEventListener('click', function() {
|
||||
const currentTheme = html.getAttribute('data-theme') || 'light';
|
||||
|
||||
Reference in New Issue
Block a user