feat: add mobile navigation drawer with backdrop, close button, and responsive table layout optimizations
Add mobile-nav-backdrop/mobile-nav-close elements with DOMContentLoaded script for hamburger navigation. Add .brand click handler to open navigation on mobile (<700px) with body.mobile-nav-open class toggle. Add backdrop/close button click handlers and nav button delegation to close drawer. Style .nav as fixed left-side drawer with 310px max-width, translateX(-105%) default, and translateX(
This commit is contained in:
@@ -1,4 +1,6 @@
|
||||
<!doctype html>
|
||||
<script>document.addEventListener('DOMContentLoaded',()=>{const brand=document.querySelector('.brand'),nav=document.querySelector('.nav');if(!brand||!nav)return;const backdrop=document.createElement('div');backdrop.className='mobile-nav-backdrop';const close=document.createElement('button');close.className='mobile-nav-close';close.type='button';close.setAttribute('aria-label','Navigation schließen');close.textContent='×';nav.prepend(close);document.body.appendChild(backdrop);const closeNav=()=>document.body.classList.remove('mobile-nav-open');brand.addEventListener('click',()=>{if(window.matchMedia('(max-width: 700px)').matches)document.body.classList.add('mobile-nav-open')});backdrop.addEventListener('click',closeNav);close.addEventListener('click',closeNav);nav.addEventListener('click',event=>{if(event.target.closest('button[data-view]'))closeNav()})});</script>
|
||||
<style>.mobile-nav-close,.mobile-nav-backdrop{display:none}@media(max-width:700px){.brand{cursor:pointer}.mobile-nav-backdrop{position:fixed;inset:0;z-index:130;background:rgba(0,0,0,.58);backdrop-filter:blur(2px)}body.mobile-nav-open .mobile-nav-backdrop{display:block}.nav{position:fixed;top:0;bottom:0;left:0;z-index:140;width:min(82vw,310px);margin:0!important;padding:62px 12px 18px!important;display:flex;flex-direction:column;align-items:stretch;gap:5px;overflow-y:auto;border:0!important;border-right:1px solid #3c4653!important;border-radius:0!important;background:rgba(28,32,39,.98)!important;box-shadow:14px 0 40px rgba(0,0,0,.35);transform:translateX(-105%);transition:transform .24s ease}.nav button{flex:0 0 auto!important;text-align:left;padding:12px 13px!important;border-radius:8px!important;font-size:13px!important}.nav button.active{background:#303b49}.mobile-nav-close{display:block;position:absolute;top:14px;right:12px;width:34px;height:34px;padding:0;border:1px solid #4a5563;border-radius:8px;background:#292f38;color:#dce8f3;font-size:23px;line-height:1}.mobile-nav-open .nav{transform:translateX(0)}body.mobile-nav-open{overflow:hidden}#movies,#sonarr table,#missing table{min-width:0;width:100%;table-layout:fixed}#movies th:nth-child(3),#movies td:nth-child(3),#movies th:nth-child(6),#movies td:nth-child(6),#movies th:nth-child(7),#movies td:nth-child(7),#sonarr th:nth-child(3),#sonarr td:nth-child(3),#sonarr th:nth-child(6),#sonarr td:nth-child(6),#sonarr th:nth-child(7),#sonarr td:nth-child(7),#missing th:nth-child(3),#missing td:nth-child(3),#missing th:nth-child(6),#missing td:nth-child(6),#missing th:nth-child(7),#missing td:nth-child(7){display:none}#movies th:nth-child(1),#sonarr th:nth-child(1),#missing th:nth-child(1){width:46%}#movies th:nth-child(2),#sonarr th:nth-child(2),#missing th:nth-child(2){width:18%}#movies th:nth-child(4),#movies th:nth-child(5),#sonarr th:nth-child(4),#sonarr th:nth-child(5),#missing th:nth-child(4),#missing th:nth-child(5){width:18%}#movies td,#sonarr td,#missing td{padding:8px 6px;font-size:11px}.badges{gap:3px}.badge{padding:2px 5px;font-size:10px}.title{max-width:100%}.tablewrap{overflow-x:hidden}.series-category>.series table{min-width:0!important}}</style>
|
||||
<script>document.addEventListener('DOMContentLoaded',()=>{const panel=document.querySelector('.system-panel'),diskList=document.querySelector('#diskList');if(!panel||!diskList)return;const extra=document.createElement('div');extra.id='systemDetails';extra.className='system-details';diskList.before(extra);const formatUptime=seconds=>{const days=Math.floor(seconds/86400),hours=Math.floor(seconds%86400/3600),minutes=Math.floor(seconds%3600/60);return `${days?days+' T ':''}${hours} Std. ${minutes} Min.`};const update=async()=>{try{const data=await (await fetch('/api/system')).json();const load=data.load||[];extra.innerHTML=`<div class="system-detail"><span class="system-detail-icon"><img src="https://api.iconify.design/mdi:chart-line.svg?color=%2360a9e6" alt="" aria-hidden="true"></span><div><small>Load Average</small><strong>${load.map(value=>Number(value).toFixed(2)).join(' · ')||'—'}</strong><em>1 / 5 / 15 Minuten</em></div></div><div class="system-detail"><span class="system-detail-icon"><img src="https://api.iconify.design/mdi:clock-outline.svg?color=%23d7adf3" alt="" aria-hidden="true"></span><div><small>Uptime</small><strong>${formatUptime(Number(data.uptime_seconds)||0)}</strong><em>Container-Laufzeit</em></div></div><div class="system-detail"><span class="system-detail-icon"><img src="https://api.iconify.design/mdi:application-cog-outline.svg?color=%23f4d267" alt="" aria-hidden="true"></span><div><small>Prozesse</small><strong>${Number(data.processes||0).toLocaleString('de-DE')}</strong><em>Aktive Prozesse</em></div></div>`}catch(error){extra.innerHTML='<div class="system-detail muted">Systemdetails momentan nicht verfügbar</div>'}};update();setInterval(update,5000)});</script>
|
||||
<style>.system-details{display:grid;grid-template-columns:repeat(3,1fr);gap:8px;margin:2px 0 17px}.system-detail{display:flex;align-items:center;gap:9px;padding:10px 11px;border:1px solid rgba(255,255,255,.07);border-radius:9px;background:rgba(40,43,49,.58)}.system-detail-icon{display:grid;place-items:center;flex:0 0 auto;width:28px;height:28px;border-radius:8px;background:rgba(96,169,230,.14)}.system-detail-icon img{width:17px;height:17px}.system-detail small,.system-detail em{display:block}.system-detail small{color:#9da5b2;font-size:10px}.system-detail strong{display:block;margin-top:2px;color:#f1f5fa;font-size:13px}.system-detail em{margin-top:2px;color:#7f8996;font-size:9px;font-style:normal}@media(max-width:700px){.system-details{grid-template-columns:1fr 1fr}.system-detail:last-child{grid-column:1 / -1}}</style>
|
||||
<script>document.addEventListener('DOMContentLoaded',()=>{const icons={overview:['mdi:movie-open-outline','mdi:television-classic','mdi:alert-outline','mdi:download-box-outline'],insight:['mdi:movie-check-outline','mdi:playlist-check','mdi:database-check-outline','mdi:monitor-eye']};const apply=(selector,keys)=>{const colors=selector.includes('overview')?['%238bc9f2','%23d7adf3','%23ff9e9e','%236ae29a']:['%238bc9f2','%23d7adf3','%23f4d267','%236ae29a'];document.querySelectorAll(selector).forEach((node,index)=>{const key=keys[index%keys.length];if(!key||node.dataset.iconApplied===key)return;const image=document.createElement('img');image.src=`https://api.iconify.design/${key}.svg?color=${colors[index%colors.length]}`;image.alt='';image.setAttribute('aria-hidden','true');node.textContent='';node.appendChild(image);node.dataset.iconApplied=key})};const update=()=>{apply('.overview-icon',icons.overview);apply('.insight-icon',icons.insight)};update();new MutationObserver(update).observe(document.body,{childList:true,subtree:true})});</script>
|
||||
|
||||
Reference in New Issue
Block a user