Skip to content

Commit

Permalink
CSS Color Mix (#1109)
Browse files Browse the repository at this point in the history
* Add color/Alpha transformer

* use cssColorMix in shadows

* add changeset

* dont apply new transformer
  • Loading branch information
lukasoppermann authored Dec 13, 2024
1 parent 02776ce commit da8a1d9
Show file tree
Hide file tree
Showing 6 changed files with 85 additions and 2 deletions.
5 changes: 5 additions & 0 deletions .changeset/poor-kids-trade.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@primer/primitives': minor
---

use cssColorMix instead of converting variables to hex when we use transparency
2 changes: 1 addition & 1 deletion scripts/buildTokens.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ const getStyleDictionaryConfig: StyleDictionaryConfigGenerator = (
include,
log: {
warnings: 'disabled', // 'warn' | 'error' | 'disabled'
verbosity: 'verbose', // 'default' | 'silent' | 'verbose'
verbosity: 'silent', // 'default' | 'silent' | 'verbose'
errors: {
brokenReferences: 'throw', // 'throw' | 'console'
},
Expand Down
3 changes: 3 additions & 0 deletions src/primerStyleDictionary.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ import {
jsonFigma,
} from './formats/index.js'
import {themeOverrides} from './preprocessors/themeOverrides.js'
import {colorAlphaToCss} from './transformers/colorAlphaToCss.js'

/**
* @name {@link PrimerStyleDictionary}
Expand Down Expand Up @@ -104,6 +105,8 @@ PrimerStyleDictionary.registerFormat({
* Transformers
*
*/
PrimerStyleDictionary.registerTransform(colorAlphaToCss)

PrimerStyleDictionary.registerTransform(colorToRgbAlpha)

PrimerStyleDictionary.registerTransform(colorToRgbaFloat)
Expand Down
49 changes: 49 additions & 0 deletions src/transformers/colorAlphaToCss.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import {getMockToken} from '../test-utilities/index.js'
import {colorAlphaToCss} from './colorAlphaToCss.js'

describe('Transformer: colorAlphaToCss', () => {
it('transforms hex3, hex6, hex8 `color` tokens without alpha value', () => {
const input = [
getMockToken({$value: '#123'}),
getMockToken({$value: '#343434'}),
getMockToken({$value: '#34343455'}),
]
const expectedOutput = ['#123', '#343434', '#34343455']
expect(input.map(item => colorAlphaToCss.transform(item, {}, {}))).toStrictEqual(expectedOutput)
})

it('transforms hex3, hex6, hex8 `color` tokens with alpha value', () => {
const input = [
getMockToken({$value: '#123', alpha: 0.25}),
getMockToken({$value: '#343434', alpha: 0.6}),
getMockToken({$value: '#34343466', alpha: 0.1}),
]
const expectedOutput = [
'color-mix(in srgb, #123, transparent 75%)',
'color-mix(in srgb, #343434, transparent 40%)',
'color-mix(in srgb, #34343466, transparent 90%)',
]
expect(input.map(item => colorAlphaToCss.transform(item, {}, {}))).toStrictEqual(expectedOutput)
})

it('transforms references with and without alpha value', () => {
const input = [
getMockToken({$value: '{base.color.green.5}'}),
getMockToken({$value: '{base.color.red.5}', alpha: 0.25}),
]
const expectedOutput = ['{base.color.green.5}', 'color-mix(in srgb, {base.color.red.5}, transparent 75%)']
expect(input.map(item => colorAlphaToCss.transform(item as TransformedToken, {}, {}))).toStrictEqual(expectedOutput)
})

it('transforms color-mix with and without alpha value', () => {
const input = [
getMockToken({$value: 'color-mix(in srgb, {base.color.red.5}, transparent 25%)'}),
getMockToken({$value: 'color-mix(in srgb, {base.color.red.5}, transparent 25%)', alpha: 0.35}),
]
const expectedOutput = [
'color-mix(in srgb, {base.color.red.5}, transparent 25%)',
'color-mix(in srgb, color-mix(in srgb, {base.color.red.5}, transparent 25%), transparent 65%)',
]
expect(input.map(item => colorAlphaToCss.transform(item as TransformedToken, {}, {}))).toStrictEqual(expectedOutput)
})
})
26 changes: 26 additions & 0 deletions src/transformers/colorAlphaToCss.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import {Transform, TransformedToken} from 'style-dictionary/types'

Check warning on line 1 in src/transformers/colorAlphaToCss.ts

View workflow job for this annotation

GitHub Actions / Test & Lint

All imports in the declaration are only used as types. Use `import type`
import {isColorWithAlpha} from '../filters/isColorWithAlpha.js'
import {getTokenValue} from './utilities/getTokenValue.js'

export const cssColorMix = (colorA: string, colorB: string, colorBPercent: number) => {
if (colorBPercent < 0 || colorBPercent > 1) {
throw new Error(
`Invalid argument for "cssColorMix", colorBPercent must be between 0 and 1, ${colorBPercent} provided.`,
)
}
if (colorBPercent === 0) return colorA
if (colorBPercent === 1) return colorB

return `color-mix(in srgb, ${colorA}, ${colorB} ${colorBPercent * 100}%)`
}

export const colorAlphaToCss: Transform = {
name: 'colorAlpha/css',
type: 'value',
transitive: true,
filter: isColorWithAlpha,
transform: (token: TransformedToken) => {
if (!token.alpha || token.alpha === null) return getTokenValue(token)
return cssColorMix(getTokenValue(token), 'transparent', 1 - token.alpha)
},
}
2 changes: 1 addition & 1 deletion src/transformers/colorToHex.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export const colorToHex: Transform = {
transitive: true,
filter: isColor,
transform: (token: TransformedToken) => {
const alphaValue = token.alpha ?? token.$extensions?.alpha
const alphaValue = token.alpha
if (alphaValue === null || alphaValue === undefined) {
return toHex(getTokenValue(token))
}
Expand Down

0 comments on commit da8a1d9

Please sign in to comment.