AnJ
AnJ

Reputation: 614

Tailwind - custom class combined with nested color pallet

I want to write a custom class, that would apply set of styles, but I want to be able to use it together with a color for the theme. It will probably easier to explain it by example.

So for example if we want to set background to a certain color we would add class like this:

<div class="bg-red">

And instead of background I would like to have my own custom class, that would apply new set of styles, but which I can still use together with a color:

<div class="custom-red">

So I started experimenting with Tailwind plugins and components. I wrote plugin like this:

function ({ matchComponents, theme }) {
  const getStyles = (color) => {
    return {
      position: 'relative',
      '&::before': {
        backgroundColor: color
        // ...
      }
    };
  };

  matchComponents({
    testbg: (value) => getStyles(value)
  }, {
    values: theme('colors')
  });
}

And it almost worked. I mean it is working for simple color like red. But my color pallet is more complex and nested.

theme: {
   colors: {
      primary: {
         DEFAULT: '#....'
         5: '#....'
         10: '#....'
         50: '#....'
      },
      secondary: {
         5: '#....'
         10: '#....'
      },
      red: '#....'
   }
}

And sadly it didn't generate all color possibilities. It just took the "shallow" keys of the colors and generated classes like custom-primary, custom-secondary, custom-red. But there is no custom-primary-5 for example.

So is there a straightforward way of doing it? I guess I could manually parse colors from theme and recursively go through the object and create separate component for each. But this seems like a completely weird thing to do, as the stuff I'm trying to do seems like a really basic use case for a tool like Tailwind.

Upvotes: 0

Views: 52

Answers (1)

Wongjn
Wongjn

Reputation: 24408

Tailwind provides a flattenColorPalette() function that helps you flatten the object structure into a flat dictionary. This should then work with any level of color value nesting.

const plugin = require("tailwindcss/plugin");
const { default: flattenColorPalette } = require("tailwindcss/lib/util/flattenColorPalette");

module.exports = {
  …
  plugins: [
    plugin(function ({ matchComponents, theme }) {
      const getStyles = (color) => {
        //  …
      };

      matchComponents({
        testbg: (value) => getStyles(value)
      }, {
        values: flattenColorPalette(theme('colors')),
      });
    }),
  ],
}

Upvotes: 1

Related Questions