镜像站点 · 本页由第三方 GitHub 只读镜像提供,非 GitHub 官方站点,不接受任何登录或凭据输入。前往 github.com
Skip to content

Commit 8da8ace

Browse files
committed
fix: apply opacity modifiers to var()-based theme colors via color-mix
Fixes #16 A theme color holding a var() reference (success: 'var(--success)') has no channels to rewrite, so applyOpacity's fallback returned the color unchanged and bg-success/10 rendered fully opaque. Such values now emit color-mix(in srgb, <color> N%, transparent), matching Tailwind. Applies to every opacity path (bg/text/border/ring/gradient stops) and to currentColor; inherit and transparent pass through unchanged.
1 parent 2e4dc55 commit 8da8ace

2 files changed

Lines changed: 65 additions & 1 deletion

File tree

‎packages/crosswind/src/rules.ts‎

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -541,7 +541,15 @@ export function applyOpacity(color: string, opacity: number): string {
541541
return `hsl(${hslMatch[1]} / ${opacity})`
542542
}
543543
}
544-
// Fallback: use opacity as-is with the color
544+
// Values whose channels can't be rewritten inline — var() references,
545+
// color-mix(), named colors, currentColor — get their alpha via color-mix
546+
// (like Tailwind), instead of silently dropping the opacity and rendering
547+
// the color fully opaque. `inherit` can't participate in color-mix, so it
548+
// passes through unchanged.
549+
if (cleanColor !== 'inherit' && cleanColor !== 'transparent') {
550+
const pct = Number((opacity * 100).toFixed(2))
551+
return `color-mix(in srgb, ${cleanColor} ${pct}%, transparent)`
552+
}
545553
return cleanColor
546554
}
547555

‎packages/crosswind/test/colors.test.ts‎

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1099,3 +1099,59 @@ describe('Nested color DEFAULT key (issue #17)', () => {
10991099
expect(css).not.toContain('--brand-DEFAULT')
11001100
})
11011101
})
1102+
1103+
describe('Opacity modifier on var()-based theme colors (issue #16)', () => {
1104+
// A theme color holding a var() reference has no channels to rewrite, so
1105+
// the opacity modifier must go through color-mix() instead of being
1106+
// silently dropped (which rendered bg-success/10 fully opaque).
1107+
const varConfig = {
1108+
...defaultConfig,
1109+
theme: {
1110+
...defaultConfig.theme,
1111+
extend: { colors: { success: 'var(--success)' } },
1112+
},
1113+
}
1114+
1115+
it('emits color-mix for bg-{varColor}/{n}', () => {
1116+
const gen = new CSSGenerator(varConfig)
1117+
gen.generate('bg-success/10')
1118+
expect(gen.toCSS(false)).toContain('background-color: color-mix(in srgb, var(--success) 10%, transparent);')
1119+
})
1120+
1121+
it('emits color-mix for text and border with variants', () => {
1122+
const gen = new CSSGenerator(varConfig)
1123+
gen.generateBatch(['text-success/50', 'hover:bg-success/15'])
1124+
const css = gen.toCSS(false)
1125+
expect(css).toContain('color: color-mix(in srgb, var(--success) 50%, transparent);')
1126+
expect(css).toContain('.hover\\:bg-success\\/15:hover')
1127+
expect(css).toContain('background-color: color-mix(in srgb, var(--success) 15%, transparent);')
1128+
})
1129+
1130+
it('emits color-mix for arbitrary opacity values', () => {
1131+
const gen = new CSSGenerator(varConfig)
1132+
gen.generate('border-success/[0.04]')
1133+
expect(gen.toCSS(false)).toContain('border-color: color-mix(in srgb, var(--success) 4%, transparent);')
1134+
})
1135+
1136+
it('keeps native alpha for channel-based theme colors', () => {
1137+
const gen = new CSSGenerator(varConfig)
1138+
gen.generate('bg-blue-500/50')
1139+
const css = gen.toCSS(false)
1140+
expect(css).toContain('/ 0.5)')
1141+
expect(css).not.toContain('color-mix')
1142+
})
1143+
1144+
it('applies color-mix to currentColor but passes inherit through', () => {
1145+
const gen = new CSSGenerator(varConfig)
1146+
gen.generateBatch(['bg-current/50', 'bg-inherit/50'])
1147+
const css = gen.toCSS(false)
1148+
expect(css).toContain('background-color: color-mix(in srgb, currentColor 50%, transparent);')
1149+
expect(css).toContain('background-color: inherit;')
1150+
})
1151+
1152+
it('does not alter the solid form of the var color', () => {
1153+
const gen = new CSSGenerator(varConfig)
1154+
gen.generate('text-success')
1155+
expect(gen.toCSS(false)).toContain('color: var(--success);')
1156+
})
1157+
})

0 commit comments

Comments
 (0)