All our expressions are written for the newer JavaScript Expressions Engine

Blog

Share design tokens across projects with JSX files

Photo of Tim Haywood
Tim Haywood

|

November 17, 2021

When working on branded content, a design system will define tokens such as colors and fonts that the whole team will use.

Whenever these tokens update, you need to update lots of After Effects projects, anywhere the values are used.

By storing brand tokens in .jsx files, modifying them in one place will update them in every project.

Writing the JSX file

In its most basic form, the .jsx file can be a list of key value pairs without any logic, much like writing a .json file.

brandProps.jsx

js
{
// Colors should be [r, g, b, a]
// and 0 ... 1
colors: {
red: [220 / 255, 96 / 255, 105 / 255, 1],
green: [141 / 255, 187 / 255, 110 / 255, 1],
blue: [87 / 255, 165 / 255, 237 / 255, 1],
},
// Font names are the same as
// text style expressions
fontFamily: {
mono: "FiraCode-Light"
heading: "Inter-Bold",
body: "Inter-Regular",
},
fontSize: {
small: "16",
regular: "26",
large: "42",
}
}

Make sure the values are in the same format you would use in an expression, for example color values should be an [r, g, b, a] array of values ranging from 0 to 1.

Referencing in Ae

To use these values in After Effects, import the .jsx file into your project and reference it in an expression.

For example, on a color property:

color

js
// Destructure the properties we need from the jsx file
const { colors } = footage("brandProps.jsx").sourceData();
// And reference their values
colors.red;

Or on a text layers Source Text:

sourceText

js
// Destructure the properties we need
const { fontFamily, fontSize } = footage("brandProps.jsx").sourceData();
text.sourceText.style.setFontSize(fontSize.regular).setFont(fontFamily.body);

For more information on writing and referencing .jsx files, see our post on writing expressions in external files.

Since you've stored the value in a .jsx file, rather than putting it directly into the property, anytime you update the file all projects that reference it will get the new value.

This allows you to share brand tokens across your whole team, and update them all at once.

Adding theming

Since you're storing the brand tokens in code, you have the flexibility to define them in any way the suits your design system. For example, storing different color values for light and dark mode.

brandProps.jsx

js
{
colors: {
dark: {
red: [],
green: [],
blue: [],
},
light: {
red: [],
green: [],
blue: [],
}
},
}

Which adds the ability to easily switch between themes in After Effects:

color

js
// Destructure the properties we need from the jsx file
const { colors } = footage("brandProps.jsx").sourceData();
// Could link to a checkbox control
const isDarkMode = true;
// Get either the dark or light set of colors
colors[isDarkMode ? "dark" : "light"].red;

Adding logic

Since .jsx files can contain functions, you can add logic to your token system.

Complex theming

For example, your color system might contain two types of tokens:

  • Palette tokens: a series of hues and tones
  • Usage tokens: tokens for specific use cases, that reference a palette token

By wrapping the values in a function you can return the usage tokens, without giving user access to the underlying palette tokens.

brandProps.jsx

js
{
function getColors() {
const palette = {
red: {
0: [],
100: [],
200: [],
},
green: {
0: [],
100: [],
200: [],
},
blue: {
0: [],
100: [],
200: [],
},
};
return {
light: {
text: palette.red.0;
background: palette.red.200,
accent: palette.green.100,
},
dark: {
text: palette.red.200,
background: palette.red.0,
accent: palette.green.0,
}
}
},
}

Value type conversion

After Effects expects color values to be a four dimensional array ([red, green, blue, alpha]), with each channel ranging from 0 to 1.

This can make adding new colors complicated, as you need to have an understanding of After Effects expressions, adding risk of getting these conversion wrong.

Rather than doing this conversion yourself, you can use After Effects built in color conversion functions.

brandProps.jsx

js
{
function getColors() {
const colors = {
navy: thisLayer.hexToRgb("#282C35"),
black: thisLayer.hexToRgb("#21242B"),
// and so on
};
return colors;
}

By wrapping each color value in thisLayer.hexToRgb(color), After Effects will convert the hex value to the format expressions expect.

Using proxies

Wrapping every color in your .jsx file gets tedious, and if you have a large amount of colors, performing conversions on every one (even if you're not using them) can slow down performance.

Rather than wrapping every color value, you can use a JavaScript Proxy to wrap them before they're accessed.

By only wrapping the values you use, you can speed up expressions for .jsx files that define a lot of colors.

brandProps.jsx

js
{
function getColors() {
const colors = {
navy: "#282C35",
black: "#21242B",
grey: "#BDBDBD",
lightGrey: "#F2F2F2",
white: "#FFFFFF",
green: "#B4DC96",
tan: "#D39763",
yellow: "#FFDA6E",
blue: "#5DAEE6",
red: "#E36A79",
purple: "#C774E8",
};
return new Proxy(colors, {
get: (target, prop) => {
return thisLayer.hexToRgb(target[prop]);
}
});
}

The proxy intercepts calls to the color object, and rather than returning the value directly, it uses our custom get method.

This method wraps the original value (target[prop]) in the After Effects hexToRgb conversion, returning the color in the format expressions expect.

Other uses

Since .jsx files are (mostly) just JavaScript files, you can place any values or logic in there that you want to share between projects.

For example, screen sizes for templates:

js
{
screens: {
instagram: [800, 1000],
facebook: [1080, 1920],
// ...
}
}

Commonly used strings:

js
{
strings: {
name: "Motion Developer",
description: "We're a consultancy of animators and developers",
}
}

Or a space system:

js
{
space: {
small: 4,
medium: 16,
large: 32,
}
}

We're big fans of using .jsx files to share logic between projects, such as our library of utility functions aeFunctions and our animation engine eKeys.

Blog

For enquiries contact us at hey@motiondeveloper.com