为AntDesign的按钮扩充几种颜色

770 阅读2分钟

背景

由于一些特殊原因,想要学习一下react,因此必不可少的接触到了AntDesign组件库,但是发现该组件库的按钮组件并不能提供花里胡哨的配置,因此才有了这篇文章。

该方案基于configProvider5.8.0新增的algorithm属性(为了能够同步顶层的暗黑模式)。

20240114165833ISlU9K55000476.png

遇到的问题:

  1. 本意是想通过@ant-design/colors包提供的generate函数自行配置颜色的,但是最终发现不知道如何获取顶层configProvider是否使用了暗黑模式,因此该函数的的第二个参数就无法达到自动获取了。(最终通过5.8.0新增的algorithm属性进行了解决)

完整代码

import { Button, ButtonProps, ConfigProvider, ThemeConfig } from 'antd'
import { useMemo, useState } from 'react';
// import { generate } from '@ant-design/colors';
interface CButtonProps extends ButtonProps {
  color?: string
}

function hexToRgb(hex: string) {
  let sColor = hex.toLowerCase();
  //十六进制颜色值的正则表达式
  const reg = /^#([0-9a-fA-f]{3}|[0-9a-fA-f]{6})$/;
  // 如果是16进制颜色
  if (sColor && reg.test(sColor)) {
    if (sColor.length === 4) {
      let sColorNew = "#";
      for (let i = 1; i < 4; i += 1) {
        sColorNew += sColor.slice(i, i + 1).concat(sColor.slice(i, i + 1));
      }
      sColor = sColorNew;
    }
    //处理六位的颜色值
    const sColorChange = [];
    for (let i = 1; i < 7; i += 2) {
      sColorChange.push(parseInt("0x" + sColor.slice(i, i + 2)));
    }
    return sColorChange
  }
  return sColor;
}
function primaryColorAlpha(color: string, alpha: number) {
  const rgb = hexToRgb(color)
  return `rgba(${rgb[0]}, ${rgb[1]}, ${rgb[2]}, ${alpha})`
}
type ColorSchema = 'primary' | 'success' | 'warning' | 'error' | 'info'
function getColorReflection(alias?: ColorSchema | string) {
  if (!alias) return ''
  const colorSchema: Record<ColorSchema, string> = {
    'primary': '#1677ff',
    'success': '#52c41a',
    'warning': '#faad14',
    'error': '#f5222d',
    'info': '#13c2c2',
  }
  return colorSchema[alias as ColorSchema] || alias
}


export default function CButton(props: CButtonProps) {

  const [componentsTheme, setComponentsTheme] = useState<ThemeConfig['components']>(() => ({}))

  const color = getColorReflection(props.color)

  useMemo(() => {
    if (color) {
      // const c = generate(color, { theme: 'default' })
      setComponentsTheme(() => {
        return {
          Button: {
            /**
             * 启用派生算法,用于生成 hover、active 等状态的样式
             * 该参数需要 antd >= 5.8.0 以上版本支持
             * @link https://ant-design.antgroup.com/docs/react/customize-theme-cn#%E4%BF%AE%E6%94%B9%E7%BB%84%E4%BB%B6%E5%8F%98%E9%87%8F
             */
            algorithm: true,

            /**
             * 如果不使用 algorithm 算法,需要将以下注释打开
             */

            colorPrimary: color,
            // colorPrimaryHover: c[4],
            // colorPrimaryActive: c[6],
            // colorPrimaryBg: c[5],
            // colorPrimaryBgHover: c[4],
            // colorPrimaryBorder: c[2],
            // colorPrimaryBorderHover: c[2],
            // colorPrimaryText: '#fff',
            // colorPrimaryTextActive: '#fff',
            // colorPrimaryTextHover: '#fff',

            // colorBgContainerDisabled: props.type === 'primary' ? primaryColorAlpha(c[5], 0.55) : 'transparent',
            // borderColorDisabled: props.danger ? primaryColorAlpha(c[5], 0.25) : primaryColorAlpha(c[5], 0.15),
            // colorTextDisabled:primaryColorAlpha(c[5], 0.75),
            // colorBgContainerDisabled: props.type === 'primary' ? color: 'transparent',
            // borderColorDisabled:color,

            colorLink: color,
            // colorLinkHover: c[3],
            // colorLinkActive: c[6],

            colorText: color,
            // colorTextDisabled: props.danger ? primaryColorAlpha(c[5], 0.6) : primaryColorAlpha(c[5], 0.5),
            // colorBgTextActive: primaryColorAlpha(c[5], 0.15),
            // textHoverBg: primaryColorAlpha(c[5], 0.06),

            // defaultBorderColor: c[2],
            // defaultColor: primaryColorAlpha(c[5], 0.88),

            colorError: color,
            // colorErrorActive: c[6],
            // colorErrorHover: c[4],
            // colorErrorBorder: c[4],
            // colorErrorBorderHover: c[4],
            // colorErrorOutline: c[6],
          }
        }
      })
    } else {
      setComponentsTheme(() => ({}))
    }
  }, [color])

  return (
    <ConfigProvider theme={{ components: componentsTheme }}>
      <Button {...props}>{props.children}</Button>
    </ConfigProvider>
  )
}