Last active
January 28, 2025 12:03
-
-
Save artursopelnik/b4d6a6f839fa98c6d8d00d4c6861d286 to your computer and use it in GitHub Desktop.
Style Dictionary: Custom 'px to rem' Transform (size/pxToRem) to handle all pixel values, not just dimensions and font sizes
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import StyleDictionary from 'style-dictionary'; | |
import { Config, PlatformConfig, DesignToken } from "style-dictionary/types"; | |
import { transformTypes } from 'style-dictionary/enums'; | |
function throwSizeError(name: string | undefined, value: string | number, unitType: string): string { | |
throw `Invalid Number: '${name ? name : ''}: ${value}' is not a valid number, cannot transform to '${unitType}' \n`; | |
} | |
function getBasePxFontSize(platform: PlatformConfig): number { | |
return (platform && platform.basePxFontSize) || 16; | |
} | |
/** | |
* Convert all pixel (px) values to rem, not just dimensions and font sizes, uses `platform.options.basePxFontSize` | |
* as the base font, or `16` if not provided | |
* Scales non-zero numbers to rem, and adds ‘rem’ to the end. | |
*/ | |
StyleDictionary.registerTransform({ | |
type: transformTypes.value, | |
name: 'size/pxToRem', | |
transitive: true, | |
// Checks if the token's value ends with 'px' and skips tokens with attributes.pxToRem set to false. | |
filter: (token: DesignToken, options: Config) => { | |
const value = options.usesDtcg ? token.$value : token.value | |
return ( | |
typeof value === 'string' && | |
value.trim().endsWith('px') && | |
!token.disablePxToRem | |
) | |
}, | |
transform: (token: DesignToken, platform: PlatformConfig, options: Config) => { | |
const value = options.usesDtcg ? token.$value : token.value; | |
const parsedVal = parseFloat(value); | |
const baseFont = getBasePxFontSize(platform); | |
if (isNaN(parsedVal)) { | |
throwSizeError(token.name, value, 'rem'); | |
} | |
return parsedVal === 0 ? '0' : `${parsedVal / baseFont}rem`; | |
} | |
}); | |
/* | |
Example | |
{ | |
"global / dimension": { | |
"1": { | |
"$type": "dimension", | |
"$value": "2px", | |
"$description": "Dimension 1", | |
"disablePxToRem": true | |
}, | |
"2": { | |
"$type": "dimension", | |
"$value": "4px", | |
"$description": "Dimension 2" | |
}, | |
"3": { | |
"$type": "dimension", | |
"$value": "8px", | |
"$description": "Dimension 3" | |
} | |
} | |
} | |
*/ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment