You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何扩展Material UI内置暗黑模式配色,实现自定义色值自动切换?

实现方案

该需求完全可以实现,无需修改MUI源码,仅通过应用层的主题配置即可达成。核心思路是:在创建主题实例时,根据当前传入的palette.mode值,动态将对应模式下的自定义色值挂载到调色板对象上。

步骤1:定义自定义色的明暗配置

先统一维护所有自定义色的亮/暗模式两套色值:

const customColorConfigs = {
  // 可添加任意数量自定义色
  myColor: {
    light: '#1976d2', // 亮模式生效色值
    dark: '#90caf9' // 暗模式生效色值
  },
  accentColor: {
    light: '#d32f2f',
    dark: '#ef9a9a'
  }
}

步骤2:封装动态主题创建函数

包装MUI的createTheme方法,根据传入的模式自动匹配自定义色值:

import { createTheme } from '@mui/material/styles'

export const getAppTheme = (mode) => {
  return createTheme({
    palette: {
      mode,
      // 批量注入自定义色,无需逐个手动编写判断逻辑
      ...Object.fromEntries(
        Object.entries(customColorConfigs).map(([colorName, colorValues]) => [
          colorName,
          colorValues[mode]
        ])
      )
    }
  })
}

步骤3:全局主题Provider配置

在Next.js的入口文件_app.js中管理模式状态,动态生成主题:

import { useState, useMemo } from 'react'
import { ThemeProvider } from '@mui/material/styles'
import CssBaseline from '@mui/material/CssBaseline'
import { getAppTheme } from './theme'

export default function App({ Component, pageProps }) {
  // 管理当前明暗模式,可根据需求对接系统偏好、本地存储等
  const [themeMode, setThemeMode] = useState('light')
  // 切换模式的方法可根据需求传递给全局任意组件调用
  const toggleThemeMode = () => {
    setThemeMode(prev => prev === 'light' ? 'dark' : 'light')
  }
  // 缓存主题实例避免不必要重渲染
  const theme = useMemo(() => getAppTheme(themeMode), [themeMode])

  return (
    <ThemeProvider theme={theme}>
      {/* CssBaseline会自动同步模式对应的全局背景、文字色 */}
      <CssBaseline />
      <Component {...pageProps} toggleThemeMode={toggleThemeMode} />
    </ThemeProvider>
  )
}

步骤4:组件内直接使用

之后就可以按照你期望的方式调用自定义色,色值会随模式自动切换:

import { Box } from '@mui/material'

const DemoComponent = () => {
  return (
    <Box
      sx={{
        color: theme => theme.palette.myColor,
        borderColor: theme => theme.palette.accentColor
      }}
    >
      测试内容
    </Box>
  )
}

可选:TypeScript类型扩展

如果使用TypeScript,需要扩展MUI的Palette类型避免类型报错,在项目根目录新建mui.d.ts:

declare module '@mui/material/styles' {
  interface Palette {
    myColor: string
    accentColor: string
  }
  interface PaletteOptions {
    myColor?: string
    accentColor?: string
  }
}

进阶:支持多阶自定义色

如果你希望自定义色和内置的primary/secondary一样支持main/light/dark/contrastText等多阶属性,只需要调整配置结构即可:

const customColorConfigs = {
  myColor: {
    light: {
      main: '#1976d2',
      light: '#42a5f5',
      dark: '#1565c0',
      contrastText: '#fff'
    },
    dark: {
      main: '#90caf9',
      light: '#e3f2fd',
      dark: '#42a5f5',
      contrastText: '#000'
    }
  }
}

使用时可以直接调用theme.palette.myColor.main,和内置色的用法完全一致。

内容的提问来源于stack exchange,提问作者paws

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.07 15:36:04