mirror of
https://github.com/unraid/api.git
synced 2026-01-01 14:10:10 -06:00
fix(theme): update theme class naming and scoping logic
- Changed theme class names from `.theme-*` to `.Theme--*` for consistency. - Updated scoping logic to prevent scoping of `.Theme--` classes, ensuring they remain global. - Enhanced theme store logic to check for existing `.Theme--` classes before applying new theme classes, preventing conflicts. - Adjusted class cleaning logic to retain `.Theme--` classes when necessary.
This commit is contained in:
@@ -5,8 +5,7 @@
|
||||
*/
|
||||
|
||||
/* Default/White Theme */
|
||||
:root,
|
||||
.theme-white {
|
||||
.Theme--white {
|
||||
--header-text-primary: #ffffff;
|
||||
--header-text-secondary: #999999;
|
||||
--header-background-color: #1c1b1b;
|
||||
@@ -20,8 +19,8 @@
|
||||
}
|
||||
|
||||
/* Black Theme */
|
||||
.theme-black,
|
||||
.theme-black.dark {
|
||||
.Theme--black,
|
||||
.Theme--black.dark {
|
||||
--header-text-primary: #1c1b1b;
|
||||
--header-text-secondary: #999999;
|
||||
--header-background-color: #f2f2f2;
|
||||
@@ -35,7 +34,7 @@
|
||||
}
|
||||
|
||||
/* Gray Theme */
|
||||
.theme-gray {
|
||||
.Theme--gray {
|
||||
--header-text-primary: #ffffff;
|
||||
--header-text-secondary: #999999;
|
||||
--header-background-color: #1c1b1b;
|
||||
@@ -49,7 +48,7 @@
|
||||
}
|
||||
|
||||
/* Azure Theme */
|
||||
.theme-azure {
|
||||
.Theme--azure {
|
||||
--header-text-primary: #1c1b1b;
|
||||
--header-text-secondary: #999999;
|
||||
--header-background-color: #f2f2f2;
|
||||
|
||||
@@ -35,7 +35,8 @@ const DEFAULT_INCLUDE_ROOT = true;
|
||||
|
||||
const KEYFRAME_AT_RULES = new Set(['keyframes']);
|
||||
const NON_SCOPED_AT_RULES = new Set(['font-face', 'page']);
|
||||
const MERGE_WITH_SCOPE_PATTERNS: RegExp[] = [/^\.theme-/, /^\.has-custom-/, /^\.dark\b/];
|
||||
const MERGE_WITH_SCOPE_PATTERNS: RegExp[] = [/^\.has-custom-/, /^\.dark\b/];
|
||||
const UNSCOPED_PATTERNS: RegExp[] = [/^\.Theme--/];
|
||||
|
||||
function shouldScopeRule(rule: Rule, targetLayers: Set<string>, includeRootRules: boolean): boolean {
|
||||
const hasSelectorString = typeof rule.selector === 'string' && rule.selector.length > 0;
|
||||
@@ -104,6 +105,12 @@ function prefixSelector(selector: string, scope: string): string {
|
||||
return trimmed;
|
||||
}
|
||||
|
||||
// Do not scope Theme-- classes - they should remain global
|
||||
const firstToken = trimmed.split(/[\s>+~]/, 1)[0] ?? '';
|
||||
if (!firstToken.includes('\\:') && UNSCOPED_PATTERNS.some((pattern) => pattern.test(firstToken))) {
|
||||
return trimmed;
|
||||
}
|
||||
|
||||
if (trimmed === ':root') {
|
||||
return scope;
|
||||
}
|
||||
@@ -112,7 +119,6 @@ function prefixSelector(selector: string, scope: string): string {
|
||||
return `${scope}${trimmed.slice(':root'.length)}`;
|
||||
}
|
||||
|
||||
const firstToken = trimmed.split(/[\s>+~]/, 1)[0] ?? '';
|
||||
const shouldMergeWithScope =
|
||||
!firstToken.includes('\\:') && MERGE_WITH_SCOPE_PATTERNS.some((pattern) => pattern.test(firstToken));
|
||||
|
||||
|
||||
@@ -168,6 +168,11 @@ export const useThemeStore = defineStore(
|
||||
const setCssVars = () => {
|
||||
const selectedTheme = theme.value.name;
|
||||
|
||||
// Check if Unraid PHP has already set a Theme-- class
|
||||
const hasExistingThemeClass =
|
||||
typeof document !== 'undefined' &&
|
||||
Array.from(document.documentElement.classList).some((cls) => cls.startsWith('Theme--'));
|
||||
|
||||
// Prepare Tailwind v4 theme classes
|
||||
const themeClasses: string[] = [];
|
||||
const customClasses: string[] = [];
|
||||
@@ -177,8 +182,10 @@ export const useThemeStore = defineStore(
|
||||
themeClasses.push('dark');
|
||||
}
|
||||
|
||||
// Apply theme-specific class for Tailwind v4 theme variants
|
||||
themeClasses.push(`theme-${selectedTheme}`);
|
||||
// Only apply theme-specific class if Unraid PHP hasn't already set it
|
||||
if (!hasExistingThemeClass) {
|
||||
themeClasses.push(`Theme--${selectedTheme}`);
|
||||
}
|
||||
|
||||
// Only set CSS variables for dynamic/user-configured values from GraphQL
|
||||
// Static theme values are handled by Tailwind v4 theme classes in @tailwind-shared
|
||||
@@ -220,22 +227,33 @@ export const useThemeStore = defineStore(
|
||||
...Array.from(document.querySelectorAll<HTMLElement>('.unapi')),
|
||||
];
|
||||
|
||||
const cleanClassList = (classList: string) =>
|
||||
classList
|
||||
const cleanClassList = (classList: string, isDocumentElement: boolean) => {
|
||||
// Don't remove Theme-- classes from documentElement if Unraid PHP set them
|
||||
if (isDocumentElement && hasExistingThemeClass) {
|
||||
return classList
|
||||
.split(' ')
|
||||
.filter((c) => c !== 'dark' && !c.startsWith('has-custom-') && c !== 'has-banner-gradient')
|
||||
.filter(Boolean)
|
||||
.join(' ');
|
||||
}
|
||||
// For .unapi roots or when we're managing the theme class, clean everything
|
||||
return classList
|
||||
.split(' ')
|
||||
.filter(
|
||||
(c) =>
|
||||
!c.startsWith('theme-') &&
|
||||
!c.startsWith('Theme--') &&
|
||||
c !== 'dark' &&
|
||||
!c.startsWith('has-custom-') &&
|
||||
c !== 'has-banner-gradient'
|
||||
)
|
||||
.filter(Boolean)
|
||||
.join(' ');
|
||||
};
|
||||
|
||||
// Apply theme and custom classes to html element and all .unapi roots
|
||||
scopedTargets.forEach((target) => {
|
||||
target.className = cleanClassList(target.className);
|
||||
const isDocumentElement = target === document.documentElement;
|
||||
target.className = cleanClassList(target.className, isDocumentElement);
|
||||
[...themeClasses, ...customClasses].forEach((cls) => target.classList.add(cls));
|
||||
|
||||
if (darkMode.value) {
|
||||
|
||||
Reference in New Issue
Block a user