背景
由于一些特殊原因,想要学习一下react,因此必不可少的接触到了AntDesign组件库,但是发现该组件库的按钮组件并不能提供花里胡哨的配置,因此才有了这篇文章。
该方案基于configProvider和5.8.0新增的algorithm属性(为了能够同步顶层的暗黑模式)。
遇到的问题:
- 本意是想通过
@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>
)
}