diff --git a/static/css/main.css b/static/css/main.css index 1ca7d53..a338316 100644 --- a/static/css/main.css +++ b/static/css/main.css @@ -73,7 +73,6 @@ html { } .message-stack { position: sticky; top: 1rem; z-index: 100; } -/* Mobile-friendly table improvements */ .table-responsive table { min-width: 600px; } @@ -83,7 +82,6 @@ html { white-space: nowrap; } -/* Allow text wrapping for description columns */ .table-responsive table td.text-wrap { white-space: normal; min-width: 200px; @@ -166,14 +164,772 @@ code { border-color: var(--myfsio-card-border); } -.myfsio-nav { +:root { + --sidebar-width: 260px; + --sidebar-collapsed-width: 72px; + --mobile-header-height: 56px; + --sidebar-bg: linear-gradient(180deg, #0f172a 0%, #1e293b 100%); + --sidebar-border: rgba(255, 255, 255, 0.08); + --sidebar-link-color: rgba(255, 255, 255, 0.7); + --sidebar-link-hover: rgba(255, 255, 255, 0.95); + --sidebar-link-active-bg: rgba(59, 130, 246, 0.2); + --sidebar-link-active-border: #3b82f6; + --sidebar-section-color: rgba(255, 255, 255, 0.4); +} + +[data-theme='dark'] { + --sidebar-bg: linear-gradient(180deg, #020617 0%, #0f172a 100%); + --sidebar-border: rgba(255, 255, 255, 0.06); + --sidebar-link-active-bg: rgba(59, 130, 246, 0.25); +} + +body { + display: flex; + min-height: 100vh; +} + +.main-wrapper { + flex: 1; + display: flex; + flex-direction: column; + min-width: 0; + transition: margin-left 0.3s cubic-bezier(0.4, 0, 0.2, 1); +} + +@media (min-width: 992px) { + .main-wrapper { + margin-left: var(--sidebar-width); + } + + body.sidebar-is-collapsed .main-wrapper { + margin-left: var(--sidebar-collapsed-width); + } +} + +.main-content { + flex: 1; + padding: 1.5rem; + max-width: 100%; + overflow-x: hidden; +} + +@media (min-width: 992px) { + .main-content { + padding: 2rem 2.5rem; + } +} + +.mobile-header { + position: fixed; + top: 0; + left: 0; + right: 0; + height: var(--mobile-header-height); + background: var(--sidebar-bg); + display: flex; + align-items: center; + justify-content: space-between; + padding: 0 1rem; + z-index: 1030; + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15); +} + +.sidebar-toggle-btn { + width: 40px; + height: 40px; + display: flex; + align-items: center; + justify-content: center; + background: rgba(255, 255, 255, 0.1); + border: none; + border-radius: 10px; + color: white; + cursor: pointer; + transition: all 0.2s ease; +} + +.sidebar-toggle-btn:hover { + background: rgba(255, 255, 255, 0.15); + transform: scale(1.05); +} + +.mobile-brand { + display: flex; + align-items: center; + gap: 0.5rem; + text-decoration: none; + color: white; + font-weight: 600; + font-size: 1.1rem; +} + +.mobile-brand img { + border-radius: 8px; +} + +.theme-toggle-mobile { + width: 40px; + height: 40px; + display: flex; + align-items: center; + justify-content: center; + background: rgba(255, 255, 255, 0.1); + border: none; + border-radius: 10px; + color: white; + cursor: pointer; + transition: all 0.2s ease; +} + +.theme-toggle-mobile:hover { + background: rgba(255, 255, 255, 0.15); +} + +@media (max-width: 991.98px) { + .main-wrapper { + padding-top: var(--mobile-header-height); + } +} + +.sidebar { + position: fixed; + top: 0; + left: 0; + width: var(--sidebar-width); + height: 100vh; + background: var(--sidebar-bg); + display: flex; + flex-direction: column; + z-index: 1040; + border-right: 1px solid var(--sidebar-border); + transition: width 0.3s cubic-bezier(0.4, 0, 0.2, 1); + overflow: visible; +} + +.sidebar-collapsed { + width: var(--sidebar-collapsed-width); +} + +html.sidebar-will-collapse .sidebar { + width: var(--sidebar-collapsed-width); +} + +html.sidebar-will-collapse .main-wrapper { + margin-left: var(--sidebar-collapsed-width); +} + +html.sidebar-will-collapse .sidebar, +html.sidebar-will-collapse .sidebar *, +html.sidebar-will-collapse .main-wrapper { + transition: none !important; +} + +html.sidebar-will-collapse .sidebar-title, +html.sidebar-will-collapse .sidebar-link-text, +html.sidebar-will-collapse .nav-section-title, +html.sidebar-will-collapse .theme-toggle-text, +html.sidebar-will-collapse .sidebar-user .user-info, +html.sidebar-will-collapse .sidebar-logout-btn .logout-text, +html.sidebar-will-collapse .sidebar-collapse-btn { + display: none !important; + opacity: 0 !important; + width: 0 !important; +} + +html.sidebar-will-collapse .sidebar-header { + justify-content: center; + padding: 1rem 0; +} + +html.sidebar-will-collapse .sidebar-brand { + justify-content: center; +} + +html.sidebar-will-collapse .nav-section { + padding: 0; + width: 100%; +} + +html.sidebar-will-collapse .sidebar-nav { + align-items: center; +} + +html.sidebar-will-collapse .sidebar-link { + justify-content: center; + align-items: center; + width: 48px; + height: 48px; + padding: 0; + margin: 0.25rem auto; + gap: 0; +} + +html.sidebar-will-collapse .sidebar-footer { + padding: 0.75rem 0.5rem; + align-items: center; +} + +html.sidebar-will-collapse .theme-toggle-sidebar, +html.sidebar-will-collapse .sidebar-user, +html.sidebar-will-collapse .sidebar-logout-btn { + justify-content: center; + width: 48px; + height: 48px; + padding: 0; + margin: 0 auto; +} + +html.sidebar-will-collapse .sidebar-user { + background: transparent; +} + +.sidebar-header { + display: flex; + align-items: center; + justify-content: space-between; + padding: 1.25rem 1rem; + border-bottom: 1px solid var(--sidebar-border); + min-height: 70px; + gap: 0.5rem; + overflow: visible; +} + +.sidebar-collapsed .sidebar-header { + justify-content: center; + padding: 1rem 0; + min-height: 70px; +} + +.sidebar-collapsed .sidebar-logo { + width: 36px; + height: 36px; +} + +.sidebar-collapsed .sidebar-brand { + justify-content: center; + cursor: pointer; + position: relative; + gap: 0; +} + +.sidebar-collapsed .sidebar-brand::after { + content: 'Click to expand'; + position: absolute; + left: calc(100% + 12px); + top: 50%; + transform: translateY(-50%); + background: #1e293b; + color: white; + padding: 0.5rem 0.875rem; + border-radius: 8px; + font-size: 0.8rem; + font-weight: 500; + white-space: nowrap; + opacity: 0; + visibility: hidden; + transition: all 0.2s ease; + z-index: 1050; + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2); +} + +.sidebar-collapsed .sidebar-brand:hover::after { + opacity: 1; + visibility: visible; +} + +.sidebar-collapsed .sidebar-collapse-btn { + display: none; +} + +.sidebar-brand { + display: flex; + align-items: center; + gap: 0.75rem; + text-decoration: none; + color: white; + overflow: visible; +} + +.sidebar-logo { + border-radius: 10px; + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3); + flex-shrink: 0; + transition: transform 0.2s ease; +} + +.sidebar-brand:hover .sidebar-logo { + transform: scale(1.05); +} + +.sidebar-title { + font-weight: 700; + font-size: 1.25rem; + letter-spacing: -0.02em; + white-space: nowrap; + opacity: 1; + transition: opacity 0.2s ease; +} + +.sidebar-collapsed .sidebar-title { + opacity: 0; + width: 0; +} + +.sidebar-collapse-btn { + width: 32px; + height: 32px; + display: flex; + align-items: center; + justify-content: center; + background: rgba(255, 255, 255, 0.1); + border: none; + border-radius: 8px; + color: rgba(255, 255, 255, 0.7); + cursor: pointer; + transition: all 0.2s ease; + flex-shrink: 0; +} + +.sidebar-collapse-btn:hover { + background: rgba(255, 255, 255, 0.15); + color: white; +} + +.sidebar-collapse-btn svg { + transition: transform 0.3s ease; +} + +.sidebar-collapsed .sidebar-collapse-btn svg { + transform: rotate(180deg); +} + +.sidebar-body { + flex: 1; + padding: 1rem 0; +} + +.sidebar-nav { + display: flex; + flex-direction: column; + gap: 0.5rem; + overflow: visible; +} + +.nav-section { + padding: 0 0.75rem; + margin-bottom: 0.5rem; + overflow: visible; +} + +.nav-section-title { + display: block; + font-size: 0.7rem; + font-weight: 600; + text-transform: uppercase; + letter-spacing: 0.08em; + color: var(--sidebar-section-color); + padding: 0.5rem 0.75rem; + white-space: nowrap; + overflow: hidden; + transition: opacity 0.2s ease; +} + +.sidebar-collapsed .nav-section-title { + opacity: 0; + height: 0; + padding: 0; + margin: 0; +} + +.sidebar-link { + display: flex; + align-items: center; + gap: 0.875rem; + padding: 0.75rem 1rem; + color: var(--sidebar-link-color); + text-decoration: none; + border-radius: 10px; + transition: all 0.2s ease; + position: relative; + overflow: visible; + margin: 0.5rem; +} + +.sidebar-link::before { + content: ''; + position: absolute; + left: 0; + top: 50%; + transform: translateY(-50%); + width: 3px; + height: 0; + background: var(--sidebar-link-active-border); + border-radius: 0 2px 2px 0; + transition: height 0.2s ease; +} + +.sidebar-link:hover { + color: var(--sidebar-link-hover); + background: rgba(255, 255, 255, 0.08); +} + +.sidebar-link.active { + color: white; + background: var(--sidebar-link-active-bg); +} + +.sidebar-link.active::before { + height: 60%; +} + +.sidebar-link svg { + flex-shrink: 0; + opacity: 0.9; + transition: transform 0.2s ease; +} + +.sidebar-link:hover svg { + transform: scale(1.1); +} + +.sidebar-link-text { + white-space: nowrap; + overflow: hidden; + transition: opacity 0.2s ease, width 0.2s ease; +} + +.sidebar-collapsed .sidebar-link-text { + opacity: 0; + width: 0; +} + +.sidebar-collapsed .sidebar-link { + justify-content: center; + align-items: center; + padding: 0; + margin: 0.25rem auto; + width: 48px; + height: 48px; + gap: 0; +} + +.sidebar-collapsed .sidebar-link svg { + width: 20px; + height: 20px; + flex-shrink: 0; +} + +.sidebar-collapsed .nav-section { + padding: 0; + width: 100%; +} + +.sidebar-collapsed .sidebar-nav { + align-items: center; +} + +.sidebar-collapsed .sidebar-link[data-tooltip]::after { + content: attr(data-tooltip); + position: absolute; + left: calc(100% + 12px); + top: 50%; + transform: translateY(-50%); + background: #1e293b; + color: white; + padding: 0.5rem 0.875rem; + border-radius: 8px; + font-size: 0.85rem; + font-weight: 500; + white-space: nowrap; + opacity: 0; + visibility: hidden; + transition: all 0.2s ease; + z-index: 1050; + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2); +} + +.sidebar-collapsed .sidebar-link[data-tooltip]:hover::after { + opacity: 1; + visibility: visible; +} + +.sidebar-footer { + padding: 1rem; + border-top: 1px solid var(--sidebar-border); + display: flex; + flex-direction: column; + gap: 0.75rem; + overflow: visible; +} + +.sidebar-collapsed .sidebar-footer { + padding: 0.75rem 0.5rem; + align-items: center; +} + +.theme-toggle-sidebar { + display: flex; + align-items: center; + gap: 0.75rem; + width: 100%; + padding: 0.75rem 1rem; + background: rgba(255, 255, 255, 0.08); + border: none; + border-radius: 10px; + color: rgba(255, 255, 255, 0.8); + cursor: pointer; + transition: all 0.2s ease; +} + +.theme-toggle-sidebar:hover { + background: rgba(255, 255, 255, 0.12); + color: white; +} + +.theme-toggle-text { + font-size: 0.875rem; + font-weight: 500; + white-space: nowrap; + overflow: hidden; + transition: opacity 0.2s ease; +} + +.sidebar-collapsed .theme-toggle-text { + opacity: 0; + width: 0; + display: none; +} + +.sidebar-collapsed .theme-toggle-sidebar { + justify-content: center; + padding: 0; + width: 48px; + height: 48px; + margin: 0 auto; + position: relative; +} + +.sidebar-collapsed .theme-toggle-sidebar svg { + width: 18px; + height: 18px; + flex-shrink: 0; +} + +.sidebar-collapsed .theme-toggle-sidebar::after { + content: 'Toggle theme'; + position: absolute; + left: calc(100% + 12px); + top: 50%; + transform: translateY(-50%); + background: #1e293b; + color: white; + padding: 0.5rem 0.875rem; + border-radius: 8px; + font-size: 0.8rem; + font-weight: 500; + white-space: nowrap; + opacity: 0; + visibility: hidden; + transition: all 0.2s ease; + z-index: 1050; + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2); +} + +.sidebar-collapsed .theme-toggle-sidebar:hover::after { + opacity: 1; + visibility: visible; +} + +.sidebar-user { + display: flex; + align-items: center; + gap: 0.75rem; + padding: 0.75rem; + background: rgba(255, 255, 255, 0.05); + border-radius: 10px; + overflow: hidden; +} + +.sidebar-user .user-avatar { + width: 36px; + height: 36px; + border-radius: 10px; + background: linear-gradient(135deg, #3b82f6, #8b5cf6); + display: flex; + align-items: center; + justify-content: center; + color: white; + flex-shrink: 0; +} + +.sidebar-user .user-info { + overflow: hidden; + transition: opacity 0.2s ease, width 0.2s ease; +} + +.sidebar-collapsed .sidebar-user .user-info { + opacity: 0; + width: 0; + display: none; +} + +.sidebar-collapsed .sidebar-user { + justify-content: center; + padding: 0; + width: 48px; + height: 48px; + margin: 0 auto; + background: transparent; + position: relative; +} + +.sidebar-collapsed .sidebar-user .user-avatar { + width: 36px; + height: 36px; +} + +.sidebar-collapsed .sidebar-user::after { + content: attr(data-username); + position: absolute; + left: calc(100% + 12px); + top: 50%; + transform: translateY(-50%); + background: #1e293b; + color: white; + padding: 0.5rem 0.875rem; + border-radius: 8px; + font-size: 0.8rem; + font-weight: 500; + white-space: nowrap; + opacity: 0; + visibility: hidden; + transition: all 0.2s ease; + z-index: 1050; + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2); +} + +.sidebar-collapsed .sidebar-user:hover::after { + opacity: 1; + visibility: visible; +} + +.sidebar-user .user-name { + font-size: 0.875rem; + font-weight: 600; + color: white; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + +.sidebar-user .user-key { + font-size: 0.75rem; + color: rgba(255, 255, 255, 0.5); + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + +.sidebar-logout-btn { + display: flex; + align-items: center; + justify-content: center; + gap: 0.75rem; + width: 100%; + padding: 0.75rem 1rem; + background: rgba(239, 68, 68, 0.15); + border: 1px solid rgba(239, 68, 68, 0.3); + border-radius: 10px; + color: #fca5a5; + font-size: 0.875rem; + font-weight: 500; + cursor: pointer; + transition: all 0.2s ease; +} + +.sidebar-logout-btn:hover { + background: rgba(239, 68, 68, 0.25); + border-color: rgba(239, 68, 68, 0.5); + color: #fecaca; +} + +.sidebar-collapsed .sidebar-logout-btn .logout-text { + display: none; +} + +.sidebar-collapsed .sidebar-logout-btn { + justify-content: center; + padding: 0; + width: 48px; + height: 48px; + margin: 0 auto; + position: relative; +} + +.sidebar-collapsed .sidebar-logout-btn svg { + width: 18px; + height: 18px; + flex-shrink: 0; +} + +.sidebar-collapsed .sidebar-logout-btn::after { + content: 'Sign out'; + position: absolute; + left: calc(100% + 12px); + top: 50%; + transform: translateY(-50%); + background: #1e293b; + color: white; + padding: 0.5rem 0.875rem; + border-radius: 8px; + font-size: 0.8rem; + font-weight: 500; + white-space: nowrap; + opacity: 0; + visibility: hidden; + transition: all 0.2s ease; + z-index: 1050; + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2); +} + +.sidebar-collapsed .sidebar-logout-btn:hover::after { + opacity: 1; + visibility: visible; +} + +.sidebar-offcanvas { + width: 280px !important; + background: var(--sidebar-bg) !important; + border-right: none !important; +} + +.sidebar-offcanvas .sidebar-header { + background: transparent; +} + +.sidebar-offcanvas .sidebar-body { + display: flex; + flex-direction: column; + padding: 0; +} + +.sidebar-offcanvas .sidebar-nav { + flex: 1; + padding: 1rem 0; +} + +.sidebar-offcanvas .sidebar-footer { + margin-top: auto; +} + +.myfsio-nav { background: var(--myfsio-nav-gradient); box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); backdrop-filter: blur(8px); -webkit-backdrop-filter: blur(8px); } -.myfsio-nav .navbar-brand { +.myfsio-nav .navbar-brand { color: #fff; font-weight: 600; letter-spacing: -0.02em; @@ -192,24 +948,24 @@ code { display: inline-block; } -.myfsio-nav .nav-link { +.myfsio-nav .nav-link { color: var(--myfsio-nav-link); transition: color 0.2s ease; } -.myfsio-nav .nav-link:hover { +.myfsio-nav .nav-link:hover { color: var(--myfsio-nav-link-hover); } .myfsio-nav .nav-link.nav-link-muted { opacity: 0.75; } -.myfsio-nav .nav-link.nav-link-muted .badge { +.myfsio-nav .nav-link.nav-link-muted .badge { color: #0f172a; background-color: #fef08a; } -[data-theme='dark'] .myfsio-nav .nav-link.nav-link-muted .badge { - color: #0f172a; +[data-theme='dark'] .myfsio-nav .nav-link.nav-link-muted .badge { + color: #0f172a; background-color: #fde047; } @@ -382,14 +1138,12 @@ code { min-width: 0; } -/* Ensure pre blocks don't overflow on mobile */ .alert pre { max-width: 100%; overflow-x: auto; -webkit-overflow-scrolling: touch; } -/* IAM User Cards */ .iam-user-card { border: 1px solid var(--myfsio-card-border); border-radius: 0.75rem; @@ -1773,7 +2527,6 @@ pre code { top: 0 !important; } - /* Ensure tables are scrollable on mobile */ .card-body .table-responsive { margin: -1rem; padding: 0; @@ -1784,13 +2537,11 @@ pre code { margin-bottom: 0; } - /* IAM users table mobile adjustments */ .table th, .table td { padding: 0.5rem 0.75rem; } - /* Better touch scrolling indicator */ .table-responsive::after { content: ''; position: absolute; @@ -1969,3 +2720,76 @@ body.theme-transitioning * { flex: 1; } } + +.modal { + z-index: 1055; +} + +.modal-backdrop { + z-index: 1050; +} + +@media (min-width: 992px) { + .toast-container { + right: 1.5rem; + } +} + +@media (min-width: 992px) { + .floating-upload-progress { + right: 1.5rem; + } +} + +.sidebar-body::-webkit-scrollbar { + width: 4px; +} + +.sidebar-body::-webkit-scrollbar-track { + background: transparent; +} + +.sidebar-body::-webkit-scrollbar-thumb { + background: rgba(255, 255, 255, 0.2); + border-radius: 2px; +} + +.sidebar-body::-webkit-scrollbar-thumb:hover { + background: rgba(255, 255, 255, 0.3); +} + +@keyframes sidebarLinkPulse { + 0%, 100% { box-shadow: 0 0 0 0 rgba(59, 130, 246, 0.4); } + 50% { box-shadow: 0 0 0 4px rgba(59, 130, 246, 0); } +} + +.sidebar-link.active { + animation: sidebarLinkPulse 2s ease-in-out infinite; +} + +.offcanvas-backdrop.show { + backdrop-filter: blur(4px); + -webkit-backdrop-filter: blur(4px); +} + +body:has(.login-card) .sidebar, +body:has(.login-card) .mobile-header { + display: none !important; +} + +body:has(.login-card) .main-wrapper { + margin-left: 0 !important; + padding-top: 0 !important; +} + +@media print { + .sidebar, + .mobile-header { + display: none !important; + } + + .main-wrapper { + margin-left: 0 !important; + padding-top: 0 !important; + } +} diff --git a/templates/base.html b/templates/base.html index 7f49232..44147be 100644 --- a/templates/base.html +++ b/templates/base.html @@ -24,105 +24,216 @@ document.documentElement.dataset.bsTheme = 'light'; document.documentElement.dataset.theme = 'light'; } + try { + if (localStorage.getItem('myfsio-sidebar-collapsed') === 'true') { + document.documentElement.classList.add('sidebar-will-collapse'); + } + } catch (err) {} })();
-