Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merge extend objects deeply by default #2679

Merged
merged 1 commit into from
Oct 26, 2020
Merged

Conversation

RobinMalfait
Copy link
Member

@RobinMalfait RobinMalfait commented Oct 26, 2020

Description by @adamwathan


This PR changes how the extend behavior under theme works by default, and merges extensions deeply/recursively instead of shallowly.

Here's a simple example — given this input:

module.exports = {
  theme: {
    extend: {
      colors: {
        red: {
          450: '#f45d5d'
        }
      }
    }
  }
}

...historically, you'd get this output:

module.exports = {
  theme: {
    colors: {
      // ...
      red: {
        450: '#f45d5d'
      }
    }
  }
}

All of the red values would be gone, only 450 would exist because the new red object replaced the entire old red object.

After this PR, you'd get this output:

module.exports = {
  theme: {
    colors: {
      // ...
      red: {
        50: '#fef2f2',
        100: '#fee2e2',
        200: '#fecaca',
        300: '#fca5a5',
        450: '#f45d5d'
        400: '#f87171',
        500: '#ef4444',
        600: '#dc2626',
        700: '#b91c1c',
        800: '#991b1b',
        900: '#7f1d1d',
      },
    }
  }
}

...where 450 is merged with the existing object.

This is a breaking change because some people might be depending on this behavior, especially third-party plugins that might have been authored with this behavior in mind when designing their own customization API.

This is one of the most common problems people run into when trying to do stuff like this in their config file though, so we think it's worth it to correct this default.

If someone did want to replace the entire color red after this PR is merged, they could still do so using one of two ways:

1. Replace all of the same sub-values

If your new color uses the same 50900 scale as the built-in color, then things will just work:

module.exports = {
  theme: {
    extend: {
      colors: {
        red: {
          50: '#fef3f2',
          100: '#fee3e2',
          200: '#fedaca',
          300: '#fca6a5',
          400: '#f97171',
          500: '#ef5444',
          600: '#dd2626',
          700: '#ba1c1c',
          800: '#9a1b1b',
          900: '#7f2d1d',
        }
      }
    }
  }
}

2. Replace the color without using extend

If you want to use a different naming scheme, don't use extend at all when overriding the values:

module.exports = {
  theme: {
    colors: {
      red: {
        lightest: '#fef3f2',
        lighter: '#fedaca',
        light: '#f97171',
        DEFAULT: '#ef5444',
        dark: '#dd2626',
        darker: '#9a1b1b',
        darkest: '#7f2d1d',
      }
    }
  }
}

This will override all of the colors so you will have to redefine each one you need, but you can do that like so:

const defaultTheme = require('tailwindcss/defaultTheme')

module.exports = {
  theme: {
    colors: {
      ...defaultTheme.colors,
      red: {
        lightest: '#fef3f2',
        lighter: '#fedaca',
        light: '#f97171',
        DEFAULT: '#ef5444',
        dark: '#dd2626',
        darker: '#9a1b1b',
        darkest: '#7f2d1d',
      }
    }
  }
}

If you are renaming everything like this though you are likely already replacing all of the colors so this won't even be an issue.


Colors are the only place where this is applicable in the default theme (arrays like in fontFamily are not deep merged), so we don't expect this will really have a big impact. If anything, I expect most people are already working around this by doing stuff like this:

const defaultTheme = require('tailwindcss/defaultTheme')

module.exports = {
  theme: {
    extend: {
      colors: {
        red: {
          ...defaultTheme.colors.red,
          450: '#f45d5d'
        }
      }
    }
  }
}

...so they'll actually be able to just delete some of that workaround code that is no longer necessary.

@adamwathan adamwathan changed the title add the ability to deep merge extended configs Merge extend objects deeply by default Oct 26, 2020
@adamwathan adamwathan merged commit 09d9262 into master Oct 26, 2020
@adamwathan adamwathan deleted the deep-merge-config branch October 26, 2020 15:15
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