diff --git a/src/layouts/modules/theme-drawer/modules/preset/modules/theme-preset.vue b/src/layouts/modules/theme-drawer/modules/preset/modules/theme-preset.vue index d268d9a3..d85d5b34 100644 --- a/src/layouts/modules/theme-drawer/modules/preset/modules/theme-preset.vue +++ b/src/layouts/modules/theme-drawer/modules/preset/modules/theme-preset.vue @@ -33,6 +33,8 @@ type ThemePreset = Pick< desc: string; i18nkey?: string; version: string; + /** Optional NaiveUI theme overrides */ + naiveui?: App.Theme.NaiveUIThemeOverride; }; const presetModules = import.meta.glob('@/theme/preset/*.json', { eager: true, import: 'default' }); @@ -80,7 +82,7 @@ const getPresetDesc = (preset: ThemePreset): string => { const applyPreset = (preset: ThemePreset): void => { const mergedPreset = defu(preset, themeSettings); - const { themeScheme, grayscale, colourWeakness, layout, watermark, ...rest } = mergedPreset; + const { themeScheme, grayscale, colourWeakness, layout, watermark, naiveui, ...rest } = mergedPreset; themeStore.setThemeScheme(themeScheme); themeStore.setGrayscale(grayscale); themeStore.setColourWeakness(colourWeakness); @@ -100,6 +102,9 @@ const applyPreset = (preset: ThemePreset): void => { tokens: { ...rest.tokens } }); + // Apply NaiveUI theme overrides if present + themeStore.setNaiveThemeOverrides(naiveui); + window.$message?.success($t('theme.appearance.preset.applySuccess')); }; diff --git a/src/store/modules/theme/index.ts b/src/store/modules/theme/index.ts index 26422b82..0dcd1826 100644 --- a/src/store/modules/theme/index.ts +++ b/src/store/modules/theme/index.ts @@ -24,6 +24,9 @@ export const useThemeStore = defineStore(SetupStoreId.Theme, () => { /** Theme settings */ const settings: Ref = ref(initThemeSettings()); + /** Optional NaiveUI theme overrides from preset */ + const naiveThemeOverrides: Ref = ref(undefined); + /** Watermark time instance with controls */ const { now: watermarkTime, pause: pauseWatermarkTime, resume: resumeWatermarkTime } = useNow({ controls: true }); @@ -53,7 +56,7 @@ export const useThemeStore = defineStore(SetupStoreId.Theme, () => { }); /** Naive theme */ - const naiveTheme = computed(() => getNaiveTheme(themeColors.value, settings.value)); + const naiveTheme = computed(() => getNaiveTheme(themeColors.value, settings.value, naiveThemeOverrides.value)); /** * Settings json @@ -198,6 +201,15 @@ export const useThemeStore = defineStore(SetupStoreId.Theme, () => { } } + /** + * Set NaiveUI theme overrides + * + * @param overrides NaiveUI theme overrides or undefined to clear + */ + function setNaiveThemeOverrides(overrides?: App.Theme.NaiveUIThemeOverride) { + naiveThemeOverrides.value = overrides; + } + /** Only run timer when watermark is visible and time display is enabled */ function updateWatermarkTimer() { const { watermark } = settings.value; @@ -284,6 +296,7 @@ export const useThemeStore = defineStore(SetupStoreId.Theme, () => { updateThemeColors, setThemeLayout, setWatermarkEnableUserName, - setWatermarkEnableTime + setWatermarkEnableTime, + setNaiveThemeOverrides }; }); diff --git a/src/store/modules/theme/shared.ts b/src/store/modules/theme/shared.ts index 82931719..826878b4 100644 --- a/src/store/modules/theme/shared.ts +++ b/src/store/modules/theme/shared.ts @@ -236,11 +236,15 @@ function getNaiveThemeColors(colors: App.Theme.ThemeColor, recommended = false) /** * Get naive theme * - * @param settings Theme settings object. - * @param settings.recommendColor Whether to use recommended color palette. - * @param settings.themeRadius Border radius to use in the theme (in px). + * @param colors Theme colors + * @param settings Theme settings object + * @param overrides Optional manual overrides from preset */ -export function getNaiveTheme(colors: App.Theme.ThemeColor, settings: App.Theme.ThemeSetting) { +export function getNaiveTheme( + colors: App.Theme.ThemeColor, + settings: App.Theme.ThemeSetting, + overrides?: GlobalThemeOverrides +) { const { primary: colorLoading } = colors; const theme: GlobalThemeOverrides = { @@ -256,5 +260,7 @@ export function getNaiveTheme(colors: App.Theme.ThemeColor, settings: App.Theme. } }; - return theme; + // If there are overrides, merge them with priority + // overrides has higher priority than auto-generated theme + return overrides ? defu(overrides, theme) : theme; } diff --git a/src/theme/preset/azir.json b/src/theme/preset/azir.json index abfd0321..d34e2475 100644 --- a/src/theme/preset/azir.json +++ b/src/theme/preset/azir.json @@ -34,5 +34,19 @@ "base-text": "rgb(224, 224, 224)" } } + }, + "naiveui": { + "Alert": { + "borderRadiusMedium": "12px", + "fontWeightStrong": "600", + "paddingMedium": "0 20px" + }, + "Card": { + "borderRadius": "16px", + "paddingMedium": "24px" + }, + "Input": { + "borderRadius": "10px" + } } } diff --git a/src/typings/app.d.ts b/src/typings/app.d.ts index ab79d1c2..215d6ac0 100644 --- a/src/typings/app.d.ts +++ b/src/typings/app.d.ts @@ -4,6 +4,9 @@ declare namespace App { namespace Theme { type ColorPaletteNumber = import('@sa/color').ColorPaletteNumber; + /** NaiveUI theme overrides that can be specified in preset */ + type NaiveUIThemeOverride = import('naive-ui').GlobalThemeOverrides; + /** Theme setting */ interface ThemeSetting { /** Theme scheme */