-
Notifications
You must be signed in to change notification settings - Fork 4.3k
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
Add support for inline
option when defining @theme
values
#14095
Conversation
Destructuring works, but it's creating an unnecessary array. We are currently interested in whether the `inline` and/or `reference` values exist in the `themeOptions` list. We already know that the very first item is going to be `@theme`, so we can skip over that by providing the `fromIndex` when using `.includes(value, fromIndex)`
function parseThemeOptions(selector: string) { | ||
let isReference = false | ||
let isInline = false | ||
|
||
for (let option of segment(selector.slice(6) /* '@theme'.length */, ' ')) { | ||
if (option === 'reference') { | ||
isReference = true | ||
} else if (option === 'inline') { | ||
isInline = true | ||
} | ||
} | ||
|
||
return { isReference, isInline } | ||
} | ||
|
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.
@RobinMalfait Decided to extract this function because the work was being done twice, and themeOptions
didn't feel like a good name for an array that contained:
['@theme', 'reference', 'inline']
Refactored to a for
loop to avoid the extra loop that calling includes
twice would incur, but admittedly sad it's more code.
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.
Nice, makes sense.
One potential thing we can do is if both options are true
early return because there is no need to keep looping if everything is found already. But since @theme
is so specific to Tailwind, there is no need for that optimization (yet).
It is possible to apply The use case is NativeWind which is a JS implementation of CSS for React Native. While it can handle the CSS variables used in the theme, it would be more performant to inline them. The workaround currently is to either use |
This PR adds support for a new
inline
option when defining a@theme
block that tells Tailwind to use raw theme values for utilities instead of referencing the corresponding generated CSS variable.This can be composed with the existing
reference
option in case you want to define a@theme
block as bothreference
(so the variables aren't generated) andinline
:Since you can have multiple
@theme
blocks, you can even define some values normally and some as inline based on how you're using them. For example you might want to useinline
for defining literal tokens like--color-red-500
, but include the variable for tokens that you want to be able to theme like--color-primary
:Breaking changes
Prior to this PR, you could
@import
a stylesheet that contained@theme
blocks as reference by adding thereference
keyword to your import:Now that
reference
isn't the only possible option when declaring your@theme
, this syntax has changed to a newtheme(…)
function that acceptsreference
andinline
as potential space-separated values:If you are using the
@import … reference
option with an earlier alpha release, you'll need to update your code to@import … theme(reference)
once this PR lands in a release.Motivation
This PR is designed to solve an issue pointed out in #14091.
Prior to this PR, generated utilities would always reference variables directly, with the raw value as a fallback:
But this can create issues with variables resolving to an unexpected value when a theme value is referencing another variable defined on
:root
.For example, say you have a CSS file like this:
Without
@theme inline
, we'd generate this output if you used thetext-fg
utility:Now if you wrote this HTML, you're probably expecting your text to be the dark mode color:
But you'd actually get the light mode color because of this rule:
The browser will try to resolve the
--color-fg
variable, which is defined on:root
. When it tries to resolve the value, it uses the value ofvar(--text-fg)
as it would resolve at:root
, not what it would resolve to based on the element that has thetext-fg
class.So
var(--color-fg)
resolves to#000
becausevar(--text-fg)
resolved to#000
at the point in the tree where the browser resolved the value ofvar(--color-fg)
.By using
@theme inline
, the.text-fg
class looks like this:With this definition, the browser doesn't try to resolve
--color-fg
at all and instead resolves--text-fg
directly which correctly resolves to#fff
as expected.