Antd 主题色动态切换

861 阅读3分钟

项目中需要支持动态主题色切换, 使用了 antd 第三方库。

  • 项目 antd 版本 升级 4 -> 5, 4 不支持动态主题色切换。
  • 项目中 类似 import Search from "antd/lib/input/Search"; 这样的引用动态样式设置不生效 需改成以下形式
import { Input } from "antd";
const { Search } = Input;

  • theme Config 获取
export default function useThemeStyleConfig() {
  const currTheme = useTheme(); // 监控用户主题变化,获取当前用户的 主题色配置
  const primaryColor = "###"; // 主色颜色
  const Config = {
    token: {
      colorPrimary: primaryColor,
      colorLink: primaryColor,
      colorLinkHover: "#d87a16",
      colorLinkActive: "#d87a16",
      lineWidthFocus: 2,
      motionDurationSlow: "0s",
      colorFillContent: "rgba(190, 190, 190, 0.2)", // 骨架屏背景色
      ...(currTheme === Theme.Dark
        ? {
            // 黑色主题的一些相关 配置
            // card border 颜色
            colorBorderSecondary: "#434343",
            colorBgBase: "#1f1f1f",
            colorTextBase: "white", // dark
            colorBorder: "#434343", // dark
            controlItemBgActive: "rgb(43,29,17)",
            colorBgSpotlight: "#1f1f1f", // tooltip
            colorWarningBg: "#2b1d11",
            colorWarningBorder: "#593815",
          }
        : {
            //白色主题配置
            colorBgBase: "white",
            colorBgSpotlight: primaryColor, // tooltip
          }),
    },
    components: {
      Radio: {
        colorPrimary: primaryColor,
      },
      // 一些组件的定制化配置
      ...(currTheme === Theme.Dark
        ? {
            Tree: {
              controlItemBgHover: "#2C2C2D",
              controlItemBgActive: "rgb(17,38,60)",
            },
            Card: {
              colorBorder: "#434343",
            },
            Tag: {
              colorBgBase: "rgba(255, 255, 255, 0.04)",
              colorBorder: "#434343",
              colorErrorBg: "#2a1215",
              colorErrorBorder: "#58181c",
              colorSuccessBg: "#162312",
              colorSuccessBorder: "#274916",
            },
          }
        : {}),
    },
  };
  return Config;
}

项目中使用 config

  // 获取当前用户的 主题色配置
  const themeConfig = useThemeStyleConfig();
  <ConfigProvider
      // 切换主题色逻辑
      theme={themeConfig}>
    // 其他类容
  </ConfigProvider>

注意有时候项目比较大且卡的情况下,调整样式都会触发整个应用重新 Build 刷新,会比较影响开发进程,可直接线上调整样式后 从右上角主题样式 copy 相应设置即可 ant-design.antgroup.com/theme-edito…

image.png

  • 一些已知的问题
  • 组件 card 在设了 size="small" token 设置样式失效
 <Card size="small" title="Small size card" extra={<a href="#">More</a>} style={{ width: 300 }}>
 </Card>

card 主题色设置, 真正生效的是 paddingLG ( 前提是 Card 不能设置 size="small" , 否则不生效。 )

 "Card": {
    "padding": 8,
    "paddingLG": 4,
    "paddingXS": 1 // card 缺少 paddinXS 选项
  },

card size 选项一共两个 default | small; size | card 的尺寸 | default | small | default 设了 size 为 samll 后导致 token 设置 的 4px 样式被 small 样式覆盖

:where(.css-dev-only-do-not-override-zqe8aq).ant-card-small >.ant-card-body {
 padding:12px ;
}
<style>

:where(.css-dev-only-do-not-override-zqe8aq).ant-card .ant-card-body {
   padding:4px;
   border-radius: 0 0 8px 8px;
}
  • 组件 Decritpions 样式设置, Decritpions 可选Size default | middle | small
    "Descriptions": {
        padding: 8 , // size 选 middle 起效,类似 padding: 8px 8px;
        paddingSM: 2, // 上下边距
        paddingLG: 4, // 左右边距
      },

转化成 css 后会变成

size="middle" 场景 生效的配置为 paddingSM, paddingLG 切以组合方式,跟一般理解 paddingSM 是对 size= "middle" 的组件 Decritpions 设置 padding, paddingLG 是对 size= "large" 的组件 Decritpions 设置 padding, 有些理解出入。

.ant-descriptions.ant-descriptions-bordered.ant-descriptions-middle .ant-descriptions-item-content {
 padding: 2px 4px;
}

size="small" 场景 生效的配置为 padding

.ant-descriptions.ant-descriptions-bordered.ant-descriptions-small .ant-descriptions-item-content {
 padding: 8px 8px;
}

size="default" 场景 生效的配置为 padding, paddingLG

.ant-descriptions.ant-descriptions-bordered .ant-descriptions-item-content {
  padding: 8px 4px;

TODO 更多诡异设置内幕待更新