Skip to content

Commit

Permalink
fix(core): resolving design values [ALT-1222] (#744)
Browse files Browse the repository at this point in the history
* fix(core): allow getBreakpointByValue to return unresolved design token values [ALT-1222]

* fix: add unit test

* fix: add more unit tests

* fix: revised unit test to use design token values from the definitions fixture
  • Loading branch information
primeinteger authored Sep 11, 2024
1 parent fbf3d88 commit 93c9cc5
Show file tree
Hide file tree
Showing 5 changed files with 259 additions and 69 deletions.
60 changes: 60 additions & 0 deletions packages/core/src/__fixtures__/designTokens.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import { DesignTokensDefinition } from '../types';

export const designTokensFixture: DesignTokensDefinition = {
color: {
bg: 'white',
font: 'black',
danger: 'red',
warning: 'orange',
success: 'green',
},
spacing: {
xs: '0.5 rem',
s: '1rem',
m: '1.5rem',
l: '2rem',
},
sizing: {
quarter: '25%',
half: '50%',
threeQuarters: '75%',
full: '100%',
},
border: {
borderless: {
width: '0px',
style: 'solid',
color: 'transparent',
},
default: {
width: '1px',
style: 'solid',
color: 'black',
},
bold: {
width: '3px',
style: 'solid',
color: 'black',
},
},
fontSize: {
default: '1rem',
small: '0.75rem',
large: '1.5rem',
},
lineHeight: {
default: '1.5',
small: '1.25',
large: '2',
},
letterSpacing: {
default: 'normal',
tight: '0.5px',
wide: '2px',
},
textColor: {
default: 'black',
muted: 'gray',
accent: 'blue',
},
};
183 changes: 182 additions & 1 deletion packages/core/src/utils/breakpoints.spec.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import { createBreakpoints } from '@/__fixtures__/breakpoints';
import { designTokensFixture } from '@/__fixtures__/designTokens';
import { getActiveBreakpointIndex, getValueForBreakpoint, mediaQueryMatcher } from './breakpoints';
import { describe, it, expect } from 'vitest';
import { defineDesignTokens } from '../registries';

describe('getValueForBreakpoint', () => {
describe('getValueForBreakpoint for css values', () => {
const breakpoints = createBreakpoints();
const variableName = 'cfBackgroundColor';
const [desktopIndex, tabletIndex, mobileIndex] = [0, 1, 2];
Expand Down Expand Up @@ -96,6 +98,185 @@ describe('getValueForBreakpoint', () => {
});
});

describe('getValueForBreakpoint for design tokens', () => {
const breakpoints = createBreakpoints();
const variableName = 'cfBackgroundColor';
const [desktopIndex, tabletIndex, mobileIndex] = [0, 1, 2];
const [desktopTokenValue, tabletTokenValue, mobileTokenValue] = [
'${color.danger}',
'${color.warning}',
'${color.success}',
];
const [desktopResolvedValue, tabletResolvedValue, mobileResolvedValue] = [
designTokensFixture.color!.danger,
designTokensFixture.color!.warning,
designTokensFixture.color!.success,
];
const valuesByBreakpoint = {
desktop: desktopTokenValue,
tablet: tabletTokenValue,
mobile: mobileTokenValue,
};
const valuesByBreakpointWithoutMobile = {
desktop: desktopTokenValue,
tablet: tabletTokenValue,
};
const valuesByBreakpointWithoutTabletAndMobile = {
desktop: desktopTokenValue,
};

beforeEach(() => {
defineDesignTokens(designTokensFixture);
});

describe('when rendering a desktop view', () => {
it('renders desktop with design token resolved', () => {
const value = getValueForBreakpoint(
valuesByBreakpoint,
breakpoints,
desktopIndex,
variableName,
);
expect(value).toEqual(desktopResolvedValue);
});
it('renders desktop with design token in string template format', () => {
const value = getValueForBreakpoint(
valuesByBreakpoint,
breakpoints,
desktopIndex,
variableName,
false,
);
expect(value).toEqual(desktopTokenValue);
});
});

describe('when rendering a tablet view', () => {
it('renders tablet with design token resolved', () => {
const value = getValueForBreakpoint(
valuesByBreakpoint,
breakpoints,
tabletIndex,
variableName,
);
expect(value).toEqual(tabletResolvedValue);
});
it('falls back to the desktop value with design token resolved', () => {
const value = getValueForBreakpoint(
valuesByBreakpointWithoutTabletAndMobile,
breakpoints,
tabletIndex,
variableName,
);
expect(value).toEqual(desktopResolvedValue);
});

it('renders tablet with design token in string template format', () => {
const value = getValueForBreakpoint(
valuesByBreakpoint,
breakpoints,
tabletIndex,
variableName,
false,
);
expect(value).toEqual(tabletTokenValue);
});
it('falls back to the desktop value with design token in string template format', () => {
const value = getValueForBreakpoint(
valuesByBreakpointWithoutTabletAndMobile,
breakpoints,
tabletIndex,
variableName,
false,
);
expect(value).toEqual(desktopTokenValue);
});
});

describe('when rendering a mobile view', () => {
it('renders the mobile value with design token resolved', () => {
const value = getValueForBreakpoint(
valuesByBreakpoint,
breakpoints,
mobileIndex,
variableName,
);
expect(value).toEqual(mobileResolvedValue);
});
it('falls back to the tablet value with design token resolved', () => {
const value = getValueForBreakpoint(
valuesByBreakpointWithoutMobile,
breakpoints,
mobileIndex,
variableName,
);
expect(value).toEqual(tabletResolvedValue);
});
it('falls back to the desktop value with design token resolved', () => {
const value = getValueForBreakpoint(
valuesByBreakpointWithoutTabletAndMobile,
breakpoints,
mobileIndex,
variableName,
);
expect(value).toEqual(desktopResolvedValue);
});

it('renders the mobile value with design token in string template format', () => {
const value = getValueForBreakpoint(
valuesByBreakpoint,
breakpoints,
mobileIndex,
variableName,
false,
);
expect(value).toEqual(mobileTokenValue);
});
it('falls back to the tablet value with design token in string template format', () => {
const value = getValueForBreakpoint(
valuesByBreakpointWithoutMobile,
breakpoints,
mobileIndex,
variableName,
false,
);
expect(value).toEqual(tabletTokenValue);
});
it('falls back to the desktop value with design token in string template format', () => {
const value = getValueForBreakpoint(
valuesByBreakpointWithoutTabletAndMobile,
breakpoints,
mobileIndex,
variableName,
false,
);
expect(value).toEqual(desktopTokenValue);
});
});

describe('when rendering a view without a matching breakpoint', () => {
it('falls back to the desktop value with design token resolved', () => {
const value = getValueForBreakpoint(
valuesByBreakpointWithoutTabletAndMobile,
breakpoints,
3,
variableName,
);
expect(value).toEqual(desktopResolvedValue);
});
it('falls back to the desktop value with design token in string template format', () => {
const value = getValueForBreakpoint(
valuesByBreakpointWithoutTabletAndMobile,
breakpoints,
3,
variableName,
false,
);
expect(value).toEqual(desktopTokenValue);
});
});
});

describe('getActiveBreakpointIndex', () => {
const breakpoints = createBreakpoints();
const mediaQueryMatches = {
Expand Down
13 changes: 10 additions & 3 deletions packages/core/src/utils/breakpoints.ts
Original file line number Diff line number Diff line change
Expand Up @@ -100,9 +100,10 @@ export const getValueForBreakpoint = (
breakpoints: Breakpoint[],
activeBreakpointIndex: number,
variableName: string,
resolveDesignTokens = true,
) => {
const eventuallyResolveDesignTokens = (value: PrimitiveValue) => {
// For some built-in design propertier, we support design tokens
// For some built-in design properties, we support design tokens
if (builtInStylesWithDesignTokens.includes(variableName)) {
return getDesignTokenRegistration(value as string, variableName);
}
Expand All @@ -116,14 +117,20 @@ export const getValueForBreakpoint = (
const breakpointId = breakpoints[index]?.id;
if (isValidBreakpointValue(valuesByBreakpoint[breakpointId])) {
// If the value is defined, we use it and stop the breakpoints cascade
return eventuallyResolveDesignTokens(valuesByBreakpoint[breakpointId]);
if (resolveDesignTokens) {
return eventuallyResolveDesignTokens(valuesByBreakpoint[breakpointId]);
}
return valuesByBreakpoint[breakpointId];
}
}
// If no breakpoint matched, we search and apply the fallback breakpoint
const fallbackBreakpointIndex = getFallbackBreakpointIndex(breakpoints);
const fallbackBreakpointId = breakpoints[fallbackBreakpointIndex]?.id;
if (isValidBreakpointValue(valuesByBreakpoint[fallbackBreakpointId])) {
return eventuallyResolveDesignTokens(valuesByBreakpoint[fallbackBreakpointId]);
if (resolveDesignTokens) {
return eventuallyResolveDesignTokens(valuesByBreakpoint[fallbackBreakpointId]);
}
return valuesByBreakpoint[fallbackBreakpointId];
}
} else {
// Old design properties did not support breakpoints, keep for backward compatibility
Expand Down
4 changes: 2 additions & 2 deletions packages/core/src/utils/styleUtils/ssrStyles.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -859,7 +859,7 @@ describe('flattenDesignTokenRegistry', () => {
font: 'black',
danger: 'red',
warning: 'orange',
succcess: 'green',
success: 'green',
},
spacing: {
xs: '0.5 rem',
Expand Down Expand Up @@ -913,7 +913,7 @@ describe('flattenDesignTokenRegistry', () => {
'color.font': 'black',
'color.danger': 'red',
'color.warning': 'orange',
'color.succcess': 'green',
'color.success': 'green',
'spacing.xs': '0.5 rem',
'spacing.s': '1rem',
'spacing.m': '1.5rem',
Expand Down
Loading

0 comments on commit 93c9cc5

Please sign in to comment.