-
Notifications
You must be signed in to change notification settings - Fork 31
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add support for HEX8 in HEXRGBa transform #341
base: main
Are you sure you want to change the base?
Conversation
🦋 Changeset detectedLatest commit: 6ae7729 The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
@@ -2,7 +2,7 @@ import Color from 'colorjs.io'; | |||
import { DesignToken } from 'style-dictionary/types'; | |||
|
|||
/** | |||
* Helper: Transforms hex rgba colors used in figma tokens: | |||
* Helper: Transforms hex to rgba colors used in figma tokens: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
* Helper: Transforms hex to rgba colors used in figma tokens: | |
* Helper: Transforms `rgba(hex, alpha)` format which is used in figma tokens, to valid CSS rgba colors: |
// Fast path for invalid hex | ||
if (hex.length < 4) return hex; | ||
|
||
// Determine format based on length | ||
const hexLength = hex.length - 1; // subtract 1 for # |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// Fast path for invalid hex | |
if (hex.length < 4) return hex; | |
// Determine format based on length | |
const hexLength = hex.length - 1; // subtract 1 for # | |
// Determine format based on length | |
const hexLength = hex.length - 1; // subtract 1 for # | |
// Fast path for invalid hex | |
if (hexLength < 3) return hex; | |
This makes more sense, otherwise as a reader of the code I'd be wondering "what about hex3, 3 is less than 4"
// Only transform hex colors with alpha channel | ||
const hasAlpha = hexLength === 4 || hexLength === 8; | ||
if (!hasAlpha) return hex; | ||
|
||
let hexColor = hex; | ||
let alpha = '1'; | ||
|
||
// Convert shorthand to full format if necessary | ||
if (hexLength === 4) { | ||
const r = hex[1], | ||
g = hex[2], | ||
b = hex[3], | ||
a = hex[4]; | ||
hexColor = `#${r}${r}${g}${g}${b}${b}`; | ||
alpha = (parseInt(a + a, 16) / 255).toString(); | ||
} else if (hexLength === 8) { | ||
alpha = (parseInt(hex.slice(7), 16) / 255).toString(); | ||
hexColor = hex.slice(0, 7); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This can be deleted entirely, as Colorjs.io can parse hex3/4/6/8 just fine.
const [r, g, b] = new Color(hexColor).srgb; | ||
return `rgba(${r * 255}, ${g * 255}, ${b * 255}, ${alpha})`; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
const [r, g, b] = new Color(hexColor).srgb; | |
return `rgba(${r * 255}, ${g * 255}, ${b * 255}, ${alpha})`; | |
const parsed = new Color(hexColor); | |
const [r, g, b] = parsed.srgb; | |
const alpha = parsed.alpha; | |
return `rgba(${r * 255}, ${g * 255}, ${b * 255}, ${alpha})`; |
if (val.startsWith('#')) { | ||
return transformHexColor(val); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can be deleted right? If it's already hex format, there's no point in transforming it to rgba()?
const [r, g, b] = new Color(hex).srgb; | ||
return `rgba(${r * 255}, ${g * 255}, ${b * 255}, ${alpha})`; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What about rgba(hex8, alpha)
or rgba(hex4, alpha)
so basically which alpha do we take if they are both defined in the hex but also in the alpha component of the expression?
expect(transformHEXRGBaForCSS({ value: '#F00F' })).to.equal('rgba(255, 0, 0, 1)'); | ||
expect(transformHEXRGBaForCSS({ value: '#F000' })).to.equal('rgba(255, 0, 0, 0)'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would expect these to have the same output as input, since it's valid hex format.
expect(transformHEXRGBaForCSS({ value: '#000000FF' })).to.equal('rgba(0, 0, 0, 1)'); | ||
expect(transformHEXRGBaForCSS({ value: '#00000000' })).to.equal('rgba(0, 0, 0, 0)'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here, so far this transform only is there to handle rgba(hex, alpha), not transform hex4/8 to rgba. I'm not entirely against repurposing this transform to also do this, but it would definitely be a significant breaking change.
Optimizes the
transformHEXRGBaForCSS
function to better handle hex colors with alpha channels: