Skip to content

Commit

Permalink
feat: add 'ts/color/modifiers format option
Browse files Browse the repository at this point in the history
  • Loading branch information
druhill authored and jorenbroekema committed Jul 14, 2023
1 parent 9a9feb7 commit 1327559
Show file tree
Hide file tree
Showing 8 changed files with 127 additions and 17 deletions.
5 changes: 5 additions & 0 deletions .changeset/chatty-pumpkins-cross.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@tokens-studio/sd-transforms': patch
---

Add 'ts/color/modifiers' option: `format`, to globally set the output format for color modifiers.
23 changes: 14 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -140,20 +140,25 @@ registerTransforms({
shadow: false,
},
excludeParentKeys: true,
'ts/color/modifiers': {
format: 'hex',
},
});
```

Options:

| name | type | required | default | description |
| ------------------ | ------------------------ | -------- | --------------- | ------------------------------------------------------------------------------------------------------------------------------------- |
| excludeParentKeys | boolean || `false` | Whether or not to exclude parent keys from your token files |
| expand | boolean \| ExpandOptions || See props below | `false` to not register the parser at all. By default, expands composition tokens. Optionally, border, shadow and typography as well. |
| expand.composition | boolean \| ExpandFilter || `true` | Whether or not to expand compositions. Also allows a filter callback function to conditionally expand per token/filePath |
| expand.typography | boolean \| ExpandFilter || `false` | Whether or not to expand typography. Also allows a filter callback function to conditionally expand per token/filePath |
| expand.shadow | boolean \| ExpandFilter || `false` | Whether or not to expand shadows. Also allows a filter callback function to conditionally expand per token/filePath |
| expand.border | boolean \| ExpandFilter || `false` | Whether or not to expand borders. Also allows a filter callback function to conditionally expand per token/filePath |
| |
| name | type | required | default | description |
| ----------------------------- | ------------------------ | -------- | --------------- | ------------------------------------------------------------------------------------------------------------------------------------- |
| excludeParentKeys | boolean || `false` | Whether or not to exclude parent keys from your token files |
| expand | boolean \| ExpandOptions || See props below | `false` to not register the parser at all. By default, expands composition tokens. Optionally, border, shadow and typography as well. |
| expand.composition | boolean \| ExpandFilter || `true` | Whether or not to expand compositions. Also allows a filter callback function to conditionally expand per token/filePath |
| expand.typography | boolean \| ExpandFilter || `false` | Whether or not to expand typography. Also allows a filter callback function to conditionally expand per token/filePath |
| expand.shadow | boolean \| ExpandFilter || `false` | Whether or not to expand shadows. Also allows a filter callback function to conditionally expand per token/filePath |
| expand.border | boolean \| ExpandFilter || `false` | Whether or not to expand borders. Also allows a filter callback function to conditionally expand per token/filePath |
| ['ts/color/modifiers'] | ColorModifierOptions || See props below | Color modifier options |
| ['ts/color/modifiers'].format | ColorModifierFormat || `undefined` | Color modifier output format override ('hex' \| 'hsl' \| 'lch' \| 'p3' \| 'srgb'), uses local format or modifier space as default |
| |

> Note: you can also import and use the `expandComposites` function to run the expansion on your token object manually.
> Handy if you have your own parsers set up (e.g. for JS files), and you want the expansions to work there too.
Expand Down
7 changes: 7 additions & 0 deletions src/TransformOptions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,14 @@ export interface ExpandOptions {
composition?: boolean | ExpandFilter<SingleCompositionToken>; // default true
}

export type ColorModifierFormat = 'hex' | 'hsl' | 'lch' | 'p3' | 'srgb';

export interface ColorModifierOptions {
format: ColorModifierFormat;
}

export interface TransformOptions {
expand?: ExpandOptions | false;
excludeParentKeys?: boolean;
['ts/color/modifiers']?: ColorModifierOptions;
}
9 changes: 8 additions & 1 deletion src/color-modifiers/transformColorModifiers.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,17 @@
import { DesignToken } from 'style-dictionary';
import { modifyColor } from './modifyColor.js';
import { ColorModifier } from '@tokens-studio/types';
import { ColorModifierOptions } from '../TransformOptions.js';
/**
* Helper: Transforms color tokens with tokens studio color modifiers
*/
export function transformColorModifiers(token: DesignToken): string | undefined {
export function transformColorModifiers(
token: DesignToken,
options?: ColorModifierOptions,
): string | undefined {
const modifier = token.$extensions['studio.tokens']?.modify as ColorModifier;
if (options?.format) {
modifier.format = options.format;
}
return modifyColor(token.value, modifier);
}
2 changes: 1 addition & 1 deletion src/registerTransforms.ts
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@ export async function registerTransforms(sd: Core, transformOpts?: TransformOpti
transitive: true,
matcher: token =>
token.type === 'color' && token.$extensions && token.$extensions['studio.tokens']?.modify,
transformer: token => transformColorModifiers(token),
transformer: token => transformColorModifiers(token, transformOpts?.['ts/color/modifiers']),
});

_sd.registerTransformGroup({
Expand Down
3 changes: 1 addition & 2 deletions test/integration/sd-transforms.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ describe('sd-transforms smoke tests', () => {
if (dict) {
cleanup(dict);
}
dict = init(cfg);
dict = init(cfg, { 'ts/color/modifiers': { format: 'hex' } });
});

afterEach(() => {
Expand All @@ -43,7 +43,6 @@ describe('sd-transforms smoke tests', () => {

it('supports tokens-studio tokens', async () => {
const file = await promises.readFile(outputFilePath, 'utf-8');
console.log(file);
expect(file).to.include(`:root {
--sdDimensionScale: 2;
--sdDimensionXs: 4px;
Expand Down
6 changes: 2 additions & 4 deletions test/integration/tokens/sd-transforms.tokens.json
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,7 @@
"modify": {
"type": "lighten",
"value": "0.1",
"space": "srgb",
"format": "hex"
"space": "srgb"
}
}
}
Expand All @@ -88,8 +87,7 @@
"modify": {
"type": "darken",
"value": "0.1",
"space": "srgb",
"format": "hex"
"space": "srgb"
}
}
}
Expand Down
89 changes: 89 additions & 0 deletions test/spec/color-modifiers/transformColorModifiers.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,95 @@ describe('transform color modifiers', () => {
expect(transformColorModifiers(token('hex'))).to.equal('#9a3535');
});

it('allows passing an output format as an option', () => {
const token = (space: ColorSpaceTypes | '') => ({
value: '#C14242',
type: 'color',
$extensions: {
'studio.tokens': {
modify: {
type: 'darken',
value: '0.2',
space,
},
},
},
});

// uses hex override for output format
expect(transformColorModifiers(token(ColorSpaceTypes.HSL), { format: 'hex' })).to.equal(
'#9c3333',
);
expect(transformColorModifiers(token(ColorSpaceTypes.LCH), { format: 'hex' })).to.equal(
'#983735',
);
expect(transformColorModifiers(token(ColorSpaceTypes.P3), { format: 'hex' })).to.equal(
'#9b3535',
);
expect(transformColorModifiers(token(ColorSpaceTypes.SRGB), { format: 'hex' })).to.equal(
'#9a3535',
);

// uses hsl override for output format
expect(transformColorModifiers(token(ColorSpaceTypes.HSL), { format: 'hsl' })).to.equal(
'hsl(0 50.6% 40.6%)',
);
expect(transformColorModifiers(token(ColorSpaceTypes.LCH), { format: 'hsl' })).to.equal(
'hsl(0.85 47.9% 40.3%)',
);
expect(transformColorModifiers(token(ColorSpaceTypes.P3), { format: 'hsl' })).to.equal(
'hsl(0.05 49% 40.7%)',
);
expect(transformColorModifiers(token(ColorSpaceTypes.SRGB), { format: 'hsl' })).to.equal(
'hsl(0 49% 40.6%)',
);

// uses lch override for output format
expect(transformColorModifiers(token(ColorSpaceTypes.HSL), { format: 'lch' })).to.equal(
'lch(37.8 51 29.8)',
);
expect(transformColorModifiers(token(ColorSpaceTypes.LCH), { format: 'lch' })).to.equal(
'lch(37.7 47.5 29.7)',
);
expect(transformColorModifiers(token(ColorSpaceTypes.P3), { format: 'lch' })).to.equal(
'lch(37.9 49.4 29.4)',
);
expect(transformColorModifiers(token(ColorSpaceTypes.SRGB), { format: 'lch' })).to.equal(
'lch(37.8 49.4 29.4)',
);

// uses p3 override for output format
expect(transformColorModifiers(token(ColorSpaceTypes.HSL), { format: 'p3' })).to.equal(
'color(display-p3 0.57 0.23 0.22)',
);
expect(transformColorModifiers(token(ColorSpaceTypes.LCH), { format: 'p3' })).to.equal(
'color(display-p3 0.55 0.24 0.22)',
);
expect(transformColorModifiers(token(ColorSpaceTypes.P3), { format: 'p3' })).to.equal(
'color(display-p3 0.56 0.24 0.22)',
);
expect(transformColorModifiers(token(ColorSpaceTypes.SRGB), { format: 'p3' })).to.equal(
'color(display-p3 0.56 0.23 0.22)',
);

// uses srgb override for output format
expect(transformColorModifiers(token(ColorSpaceTypes.HSL), { format: 'srgb' })).to.equal(
'rgb(61.2% 20.1% 20.1%)',
);
expect(transformColorModifiers(token(ColorSpaceTypes.LCH), { format: 'srgb' })).to.equal(
'rgb(59.5% 21.5% 21%)',
);
expect(transformColorModifiers(token(ColorSpaceTypes.P3), { format: 'srgb' })).to.equal(
'rgb(60.6% 20.8% 20.7%)',
);
expect(transformColorModifiers(token(ColorSpaceTypes.SRGB), { format: 'srgb' })).to.equal(
'rgb(60.5% 20.7% 20.7%)',
);

// without space, return original
expect(transformColorModifiers(token(''))).to.equal('#C14242');
});

it('can convert from a non-srgb space to srgb space to then format it as a hex color (which is fundamentally rgb)', () => {
const token = {
value: '#C14242',
Expand Down

0 comments on commit 1327559

Please sign in to comment.