Skip to content

Conversation

@adamwathan
Copy link
Member

@adamwathan adamwathan commented Sep 4, 2024

This PR adds a new default option to @theme to make it possible for plugins/JS config files to override default theme values, and also ensures that the final set of CSS variables we output takes into account any theme values added by plugins/JS config files.


Previously, if you were using the default theme but also had a JS config file that overrode any of those defaults like this:

// ./tailwind.config.js
export default {
  theme: {
    extend: {
      colors: {
        red: {
          '500': 'tomato',
        },
      }
    }
  }
}

…then utilities like text-red-500 would correctly use color: tomato, but the --color-red-500 CSS variable would still be set to the default value:

:root {
  --color-red-500: #ef4444;
}

This feels like a straight-up bug — if #ef4444 is not part of your design system because you've overridden it, it shouldn't show up in your set of CSS variables anywhere.

So this PR fixes this issue by making sure we don't print the final set of CSS variables until all of your plugins and config files have had a chance to update the theme.


The second issue is that we realized people have different expectations about how plugin/config theme values should interact with Tailwind's default theme vs. explicitly user-configured theme values.

Take this setup for instance:

@import "tailwindcss";
@config "./tailwind.config.js";

If tailwind.config.js overrides red-500 to be tomato, you'd expect text-red-500 to actually be tomato, not the default #ef4444 color.

But in this setup:

@import "tailwindcss";
@config "./tailwind.config.js";
@theme {
  --color-red-500: #f00;
}

…you'd expect text-red-500 to be #f00. This is despite the fact that currently in Tailwind there is no difference here — they are both just @theme blocks, one just happens to be coming from an imported file (@import "tailwindcss").

So to resolve this ambiguity, I've added a default option to @theme for explicitly registering theme values as "defaults" that are safe to override with plugin/JS config theme values:

@import "tailwindcss";
@config "./tailwind.config.js";
@theme default {
  --color-red-500: #f00;
}

Now text-red-500 would be tomato here as per the config file.

This API is not something users are generally going to interact with — they will almost never want to use default explicitly. But in this PR I've updated the default theme we ship with to include default so that it interacts in a more intuitive way with plugins and JS config files.


Finally, this PR makes sure all theme values registered by plugins/configs are registered with isReference: true to make sure they do not end up in the final CSS at all.

This is important to make sure that the super weird shit we used to do in configs in v3 doesn't get translated into nonsense variables that pollute your output (hello typography plugin I'm looking at you).

If we don't do this, you'll end up with CSS variables like this:

:root {
  --typography-sm-css-blockquote-padding-inline-start: 1.25em;
}

Preventing theme values registered in plugins/configs from outputting CSS values also serves the secondary purpose of nudging users to migrate to the CSS config if they do want CSS variables for their theme values.

css`
@theme {
--color-red: red;
--color-orange: orange;
Copy link
Member

Choose a reason for hiding this comment

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

Hm am I the only one who finds it confusing that we manually specify --color-orange here as a theme variable that is not inline and yet, because of the plugin that we import later, it won't be emitted as CSS variable. I understand the reason that we don't want to emit CSS variables for plugins because of the weird names that some plugins use but if we overwrite something that is part of the user configured theme, I would kind of expect the CSS variable to still work (if someone writes a @theme like this, I think they expect var(--color-orange) to work. 🤔

Copy link
Member

@philipp-spiess philipp-spiess left a comment

Choose a reason for hiding this comment

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

LGTM, but left a note inline

@adamwathan adamwathan changed the title Process plugins before outputting theme variables in CSS Add default option to @theme to support overriding default theme values from plugins/JS config files Sep 4, 2024
@adamwathan adamwathan force-pushed the fix/render-theme-after-plugins branch from 02985d6 to 7bdc665 Compare September 4, 2024 15:33
@philipp-spiess philipp-spiess self-requested a review September 4, 2024 15:41
@adamwathan adamwathan merged commit d6a67be into next Sep 4, 2024
@adamwathan adamwathan deleted the fix/render-theme-after-plugins branch September 4, 2024 15:49
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.

5 participants