diff --git a/sidebar.js b/sidebar.js index 9560204..8303bbf 100644 --- a/sidebar.js +++ b/sidebar.js @@ -38,10 +38,34 @@ menu.appendChild(btn); } + // --- Lock button icon state --- + initLockButton(); + // --- Search overlay (delayed to wait for search plugin init) --- setTimeout(initSearchOverlay, 800); } + function initLockButton() { + var lockItem = document.querySelector('.nav-item.LockButton'); + if (!lockItem) return; + var lockLink = lockItem.querySelector('a'); + if (!lockLink) return; + + function updateLockState() { + var title = lockLink.getAttribute('title') || ''; + if (title.toLowerCase().indexOf('unlock') > -1) { + lockItem.classList.add('is-locked'); + } else { + lockItem.classList.remove('is-locked'); + } + } + + updateLockState(); + + var observer = new MutationObserver(updateLockState); + observer.observe(lockLink, { attributes: true, attributeFilter: ['title'] }); + } + function initSearchOverlay() { if (!window.jQuery) return; @@ -319,12 +343,26 @@ observer.observe(target, { childList: true, subtree: true }); } + // Replace Tailscale sidebar icon with light SVG + function replaceTailscaleIcon() { + var imgs = document.querySelectorAll('img[alt="Tailscale"]'); + imgs.forEach(function(img) { + var url = CDN_SVG + '/tailscale-light.svg'; + if (img.getAttribute('src') !== url) { + img.src = url; + img.removeAttribute('onerror'); + } + }); + } + // Initialize when DOM is ready function initIcons() { // Initial replacement setTimeout(replaceIcons, 500); + setTimeout(replaceTailscaleIcon, 500); // Second pass after FolderView finishes its DOM work setTimeout(replaceIcons, 2000); + setTimeout(replaceTailscaleIcon, 2000); // Start watching for future changes startObserver(); } @@ -335,3 +373,136 @@ initIcons(); } })(); + +// ============================================================= +// Pie Chart Recoloring — vibrant theme colors for System donuts +// ============================================================= +(function() { + 'use strict'; + + // Unraid's muted defaults → vibrant theme replacements + var COLOR_MAP = { + 'rgb(68,119,170)': '#7EB8DA', // accent blue (used) + 'rgb(204,204,204)': 'rgba(255,255,255,0.10)', // free → subtle + 'rgb(34,136,51)': '#4ade80', // green + 'rgb(170,68,153)': '#f97316', // purple → orange + 'rgb(238,102,119)': '#ef4444', // red + 'rgb(0,153,136)': '#22d3ee', // teal → cyan + 'rgb(221,204,119)': '#facc15', // yellow + 'rgb(136,34,85)': '#f87171', // dark red → light red + 'rgb(17,119,51)': '#22c55e', // dark green → bright green + 'rgb(51,34,136)': '#818cf8', // dark purple → indigo + 'rgb(102,153,204)': '#93c5fd' // light blue + }; + + function recolorPie(pie) { + var style = pie.getAttribute('style'); + if (!style || style.indexOf('conic-gradient') === -1) return; + + var newStyle = style; + var keys = Object.keys(COLOR_MAP); + for (var i = 0; i < keys.length; i++) { + // Replace with global flag via split/join + newStyle = newStyle.split(keys[i]).join(COLOR_MAP[keys[i]]); + } + + if (newStyle !== style) { + pie.setAttribute('style', newStyle); + } + } + + function recolorAll() { + var pies = document.querySelectorAll('div.pie'); + pies.forEach(recolorPie); + } + + function startObserver() { + var target = document.getElementById('displaybox') || document.body; + var observer = new MutationObserver(function(mutations) { + for (var i = 0; i < mutations.length; i++) { + var m = mutations[i]; + if (m.type === 'attributes' && m.attributeName === 'style') { + var el = m.target; + if (el.classList && el.classList.contains('pie')) { + recolorPie(el); + } + } + if (m.type === 'childList' && m.addedNodes.length > 0) { + recolorAll(); + } + } + }); + observer.observe(target, { + childList: true, + subtree: true, + attributes: true, + attributeFilter: ['style'] + }); + } + + function init() { + setTimeout(recolorAll, 600); + setTimeout(recolorAll, 2000); + startObserver(); + } + + if (document.readyState === 'loading') { + document.addEventListener('DOMContentLoaded', init); + } else { + init(); + } +})(); + +// ============================================================= +// System Legend Colors — match pie segment colors in legends +// ============================================================= +(function() { + 'use strict'; + + // Unraid default legend colors → vibrant theme colors + var LEGEND_MAP = { + 'rgb(68, 119, 170)': '#7EB8DA', + 'rgb(204, 204, 204)': 'rgba(255,255,255,0.35)', + 'rgb(34, 136, 51)': '#4ade80', + 'rgb(170, 68, 153)': '#f97316', + 'rgb(238, 102, 119)': '#ef4444', + 'rgb(0, 153, 136)': '#22d3ee', + 'rgb(221, 204, 119)': '#facc15', + 'rgb(136, 34, 85)': '#f87171', + 'rgb(17, 119, 51)': '#22c55e', + 'rgb(51, 34, 136)': '#818cf8', + 'rgb(102, 153, 204)': '#93c5fd' + }; + + function recolorLegends() { + var icons = document.querySelectorAll('#dynamic i.fa-circle'); + icons.forEach(function(icon) { + var currentColor = icon.style.color; + if (!currentColor) return; + var mapped = LEGEND_MAP[currentColor]; + if (mapped) { + icon.style.setProperty('color', mapped, 'important'); + } + }); + } + + function startObserver() { + var target = document.getElementById('dynamic') || document.getElementById('displaybox') || document.body; + var observer = new MutationObserver(function() { + recolorLegends(); + }); + observer.observe(target, { childList: true, subtree: true }); + } + + function init() { + setTimeout(recolorLegends, 700); + setTimeout(recolorLegends, 2500); + startObserver(); + } + + if (document.readyState === 'loading') { + document.addEventListener('DOMContentLoaded', init); + } else { + init(); + } +})(); diff --git a/style.css b/style.css index 2a9ce46..ae53350 100644 --- a/style.css +++ b/style.css @@ -3,6 +3,11 @@ Mountain wallpaper + frosted glass cards ============================================ */ +/* --- Prevent horizontal scrollbar --- */ +html { + overflow-x: hidden; +} + /* --- CSS Variables --- */ :root { /* Accent: cool steel blue to match B&W mountains */ @@ -180,18 +185,17 @@ body::before { transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1); } -/* Expanded: chevron in visible circle, rotated to point left */ +/* Expanded: round hover highlight, rotated to point left */ html.sidebar-expanded #sidebar-toggle-btn { width: 36px !important; height: 36px !important; box-sizing: border-box !important; - background: rgba(255, 255, 255, 0.06) !important; - border: 1px solid rgba(255, 255, 255, 0.10) !important; + background: transparent !important; + border: none !important; } html.sidebar-expanded #sidebar-toggle-btn:hover { - background: rgba(255, 255, 255, 0.12) !important; - border-color: rgba(255, 255, 255, 0.20) !important; + background: rgba(255, 255, 255, 0.10) !important; } html.sidebar-expanded #sidebar-toggle-btn svg { @@ -323,6 +327,7 @@ html.sidebar-expanded #sidebar-toggle-btn svg { .Theme--sidebar .nav-item.LogButton a:before { content: "\f0f6" !important; } .Theme--sidebar .nav-item.HelpButton a:before { content: "\f059" !important; } .Theme--sidebar .nav-item.LockButton a:before { content: "\f09c" !important; font-family: FontAwesome !important; } +.Theme--sidebar .nav-item.LockButton.is-locked a:before { content: "\f023" !important; } /* --- EXPANDED SIDEBAR --- Compound selectors: both classes on */ @@ -382,6 +387,7 @@ html.sidebar-expanded.Theme--sidebar .nav-tile.right .nav-item a { } /* --- Content area shifts for sidebar (push, not overlap) --- */ +#header, #displaybox, #footer, #copyright { @@ -389,6 +395,7 @@ html.sidebar-expanded.Theme--sidebar .nav-tile.right .nav-item a { transition: margin-left 0.3s cubic-bezier(0.4, 0, 0.2, 1) !important; } +html.sidebar-expanded.Theme--sidebar #header, html.sidebar-expanded.Theme--sidebar #displaybox, html.sidebar-expanded.Theme--sidebar #footer, html.sidebar-expanded.Theme--sidebar #copyright { @@ -936,13 +943,21 @@ div.tile { overflow: hidden !important; } -/* Dashboard tables → block layout, transparent */ +/* Dashboard tables → block layout, transparent, no stacking blur */ table.dashboard { display: block !important; width: 100% !important; background: transparent !important; border: none !important; box-shadow: none !important; + backdrop-filter: none !important; + -webkit-backdrop-filter: none !important; +} + +table.dashboard > tbody:not(.sortable), +table.dashboard > thead:not(.stopgap) { + backdrop-filter: none !important; + -webkit-backdrop-filter: none !important; } /* Hide colgroup (not needed with block layout) */ @@ -960,7 +975,7 @@ table.dashboard > tbody.sortable { border-radius: var(--glass-radius) !important; box-shadow: var(--glass-shadow) !important; margin-bottom: 20px !important; - padding-bottom: 8px !important; + padding-bottom: 14px !important; overflow: hidden !important; position: relative; transition: background 0.3s ease, border-color 0.3s ease, box-shadow 0.3s ease !important; @@ -1018,14 +1033,32 @@ table.dashboard > tbody.sortable > tr:first-child { /* Tile header text */ span.tile-header, -span.tile-header-left, -span.tile-header-right { +span.tile-header-left { color: var(--glass-text-heading) !important; font-weight: 600 !important; letter-spacing: 0.3px !important; font-size: 1em !important; } +/* Card header control icons — transparent, white icons */ +span.tile-header-right { + color: rgba(255, 255, 255, 0.55) !important; + font-size: 0.85em !important; +} + +span.tile-header-right i, +span.tile-header-right .fa { + background: transparent !important; + border: none !important; + color: rgba(255, 255, 255, 0.55) !important; + cursor: pointer; +} + +span.tile-header-right i:hover, +span.tile-header-right .fa:hover { + color: rgba(255, 255, 255, 0.85) !important; +} + /* Tile header layout */ span.tile-header { display: flex !important; @@ -1051,7 +1084,8 @@ table.dashboard .usage-disk, table.dashboard .usage-bar { background: rgba(255, 255, 255, 0.08) !important; border-radius: 8px !important; - height: 6px !important; + height: 8px !important; + margin: 6px 0 !important; overflow: hidden !important; } @@ -1062,6 +1096,34 @@ table.dashboard .usage-bar > span { height: 100% !important; } +/* CPU bars — thin color-coded bars (higher specificity) */ +#displaybox table.dashboard .usage-disk { + height: 10px !important; + border-radius: 5px !important; +} + +#displaybox table.dashboard .usage-disk > span { + border-radius: 5px !important; +} + +#displaybox table.dashboard .usage-disk.greenbar > span { + background: linear-gradient(90deg, #22c55e, #4ade80) !important; +} + +#displaybox table.dashboard .usage-disk.orangebar > span { + background: linear-gradient(90deg, #f97316, #fb923c) !important; +} + +#displaybox table.dashboard .usage-disk.redbar > span { + background: linear-gradient(90deg, #ef4444, #f87171) !important; +} + +/* Hide empty pill label text inside CPU bars */ +#displaybox table.dashboard .usage-disk > span { + font-size: 0 !important; + color: transparent !important; +} + /* Docker container icons in dashboard */ table.dashboard img { border-radius: 6px !important; @@ -1118,6 +1180,88 @@ table.dashboard td a:hover { color: var(--glass-accent-hover) !important; } +/* Docker link — add appname links to accent color */ +table.dashboard span.appname a { + color: var(--glass-accent) !important; +} + +table.dashboard span.appname a:hover { + color: var(--glass-accent-hover) !important; +} + +/* Docker text — force white in dashboard (FolderView sets blue) */ +#docker_view span, +#docker_view .inner span { + color: var(--glass-text) !important; +} + +#docker_view a { + color: var(--glass-accent) !important; +} + +/* CPU chart canvas — invert for dark background */ +#cpuchart { + filter: invert(1) hue-rotate(180deg) !important; +} + +#cpu_chart td { + width: 100% !important; +} + +#cpu_chart canvas { + width: 100% !important; +} + +/* System donut charts — thinner ring with opaque center */ +div.pie::after { + content: '' !important; + position: absolute !important; + top: 50% !important; + left: 50% !important; + transform: translate(-50%, -50%) !important; + width: 78% !important; + height: 78% !important; + border-radius: 50% !important; + background: rgba(20, 20, 30, 0.85) !important; +} + +div.pie { + position: relative !important; +} + +/* Ensure labels are above donut hole */ +div.pie span, +div.pie div { + position: relative !important; + z-index: 1 !important; +} + +/* Toggle switch — glass style */ +.switch-button-background { + width: 40px !important; + height: 22px !important; + border-radius: 12px !important; + background: rgba(255, 255, 255, 0.12) !important; + border: 1px solid rgba(255, 255, 255, 0.15) !important; + position: relative !important; + cursor: pointer !important; + transition: background 0.25s ease, border-color 0.25s ease !important; +} + +.switch-button-background.checked { + background: var(--glass-accent) !important; + border-color: var(--glass-accent) !important; +} + +.switch-button-button { + width: 18px !important; + height: 18px !important; + border-radius: 50% !important; + background: #fff !important; + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3) !important; + transition: transform 0.25s ease !important; +} + /* ============================================ INNER PAGES — Content Glass Wrapper @@ -1623,11 +1767,6 @@ div.clone-settings { background: transparent !important; } -/* Checkbox / switch styling */ -.switch-button-background { - border-radius: 12px !important; -} - /* Selection color */ ::selection { background: rgba(126, 184, 218, 0.3);