Figma extractor

How to use themes in your project

Wire generated themes into next-themes and Tailwind

Enable usage of themes

Firstly, you should enable usage of themes in the config. You can enable usage of themes for colors and effects.

Set an array of allowedThemes and a defaultTheme in Config -> styles:

figma-extractor.config.js
module.exports = {
  // ...
  styles: {
    exportPath: './theme',
    allowedThemes: ['light', 'dark'],
    defaultTheme: 'light',
    // ...
  },
};

For more information follow Configuration.

Launch the extractor

After a successful launch of the extractor you will see the created files (click a file to preview its content):

index.ts
vars.css
index.ts
vars.css
index.ts
vars.css
with-vars.ts
index.ts
vars.css
index.ts
vars.css
index.ts
vars.css
with-vars.ts
themes-list.ts
themes-list.ts
/* eslint-disable max-lines */
/* eslint-disable @typescript-eslint/naming-convention */

// THIS FILE IS GENERATED AUTOMATICALLY. DON'T CHANGE IT.

export const DEFAULT_THEME = 'light';

export const THEMES = ['dark', 'light'] as const;

export type Theme = (typeof THEMES)[number];

Install the next-themes package in your project

Generated files can be used with next-themes — a great solution for switching themes.

Include received themes in next-themes

Inside app.tsx you should add the following code:

app.tsx
import { THEMES, DEFAULT_THEME } from '@sh/ui/theme/themes-list';

<ThemeProvider attribute="data-theme" defaultTheme={DEFAULT_THEME} themes={[...THEMES]}>
  {children}
</ThemeProvider>;

Connect the generated theme to Tailwind

These examples target Tailwind CSS 4. The recommended way is to keep a tailwind.config.ts and load it from CSS with the @config directive — it stays a single source of truth and picks up the generated tokens automatically. Mapping the variables inline with @theme inline also works, but it's extra manual work (you list and maintain every token by hand), so reach for it only if you specifically want a config-less setup.

This is the recommended, more idiomatic setup. Keep a tailwind.config.ts that imports the generated with-vars.ts files, and load that config from your CSS with the @config directive — no need to re-declare tokens by hand.

tailwind.config.ts
import { colors } from './theme/colors/with-vars';
import { effects } from './theme/effects/with-vars';

/** @type {import('tailwindcss').Config} */
const config = {
  theme: {
    ...effects,
    colors: {
      transparent: 'transparent',
      current: 'currentColor',
      ...colors,
    },
  },
};

export default config;

Import with-vars.ts, not index.ts. with-vars.ts references the CSS variables so themes switch correctly; index.ts contains raw data from Figma and is only kept for legacy code.

Then, in your global stylesheet, import Tailwind, point it at the config with @config, and import the generated vars.css files (the root theme and every theme):

ui/organisms/global-styles/index.css
@import 'tailwindcss';
@config './tailwind.config.ts';

/* generated variables — :root + one selector per theme */
@import '@sh/ui/theme/colors/vars.css';
@import '@sh/ui/theme/colors/light/vars.css';
@import '@sh/ui/theme/colors/dark/vars.css';

@import '@sh/ui/theme/effects/vars.css';
@import '@sh/ui/theme/effects/light/vars.css';
@import '@sh/ui/theme/effects/dark/vars.css';

The @config path is resolved relative to the CSS file — adjust ./tailwind.config.ts to wherever your config actually lives (for example ../../tailwind.config.ts).

Finish

Now you can use Tailwind classes as usual.

To validate class names against your theme (catch typos and unknown utilities from the generated tokens), add eslint-plugin-tailwindcss to your ESLint config. It lints Tailwind class names — including the custom utilities generated from your Figma variables — so invalid classes are caught during development.

On this page