Skip to content

Commit

Permalink
fix(core): additional space design tokens
Browse files Browse the repository at this point in the history
- breaking change, adding new space design tokens and adjusting scale
- add support for scaling tokens for space/layout/typography
- minor css perf improvements

Signed-off-by: Cory Rylan <splintercode.cb@gmail.com>
  • Loading branch information
coryrylan committed Jan 4, 2022
1 parent 52d2063 commit 1f96d06
Show file tree
Hide file tree
Showing 49 changed files with 387 additions and 354 deletions.
2 changes: 1 addition & 1 deletion packages/core/.browserslistrc
@@ -1,2 +1,2 @@
# Browsers that we support
chrome 89
chrome 96
40 changes: 24 additions & 16 deletions packages/core/build/build.tokens.ts
Expand Up @@ -102,7 +102,7 @@ function buildJSONTokens(path) {

function buildSassTokens(path) {
const values = tokens
.map(token => `${tokenToSass(token, false)}\n`)
.map(token => `${tokenToSass(token)}\n`)
.join('')
.trim();
fs.writeFileSync(path, `// ${experimental}\n${values}`);
Expand All @@ -111,7 +111,7 @@ function buildSassTokens(path) {
function buildCSSTokens(path) {
const cssTokens = `
:root {
${tokens.map(token => ` --cds-${camelCaseToKebab(token.name)}: ${convertCSSValue(token, 20, false)};`).join('\n')}
${tokens.map(token => ` ${getTokenCSSName(token)}: ${convertCSSValue(token, false)};`).join('\n')}
}`;

fs.writeFileSync(path, cssTokens);
Expand All @@ -132,21 +132,23 @@ ${tokens

function tokenToSass(token: Token, fallback = false) {
const propName = camelCaseToKebab(token.name);
let staticValue;
let fallbackValue = convertCSSValue(token);

if (typeof token.value === 'number') {
staticValue = convertCSSValue(token);
} else if ((typeof token.value === 'string' && token.value.slice(-2) === 'em') || token.config.static) {
staticValue = token.value;
fallbackValue = `${token.value / 16}rem`; // worst case scenario, fallback to base 16 if base 20 not set at root
}

const dynamicVar = `$cds-${propName}: var(--cds-${camelCaseToKebab(token.name)}${
fallback ? `, ${convertCSSValue(token)}` : ''
})${fallback ? '' : ' !default'};`;
if (token.config.raw) {
fallbackValue = token.value;
}

const dynamicValue = `$cds-${propName}: var(${getTokenCSSName(token)}${
fallback ? `, ${fallbackValue}` : ''
}) !default;`;
const staticValue =
token.config.static || typeof token.value === 'number' ? `\n$cds-${propName}-static: ${token.value} !default;` : '';

return `${dynamicVar}${
token.config.static ? `\n$cds-${propName}-static: ${staticValue}${fallback ? '' : ' !default'};` : ''
}`;
return `${dynamicValue}${staticValue}`;
}

function flattenTokens(theme: any) {
Expand All @@ -168,24 +170,30 @@ function flattenTokens(theme: any) {
return flatten(theme);
}

function convertCSSValue(token: Token, base = 20, fallback = true) {
function convertCSSValue(token: Token, fallback = true) {
let value = token.value;

if (token.alias instanceof Token) {
value = `var(--cds-${camelCaseToKebab(token.alias.name)}${
fallback ? `, ${convertCSSValue(token.alias, 20, fallback)}` : ''
fallback ? `, ${convertCSSValue(token.alias, fallback)}` : ''
})`;
} else if (token.config.static) {
} else if (token.config.raw) {
value = token.value;
} else if (token.config.scale) {
value = `calc(${token.value} * var(--cds-${camelCaseToKebab(token.config.scale.name)}))`;
} else if (typeof token.value === 'number') {
value = `calc((${token.value} / var(--cds-global-base, ${base})) * 1rem)`;
value = `calc(${token.value} * (1rem / var(--cds-global-base)))`;
} else if (isHSL(token.value)) {
value = `hsl(${token.value[0]}, ${token.value[1]}%, ${token.value[2]}%)`;
}

return value;
}

function getTokenCSSName(token: Token) {
return `--cds-${camelCaseToKebab(token.name)}`;
}

function camelCaseToKebab(val: string) {
return val.replace(/([A-Z]|\d+)/g, '-$1').toLocaleLowerCase();
}
Expand Down
12 changes: 10 additions & 2 deletions packages/core/build/token-utils.ts
Expand Up @@ -5,7 +5,9 @@
*/

export interface CdsTheme {
internal: Tokens;
global: {
scale: Tokens;
layout: Tokens;
space: Tokens;
color: Tokens;
Expand All @@ -20,12 +22,18 @@ export interface Tokens {
[key: string]: Token | Tokens;
}

export function token(value: any, config: any = {}) {
export function token(value: any, config: TokenConfig = {}) {
return new Token(value, config);
}

export type HSL = [number, number, number];

export interface TokenConfig {
raw?: boolean; // generate token with no format type conversions (px to rem)
static?: boolean; // generate secondary static variable (wont generate dynamice css var usefull for media queries, calc)
scale?: Token; // set a token scale multiplier on numeric types
}

export class Token {
name = '';
private _value: Token | number | string | HSL;
Expand All @@ -38,7 +46,7 @@ export class Token {
return this._value instanceof Token ? this._value : null;
}

constructor(value: Token | number | string | HSL, public config: { static?: boolean } = {}) {
constructor(value: Token | number | string | HSL, public config: TokenConfig = {}) {
this._value = value;
}

Expand Down
124 changes: 71 additions & 53 deletions packages/core/build/tokens.ts
Expand Up @@ -6,43 +6,62 @@

import { token, CdsTheme } from './token-utils';

// internal optimization so tokens can refer to pre-calculated values rather than generating/duplicating the same calc over many tokens
const internal = {
scale1: token('calc((1rem / var(--cds-global-base)) * var(--cds-global-scale-layout-space))', { raw: true }),
scale2: token('calc((1rem / var(--cds-global-base)) * var(--cds-global-scale-space))', { raw: true }),
scale3: token('calc((1rem / var(--cds-global-base)) * var(--cds-global-scale-typography))', { raw: true }),
};

const base = token(20, { raw: true });

const scale = {
space: token(1, { raw: true }),
layoutSpace: token(1, { raw: true }),
typography: token(1, { raw: true }),
};

const layout = {
space: {
xxs: token(2),
xs: token(4),
sm: token(6),
md: token(12),
lg: token(24),
xl: token(48),
xxl: token(96),
},
grid: {
cols: token(12, { static: true }),
cols: token(12, { raw: true }),
},
width: {
xs: token('576px', { static: true }),
sm: token('768px', { static: true }),
md: token('992px', { static: true }),
lg: token('1200px', { static: true }),
xl: token('1440px', { static: true }),
xs: token('576px', { raw: true, static: true }),
sm: token('768px', { raw: true, static: true }),
md: token('992px', { raw: true, static: true }),
lg: token('1200px', { raw: true, static: true }),
xl: token('1440px', { raw: true, static: true }),
},
space: {
xxxs: token(2, { scale: internal.scale1 }),
xxs: token(4, { scale: internal.scale1 }),
xs: token(8, { scale: internal.scale1 }),
sm: token(12, { scale: internal.scale1 }),
md: token(16, { scale: internal.scale1 }),
lg: token(24, { scale: internal.scale1 }),
xl: token(32, { scale: internal.scale1 }),
xxl: token(48, { scale: internal.scale1 }),
xxxl: token(64, { scale: internal.scale1 }),
},
};

const space = {
0: token(0),
1: token(1),
2: token(2),
3: token(4),
4: token(6),
5: token(8),
6: token(12),
7: token(16),
8: token(18),
9: token(24),
10: token(32),
11: token(36),
12: token(48),
13: token(72),
0: token(0, { scale: internal.scale2 }),
1: token(1, { scale: internal.scale2 }),
2: token(2, { scale: internal.scale2 }),
3: token(4, { scale: internal.scale2 }),
4: token(6, { scale: internal.scale2 }),
5: token(8, { scale: internal.scale2 }),
6: token(12, { scale: internal.scale2 }),
7: token(16, { scale: internal.scale2 }),
8: token(18, { scale: internal.scale2 }),
9: token(24, { scale: internal.scale2 }),
10: token(32, { scale: internal.scale2 }),
11: token(36, { scale: internal.scale2 }),
12: token(48, { scale: internal.scale2 }),
13: token(64, { scale: internal.scale2 }),
14: token(72, { scale: internal.scale2 }),
15: token(96, { scale: internal.scale2 }),
};

const color = {
Expand Down Expand Up @@ -342,19 +361,17 @@ const typography = {
extrabold: token('600'),
},
fontSize: {
0: token(10),
1: token(11),
2: token(12),
3: token(13),
4: token(14),
5: token(16),
6: token(20),
7: token(24),
8: token(32),
9: token(40),
},
baseFontSize: token('125%'), // deprecated for removal in 6.0
baseFontSizePx: token(20), // deprecated for removal in 6.0
0: token(10, { scale: internal.scale3 }),
1: token(11, { scale: internal.scale3 }),
2: token(12, { scale: internal.scale3 }),
3: token(13, { scale: internal.scale3 }),
4: token(14, { scale: internal.scale3 }),
5: token(16, { scale: internal.scale3 }),
6: token(20, { scale: internal.scale3 }),
7: token(24, { scale: internal.scale3 }),
8: token(32, { scale: internal.scale3 }),
9: token(40, { scale: internal.scale3 }),
},
fontFamily: token("'Clarity City', 'Avenir Next', sans-serif"),
headerFontFamily: token("'Clarity City', 'Avenir Next', sans-serif"),
monospaceFontFamily: token('ui-monospace, Consolas, Menlo, Monaco, monospace'),
Expand All @@ -372,61 +389,61 @@ const typography = {
},
},
body: {
fontSize: token(14),
fontSize: token(14, { scale: internal.scale3 }),
lineHeight: token('1.42857em', { static: true }), // static for line height eraser calcs
letterSpacing: token('-0.014286em'),
fontWeight: token('400'),
},
display: {
fontSize: token(40),
fontSize: token(40, { scale: internal.scale3 }),
lineHeight: token('1.1em', { static: true }),
letterSpacing: token('-0.0125em'),
fontWeight: token('400'),
},
heading: {
fontSize: token(32),
fontSize: token(32, { scale: internal.scale3 }),
lineHeight: token('1.125em', { static: true }),
letterSpacing: token('-0.0125em'),
fontWeight: token('400'),
},
title: {
fontSize: token(24),
fontSize: token(24, { scale: internal.scale3 }),
lineHeight: token('1.16667em', { static: true }),
letterSpacing: token('-0.008333em'),
fontWeight: token('400'),
},
section: {
fontSize: token(20),
fontSize: token(20, { scale: internal.scale3 }),
lineHeight: token('1.2em', { static: true }),
letterSpacing: token('-0.01em'),
fontWeight: token('400'),
},
subsection: {
fontSize: token(16),
fontSize: token(16, { scale: internal.scale3 }),
lineHeight: token('1.25em', { static: true }),
letterSpacing: token('-0.0125em'),
fontWeight: token('400'),
},
message: {
fontSize: token(16),
fontSize: token(16, { scale: internal.scale3 }),
lineHeight: token('1.25em', { static: true }),
letterSpacing: token('-0.0125em'),
fontWeight: token(400),
},
secondary: {
fontSize: token(13),
fontSize: token(13, { scale: internal.scale3 }),
lineHeight: token('1.23077em', { static: true }),
letterSpacing: token('-0.007692em'),
fontWeight: token('400'),
},
caption: {
fontSize: token(11),
fontSize: token(11, { scale: internal.scale3 }),
lineHeight: token('1.454545em', { static: true }),
letterSpacing: token('0.018182em'),
fontWeight: token('400'),
},
smallcaption: {
fontSize: token(10),
fontSize: token(10, { scale: internal.scale3 }),
lineHeight: token('1.2em', { static: true }),
letterSpacing: token('0.05em'),
fontWeight: token('500'),
Expand Down Expand Up @@ -569,6 +586,7 @@ const aliases = {
};

export const baseTheme: CdsTheme = {
global: { layout, space, color, typography, animation, base: token(20, { static: true }) },
global: { base, scale, layout, space, color, typography, animation },
aliases,
internal,
};
4 changes: 2 additions & 2 deletions packages/core/docs/welcome.stories.ts
Expand Up @@ -16,12 +16,12 @@ export default {

export const core = () => {
return html`
<section cds-layout="vertical gap:xl align:center m-t:xxl" cds-text="center">
<section cds-layout="vertical gap:xxl align:center m-t:xxxl" cds-text="center">
<img
src="${img}"
alt="Clarity Core"
cds-layout="fill"
style="max-width: calc(var(--cds-global-layout-space-xl) * 3)"
style="max-width: calc(var(--cds-global-layout-space-xxl) * 3)"
/>
<h1 cds-text="display">
Clarity Core
Expand Down
6 changes: 3 additions & 3 deletions packages/core/package.json
Expand Up @@ -89,7 +89,7 @@
"bundlesize": "1.0.0-beta.2",
"cem-plugin-readonly": "0.0.2",
"cem-plugin-module-file-extensions": "0.0.2",
"csso": "4.2.0",
"csso": "5.0.0",
"custom-elements-hmr-polyfill": "1.0.3",
"del-cli": "1.1.0",
"eslint": "8.3.0",
Expand All @@ -105,7 +105,7 @@
"npm-run-all": "4.1.5",
"patch-package": "6.4.7",
"playwright": "1.11.1",
"purgecss": "4.0.3",
"purgecss": "4.1.3",
"replace": "1.2.0",
"rollup-plugin-copy": "3.4.0",
"rollup-plugin-delete": "2.0.0",
Expand All @@ -115,7 +115,7 @@
"rollup-plugin-styles": "3.14.1",
"rollup-plugin-sourcemaps": "0.6.3",
"rollup-plugin-terser": "7.0.2",
"sass": "1.26.10",
"sass": "1.44.0",
"source-map-explorer": "2.5.2",
"stylelint": "10.0.1",
"stylelint-config-recommended": "2.2.0",
Expand Down

0 comments on commit 1f96d06

Please sign in to comment.