Last active
April 11, 2022 08:11
-
-
Save bwindels/16930ddb0bc0f0e14009f8880793f7bf to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class IconSerializer { | |
toURL(iconData: string, path: string): string { | |
// for build-time, we emit an asset with iconData and a name derived from path | |
// for run-time, we return a base64 data url of iconData | |
return ""; | |
} | |
} | |
class Icon { | |
constructor( | |
// the variable name the postcss plugin came up with when it replaced the url() expression with var() | |
readonly urlVariable: string, | |
// the color names specified in ?colors=...,... in the url | |
private readonly colorNames: string[], | |
// the file contents of the icon | |
private readonly iconData: string, | |
// the icon path without the query parameter | |
private readonly path: string, | |
// how the icon should be serialized, based on whether we're running at build time or runtime | |
private readonly serializer: IconSerializer | |
) {} | |
createURLWithColors(colorValues: Map<string, string>): string { | |
const iconData = ;/// | |
// parse svg in this.iconData, and look for colors in certain attributes, | |
// replacing hard-coded colors ([fushia, orange, ...]) with colors in colorValues | |
// of which we look up the name in this.colorNames | |
return this.serializer.toURL(iconData, this.path); | |
} | |
} | |
// during build time, this would be called from a postcss plugin to figure out what to pass as the "variables" options to the "postcss-css-variables" plugin | |
// during dev time, we would run this just before loading a css file where the css variables haven't been replaced yet, and we would | |
// set all the calculated variables on the document in a style argument. | |
export function expandDerivedVariables( | |
// all the derived variables used in the theme css (detected by a postcss plugin), same format as in theme definition file | |
derivedVariables: string[], | |
// the base color values provided by a JSON file | |
baseValues: Map<string, string>, | |
// icons detected by a postcss plugin, e.g. all usages of a url('icon.svg?colors=icon-color,...') | |
icons: Icon[] | |
): Map<string, string> { | |
const values = new Map(baseValues); | |
// calculate variable values from derivedVariables and add them to the values map | |
for (const icon of icons) { | |
values.set(icon.urlVariable, icon.createURLWithColors(values)); // in dev will turn to base64, prod to asset path | |
} | |
return values; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var postcss = require("postcss"); | |
var cssvariables = require("postcss-css-variables"); | |
var fs = require("fs"); | |
var mycss = fs.readFileSync("input.css", "utf8"); | |
/* | |
to support something like --avatar-color-darker-20 we will need | |
to write a plugin that takes the basic color set as an input and | |
first finds all the variables in the css AST. | |
Then it finds the ones that folow the --darker/fn pattern and parse | |
the names and calculate the derived color. Then once it has figured out | |
which variables need to be defined, it calls cssvariables as a nested plugin | |
with the variables option. | |
the plugin could also throw if it finds any variables that are not in the basic | |
color set | |
*/ | |
// use off-color package to derive colors? | |
// good plugin api to find fn usages like url and var: | |
// https://github.com/devex-web-frontend/postcss-assets-rebase/blob/master/index.js | |
// Process your CSS with postcss-css-variables | |
var output = postcss([cssvariables({ | |
variables: { | |
"icon-color": "red", | |
"avatar-color--darken-20": "blue", | |
"avatar-color--lighten-20": "lightblue", | |
} | |
})]).process(mycss).css; | |
console.log(output); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// a theme with it's own css file | |
// the source section is generated by the build system | |
{ | |
"version": 1, //format version | |
"name": "Element", | |
"source": { | |
// this css file has the css variables replaced with literal values and is compatible with IE11 | |
"built-asset": "element-theme-ac77c7b7.css", | |
// optional, the same style sheets with css variables not yet replaced. | |
// this is the style sheets that will be used when this theme or derived theme is loaded at runtime. | |
"runtime-asset": "element-theme-runtime-89er9w9e.css", | |
"derived-variables": [ | |
"icon-color--darker-20", | |
"foo-color=icon-color--lighter-20", // include aliases so we can also derive colors from them | |
"foo-color--darker-10" | |
], | |
"icons": { | |
"icon-url-1": "chevron-38g9h89s.svg?colors=icon-color", | |
"icon-url-2": "add-7sd8s78d.svg", | |
}, | |
}, | |
"values": { | |
// this is the same format as font-faces in custom themes in element | |
"font-faces": [ | |
{ | |
"font-family": "Inter", | |
"src": [{"asset": "/fonts/Inter.ttf", "format": "ttf"}] | |
} | |
], | |
"variants": { | |
"light": { | |
"base": true, | |
"default": true, // can be specified for a dark and non-dark variant | |
"name": "Light", | |
"variables": { | |
// could also be logo urls, or fonts, not only colors | |
"icon-color": "#CCC", | |
"text-color": "#222", | |
"default-font": "Inter, sans", // only needs to be listed in the default variant, the other variants will expand on this one | |
"monospace-font" "'Courier new'" | |
} | |
}, | |
"dark": { | |
"dark": true, | |
"default": true, | |
"name": "Dark", | |
"variables": { | |
"icon-color": "#111", | |
"text-color": "#DDD" | |
} | |
}, | |
"dark-blue": { | |
"dark": true, | |
"name": "Dark Blue", | |
"variables": { | |
"icon-color": "#001", | |
"text-color": "#AAD" | |
} | |
} | |
} | |
} | |
} | |
// a derived theme | |
{ | |
"name": "Customer", | |
"source": { | |
"extends": "element" // id listed in config file or url | |
}, | |
"values": { | |
// branded font and colors and logo | |
} | |
} |
The above mapping is after the build system has run. Before the build is done it will be something like this:
{
"themes": {"element": null},
"theme_default": "element"
}
the theme location is left empty/null as it should always be
`${themeBaseDir}/${themeName}`
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
supported themes will be listed in the config file, that way to add a (custom) theme you do need to control the hosting server but you don't need to build hydrogen
e.g.: