feat: Comprehensive mobile UI improvements

Dashboard mobile changes:
- Sidebar becomes slide-out drawer with overlay
- Added mobile filter toggle button
- Table wrapped for horizontal scroll
- Stats grid: 2 columns on tablet, 1 on phone
- Larger touch targets (44px minimum)
- Full-width modals with better spacing
- Admin dropdown slides up from bottom
- Fixed bulk action bar at bottom

Ticket page mobile changes:
- Stack metadata vertically
- Full-width buttons and inputs
- Scrollable tabs
- Better comment form layout
- Improved timeline readability

General:
- Prevent iOS zoom with 16px input font
- Touch-friendly spacing throughout

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-01-23 22:10:29 -05:00
parent ee317d6662
commit 7465fb6fc4
4 changed files with 619 additions and 0 deletions

View File

@@ -27,6 +27,71 @@ function toggleSidebar() {
}
}
/**
* Mobile sidebar functions
*/
function openMobileSidebar() {
const sidebar = document.getElementById('dashboardSidebar');
const overlay = document.getElementById('mobileSidebarOverlay');
if (sidebar) {
sidebar.classList.add('mobile-open');
}
if (overlay) {
overlay.classList.add('active');
}
document.body.style.overflow = 'hidden';
}
function closeMobileSidebar() {
const sidebar = document.getElementById('dashboardSidebar');
const overlay = document.getElementById('mobileSidebarOverlay');
if (sidebar) {
sidebar.classList.remove('mobile-open');
}
if (overlay) {
overlay.classList.remove('active');
}
document.body.style.overflow = '';
}
// Initialize mobile sidebar elements
function initMobileSidebar() {
const sidebar = document.getElementById('dashboardSidebar');
const dashboardMain = document.querySelector('.dashboard-main');
if (!sidebar || !dashboardMain) return;
// Create overlay if it doesn't exist
if (!document.getElementById('mobileSidebarOverlay')) {
const overlay = document.createElement('div');
overlay.id = 'mobileSidebarOverlay';
overlay.className = 'mobile-sidebar-overlay';
overlay.onclick = closeMobileSidebar;
document.body.appendChild(overlay);
}
// Create mobile filter toggle button if it doesn't exist
if (!document.getElementById('mobileFilterToggle')) {
const toggleBtn = document.createElement('button');
toggleBtn.id = 'mobileFilterToggle';
toggleBtn.className = 'mobile-filter-toggle';
toggleBtn.innerHTML = '<span>☰</span> Filters & Options';
toggleBtn.onclick = openMobileSidebar;
toggleBtn.style.display = 'none'; // Hidden by default, shown via CSS media query
dashboardMain.insertBefore(toggleBtn, dashboardMain.firstChild);
}
// Create close button inside sidebar if it doesn't exist
if (!sidebar.querySelector('.mobile-sidebar-close')) {
const closeBtn = document.createElement('button');
closeBtn.className = 'mobile-sidebar-close';
closeBtn.innerHTML = '×';
closeBtn.onclick = closeMobileSidebar;
closeBtn.style.display = 'none'; // Hidden by default, shown via CSS media query
sidebar.insertBefore(closeBtn, sidebar.firstChild);
}
}
// Restore sidebar state on page load
document.addEventListener('DOMContentLoaded', function() {
const savedState = localStorage.getItem('sidebarCollapsed');
@@ -40,6 +105,9 @@ document.addEventListener('DOMContentLoaded', function() {
// Main initialization
document.addEventListener('DOMContentLoaded', function() {
// Initialize mobile sidebar for dashboard
initMobileSidebar();
// Check if we're on the dashboard page
const hasTable = document.querySelector('table');
const isTicketPage = window.location.pathname.includes('/ticket/') ||