Skip to content

Commit 9ea3162

Browse files
Fix border transformer to work with new W3C dimension format and ensure px values in styleLint output
Co-authored-by: lukasoppermann <[email protected]>
1 parent e4c33a4 commit 9ea3162

File tree

4 files changed

+88
-8
lines changed

4 files changed

+88
-8
lines changed

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/transformers/borderToCss.test.ts

Lines changed: 55 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import {getMockToken} from '../test-utilities/index.js'
22
import {borderToCss} from './borderToCss.js'
33

44
describe('Transformer: borderToCss', () => {
5-
it('transforms `border` token to css border string', () => {
5+
it('transforms `border` token to css border string with string width', () => {
66
const input = getMockToken({
77
$value: {
88
color: '#000000',
@@ -15,8 +15,43 @@ describe('Transformer: borderToCss', () => {
1515
expect(borderToCss.transform(input, {}, {})).toStrictEqual(expectedOutput)
1616
})
1717

18+
it('transforms `border` token to css border string with dimension object width', () => {
19+
const input = getMockToken({
20+
$value: {
21+
color: '#000000',
22+
style: 'solid',
23+
width: {value: 2, unit: 'px'},
24+
},
25+
})
26+
27+
const expectedOutput = '2px solid #000000'
28+
expect(borderToCss.transform(input, {}, {})).toStrictEqual(expectedOutput)
29+
})
30+
31+
it('transforms `border` token to css border string with array width from dimension/remPxArray', () => {
32+
const input = getMockToken({
33+
$value: {
34+
color: '#000000',
35+
style: 'solid',
36+
width: ['0.125rem', '2px'], // Array from dimension/remPxArray transformer
37+
},
38+
})
39+
40+
const expectedOutput = '2px solid #000000' // Should use px value for styleLint
41+
expect(borderToCss.transform(input, {}, {})).toStrictEqual(expectedOutput)
42+
})
43+
44+
it('returns already transformed string values as-is', () => {
45+
const input = getMockToken({
46+
$value: '1px solid #000000',
47+
})
48+
49+
const expectedOutput = '1px solid #000000'
50+
expect(borderToCss.transform(input, {}, {})).toStrictEqual(expectedOutput)
51+
})
52+
1853
it('throws an error when required values are missing', () => {
19-
// missing blur
54+
// missing width
2055
expect(() =>
2156
borderToCss.transform(
2257
getMockToken({
@@ -30,7 +65,7 @@ describe('Transformer: borderToCss', () => {
3065
),
3166
).toThrowError()
3267

33-
// missing spread
68+
// missing style
3469
expect(() =>
3570
borderToCss.transform(
3671
getMockToken({
@@ -44,7 +79,7 @@ describe('Transformer: borderToCss', () => {
4479
),
4580
).toThrowError()
4681

47-
// missing offsets
82+
// missing color
4883
expect(() =>
4984
borderToCss.transform(
5085
getMockToken({
@@ -58,4 +93,20 @@ describe('Transformer: borderToCss', () => {
5893
),
5994
).toThrowError()
6095
})
96+
97+
it('throws an error for invalid width values', () => {
98+
expect(() =>
99+
borderToCss.transform(
100+
getMockToken({
101+
$value: {
102+
color: '#000000',
103+
style: 'solid',
104+
width: 123, // Invalid: number instead of string or object
105+
},
106+
}),
107+
{},
108+
{},
109+
),
110+
).toThrowError('Invalid width value')
111+
})
61112
})

src/transformers/borderToCss.ts

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import type {Transform, TransformedToken} from 'style-dictionary/types'
22
import {isBorder} from '../filters/isBorder.js'
33
import type {BorderTokenValue} from '../types/borderTokenValue.js'
4+
import {dimensionToString} from './utilities/dimensionToString.js'
45

56
/**
67
* checks if all required properties exist on shadow token
@@ -13,6 +14,31 @@ const checkForBorderTokenProperties = (border: Record<string, unknown>): border
1314
}
1415
return false
1516
}
17+
18+
/**
19+
* Converts width value to string, handling different formats
20+
* @param width - The width value (string, dimension object, or array from dimension/remPxArray)
21+
* @returns CSS width string
22+
*/
23+
const getWidthString = (width: unknown): string => {
24+
// If it's already a string, return as is
25+
if (typeof width === 'string') {
26+
return width
27+
}
28+
29+
// If it's an array from dimension/remPxArray transformer, use the px value (second element)
30+
if (Array.isArray(width) && width.length === 2) {
31+
return width[1] // Return the px value for styleLint compatibility
32+
}
33+
34+
// If it's a dimension object, convert to string
35+
if (typeof width === 'object' && width !== null && 'value' in width && 'unit' in width) {
36+
return dimensionToString(width as {value: number; unit: string})
37+
}
38+
39+
throw new Error(`Invalid width value: ${JSON.stringify(width)}`)
40+
}
41+
1642
/**
1743
* @description converts w3c border tokens in css border string
1844
* @type valueTransformer — [StyleDictionary.ValueTransform](https://github.com/amzn/style-dictionary/blob/main/types/Transform.d.ts)
@@ -36,7 +62,10 @@ export const borderToCss: Transform = {
3662
`Invalid border token property ${JSON.stringify(value)}. Must be an object with color, width and style properties.`,
3763
)
3864
}
65+
66+
const widthString = getWidthString(value.width)
67+
3968
/* width | style | color */
40-
return `${value.width} ${value.style} ${value.color}`
69+
return `${widthString} ${value.style} ${value.color}`
4170
},
4271
}

src/types/borderTokenValue.d.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,6 @@
55
export type StrokeStyleString = 'solid' | 'dashed' | 'dotted' | 'double' | 'groove' | 'ridge' | 'outset' | 'inset'
66
export type BorderTokenValue = {
77
color: string
8-
width: string
8+
width: string | {value: number; unit: string} | [string, string] // Support string, dimension object, or array from transformers
99
style: StrokeStyleString
1010
}

0 commit comments

Comments
 (0)