Skip to content

Conversation

MattStypa
Copy link
Contributor

@MattStypa MattStypa commented Mar 13, 2019

Overview

Tailwind will now export resolved default configuration allowing users to more intuitively extend the theme.

const defaultConfig = require('tailwindcss/defaultConfig')

module.exports = {
  // ...
  theme: {
    borderWidths: {
      ...defaultConfig.theme.borderWidths,
      '10': '10px',
      '12': '12px',
    },
  }
}

Currently, users have to use the special extend section of the theme object to accomplish this.

module.exports = {
  theme: {

    // Completely replaced values:
    colors: {
      // User's custom color palette
    },
    fonts: {
      // User's custom font stack
    },

    // Values that extend the defaults with a few extras:
    extend: {
      shadows: {
        xl: '0 25px 40px 0 rgba(0,0,0,0.11), 0 10px 20px 0 rgba(0,0,0,0.05)',
      },
      opacity: {
        '60': '.6',
      }
    },
  },
}

Resolving of the computed values

Previously, only root level values would be resolved. I changed the resolution logic to be recursive as I feel it is more intuitive and easier to explain in documentation.

Note on the new dependency

I created a new NPM module for this specific purpose and added it as a dependency. This solves the issue of maintaining none ES6 code in an ES6 codebase.

The resolution of the default configuration needs to be accessible before babelification to allow projects depending on Tailwind to properly import it. Additionally, Tailwind needs to use the same code when resolving user-provided configuration files. By moving the bulk of the generic code into a separate package, we don't have to run code from outside of the src directory or put none ES6 code in the src directory.

}

const getConfigFunction = config => () => {
if (_.isUndefined(config) && !_.isObject(config)) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The 2nd part of this conditional is unnecessary. An undefined variable will never be an object.

@adamwathan
Copy link
Member

I don't think it's possible to match the functionality of the extend key using the spread operator, I went down this road at first as well before finding situations where it was a lot easier on the end user if we handled the merging for them intuitively.

For example, say this is the default config:

{
  theme: {
    spacing: {
      0: '0px',
      1: '10px',
      2: '20px',
      3: '30px',
    },
    width: ({ spacing }) => ({
      ...spacing,
      '1/4': '25%',
      '1/2': '50%',
      '3/4': '75%',
    })
  }
}

If the user provides this config:

{ 
  theme: {
    extend: {
      spacing: {
        custom: '999px',
      },
      width: {
        otherCustom: '111px',
      },
    },
  },
}

The resolved config would be this:

{
  theme: {
    spacing: {
      0: '0px',
      1: '10px',
      2: '20px',
      3: '30px',
      custom: '999px',
    },
    width: {
      0: '0px',
      1: '10px',
      2: '20px',
      3: '30px',
      custom: '999px',
      '1/4': '25%',
      '1/2': '50%',
      '3/4': '75%',
      otherCustom: '111px',
    }
  }
}

Trying to accomplish this same thing using the spread operator means the end user has to do something like this:

const defaultConfig = require('tailwindcss/defaultConfig')

module.exports = { 
  theme: {
    spacing: {
      ...defaultConfig.spacing,
      custom: '999px',
    },
    width: ({ spacing }) => {
      ...spacing,
      ...defaultConfig.width,
      otherCustom: '111px',
    },
  },
}

...which would result in all of the spacing keys actually being double declared inside the width object, which seems gross even though it doesn't really matter.

Also, I don't know for sure, but I don't think it's safe for us to export the actual default config as an object because modules are singletons, so if the user mutates the config it's going to mean when we import the default config in other places in Tailwind (like as part of processing @apply rules) we will get the mutated version, which is likely not what we want.

@MattStypa MattStypa closed this Mar 13, 2019
@MattStypa
Copy link
Contributor Author

@adamwathan Thank you for taking the time to explain this.

This initiative was a result of some of the issues I encountered updating the CLI toolset.

This explanation will help me avoid going down the wrong path.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants