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.
This commit is contained in:
Eli Bosley
2025-08-31 15:23:17 -04:00
parent 3faa637d97
commit 67a6a2e7c8
6 changed files with 89 additions and 139 deletions

View File

@@ -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;
}
}

View File

@@ -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";
?>
]]>
</INLINE>

View File

@@ -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;
}

View File

@@ -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",

View File

@@ -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(() => {

View File

@@ -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 = {