Tailwind matchUtilities插件如何获取主题DEFAULT默认颜色值?
Tailwind渐变边框插件:DEFAULT颜色值调用问题及解决办法
问题背景
我正在开发一个生成渐变边框的Tailwind插件,现有方案已可用但需要优化。当前遇到的核心问题是无法直接调用颜色配置中的DEFAULT值:使用类名bg-border-destructive-foreground可正常生效,但bg-border-destructive无法调用destructive的DEFAULT颜色,必须写成bg-border-destructive-DEFAULT才有效。
主题颜色配置
{ primary: { DEFAULT: "hsl(var(--primary))", foreground: "hsl(var(--primary-foreground))", }, ring: "hsl(var(--ring))", secondary: { DEFAULT: "hsl(var(--secondary))", foreground: "hsl(var(--secondary-foreground))", }, }
当前插件代码
export default bgBorderPlugin(({ matchUtilities, theme }) => { const borderBase = { borderStyle: "double", borderColor: "transparent", backgroundOrigin: "border-box", backgroundClip: "padding-box, border-box", }; // 使用`theme("colors.[name]", "")`避免颜色不存在时的TS异常 const gradient = `conic-gradient( from -47deg at 48.86% 48.52%, ${theme("colors.green.300", "")} 0deg, ${theme("colors.orange.200", "")} 50.625deg, ${theme("colors.stone.100", "")} 107.915deg, ${theme("colors.pink.400", "")} 156.275deg, ${theme("colors.violet.400", "")} 252.343deg, ${theme("colors.stone.100", "")} 282.483deg, ${theme("colors.green.300", "")} )`; matchUtilities( { // 工具类名称 "bg-border": (value: string) => { // 拆分背景色和边框色参数 let [bgColor, borderColor] = value.split(" "); // 未指定背景色时默认使用预设渐变 if (!bgColor) { bgColor = "gradient"; } // 从主题中获取背景色值 const color1 = theme(`colors.${bgColor.replace("-", ".")}`, ""); // 构建背景色渐变 const color1Gradient = bgColor === "gradient" ? gradient : `conic-gradient(from -47deg, ${color1}, ${color1})`; // 未指定边框色时默认使用预设渐变 if (!borderColor) { borderColor = "gradient"; } // 从主题中获取边框色值 const color2 = theme(`colors.${borderColor.replace("-", ".")}`, ""); // 构建边框色渐变 const color2Gradient = borderColor === "gradient" ? gradient : `conic-gradient(from -47deg, ${color2}, ${color2})`; return { ...borderBase, backgroundImage: `${color1Gradient}, ${color2Gradient}`, }; }, }, {}, ); });
问题原因
当调用theme("colors.destructive")时,返回的是包含DEFAULT和foreground的对象而非直接颜色值,当前代码直接将对象插入渐变字符串会导致CSS无效;只有明确指定theme("colors.destructive.DEFAULT")才能拿到正确的颜色值。
解决方案
新增一个工具函数处理颜色值获取:如果从主题拿到的是包含子属性的对象,自动提取DEFAULT值;如果是直接颜色值则直接使用。修改后的插件代码如下:
export default bgBorderPlugin(({ matchUtilities, theme }) => { const borderBase = { borderStyle: "double", borderColor: "transparent", backgroundOrigin: "border-box", backgroundClip: "padding-box, border-box", }; const gradient = `conic-gradient( from -47deg at 48.86% 48.52%, ${theme("colors.green.300", "")} 0deg, ${theme("colors.orange.200", "")} 50.625deg, ${theme("colors.stone.100", "")} 107.915deg, ${theme("colors.pink.400", "")} 156.275deg, ${theme("colors.violet.400", "")} 252.343deg, ${theme("colors.stone.100", "")} 282.483deg, ${theme("colors.green.300", "")} )`; // 新增:自动处理DEFAULT颜色的工具函数 const getThemeColor = (colorKey) => { const colorPath = colorKey.replace("-", "."); const colorValue = theme(`colors.${colorPath}`, ""); // 若为包含DEFAULT的对象,返回DEFAULT值 if (typeof colorValue === "object" && colorValue !== null && colorValue.DEFAULT) { return colorValue.DEFAULT; } // 直接返回颜色值(包括单一颜色如ring,或子属性如destructive-foreground) return colorValue; }; matchUtilities( { "bg-border": (value: string) => { let [bgColor, borderColor] = value.split(" "); if (!bgColor) { bgColor = "gradient"; } // 使用工具函数获取背景色 const color1 = getThemeColor(bgColor); const color1Gradient = bgColor === "gradient" ? gradient : `conic-gradient(from -47deg, ${color1}, ${color1})`; if (!borderColor) { borderColor = "gradient"; } // 使用工具函数获取边框色 const color2 = getThemeColor(borderColor); const color2Gradient = borderColor === "gradient" ? gradient : `conic-gradient(from -47deg, ${color2}, ${color2})`; return { ...borderBase, backgroundImage: `${color1Gradient}, ${color2Gradient}`, }; }, }, {}, ); });
效果验证
修改后:
bg-border-destructive可直接调用destructive的DEFAULT颜色,无需添加-DEFAULT后缀bg-border-destructive-foreground仍可正常调用destructive.foreground颜色- 单一颜色类如
bg-border-ring也能正常工作
内容的提问来源于stack exchange,提问作者Pierre Olivier Tran
相关产品推荐
相关产品推荐

