Create a Design System with Turborepo, React, Tailwind — connect it to Figma variables (3/3)

Fokker Chartier
5 min readOct 7, 2023

--

Export + prepare Figma Variables

core.json Tokens.

{
"dimensions": {
"dim-0": {
"$type": "number",
"value": 0
},
"dim-2": {
"$type": "number",
"value": 2
},
"dim-4": {
"$type": "number",
"value": 4
},
"dim-8": {
"$type": "number",
"value": 8
},
"dim-12": {
"$type": "number",
"value": 12
},
"dim-16": {
"$type": "number",
"value": 16
},
"dim-24": {
"$type": "number",
"value": 24
},
"dim-32": {
"$type": "number",
"value": 32
},
"dim-40": {
"$type": "number",
"value": 40
},
"dim-48": {
"$type": "number",
"value": 48
},
"dim-56": {
"$type": "number",
"value": 56
},
"dim-66": {
"$type": "number",
"value": 64
},
"dim-72": {
"$type": "number",
"value": 72
},
"dim-80": {
"$type": "number",
"value": 80
}
},
"colors": {
"color-brand": {
"$type": "color",
"value": "#a821ca"
},
"Color-coconut": {
"$type": "color",
"value": "#ffffff"
}
}
}

semantic.json

{
"dimension": {
"dimension-xl": {
"$type": "number",
"value": "{dimensions.dim-66}"
},
"dimension-l": {
"$type": "number",
"value": "{dimensions.dim-48}"
},
"dimension-m": {
"$type": "number",
"value": "{dimensions.dim-40}"
},
"dimension-s": {
"$type": "number",
"value": "{dimensions.dim-32}"
}
},
"Border-Radius": {
"border-radius-sm": {
"$type": "number",
"value": "{dimensions.dim-2}"
},
"border-radius-md": {
"$type": "number",
"value": "{dimensions.dim-4}"
},

"full": {
"$type": "number",
"value": "9999"
}
},

"border-width": {
"sm": {
"$type": "number",
"value": "1"
},
"md": {
"$type": "number",
"value": "{dimensions.dim-2}"
}
},

"Colors": {
"primary": {
"$type": "color",
"value": "{colors.color-brand}"
},
"font-invert": {
"$type": "color",
"value": "{colors.Color-coconut}"
}
},
"spacing": {
"sm": {
"$type": "number",
"value": "{dimensions.dim-8}"
},
"md": {
"$type": "number",
"value": "{dimensions.dim-16}"
},
"l": {
"$type": "number",
"value": "{dimensions.dim-24}"
},
"xl": {
"$type": "number",
"value": "{dimensions.dim-32}"
},
"xl 2": {
"$type": "number",
"value": "{dimensions.dim-40}"
}
}
}

In order for the exported Figma variables to be edited with StyleDictionary, some minor search and replace changes are required. If you want to use Figma variable tokens in a real project environment, you have to change them in StyleDictionary or before in a custom script. Find and replace all “$ in both json files, at least the leading $ in all “value” entries, as seen above.
Save the files and copy them both files into the new module in the subfolder tokens.

Style Dictionary Module

Create a new module tokentransform in the package folder, with the following structure:

Copy the following content into the sd.config.js file

module.exports = {
format: {
// Adding a custom format to show how to get an alias's name.
},

source: ["tokens/**/*.json"],
platforms: {
json: {
buildPath: "build/",
files: [
{
destination: "tokens.json",
format: "json/nested",
},
],
},
},
};

Copy this into the package.json

{
"name": "tokentranform",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"sd:js": "style-dictionary build --config ./sd.config-js.js"
},
"keywords": [],
"author": "",
"license": "ISC",
"files": [
"./build/tokens.json"

],
"dependencies": {
"style-dictionary": "^3.8.0"
}
}

Link the module inside the main and the next app package.json, like.

"tokentransform": "*"

In the project root folder enter yarn (or npm i if you use npm ). Finally lets test the setup by cd ./packages/tokentransform && yarn sd:js (respective npm). If everything is fine you see

yarn run v1.22.19
$ style-dictionary build --config ./sd.config-js.js

json
✔︎ build/tokens.json
✨ Done in 0.30s.

and thetokens.json file is created in your ./build folder.

Turborepo failed

To watchmode the modules tailwind.config.…big disklike Vercel!!!
For the sake of this example we move the setup into the next App tailwind.config.js we created in Part 2.

/** @type {import('tailwindcss').Config} */
// import defaultConfig from "tailwindsetup";
// @ts-ignore
import figmatokens from 'tokentranform/build/tokens.json';




const pxToRem = (px, base = 16) => `${px / base}rem`

const tailwindsetup = {
//...defaultConfig,

theme: {
colors: figmatokens.Colors,
textColors: figmatokens.Colors,
backgroundColors: figmatokens.Colors,
height: figmatokens.dimension,
borderRadius: figmatokens["Border-Radius"],
padding: figmatokens.spacing,
borderWidths: figmatokens["Border-Widths"], //

},


content: [
"./src/pages/**/*.{js,ts,jsx,tsx,mdx}",
"./src/components/**/*.{js,ts,jsx,tsx,mdx}",
"./src/app/**/*.{js,ts,jsx,tsx,mdx}",
],
};


export default tailwindsetup

We overwrite the theme here. See all possibile tailwind-modules to be extended or overwriten here. This cheat-sheet is also very usefull, as this VS-Code plugin is too.

Finally edit the page.tsx inside ./{appname}/src/app/… so it looks like

import { Card } from "ui";

const Home = () => {
return (
<main className="flex min-h-screen flex-col items-center gap-6 p-24">
<h1 className="text-6xl text-bubblegum">Buttons</h1>

<button
className="
inline-flex
items-center
justify-center
bg-primary
hover:bg-primary/80
h-dimension-xl
rounded-border-radius-md
text-xl
px-xl
"
>
Button XL
</button>

<button
className="
inline-flex
items-center
justify-center
bg-primary
hover:bg-primary/80
h-dimension-l
rounded-border-radius-md
text-l
px-l
"
>
Button L
</button>

<button
className="
inline-flex
items-center
justify-center
bg-primary
hover:bg-primary/80
h-dimension-m
rounded-border-radius-md
text-sm
px-md
hover:text-font-invert/20
text-font-invert/80

"
>
Button Default
</button>

<button
className="
inline-flex
items-center
justify-center
hover:bg-primary
hover:text-font-invert
hover:rounded-full
h-dimension-m
rounded-border-radius-md
border-2
text-sm
text-primary
px-md

"
>
Ghost L
</button>
</main>
);
};

export default Home;

Restart the dev server from the project root folder with yarn dev.
And the page should look like

This is my workflow on how to “Create a Design System with Turborepo, React, Tailwind — connect it to Figma using Tokens/Variables”..
Pixel perfect Figma Design to HTML/CSS

Hot or Not?

🤌🏼 Figma Variables: Feels faster/nativer then TokenStudio. But its missing a lot of design token features. And is per default encapsulated in Figma. Weeird Format if using API. Figma 🙏🏻 plz follow W3C Proposal… Stick to standards!!!. FlexBox, Grid Layout… 🆘 There is not a single browser in the world that uses autolayout. okay!?

🤮 Figma Dev Tool: Complete useless for a Design Token workflow. Too me almost useless. Same to VS Code Plugin. Does this Dev Tool bring the Dev and UI/UX people closer? I don’t think so.

🤙🏼 Turborepo: Faster and super easy to grap up. But it’s Miss a lot of what NX provides. Most missing thang. Watchmode of module files is weird. Personally I will stay with NX (👑 for Design systems / Monorepos )

Tailwind 😍: Okay, the amount of classnames in code is annoying and makes JSX codelines unreadable. But CVA to and ShadcnUI to your rescue makes it 🥰..

Soon on this channel

Create a Design System with NX, React, Tailwind+CVA , Radix/Shadcn UI — connect it to Figma using Figma Token Studio & Style Dictionary.

Part 1 Turbrepo
Part 2 Figma design

Dont forget to 👏

--

--