From 67a6a2e7c8b3e7bb0d22989cf3cbbf014c4891a7 Mon Sep 17 00:00:00 2001 From: Eli Bosley Date: Sun, 31 Aug 2025 15:23:17 -0400 Subject: [PATCH] refactor: enhance CSS variable management and layer structure for improved theme integration - Introduced overrides for Tailwind v4 global styles to utilize webgui variables, ensuring better compatibility and theming. - Scoped border colors and other styles to specific components, preventing unintended style leakage. - Updated layer definitions in main.css to prioritize webgui styles effectively, enhancing overall style management. - Added new Tailwind v4 color variables for utility classes in the theme store, improving customization options. --- @tailwind-shared/css-variables.css | 96 ++++++++++----------------- plugin/plugins/dynamix.unraid.net.plg | 44 ------------ web/assets/main.css | 71 ++++++++++---------- web/package.json | 2 +- web/store/theme.ts | 9 +++ web/themes/types.d.ts | 6 ++ 6 files changed, 89 insertions(+), 139 deletions(-) diff --git a/@tailwind-shared/css-variables.css b/@tailwind-shared/css-variables.css index 9ddc00dcf..c4a4713f3 100644 --- a/@tailwind-shared/css-variables.css +++ b/@tailwind-shared/css-variables.css @@ -1,7 +1,27 @@ /* Hybrid theme system: Native CSS + Theme Store fallback */ @layer base { + /* Override Tailwind v4 global styles that leak outside components */ + *, ::after, ::before, ::backdrop { + /* Reset border-color to initial to prevent Tailwind from affecting webgui */ + border-color: initial; + } + + /* Properly scope border colors to our components only */ + .unraid-reset *, + .unraid-reset ::after, + .unraid-reset ::before, + .unapi *, + .unapi ::after, + .unapi ::before { + border-color: hsl(var(--border)); + } + /* Light mode defaults */ :root { + /* Override Tailwind v4 global styles to use webgui variables */ + --ui-bg: var(--background-color) !important; + --ui-text: var(--text-color) !important; + --background: 0 0% 100%; --foreground: 0 0% 3.9%; --muted: 0 0% 96.1%; @@ -30,6 +50,10 @@ /* Dark mode */ .dark { + /* Override Tailwind v4 global styles to use webgui variables */ + --ui-bg: var(--background-color) !important; + --ui-text: var(--text-color) !important; + --background: 0 0% 3.9%; --foreground: 0 0% 98%; --muted: 0 0% 14.9%; @@ -64,67 +88,19 @@ --border: 0 0% 14.9%; } - /* For web components: inherit CSS variables from the host */ - :host { - --background: inherit; - --foreground: inherit; - --muted: inherit; - --muted-foreground: inherit; - --popover: inherit; - --popover-foreground: inherit; - --card: inherit; - --card-foreground: inherit; - --border: inherit; - --input: inherit; - --primary: inherit; - --primary-foreground: inherit; - --secondary: inherit; - --secondary-foreground: inherit; - --accent: inherit; - --accent-foreground: inherit; - --destructive: inherit; - --destructive-foreground: inherit; - --ring: inherit; - --chart-1: inherit; - --chart-2: inherit; - --chart-3: inherit; - --chart-4: inherit; - --chart-5: inherit; + /* For embedded components: just override the Tailwind v4 globals */ + .unraid-reset, + .unapi { + /* Override Tailwind v4 global styles to use webgui variables */ + --ui-bg: var(--background-color) !important; + --ui-text: var(--text-color) !important; } - /* Class-based dark mode support for web components using :host-context */ - :host-context(.dark) { - --background: 0 0% 3.9%; - --foreground: 0 0% 98%; - --muted: 0 0% 14.9%; - --muted-foreground: 0 0% 63.9%; - --popover: 0 0% 3.9%; - --popover-foreground: 0 0% 98%; - --card: 0 0% 3.9%; - --card-foreground: 0 0% 98%; - --border: 0 0% 14.9%; - --input: 0 0% 14.9%; - --primary: 0 0% 98%; - --primary-foreground: 0 0% 9%; - --secondary: 0 0% 14.9%; - --secondary-foreground: 0 0% 98%; - --accent: 0 0% 14.9%; - --accent-foreground: 0 0% 98%; - --destructive: 0 62.8% 30.6%; - --destructive-foreground: 0 0% 98%; - --ring: 0 0% 83.1%; - --chart-1: 220 70% 50%; - --chart-2: 160 60% 45%; - --chart-3: 30 80% 55%; - --chart-4: 280 65% 60%; - --chart-5: 340 75% 55%; - } - - /* Alternative class-based dark mode support for specific Unraid themes */ - :host-context(.dark[data-theme='black']), - :host-context(.dark[data-theme='gray']) { - --background: 0 0% 3.9%; - --foreground: 0 0% 98%; - --border: 0 0% 14.9%; + /* Class-based dark mode support for embedded components */ + .dark .unraid-reset, + .dark .unapi { + /* Override Tailwind v4 global styles to use webgui variables */ + --ui-bg: var(--background-color) !important; + --ui-text: var(--text-color) !important; } } \ No newline at end of file diff --git a/plugin/plugins/dynamix.unraid.net.plg b/plugin/plugins/dynamix.unraid.net.plg index f24783b66..e86b0e114 100755 --- a/plugin/plugins/dynamix.unraid.net.plg +++ b/plugin/plugins/dynamix.unraid.net.plg @@ -195,50 +195,6 @@ exit 0 if (!is_dir($backupDir)) { mkdir($backupDir, 0755, true); } - - // Function to patch CSS - we'll just add a layer wrapper - function patchCssContent($content) { - // Simply wrap everything in a @layer to control cascade order - // Our Tailwind styles in later layers will override - return "@layer webgui {\n" . $content . "\n}"; - } - - // Process only default-* and dynamix-* CSS files - foreach (glob("$cssDir/*.css") as $cssFile) { - $filename = basename($cssFile); - - // Only process default-* and dynamix-* files - if (!preg_match('/^(default-|dynamix-).*\.css$/', $filename)) { - continue; - } - - $backupFile = "$backupDir/$filename"; - - // Read file content - $content = file_get_contents($cssFile); - - // Skip if already patched - if (strpos($content, "/* Unraid API compatibility patch - exclusion based */") !== false) { - echo " $filename already patched, skipping...\n"; - continue; - } - - // Create backup if it doesn't exist - if (!file_exists($backupFile)) { - copy($cssFile, $backupFile); - } - - echo " Patching $filename...\n"; - - // Add compatibility patch comment and wrap in layer - $patchedContent = "/* Unraid API compatibility patch - layer based */\n"; - $patchedContent .= patchCssContent($content); - - // Write modified content back - file_put_contents($cssFile, $patchedContent); - } - - echo "CSS patching complete.\n"; ?> ]]> diff --git a/web/assets/main.css b/web/assets/main.css index 3f68109ed..a0a6b3559 100644 --- a/web/assets/main.css +++ b/web/assets/main.css @@ -3,8 +3,8 @@ * This prevents Tailwind from applying global resets that affect webgui */ -/* Define layers for Tailwind v4 - webgui first so our layers override */ -@layer webgui, theme, base, components, utilities; +/* Define layers for Tailwind v4 - base first, webgui later for higher priority */ +@layer base, theme, components, utilities, webgui; /* Import only the parts of Tailwind we need - NO PREFLIGHT */ @import 'tailwindcss/theme.css' layer(theme); @@ -27,7 +27,7 @@ /* Container with proper isolation */ .unraid-reset { isolation: isolate; - display: contents; + /* Removed display: contents to maintain stacking context for modals */ /* Set base typography that webgui can't override */ font-family: Inter, system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif; @@ -134,29 +134,29 @@ .unraid-reset input[type="submit"], .unraid-reset input[type="reset"], .unraid-reset a.button { - /* Reset ALL webgui button properties including CSS variables */ - font-family: inherit !important; - font-size: inherit !important; - font-weight: normal !important; - letter-spacing: normal !important; - text-transform: none !important; - min-width: auto !important; - margin: 0 !important; - padding: 0 !important; - text-align: center !important; - text-decoration: none !important; - white-space: nowrap !important; - cursor: pointer !important; - outline: none !important; - border-radius: 0 !important; - border: none !important; - color: inherit !important; - background: transparent !important; - background-size: auto !important; - appearance: none !important; - box-sizing: border-box !important; + /* Reset webgui button properties - use !important only where absolutely necessary */ + font-family: inherit; + font-size: inherit; + font-weight: normal; + letter-spacing: normal; + text-transform: none; + min-width: auto; + margin: 0; + padding: 0; + text-align: center; + text-decoration: none; + white-space: nowrap; + cursor: pointer; + outline: none; + border-radius: 0; + border: none; + color: inherit; + background: transparent; + background-size: auto; + appearance: none; + box-sizing: border-box; - /* Override CSS variables from webgui */ + /* Override CSS variables from webgui - these need !important */ --button-border: none !important; --button-text-color: inherit !important; --button-background: transparent !important; @@ -196,17 +196,20 @@ } -/* Modal z-index management - scoped to Unraid containers */ -.unraid [role="dialog"], -.unraid [data-headlessui-portal], -.unraid #teleports > *, -.unraid #modals > *, -.unraid unraid-modals > * { +/* Modal z-index management - ensure modals appear above webgui */ +[role="dialog"], +[data-headlessui-portal], +#teleports, +#modals, +unraid-modals, +.z-50 { z-index: 99999 !important; + position: relative; } -/* Modal backdrops - scoped to Unraid containers */ -.unraid .fixed.inset-0[aria-hidden="true"], -.unraid [data-headlessui-portal] .fixed.inset-0 { +/* Modal backdrops */ +.fixed.inset-0[aria-hidden="true"], +[data-headlessui-portal] .fixed.inset-0, +.fixed.inset-0.z-50 { z-index: 99998 !important; } \ No newline at end of file diff --git a/web/package.json b/web/package.json index d80db4c36..485fceb21 100644 --- a/web/package.json +++ b/web/package.json @@ -11,7 +11,7 @@ "serve": "NODE_ENV=production PORT=${PORT:-4321} node .output/server/index.mjs", "// Build": "", "prebuild:dev": "pnpm predev", - "build:dev": "nuxi build --dotenv .env.production && pnpm run manifest-ts && pnpm run deploy-to-unraid:dev", + "build:dev": "pnpm run build && pnpm run deploy-to-unraid:dev", "build:webgui": "pnpm run type-check && nuxi build --dotenv .env.production && pnpm run manifest-ts && pnpm run copy-to-webgui-repo", "build": "NODE_ENV=production nuxi build --dotenv .env.production && pnpm run build:standalone && pnpm run manifest-ts && pnpm run validate:css", "build:standalone": "vite build --config vite.standalone.config.ts && pnpm run manifest-standalone", diff --git a/web/store/theme.ts b/web/store/theme.ts index 957b8eae3..6241f25d8 100644 --- a/web/store/theme.ts +++ b/web/store/theme.ts @@ -117,15 +117,24 @@ export const useThemeStore = defineStore('theme', () => { // overwrite with hex colors set in webGUI @ /Settings/DisplaySettings if (theme.value.textColor) { customTheme['--header-text-primary'] = theme.value.textColor; + // Also set the Tailwind v4 color variable for utility classes + customTheme['--color-header-text-primary'] = theme.value.textColor; } if (theme.value.metaColor) { customTheme['--header-text-secondary'] = theme.value.metaColor; + // Also set the Tailwind v4 color variable for utility classes + customTheme['--color-header-text-secondary'] = theme.value.metaColor; } if (theme.value.bgColor) { customTheme['--header-background-color'] = theme.value.bgColor; + // Also set the Tailwind v4 color variable for utility classes + customTheme['--color-header-background'] = theme.value.bgColor; customTheme['--header-gradient-start'] = hexToRgba(theme.value.bgColor, 0); customTheme['--header-gradient-end'] = hexToRgba(theme.value.bgColor, 0.7); + // Also set the Tailwind v4 color variables for gradient utility classes + customTheme['--color-header-gradient-start'] = hexToRgba(theme.value.bgColor, 0); + customTheme['--color-header-gradient-end'] = hexToRgba(theme.value.bgColor, 0.7); } requestAnimationFrame(() => { diff --git a/web/themes/types.d.ts b/web/themes/types.d.ts index f055786d4..ea39be039 100644 --- a/web/themes/types.d.ts +++ b/web/themes/types.d.ts @@ -35,6 +35,12 @@ type BaseThemeVariables = { '--header-gradient-start': string; '--header-gradient-end': string; '--banner-gradient': string | null; + // Tailwind v4 color variables for utility classes + '--color-header-text-primary'?: string; + '--color-header-text-secondary'?: string; + '--color-header-background'?: string; + '--color-header-gradient-start'?: string; + '--color-header-gradient-end'?: string; }; type LegacyThemeVariables = {