Skip to content

Commit

Permalink
feat: introduce theming capabilities (#4474)
Browse files Browse the repository at this point in the history
Co-authored-by: Pavel Denisjuk <[email protected]>
  • Loading branch information
adrians5j and Pavel910 authored Jan 21, 2025
1 parent 9707cc2 commit f24eea6
Show file tree
Hide file tree
Showing 27 changed files with 3,053 additions and 515 deletions.
5 changes: 1 addition & 4 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,5 @@ lerna.json
.stormTests
*storybook.log
.normalizedFigmaExport.json

# TODO remove after moving traffic splitting config to WPC
gateway.*.json

.normalizedPrimitivesFigmaExport.json
packages/tasks/tpl/*
13 changes: 10 additions & 3 deletions packages/admin-ui/DEVELOPMENT.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,19 @@ One of the main things we define via the [`tailwind.config.js`](./tailwind.confi
But, do note that all the default theme-values are not actually defined in the `tailwind.config.js` file, but rather in the `tailwind.config.theme.js` file, which is a file that is generated from a Figma export (more on this in the next section).

### Figma To Code
Since manually transferring values from the mentioned Figma file into code has shown to be a very cumbersome process, we've created a script that basically takes a Figma export and generates all the necessary Tailwind CSS configuration. Note that when we say "Figma export", we basically mean an export of Alias tokens, created by this [Export/Import Variables](https://www.figma.com/community/plugin/1256972111705530093/export-import-variables) plugin.
Since manually transferring values from the mentioned Figma file into code has shown to be a very cumbersome process, we've created a script that basically takes a Figma export and generates all the necessary Tailwind CSS configuration.

Once the export is downloaded, we place it in `packages/admin-ui/scripts/importFromFigma/exports/Alias tokens.json`, and then we run the following command from project root:
When we say "Figma export", we basically mean exports of (1) Primitives and (2) Alias tokens, which are created by this [Export/Import Variables](https://www.figma.com/community/plugin/1256972111705530093/export-import-variables) plugin.

The exports need to be downloaded and place into the `packages/admin-ui/scripts/importFromFigma/exports` folder. Ultimately, we should end up with the following two:

1. `packages/admin-ui/scripts/importFromFigma/exports/Alias tokens.json`
2. `packages/admin-ui/scripts/importFromFigma/exports/Primitives.json`

Finally, from project root, we run the following script:

```bash
yarn webiny-admin-import-from-figma
```

This will generate a new `tailwind.config.theme.js` file, which will contain all the necessary Tailwind CSS configuration. On top of that, it will also generate a `src/styles.scss` file, which contains actual values for CSS variables that are referenced in the `tailwind.config.theme.js` file.
First, the script will regenerate the `tailwind.config.theme.js` file, which will contain all the necessary Tailwind CSS configuration. Second, it will also regenerate the `src/styles.scss` file, which contains actual values for CSS variables that are referenced in the `tailwind.config.theme.js` file.
1 change: 0 additions & 1 deletion packages/admin-ui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,6 @@
"rimraf": "^5.0.5",
"sass": "1.44.0",
"storybook": "7.6.20",
"tailwindcss": "^3.4.6",
"ttypescript": "^1.5.12",
"typescript": "4.9.5"
},
Expand Down
18 changes: 15 additions & 3 deletions packages/admin-ui/scripts/importFromFigma.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
const fs = require("fs");
const { green } = require("chalk");
const path = require("path");
const aliasTokensExport = require("./importFromFigma/exports/Alias tokens.json");
const { normalizeFigmaExport } = require("./importFromFigma/normalizeFigmaExport");
const {
normalizePrimitivesFigmaExport
} = require("./importFromFigma/normalizePrimitivesFigmaExport");
const { createTailwindConfigTheme } = require("./importFromFigma/createTailwindConfigTheme");
const { createThemeScss } = require("./importFromFigma/createThemeScss");
const { formatCode } = require("./importFromFigma/formatCode");
Expand All @@ -13,13 +15,18 @@ const saveFileAndFormat = async (filePath, content) => {
};

(async () => {
const normalizedFigmaExport = normalizeFigmaExport(aliasTokensExport);
const normalizedFigmaExport = normalizeFigmaExport();
const normalizedPrimitivesFigmaExport = normalizePrimitivesFigmaExport();
const tailwindConfigTheme = createTailwindConfigTheme(normalizedFigmaExport);
const stylesScss = createThemeScss(normalizedFigmaExport, tailwindConfigTheme);
const stylesScss = createThemeScss(normalizedFigmaExport, normalizedPrimitivesFigmaExport);

const paths = {
cwd: process.cwd(),
normalizedFigmaExport: path.join(__dirname, "../.normalizedFigmaExport.json"),
normalizedPrimitivesFigmaExport: path.join(
__dirname,
"../.normalizedPrimitivesFigmaExport.json"
),
createTailwindConfigTheme: path.join(__dirname, "../tailwind.config.theme.js"),
stylesScss: path.join(__dirname, "../src/theme.scss")
};
Expand All @@ -42,6 +49,11 @@ const saveFileAndFormat = async (filePath, content) => {
JSON.stringify(normalizedFigmaExport, null, 2)
);

await saveFileAndFormat(
paths.normalizedPrimitivesFigmaExport,
JSON.stringify(normalizedPrimitivesFigmaExport, null, 2)
);

await saveFileAndFormat(
paths.createTailwindConfigTheme,
`module.exports = ${JSON.stringify(tailwindConfigTheme, null, 2)};`
Expand Down
54 changes: 48 additions & 6 deletions packages/admin-ui/scripts/importFromFigma/createThemeScss.js
Original file line number Diff line number Diff line change
@@ -1,17 +1,51 @@
const fs = require("fs");

const createThemeScss = normalizedFigmaExport => {
// We don't need tokens that end with `-a{one or two numbers}` because they are used for
// alpha colors. We don't need these because we can use the /alpha function in Tailwind CSS.
const isColorWithAlpha = variantName => {
return variantName.match(/^.*-a\d{1,2}$/);
};

const createThemeScss = (normalizedFigmaExport, normalizedPrimitivesFigmaExport) => {
// Generate `theme.scss` file.
let stylesScss = fs.readFileSync(__dirname + "/templates/theme.scss.txt", "utf8");

// 0. Colors
{
let currentBgColorGroup = null;
const bgColors = normalizedPrimitivesFigmaExport
.filter(item => item.type === "colors")
.map(variable => {
const [colorGroup] = variable.variantName.split("-");
const cssVar = `--color-${variable.variantName}: ${variable.hsla.h} ${variable.hsla.s}% ${variable.hsla.l}%;`;

if (!currentBgColorGroup) {
currentBgColorGroup = colorGroup;
return cssVar;
}

if (!currentBgColorGroup || currentBgColorGroup !== colorGroup) {
currentBgColorGroup = colorGroup;
return ["", cssVar];
}
return cssVar;
})
.flat()
.reverse();

stylesScss = stylesScss.replace("{COLORS}", bgColors.join("\n"));
}

// 1. Background color.
{
let currentBgColorGroup = null;
const bgColors = normalizedFigmaExport
.filter(item => item.type === "backgroundColor")
.filter(variable => !isColorWithAlpha(variable.variantName))
.map(variable => {
const [colorGroup] = variable.variantName.split("-");
const cssVar = `--bg-${variable.variantName}: ${variable.hsla.h} ${variable.hsla.s}% ${variable.hsla.l}%;`;
const cssVarName = variable.aliasName.replace("colors/colors-", "color-");
const cssVar = `--bg-${variable.variantName}: var(--${cssVarName});`;

if (!currentBgColorGroup) {
currentBgColorGroup = colorGroup;
Expand All @@ -34,9 +68,11 @@ const createThemeScss = normalizedFigmaExport => {
let currentBorderColor = null;
const borderColors = normalizedFigmaExport
.filter(item => item.type === "borderColor")
.filter(variable => !isColorWithAlpha(variable.variantName))
.map(variable => {
const [colorGroup] = variable.variantName.split("-");
const cssVar = `--border-${variable.variantName}: ${variable.hsla.h} ${variable.hsla.s}% ${variable.hsla.l}%;`;
const cssVarName = variable.aliasName.replace("colors/colors-", "color-");
const cssVar = `--border-${variable.variantName}: var(--${cssVarName});`;

if (!currentBorderColor) {
currentBorderColor = colorGroup;
Expand Down Expand Up @@ -81,9 +117,11 @@ const createThemeScss = normalizedFigmaExport => {
let currentFillColorGroup = null;
const fillColors = normalizedFigmaExport
.filter(item => item.type === "fill")
.filter(variable => !isColorWithAlpha(variable.variantName))
.map(variable => {
const [colorGroup] = variable.variantName.split("-");
const cssVar = `--fill-${variable.variantName}: ${variable.hsla.h} ${variable.hsla.s}% ${variable.hsla.l}%;`;
const cssVarName = variable.aliasName.replace("colors/colors-", "color-");
const cssVar = `--fill-${variable.variantName}: var(--${cssVarName});`;

if (!currentFillColorGroup) {
currentFillColorGroup = colorGroup;
Expand Down Expand Up @@ -139,9 +177,11 @@ const createThemeScss = normalizedFigmaExport => {
let currentRingColorGroup = null;
const ringColors = normalizedFigmaExport
.filter(item => item.type === "ringColor")
.filter(variable => !isColorWithAlpha(variable.variantName))
.map(variable => {
const [colorGroup] = variable.variantName.split("-");
const cssVar = `--ring-${variable.variantName}: ${variable.hsla.h} ${variable.hsla.s}% ${variable.hsla.l}%;`;
const cssVarName = variable.aliasName.replace("colors/colors-", "color-");
const cssVar = `--ring-${variable.variantName}: var(--${cssVarName});`;

if (!currentRingColorGroup) {
currentRingColorGroup = colorGroup;
Expand Down Expand Up @@ -191,9 +231,11 @@ const createThemeScss = normalizedFigmaExport => {
let currentTextColor = null;
const textColors = normalizedFigmaExport
.filter(item => item.type === "textColor")
.filter(variable => !isColorWithAlpha(variable.variantName))
.map(variable => {
const [colorGroup] = variable.variantName.split("-");
const cssVar = `--text-${variable.variantName}: ${variable.hsla.h} ${variable.hsla.s}% ${variable.hsla.l}%;`;
const cssVarName = variable.aliasName.replace("colors/colors-", "color-");
const cssVar = `--text-${variable.variantName}: var(--${cssVarName});`;

if (!currentTextColor) {
currentTextColor = colorGroup;
Expand Down

Large diffs are not rendered by default.

Loading

0 comments on commit f24eea6

Please sign in to comment.