tailwindcss-variables icon indicating copy to clipboard operation
tailwindcss-variables copied to clipboard

Generate Dynamic Custom Properties in Config

Open secondmanveran opened this issue 10 months ago • 1 comments

Versions:

  • Package Version: 2.6.1
  • Tailwindcss Version: 3.3.3

Question:

I'm trying to create the full suite of Tailwind classes into custom props for a package I'm working on.

I've already created the full color palette which look like so:

:root {
  --colors-inherit: inherit;
  --colors-current: currentColor;
  --colors-transparent: transparent;
  --colors-black: #000;
  --colors-white: #fff;
  --colors-slate-50: #f8fafc;
  --colors-slate-100: #f1f5f9;
  ...
}

Now I want to generate other elements with color props, but I want to use the variable obviously as opposed to the hex code again:

:root {
  --border-black: var(--colors-black);
  --bg-slate-400: var(--colors-slate-400);
  ...
}

It would be supper unproductive to have to change hexes all over the place wherever the color prop is used.

So in my Tailwind Config I have the variables property as a function passing in theme and colors:

variables: (theme, colors) => ({
  DEFAULT: {
    bg: {
      '': ??? // what to do here to loop through colors
    }
  }
})

If I do the following:

bg: {
  '': theme('colors')
}

I'll get all the colors with hex

:root {
  ...
  --bg-slate-400: #94a3b8;
  ...
}

How can I dynamically loop through the colors array and generate vars:

`var(--colors-${color}-${number})`

Thanks

secondmanveran avatar Aug 10 '23 06:08 secondmanveran

I resolved this if anyone else might need this functionality. Add the following function at the end of your Tailwind config:

const refactorColors = themeColors => {
  const colors = {}

  for (const color in themeColors) {
    if (
      color === 'inherit' ||
      color === 'current' ||
      color === 'transparent' ||
      color === 'black' ||
      color === 'white'
    ) {
      colors[color] = `var(--colors-${color})`
    } else {
      for (const number in themeColors[color]) {
        colors[`${color}-${number}`] = `var(--colors-${color}-${number})`
      }
    }
  }

  return colors
}

Then in your variables prop you can call this function, passing in the theme('colors') object.

export default {
  content: ['./src/**/*.{vue,js}'],
  theme: {
    extend: {},
    variables: theme => ({
      DEFAULT: {
        bg: {
          ...refactorColors(theme('colors'))
        }
      }
    })
  },
  plugins: [forms, variablePlugin]
}

This will produce a full list of bg- prefixed colors assigned to the base --color variable.

:root {
  --bg-inherit: var(--colors-inherit);
  --bg-current: var(--colors-current);
  --bg-transparent: var(--colors-transparent);
  --bg-black: var(--colors-black);
  --bg-white: var(--colors-white);
  --bg-slate-50: var(--colors-slate-50);
  --bg-slate-100: var(--colors-slate-100);
  --bg-slate-200: var(--colors-slate-200);
  --bg-slate-300: var(--colors-slate-300);
  --bg-slate-400: var(--colors-slate-400);
  --bg-slate-500: var(--colors-slate-500);
  --bg-slate-600: var(--colors-slate-600);
  --bg-slate-700: var(--colors-slate-700);
  --bg-slate-800: var(--colors-slate-800);
  --bg-slate-900: var(--colors-slate-900);
  --bg-slate-950: var(--colors-slate-950);
  ...
}

Of course you can set any color based custom props by modifying the variable prop.

variables: theme => ({
  DEFAULT: {
    border: {
      ...refactorColors(theme('colors'))
    }
  }
})

Result:

:root {
  --border-inherit: var(--colors-inherit);
  --border-current: var(--colors-current);
  --border-transparent: var(--colors-transparent);
  --border-black: var(--colors-black);
  --border-white: var(--colors-white);
  --border-slate-50: var(--colors-slate-50);
  --border-slate-100: var(--colors-slate-100);
  --border-slate-200: var(--colors-slate-200);
  --border-slate-300: var(--colors-slate-300);
  --border-slate-400: var(--colors-slate-400);
  --border-slate-500: var(--colors-slate-500);
  --border-slate-600: var(--colors-slate-600);
  --border-slate-700: var(--colors-slate-700);
  --border-slate-800: var(--colors-slate-800);
  --border-slate-900: var(--colors-slate-900);
  --border-slate-950: var(--colors-slate-950);
  ...
}

Hopefully it will be useful to someone 😄

secondmanveran avatar Aug 15 '23 20:08 secondmanveran