diff --git a/assets/icons/openzfs-light.svg b/assets/icons/openzfs-light.svg
new file mode 100644
index 0000000..9b2dacf
--- /dev/null
+++ b/assets/icons/openzfs-light.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/sidebar.js b/sidebar.js
index 8303bbf..43e32bd 100644
--- a/sidebar.js
+++ b/sidebar.js
@@ -324,7 +324,10 @@
var replaceTimer = null;
function debouncedReplace() {
if (replaceTimer) clearTimeout(replaceTimer);
- replaceTimer = setTimeout(replaceIcons, 200);
+ replaceTimer = setTimeout(function() {
+ replaceIcons();
+ replacePluginIcons();
+ }, 200);
}
// Watch for DOM changes (AJAX loads, FolderView manipulation)
@@ -343,14 +346,48 @@
observer.observe(target, { childList: true, subtree: true });
}
- // Replace Tailscale sidebar icon with light SVG
- function replaceTailscaleIcon() {
- var imgs = document.querySelectorAll('img[alt="Tailscale"]');
+ // Plugin icon source → selfh.st light SVG replacement
+ // Maps partial src paths to icon names in /custom/assets/icons/
+ var PLUGIN_ICON_MAP = {
+ '/plugins/tailscale/': 'tailscale',
+ '/plugins/zfs.master/': 'openzfs',
+ // SNMP has no selfh.st icon — leave for CSS invert filter
+ };
+
+ // Replace plugin icons on Settings/Plugins/Tools pages with selfh.st light SVGs.
+ // Also replaces Tailscale sidebar icon (img[alt="Tailscale"]).
+ function replacePluginIcons() {
+ // Settings/Tools/Plugins grid icons
+ var imgs = document.querySelectorAll('#displaybox img, 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');
+ // Skip container icons (handled by replaceIcons)
+ if (img.classList.contains('img')) return;
+ // Skip sidebar logo
+ if (img.id === 'sidebar-logo') return;
+ // Skip already replaced
+ if (img.getAttribute('data-glass-icon')) return;
+
+ var src = img.getAttribute('src') || '';
+ var keys = Object.keys(PLUGIN_ICON_MAP);
+ for (var i = 0; i < keys.length; i++) {
+ if (src.indexOf(keys[i]) !== -1) {
+ var iconName = PLUGIN_ICON_MAP[keys[i]];
+ var url = CDN_SVG + '/' + iconName + '-light.svg';
+ img.src = url;
+ img.setAttribute('data-glass-icon', iconName);
+ img.removeAttribute('onerror');
+ return;
+ }
+ }
+
+ // Also handle Tailscale by alt attribute (sidebar)
+ if (img.alt === 'Tailscale') {
+ var tsUrl = CDN_SVG + '/tailscale-light.svg';
+ if (src !== tsUrl) {
+ img.src = tsUrl;
+ img.setAttribute('data-glass-icon', 'tailscale');
+ img.removeAttribute('onerror');
+ }
}
});
}
@@ -359,10 +396,10 @@
function initIcons() {
// Initial replacement
setTimeout(replaceIcons, 500);
- setTimeout(replaceTailscaleIcon, 500);
+ setTimeout(replacePluginIcons, 500);
// Second pass after FolderView finishes its DOM work
setTimeout(replaceIcons, 2000);
- setTimeout(replaceTailscaleIcon, 2000);
+ setTimeout(replacePluginIcons, 2000);
// Start watching for future changes
startObserver();
}
diff --git a/style.css b/style.css
index ae53350..325abde 100644
--- a/style.css
+++ b/style.css
@@ -1013,6 +1013,12 @@ table.dashboard > tbody.sortable > tr:last-child {
border-bottom: none !important;
}
+/* Hide compact Load: row in Processor card — Overall Load row shows same info.
+ Unraid's DashStats.css hides span.switch but the row keeps 33px of padding/gap */
+table.dashboard > tbody.sortable > tr:has(.head_bar) {
+ display: none !important;
+}
+
/* Dashboard card cells
NOTE: display must NOT use !important so Unraid's jQuery .hide() can override */
table.dashboard > tbody.sortable > tr > td {
@@ -1199,8 +1205,14 @@ table.dashboard span.appname a:hover {
color: var(--glass-accent) !important;
}
-/* CPU chart canvas — invert for dark background */
+/* CPU chart — force block display (inline style sets table-row, breaking layout) */
+#cpu_chart {
+ display: block !important;
+}
+
+/* CPU chart canvas — invert for dark background, block to prevent inline offset */
#cpuchart {
+ display: block !important;
filter: invert(1) hue-rotate(180deg) !important;
}
@@ -1254,12 +1266,20 @@ div.pie div {
}
.switch-button-button {
+ position: absolute !important;
+ top: 50% !important;
+ left: 2px !important;
+ transform: translateY(-50%) !important;
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;
+ transition: left 0.25s ease, transform 0.25s ease !important;
+}
+
+.switch-button-background.checked .switch-button-button {
+ left: calc(100% - 20px) !important;
}
@@ -2151,3 +2171,324 @@ img.popupIcon {
.ca_credit {
color: var(--glass-text-muted) !important;
}
+
+
+/* ============================================
+ BUG FIXES — Phase 2: Text & Label Visibility
+ ============================================ */
+
+/* Fix: Unraid tables use
in , not | .
+ Our existing rules only target thead th — add thead td. */
+#displaybox table:not(.dashboard) thead td {
+ color: var(--glass-text-muted) !important;
+ font-weight: 500 !important;
+ text-transform: uppercase !important;
+ font-size: 0.72em !important;
+ letter-spacing: 0.6px !important;
+ border-bottom: 1px solid rgba(255, 255, 255, 0.06) !important;
+ padding: 12px 16px !important;
+ background: transparent !important;
+}
+
+/* Also cover generic thead td (non-#displaybox context) */
+table thead td {
+ color: var(--glass-text-muted) !important;
+ font-weight: 500 !important;
+}
+
+/* Plugins page: table header row has opaque dark bg from tablesorter.
+ The grid role table uses | which is fine, but ensure plugin
+ description text, author, version are clearly visible. */
+#displaybox table.tablesorter tbody td,
+#displaybox table.tablesorter tbody th,
+#displaybox .plugin_list td,
+#displaybox table[role="grid"] td,
+#displaybox table[role="grid"] [role="gridcell"] {
+ color: var(--glass-text) !important;
+}
+
+/* Plugin name (h4/strong) and description (p) */
+#displaybox table.tablesorter h4,
+#displaybox table.tablesorter strong,
+#displaybox table[role="grid"] h4,
+#displaybox table[role="grid"] strong {
+ color: var(--glass-text-heading) !important;
+}
+
+#displaybox table.tablesorter p,
+#displaybox table[role="grid"] p {
+ color: var(--glass-text-muted) !important;
+}
+
+/* Plugin status text */
+#displaybox table.tablesorter .up-to-date,
+#displaybox table[role="grid"] .up-to-date {
+ color: #4ade80 !important;
+}
+
+/* Settings/Tools/Plugins icon grid labels (.PanelText) —
+ currently inherits accent blue from . Make labels white for readability. */
+.PanelText {
+ color: var(--glass-text) !important;
+}
+
+/* Settings/Tools section headers (injected by Unraid as spans with inline styles) */
+#displaybox .content > span[style],
+#displaybox .content span[style*="font-size"] {
+ color: var(--glass-text-heading) !important;
+}
+
+
+/* ============================================
+ BUG FIXES — Phase 3: Icon Coloring
+ ============================================ */
+
+/* Settings/Plugins/Tools icon grid: non-FA icons are PNG/SVG .
+ Plugin icons that have selfh.st light SVG replacements get swapped via JS
+ (sidebar.js replacePluginIcons). For others, apply invert filter.
+ We scope this to only target icons inside the icon-grid span (not the
+ whole page) and exclude icons already replaced by JS (data-glass-icon). */
+#displaybox .icon-setting img:not([data-glass-icon]),
+#displaybox .page-setting img:not([data-glass-icon]),
+#displaybox .icon-app img:not([data-glass-icon]),
+#displaybox a[href*="/Settings/"] > span:first-child img:not([data-glass-icon]),
+#displaybox a[href*="/Tools/"] > span:first-child img:not([data-glass-icon]),
+#displaybox table[role="grid"] td:first-child img:not([data-glass-icon]) {
+ filter: brightness(0) invert(1) !important;
+ opacity: 0.85 !important;
+}
+
+/* Plugin list: first-cell icons (some are not FA) */
+#displaybox table.tablesorter td:first-child img:not([data-glass-icon]),
+#displaybox table[role="grid"] [role="gridcell"]:first-child img:not([data-glass-icon]) {
+ filter: brightness(0) invert(1) !important;
+ opacity: 0.85 !important;
+}
+
+
+/* ============================================
+ BUG FIXES — Phase 4: Shadow & Rounding
+ ============================================ */
+
+/* Soften box-shadow on inner page tables */
+#displaybox table:not(.dashboard) {
+ box-shadow: 0 4px 16px rgba(0, 0, 0, 0.15), inset 0 1px 0 rgba(255, 255, 255, 0.08) !important;
+}
+
+/* Array Operation page: stacked form sections —
+ first/middle/last rounding for unified container look.
+ Unraid uses div.Panel for each section on Array Op. */
+#displaybox div.Panel + div.Panel {
+ margin-top: -1px !important;
+ border-top: 1px solid rgba(255, 255, 255, 0.06) !important;
+}
+
+#displaybox div.Panel:not(:first-of-type):not(:last-of-type) {
+ border-radius: 0 !important;
+}
+
+#displaybox div.Panel:not(:first-of-type):not(:last-of-type)::before {
+ display: none !important;
+}
+
+#displaybox div.Panel + div.Panel:last-of-type {
+ border-radius: 0 0 var(--glass-radius) var(--glass-radius) !important;
+}
+
+#displaybox div.Panel:first-of-type:has(+ div.Panel) {
+ border-radius: var(--glass-radius) var(--glass-radius) 0 0 !important;
+ margin-bottom: 0 !important;
+}
+
+
+/* ============================================
+ BUG FIXES — Phase 5: Table & Form Styling
+ ============================================ */
+
+/* Shares Browse page: file browser table uses a darker style.
+ Target the browse page specifically via URL-based class or #dir_list */
+#dir_list,
+table.file_browser,
+#displaybox table.browse_table,
+#displaybox div[id*="browse"] table {
+ background: rgba(255, 255, 255, 0.06) !important;
+ border: 1px solid var(--glass-border) !important;
+ border-radius: var(--glass-radius) !important;
+}
+
+#dir_list thead td,
+#dir_list thead th,
+table.file_browser thead td,
+table.file_browser thead th {
+ background: rgba(255, 255, 255, 0.04) !important;
+ color: var(--glass-text-muted) !important;
+}
+
+#dir_list tbody tr:nth-child(even),
+table.file_browser tbody tr:nth-child(even) {
+ background: rgba(255, 255, 255, 0.03) !important;
+}
+
+#dir_list tbody tr:hover,
+table.file_browser tbody tr:hover {
+ background: rgba(255, 255, 255, 0.05) !important;
+}
+
+/* Share Settings form page: wrap form content in glass styling.
+ The form uses dl/dt/dd inside a content div. */
+#displaybox .content > form,
+#displaybox form[method],
+#displaybox div.clone-settings,
+#displaybox > .content > table:not(.dashboard):not(.tablesorter):not(.disk_status):not(.share_status) {
+ background: rgba(255, 255, 255, 0.06) !important;
+ backdrop-filter: blur(30px) saturate(1.3) !important;
+ -webkit-backdrop-filter: blur(30px) saturate(1.3) !important;
+ border: 1px solid var(--glass-border) !important;
+ border-radius: var(--glass-radius) !important;
+ padding: 16px !important;
+ margin-bottom: 16px !important;
+}
+
+/* Apps detail panel: ensure tags/buttons area has glass bg */
+#alternateView .ca_template,
+#alternateView table {
+ background: transparent !important;
+ border: none !important;
+ box-shadow: none !important;
+}
+
+
+/* ============================================
+ BUG FIXES — Phase 6: Bars & Button Visibility
+ ============================================ */
+
+/* Main page usage bars: match dashboard style (thin, rounded, gradient) */
+#displaybox table:not(.dashboard) .usage-disk,
+#displaybox table:not(.dashboard) .usage-bar {
+ height: 8px !important;
+ border-radius: 8px !important;
+ background: rgba(255, 255, 255, 0.08) !important;
+ overflow: hidden !important;
+ margin: 4px 0 !important;
+}
+
+#displaybox table:not(.dashboard) .usage-disk > span,
+#displaybox table:not(.dashboard) .usage-bar > span {
+ height: 100% !important;
+ border-radius: 8px !important;
+ background: linear-gradient(90deg, rgba(126, 184, 218, 0.5), var(--glass-accent)) !important;
+ font-size: 0 !important;
+}
+
+/* Color-coded bars on Main page */
+#displaybox table:not(.dashboard) .usage-disk.greenbar > span {
+ background: linear-gradient(90deg, #22c55e, #4ade80) !important;
+}
+
+#displaybox table:not(.dashboard) .usage-disk.orangebar > span {
+ background: linear-gradient(90deg, #f97316, #fb923c) !important;
+}
+
+#displaybox table:not(.dashboard) .usage-disk.redbar > span {
+ background: linear-gradient(90deg, #ef4444, #f87171) !important;
+}
+
+/* Plugins Update: ensure update arrow buttons are visible */
+#displaybox table.tablesorter input[type="button"],
+#displaybox table[role="grid"] input[type="button"],
+#displaybox table.tablesorter button:not([disabled]),
+#displaybox table[role="grid"] button:not([disabled]) {
+ background: var(--glass-accent-subtle) !important;
+ color: var(--glass-accent) !important;
+ border: 1px solid rgba(126, 184, 218, 0.25) !important;
+}
+
+/* VM action buttons — ensure visibility */
+#displaybox #vm_list button,
+#displaybox #vm_list input[type="button"] {
+ background: var(--glass-accent-subtle) !important;
+ color: var(--glass-accent) !important;
+ border: 1px solid rgba(126, 184, 218, 0.25) !important;
+}
+
+
+/* ============================================
+ BUG FIXES — Phase 7: Page-Specific Layouts
+ ============================================ */
+
+/* Dashboard #3: header clipping — ensure UNRAID banner is fully visible */
+#header {
+ overflow: visible !important;
+ z-index: 100 !important;
+}
+
+/* Ensure the Unraid logo/brand area doesn't clip */
+#header > div:first-child,
+#header .brand,
+#header a[href*="unraid.net"] {
+ overflow: visible !important;
+}
+
+/* Docker #1: folder-preview wrapper has opaque glass bg.
+ Make it more subtle/transparent so container items
+ don't appear in a "tab-like" wrapper. */
+.folder-preview,
+div[class*="folder-preview"] {
+ background: rgba(255, 255, 255, 0.03) !important;
+ border: 1px solid rgba(255, 255, 255, 0.06) !important;
+ border-radius: 10px !important;
+ backdrop-filter: none !important;
+ -webkit-backdrop-filter: none !important;
+}
+
+/* Docker folder-storage cell — reduce the wrapper appearance */
+td.folder-storage {
+ background: transparent !important;
+ border: none !important;
+ padding: 4px 8px !important;
+}
+
+/* Apps #1: ribbon/badge corner rounding.
+ Ensure the card clips the ribbon properly. */
+.ca_holder {
+ overflow: hidden !important;
+ border-radius: 16px !important;
+}
+
+/* Badge text positioning — ensure visible */
+.ca_holder .installedCardBackground + span,
+.ca_holder .betaCardBackground + span,
+.ca_holder .officialCardBackground + span,
+.ca_holder .warningCardBackground + span,
+.ca_holder .greenCardBackground + span {
+ color: #fff !important;
+ font-size: 10px !important;
+ z-index: 2 !important;
+}
+
+/* ZFS Master: toggle icon gap fix.
+ The toggle/refresh area sits in a div that has excess margin.
+ Tighten the layout. */
+#displaybox [id*="zfs"] .switch-button-background,
+#displaybox [id*="ZFS"] .switch-button-background {
+ display: inline-block !important;
+ vertical-align: middle !important;
+ margin: 0 8px !important;
+}
+
+/* Fix stacked panels: don't apply to tabpanel children
+ which have their own panel structure */
+[role="tabpanel"] div.Panel + div.Panel {
+ margin-top: 16px !important;
+ border-top: 1px solid var(--glass-border) !important;
+ border-radius: var(--glass-radius) !important;
+}
+
+[role="tabpanel"] div.Panel:not(:first-of-type):not(:last-of-type) {
+ border-radius: var(--glass-radius) !important;
+}
+
+[role="tabpanel"] div.Panel:first-of-type:has(+ div.Panel) {
+ border-radius: var(--glass-radius) !important;
+ margin-bottom: 16px !important;
+}
| |