Skip to content

Commit

Permalink
🎨 修改主题配置功能
Browse files Browse the repository at this point in the history
  • Loading branch information
Mikasa33 committed Jun 11, 2024
1 parent 7769a7e commit 3e825a6
Show file tree
Hide file tree
Showing 5 changed files with 260 additions and 18 deletions.
76 changes: 76 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,3 +67,79 @@ pnpm up
pnpm lint
pnpm lint:fix
```

## 主题

### 主题配置

```ts
const themeSetting = {
themeMode: 'auto',
themeColor: {
primaryColor: '#18A058',
infoColor: '#2080F0',
successColor: '#18A058',
warningColor: '#F0A020',
errorColor: '#D03050',
},
darkThemeColor: {
primaryColor: '#63e2b7',
infoColor: '#70c0e8',
successColor: '#63e2b7',
warningColor: '#f2c97d',
errorColor: '#e88080',
},
layoutMode: 'vertical',
header: {
show: true,
height: 64,
inverted: false,
},
sider: {
show: true,
width: 240,
collapsedWidth: 64,
inverted: false,
},
footer: {
show: true,
height: 64,
inverted: false,
},
page: {
animate: true,
animateMode: 'fade-slide',
loadingBar: true,
},
}

const { setting } = useThemeSetting({ initialValue: themeSetting })
```

### 主题模式

- 明亮
- 暗黑
- 系统

```ts
const mode = useColorMode()
console.log(mode.value) // 'light' | 'dark' | 'auto'
```

### 全局化配置

```ts
const configProviderProps = useNaiveConfigProvider()
```

```html
<NConfigProvider v-bind="configProviderProps"> ... </NConfigProvider>
```

### 脱离上下文的 API

```ts
const { dialog } = useNaiveApi()
dialog.warning('warning!')
```
23 changes: 16 additions & 7 deletions src/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,21 @@ import { cloneDeep } from 'lodash-es'
import { themeSetting } from '~/settings/theme'
const { setting } = useThemeSetting({ initialValue: cloneDeep(themeSetting) })
const { theme, themeOverrides } = useNaiveTheme({
themeOverrides: computed(() => ({
common: setting.value?.themeColor,
const configProviderProps = useNaiveConfigProvider({
themeOverrides: {
common: {
borderRadius: '8px',
},
Card: {
borderRadius: '12px',
},
Drawer: {
borderRadius: '12px',
},
},
lightThemeOverrides: computed(() => ({
common: setting.value?.lightThemeColor,
})),
darkThemeOverrides: computed(() => ({
common: setting.value?.darkThemeColor,
Expand All @@ -14,10 +26,7 @@ const { theme, themeOverrides } = useNaiveTheme({
</script>

<template>
<YConfigProvider
:theme
:theme-overrides
>
<YConfigProvider v-bind="configProviderProps">
<RouterView />
</YConfigProvider>
</template>
156 changes: 156 additions & 0 deletions src/composables/useNaiveConfigProvider.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
import type { UseColorModeOptions } from '@vueuse/core'
import { merge } from 'lodash-es'
import type { ConfigProviderProps, GlobalThemeOverrides } from 'naive-ui'
import { commonDark, darkTheme, dateZhCN, zhCN } from 'naive-ui'
import type { MaybeRefOrGetter } from 'vue'

export type ColorType = 'primary' | 'info' | 'success' | 'warning' | 'error'
export type ColorScene = '' | 'Suppl' | 'Hover' | 'Pressed'
export interface ColorAction {
scene: ColorScene
handler: (color: string) => string
}

export interface UseNaiveConfigProviderOptions {
/**
* 是否不存在 DOM 包裹
*/
abstract?: ConfigProviderProps['abstract']
/**
* 屏幕响应式断点,对 n-grid 生效。这个属性不是响应式的,你需要在组件第一次挂载时就设定好
*/
breakpoints?: ConfigProviderProps['breakpoints']
/**
* 内部所有组件的类的前缀,仅首次设定会生效
*/
clsPrefix?: ConfigProviderProps['clsPrefix']
/**
* 对后代组件生效的日期语言对象,为 null 时会使用默认 dateEnUS,为 undefined 时会继承上级 n-config-provider
*/
dateLocale?: ConfigProviderProps['dateLocale']
/**
* 是否禁用 inline css 主题变量,如果你不会频繁调整主题变量,并且需要 SSR 或者想让 devtools 看起来更干净,可以打开这个选项。注意,这个属性不是响应式的
*/
inlineThemeDisabled?: ConfigProviderProps['inlineThemeDisabled']
/**
* 公式组件需要的 katex 对象
*/
katex?: ConfigProviderProps['katex']
/**
* 对后代组件生效的语言对象,为 null 时会使用默认 enUS,为 undefined 时会继承上级 n-config-provider
*/
locale?: ConfigProviderProps['locale']
/**
* n-config-provider 内部组件被卸载于其他位置的 DOM 的类名
*/
namespace?: ConfigProviderProps['namespace']
/**
* 是否禁用默认样式,如果你禁用了它,便可以完全控制全局样式。你也可以使用 n-global-style 去挂载全局样式(推荐,样式是响应式的)
*/
preflightStyleDisabled?: ConfigProviderProps['preflightStyleDisabled']
/**
* n-config-provider 被渲染成的元素
*/
tag?: ConfigProviderProps['tag']
/**
* 主题模式
*/
themeMode?: UseColorModeOptions['initialValue']
/**
* Naive UI 主题覆盖
*/
themeOverrides?: MaybeRefOrGetter<GlobalThemeOverrides | null>
/**
* Naive UI 明亮主题覆盖
*/
lightThemeOverrides?: MaybeRefOrGetter<GlobalThemeOverrides | null>
/**
* Naive UI 暗黑主题覆盖
*/
darkThemeOverrides?: MaybeRefOrGetter<GlobalThemeOverrides | null>
}

export interface UseNaiveConfigProviderReturn extends ConfigProviderProps {}

export function useNaiveConfigProvider(options: UseNaiveConfigProviderOptions = {}): UseNaiveConfigProviderReturn {
const {
dateLocale = dateZhCN,
locale = zhCN,
themeMode,
themeOverrides: initialThemeOverrides = {},
lightThemeOverrides: initialLightThemeOverrides = {},
darkThemeOverrides: initialDarkThemeOverrides = {},
...opts
} = options

const mode = useColorMode({ initialValue: themeMode })
const isDark = computed(() => mode.value === 'dark')
const theme = computed(() => isDark.value ? darkTheme : null)

const currentThemeOverrides = computed(() => {
const themeOverrides = isDark.value ? toValue(initialDarkThemeOverrides) : toValue(initialLightThemeOverrides)
return merge(themeOverrides, toValue(initialThemeOverrides))
})
const themeOverrides = computed(() => {
if (!currentThemeOverrides.value)
return {}

const commonColor = getCommonColor(currentThemeOverrides.value.common, isDark.value)
return {
...currentThemeOverrides.value,
common: {
...currentThemeOverrides.value.common,
...commonColor,
},
}
})

function getGenerateColors(color: string, isDark: boolean): string[] {
return isDark
? generateColorPalettes(color, true, commonDark.bodyColor)
: generateColorPalettes(color)
}

function getCommonColor(commonColor: GlobalThemeOverrides['common'], isDark: boolean) {
const result: any = {}
const keys = Object.keys(commonColor!) as ColorType[]

const colorActions: ColorAction[] = [
{
scene: '',
handler: color => color,
},
{
scene: 'Hover',
handler: color => getGenerateColors(color, isDark)[4],
},
{
scene: 'Suppl',
handler: color => getGenerateColors(color, isDark)[4],
},
{
scene: 'Pressed',
handler: color => getGenerateColors(color, isDark)[6],
},
]
keys.forEach((key) => {
if (key.includes('Color')) {
colorActions.forEach((action) => {
const color = action.handler((commonColor as any)[key])
const colorKey = key + action.scene
result[colorKey] = color
})
}
})

return result
}

return reactive<any>({
dateLocale,
locale,
theme,
themeOverrides,
...opts,
})
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import type { DialogApi, LoadingBarApi, MessageApi, NotificationApi } from 'naive-ui'
import type { ConfigProviderProps, DialogApi, LoadingBarApi, MessageApi, NotificationApi } from 'naive-ui'
import { createDiscreteApi } from 'naive-ui'

export interface UseNaiveApiReturn {
export interface UseNaiveDiscreteApiOptions extends ConfigProviderProps {}

export interface UseNaiveDiscreteApiReturn {
/**
* Naive UI 对话框 API
*/
Expand All @@ -23,25 +25,23 @@ export interface UseNaiveApiReturn {
/**
* Naive UI 脱离上下文的 API
*/
export function useNaiveApi(): UseNaiveApiReturn {
export function useNaiveDiscreteApi(options: UseNaiveDiscreteApiOptions = {}): UseNaiveDiscreteApiReturn {
const { setting } = useThemeSetting()

const { theme, themeOverrides } = useNaiveTheme({
themeOverrides: computed(() => ({
common: setting.value?.themeColor,
const configProviderProps = useNaiveConfigProvider({
lightThemeOverrides: computed(() => ({
common: setting.value?.lightThemeColor,
})),
darkThemeOverrides: computed(() => ({
common: setting.value?.darkThemeColor,
})),
...options,
})

const { dialog, loadingBar, message, notification } = createDiscreteApi(
['message', 'dialog', 'notification', 'loadingBar'],
{
configProviderProps: {
theme: theme.value,
themeOverrides: themeOverrides.value,
},
configProviderProps,
},
)

Expand Down
3 changes: 2 additions & 1 deletion src/settings/theme.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
export const themeSetting = {
themeMode: 'auto',
themeColor: {
lightThemeColor: {
primaryColor: '#18A058',
infoColor: '#2080F0',
successColor: '#18A058',
Expand All @@ -24,6 +24,7 @@ export const themeSetting = {
show: true,
width: 240,
collapsedWidth: 64,
collapsed: false,
inverted: false,
},
footer: {
Expand Down

0 comments on commit 3e825a6

Please sign in to comment.