-
Notifications
You must be signed in to change notification settings - Fork 4.6k
Restructure config file for 1.0 #637
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
Conversation
Temporary intermediate step.
Modules key no longer actually exists in the config so this is pointless.
Eventually users won't even be able to generate this file this way, so these comments just aren't valuable to store anymore.
The only thing I don't like about this is that I can no longer peek into my tailwind configuration to check what width values do I have, etc. |
All the changes look pretty fine and make the entire config file more readable since it is now better structured. Also, the entire PR description explains the changes understandable. All in all, great job! 👏 What I haven't understood entirely is how one would unset certain values. Like, if the default config has margin styles, but I don't want them in my stylesheet, how would I accomplish that? Do I have to do a |
@rathesDot it seems to me like you could just do module.exports = {
theme: {
// This will completely replace the default margin values
margin: {},
},
} @m1guelpf You could just go look at the default tailwind config that will be inside the package right? If you set any custom ones it would work the exact same as it does now, just go look in your config, but if you don't set them explicitly, they will just be whatever the defaults are. |
@JacobBennett I think @m1guelpf's point was he could just open This isn't such a huge issue if you use an IDE. I can jump to the declaration of Either way, you could still keep your config file as a clone (plus your changes) of the default config if you wanted to. That's the beauty of Tailwind. 😃 There are some extremely well-thought-out defaults set. Keep them all, add to them, or change everything. That's up to you to decide. |
Love the new style, all the changes make a lot of sense to me and I can't see any problems other than what's already been pointed out, the agonising over getting it right really paid off 👍🏻 I completely echo @m1guelpf's thoughts on how it'd be a bit less convenient to have to go between two files to find values. I imagine it would be fairly simple to have some tooling build up the combined config file into something viewable for the sake of development though, so it's not a huge concern. |
@JacobBennett That is another approach, but it feels wrong to me to add stuff to your config to actually remove stuff. A solution would be to have an option that allows disabling the default-fallback. Then Tailwind would only generate styles from the given values. I think that this option could also help @m1guelpf's concern. You could then easily copy the default file to your own, disable the fallback and then work in the way as it does right now as well. |
Maybe this is the right moment to think about responsive values? In my projects I'm very often use values in the tailwind-config with css-variables defined in a seperate css file. So its possible to change e.g. the text-size or margins and paddings depending on breakpoints. Thinking of component-spaces for me it is very useful if I have to change the padding of all components on a higher breakpoint. Or thinking of text-sizes. You always have to change the text-size of your headlines for smaller screens. Or 'text-xs' is too small for mobile. If you restructure the config file now maybe there is a way to do this in the configuration? |
Thanks everyone for the feedback so far!
@m1guelpf: This is a totally valid concern and is one of the biggest trade-offs in taking this approach. What made me more comfortable with it was realizing that there are a whole host of other classes in Tailwind that you can't learn from your config file, and that you would have to consult the documentation for anyways, like all of the whitespace classes, overflow classes, text decoration classes, etc. My hope is that if you are relying on the defaults, you will eventually just learn them and not have to reference any of those values in the docs anyways, and if you are not relying on the defaults, then your custom values will be right there in your config file just like they always were. I am pretty convinced we'll include some sort of Based on the number of 👍 reactions it looks like a lot of other people have this same hesitation, so please let me know if what I said eases your concerns or if you have any other thoughts.
@rathesDot: Hey! So the recommend approach to disable the margin classes entirely is to disable the module.exports = {
// ...
corePlugins: {
margin: false,
}
} This is really similar to how you would disable it already in Tailwind 0.x, except now you do it in
@rathesDot: I totally understand this feeling, and my first iterations of the new config file format actually had all of the core plugins listed right in the Plus the config file looked like a complete disaster: https://gist.github.com/adamwathan/569cf056631950ff0eda7f4b50240e98 |
@adamwathan Even though I'm not entirely convinced, I understand your reasoning! Thanks for the explanation! For me it isn't a big hassle, it just felt strange. But I'm pretty sure that I won't notice that anymore once I get used to the new config file! Also, a big hand for the awesome work! |
Hey @adamwathan, I think the answer to this is to do sort of what |
This would also be a great moment for someone to release a way to generate custom documentation from your tailwind config 😉 |
tailwind print-config theme.colors |
Extending from what @aparajita suggested, I think some sort of API for this would be great, not only for people who want to get a visual "tree" of their config, but also to help plugin developers. One of the biggest benefits for me of the current config is it's really easy to parse the config and know what the output is going to look like. Config looks really good though, I love the simplicity of it 😍 |
I like @aparajita's suggestion, but that sounds for me like a Nice-To-Have that can be perfectly added after the config was released as it is proposed in this PR... |
@@ -18,14 +18,12 @@ describe('cli', () => { | |||
it('creates a Tailwind config file', () => { | |||
return cli(['init']).then(() => { | |||
expect(utils.writeFile.mock.calls[0][0]).toEqual(constants.defaultConfigFile) | |||
expect(utils.writeFile.mock.calls[0][1]).toContain('defaultConfig') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What do you think about checking for defaultTheme
instead of dropping this assertion?
expect(utils.writeFile.mock.calls[0][1]).toContain('defaultTheme')
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure what I even want to scaffold for the config file when people use tailwind init
yet so just gonna punt on it entirely for now I think.
Going to merge this for now as I have a bunch of other stuff I'm working on that depends on it, still time to make changes if necessary though. |
What happens when you extend the default themes and use keys already set by the defaultTheme? They still override the default or would you get some duplicate keys - errors?
It feels like a lot of work if I have to manually check if all the values I want to override exist in the default config or not. Sharing the concerns of @m1guelpf. Think the |
@jan-dh It's just javascript, so if you do it in that order, you override the defaults. |
Little typo in Item 7.
should be
|
This PR changes some decisions about the config file structure that we never would have made had we known that eventually we would be adding the
modules
key and theoptions
key.TL;DR: Some sections have moved or been renamed, and we are going to start encouraging people to keep their config files much simpler and inherit our defaults unless they explicitly want to override or extend them.
Example of what a new Tailwind config file might look like:
Many thanks to @reinink, @samselikoff, @taylorotwell, @derrickreimer, @davidhemphill, and @jasonmccreary for putting up with my incessant badgering, whining, desperate requests for feedback and border-line depression trying to make this not suck over the last three weeks. You don't even want to see all of the iterations this went through 😩
How the config file structure has changed
Options are now top-level.
The
options
key as been removed and theseparator
,prefix
, andimportant
options are now top-level keys in the config file:This is part of a larger vision where the config file is truly more of a config file, and details about your design system are just a specific part of that rather than the top-level focus. Think of it more like a
postcss.config.js
or ababel.config.js
file — a bunch of options for configuring Tailwind the tool, where your styles are just one part of that.Style-related options have moved to a new
theme
section.All of the top-level options related to your design system (
screens
,colors
,fonts
,backgroundColors
,padding
,margin
, etc) have been nested inside a newtheme
section.After introducing the
modules
,options
, andplugins
sections, it felt very off to have all of the style options be direct siblings of options that were much more configuration-ish.It also made things look a bit weird if you (like many) kept your style-related configuration in other files, because you need to spread your styles into the configuration at the top-level:
With everything nested underneath the new
theme
section, the example above would look like this:Not a huge difference, but conceptually I think it makes a lot more sense for those options to be grouped together instead of all sitting at the top-level alongside things like
options
andmodules
.Your
theme
section is merged with the defaulttheme
values.Tailwind already works this way in 0.x, but it's worth noting here for clarity.
You can leave your
theme
section completely empty and your build will just use Tailwind's default values.If you provide any keys, those keys will override the default values.
To extend any of Tailwind's defaults, you can grab the default values from
tailwindcss/defaultTheme
and spread them in:Note that the
tailwindcss/defaultTheme
module exports a function that returns the default theme (to avoid accidental mutation).Based on a lot of user interviews I've done over the last few weeks and a poll I conducted on Twitter, I learned that a lot of people really value having Tailwind provide well-considered default values.
So for v1.0, we are going to take a bit of a more opinionated stance and encourage partial customization of the default config by just overriding and extending the parts you want to change instead of publishing the entire default config by default for you to own and manipulate.
Everything of course will still be as customizable as ever, but the hope is that most people's config files will end up being much shorter/simpler, and serve just as a reference for the user's customizations, rather than having all of the defaults and their customizations combined into one giant file, where it's hard to tell what came with Tailwind out of the box vs. what was added by the user.
The
modules
section has been renamed tovariants
."Modules" was a word we just kinda grabbed because we needed something, and we wanted to use that section of the config to both specify variants and disable modules if necessary.
Now that all of Tailwind's internal "modules" are actually just core plugins, I want to deprecate this terminology entirely, and make this section of the config purely about configuring variants for core plugins.
Your
variants
section is merged with the defaultvariants
values.Just like the
theme
section, you only need to provide values for thevariants
you'd like to override.If you are fine with the defaults, you don't even need to provide the key.
To add
hover
variants toopacity
for example, you'd just add theopacity
key and list the variants you want to generate:It's important to note that whatever you provide overrides the default value, it's not merged. So to add a
hover
variant toopacity
, you need to re-specify theresponsive
variant too, unless of course you don't want to generate it.We may make it easier to simply extend this configuration later, but I don't think this will be a real pain point for anyone in practice.
Modules are disabled in the
corePlugins
section, not thevariants
section.Instead of setting a
modulecore plugin tofalse
in thevariants
section of your config to disable it, you now set that plugin tofalse
in a newcorePlugins
section of the config:The motivation behind this is that in the near future, I plan to rewrite our
preflight
styles as a core plugin as well, and if users want to disable preflight, doing so in thevariants
section of the config makes no sense because there's no way to add "responsive" or "hover" versions of preflight.We may also move the
container
plugin back to being a true "core plugin" instead of just a third-party plugin that happens to be in the same repository, so this change is also important in order for people to disable that plugin if we make that change.Overall, it just makes sense that disabling core plugins is divorced from variant configuration, because the idea of variants isn't relevant for every core plugin.
Core plugins can be configured directly through the
corePlugins
section.In Convert built-in utility modules to private plugins #620, all of Tailwind's built-in modules were rewritten to use the plugin system, so there is no difference between the code we write to add new core functionality to Tailwind and the code that someone might write when authoring a third-party plugin.
Part of this included each plugin becoming directly configurable (for Tailwind's benefit internally), much like a third-party plugin would be.
Essentially, there's no reason you couldn't disable a core plugin, then re-introduce it by adding it your
plugins
key and passing it the appropriate configuration:In addition to allowing you to disable core plugins, the
corePlugins
key also allows you to completely override a core plugin's configuration, by providing a configuration object for that plugin.This example does exactly the same thing as the previous example:
There's essentially no reason at all to do this currently (it's much simpler to configure a core plugin through the
variants
andtheme
keys), but designing the configuration file this way means it could be possible to pass advanced configuration options to core plugins in the future that might not be exposed through thetheme
section.For example, perhaps the
margin
plugin could expose an additional option to let you customize the class names tomargin-{side}-{size}
instead of the defaultm{size}-{size}
syntax:I don't have concrete plans to introduce features like this to the core plugins, but designing the config file this way at least makes it possible.
Every section is optional, as is the entire config file.
As I alluded to in point 3, one of the main themes for Tailwind v1.0 is going to be doubling down on the defaults and shouldering more of the burden for making sure the default values are awesome.
Until now, it's been easy to tell people "just customize it in your config" if they weren't happy with a default value. Going forward, I'd like to try even harder to make the defaults as widely usable as possible so that customization because more of an escape hatch than a mandatory step in using Tailwind.
As I mentioned before, there are no plans to make it harder or impossible to customize any of the things you can currently customize — being able to customize things is the whole reason I created the framework! But rather than sending the message of "you own every value the framework uses, customize the hell out of it", I want to start saying "we've worked really hard to give you the best possible starting point we could create, but if you need to change or extend the framework in any way, it's easy to do".
Certain things are going to be very commonly completely replaced, like colors and fonts. But we should be able to make most of the other stuff suitable for just about any project right out of the box. Sure you might need to add an extra margin or padding value here and there, but in general you should be able to rely on our defaults and get pretty far.
All that to say, in this config file, every single key is optional. You don't even need to provide a config file at all if you don't want:
All of this is already true in Tailwind 0.x for what it's worth, but most people don't use Tailwind this way because it's not the path we encourage.
So in a future PR, the
tailwind init
command will be changing as well, to create a much more minimal config file by default, with perhaps an extra flag you can pass if you want to generate the entire thing (like atailwind init --eject
or something) and not inherit the default values at all.Upgrade path
This is a pretty significant breaking change with two components:
You'll need to update your config file.
This is the obvious one, and it's very easy because it just involves renaming
modules
tovariants
, moving anyfalse
values inmodules
to thecorePlugins
section, and nesting all of your style configuration under the newtheme
key. Minor annoyance but 10 minutes of effort, and we can probably write a tool to upgrade it for you automatically.You need to tweak any uses of the config() function in your custom CSS.
This is the more annoying part. Previously you could get access to one of your colors for example by using
config('colors.red')
. Now that colors are nested under thetheme
section, you need to update those references toconfig('theme.colors.red')
. There's a good chance I introduce a newtheme()
function you can use in your CSS that is automatically scoped to the theme section, and that should make this update easier.If anyone is actually using
config()
to access things like prefix, separator, important, or variant configuration, I'd love to know. I can't think of any good reason to ever do that, so we may even deprecate theconfig()
function entirely in favor thetheme()
function I proposed above.