diff --git a/config.json b/config.json deleted file mode 100644 index 77cd699..0000000 --- a/config.json +++ /dev/null @@ -1,50 +0,0 @@ -{ - "source": ["src/tokens/**/*.json"], - "platforms": { - "js": { - "transformGroup": "js", - "buildPath": "src/build/js/", - "files": [ - { - "destination": "colours.js", - "format": "javascript/module-flat", - "options": { - "outputReferences": true - }, - "filter": { - "attributes": { - "category": "colour" - } - } - }, - { - "destination": "colours.d.ts", - "format": "typescript/es6-declarations", - "filter": { - "attributes": { - "category": "colour" - } - } - } - ] - }, - "css": { - "transformGroup": "css", - "buildPath": "src/build/css/", - "files": [ - { - "destination": "colours.css", - "format": "css/variables", - "options": { - "outputReferences": true - }, - "filter": { - "attributes": { - "category": "colour" - } - } - } - ] - } - } -} diff --git a/package.json b/package.json index fb47677..f1e1275 100644 --- a/package.json +++ b/package.json @@ -18,7 +18,7 @@ ], "scripts": { "build:clean": "rm -rf dist ssr", - "build:tokens": "style-dictionary build", + "build:tokens": "style-dictionary build --config ./sd.config.js", "build:types": "tsc --emitDeclarationOnly", "build": "npm run build:clean && npm run build:types && rollup -c ./config/rollup.config.js --environment NODE_ENV:production && node ./ssr/html.js", "dev": "npm run build:types && rollup -c ./config/rollup.config.js -w", diff --git a/sd.config.js b/sd.config.js new file mode 100644 index 0000000..24f29ea --- /dev/null +++ b/sd.config.js @@ -0,0 +1,182 @@ +const StyleDictionary = require('style-dictionary'); + +const { + fileHeader, +} = StyleDictionary.formatHelpers; + +/** + * Custom format for outputting tokens as CSS variables with media queries + * + * e.g. + * + * :root { + * --space-sm: calc(0.75 * var(--space-unit)); + * + * @include mq(sm) { + * --space-sm: calc(1 * var(--space-unit)); + * } + * } + * + */ +StyleDictionary.registerFormat({ + name: "custom/format/css-variables-with-media-queries", + formatter: function({dictionary, file, options}) { + const { outputReferences } = options; + const subTypes = Object.keys(dictionary.properties.space) + // console.log(subTypes) + + return fileHeader({file}) + + + subTypes.map(type => { + const before = type === 'base' + ? `:root {\n` + : `@media (min-width: ${type}) {\n :root {\n`; + const after = type === 'base' ? '\n}\n' : '\n }\n}\n'; + + const tokens = dictionary.allTokens.filter(({attributes}) => attributes.type === type); + + return before + tokens.map( + function(prop) { + const prefix = '--'; + const suffix = ';'; + const { attributes } = prop; + const variableName = `${attributes.category}-${attributes.item}`; + let to_ret_prop = ` --${variableName}: `; + let value = prop.value; + + /** + * A single value can have multiple references either by interpolation: + * "value": "{size.border.width.value} solid {color.border.primary.value}" + * or if the value is an object: + * "value": { + * "size": "{size.border.width.value}", + * "style": "solid", + * "color": "{color.border.primary.value"} + * } + * This will see if there are references and if there are, replace + * the resolved value with the reference's name. + */ + if (outputReferences && dictionary.usesReference(prop.original.value)) { + // Formats that use this function expect `value` to be a string + // or else you will get '[object Object]' in the output + if (typeof value === 'string') { + const refs = dictionary.getReferences(prop.original.value); + refs.forEach(ref => { + // value should be a string that contains the resolved reference + // because Style Dictionary resolved this in the resolution step. + // Here we are undoing that by replacing the value with + // the reference's name + if (ref.value && ref.name) { + value = value.replace(ref.value, function() { + // if (format === 'css') { + return `var(${prefix}${ref.name})` + // } else { + // return `${prefix}${ref.name}`; + // } + }); + } + }); + } + } + + to_ret_prop += prop.attributes.category === 'asset' ? `"${value}"` : value; + + // if (format == 'sass' && prop.themeable === true) { + // to_ret_prop += ' !default'; + // } + + to_ret_prop += suffix; + + if (prop.comment && commentStyle !== 'none') { + if (commentStyle === 'short') { + to_ret_prop = to_ret_prop.concat(` // ${prop.comment}`); + } else { + to_ret_prop = to_ret_prop.concat(` /* ${prop.comment} */`); + } + } + + return to_ret_prop; + } + ) + .join("\n") + + after + }).join("\n") + } +}); + +module.exports = { + source: ['src/tokens/**/*.json'], + platforms: { + js: { + transformGroup: 'js', + buildPath: 'src/build/js/', + files: [ + { + destination: 'colours.js', + format: 'javascript/module-flat', + options: { + outputReferences: true + }, + filter: { + attributes: { + category: 'colour' + } + } + }, + { + destination: 'colours.d.ts', + format: 'typescript/es6-declarations', + filter: { + attributes: { + category: 'colour' + } + } + } + ] + }, + css: { + transformGroup: 'css', + buildPath: 'src/build/css/', + files: [ + { + destination: 'colours.css', + format: 'css/variables', + options: { + outputReferences: true, + selector: '.foo' + }, + filter: { + attributes: { + category: 'colour' + } + } + }, + { + destination: 'spacing.css', + format: 'css/variables', + options: { + outputReferences: true, + selector: '.foo' + }, + filter: { + attributes: { + category: 'space' + } + } + }, + { + destination: 'test.css', + format: 'custom/format/css-variables-with-media-queries', + options: { + outputReferences: true + }, + filter: { + attributes: { + category: 'space' + } + } + } + ] + } + } +} diff --git a/src/tokens/spacing/base.json b/src/tokens/spacing/base.json index 11b7b81..0002caf 100644 --- a/src/tokens/spacing/base.json +++ b/src/tokens/spacing/base.json @@ -1,29 +1,52 @@ { "space": { - "unit": { - "value": "0.5" - }, - "xs": { - "default": { - "value": "calc(0.5 * {space.unit.value})" + "base": { + "unit": { + "type": "base", + "value": "0.5rem" + }, + "xs": { + "type": "base", + "value": "calc(0.5 * {space.base.unit.value})" + }, + "sm": { + "type": "base", + "value": "calc(0.75 * {space.base.unit.value})" + }, + "md": { + "value": "{space.base.unit.value}" + }, + "lg": { + "value": "calc(2 * {space.base.unit.value})" + }, + "xl": { + "value": "calc(4 * {space.base.unit.value})" } }, "sm": { - "default": { - "value": "calc(0.75 * {space.unit.value})" - }, "sm": { - "value": "calc(0.5 * {space.unit.value})" + "value": "{space.base.unit.value}" + }, + "md": { + "value": "calc(1.5 * {space.base.unit.value})" + }, + "lg": { + "value": "calc(3 * {space.base.unit.value})" + }, + "xl": { + "value": "calc(6 * {space.base.unit.value})" } }, "md": { - "value": "{space.unit.value}" - }, - "lg": { - "value": "calc(0.5 * {space.unit.value})" - }, - "xl": { - "value": "calc(0.5 * {space.unit.value})" + "md": { + "value": "calc(2 * {space.base.unit.value})" + }, + "lg": { + "value": "calc(4 * {space.base.unit.value})" + }, + "xl": { + "value": "calc(8 * {space.base.unit.value})" + } } }, "media-query": {