Skip to content

Conversation

@woohm402
Copy link
Contributor

@woohm402 woohm402 commented May 22, 2025

Summary

Fixes #18114.

It Seems in apply-config-to-theme.ts#keyPathToCssProperty function the theme key is transformed as:

  • . is replaced with -
  • /([a-z])([A-Z])/ is replaced with $1-$2.toLowerCase()

However in theme.ts#resolve, when failed to find exact key, it only replaces

  • . is replaced with -

It seems the second transformation step is missing in theme.ts#resolve, causing inconsistencies when using camelCase or PascalCase theme keys.

Test plan

All unit tests pass, including the new test case covering this behavior.

@woohm402 woohm402 requested a review from a team as a code owner May 22, 2025 16:37
@woohm402
Copy link
Contributor Author

I haven’t thoroughly tested all possible edge cases, so there might be scenarios I missed.
If anything seems off or needs more coverage, I’d be happy to follow up 😀

@thecrypticace thecrypticace self-assigned this May 22, 2025
@thecrypticace
Copy link
Contributor

thecrypticace commented Nov 19, 2025

I can see two potential issues with this approach:

  1. Take for example the following theme from CSS:
@theme {
  --color-light-green: #0000ff;
}

I'd now be able to write either bg-light-green or bg-lightGreen when the second one is definitely not intended given that the theme is defined in CSS.

  1. Given the following JS config:
export default {
  theme: {
    extend: {
      lightGreen: "#0000ff"
    },
  },
}

The suggested color would still be bg-light-green because suggestions are generated from the theme keys. And this definitely doesn't feel like the intended behavior.

@thecrypticace
Copy link
Contributor

I went with a different approach due to the above points but def appreciate the PR!

pull bot pushed a commit to steinsi/Tailwind that referenced this pull request Nov 21, 2025
…bs#19337)

Fixes tailwindlabs#18114
Closes tailwindlabs#18115

This PR changes JS config handling such that we always preserve casing
for theme keys (when possible).

Now there are *two* exceptions to this rule:

1. Top-level keys in the theme *do* get converted to kebab-case. As CSS
variables are not generated from these this shouldn't be a big issue.

All of our internal plugins look for kebab-case keys. So, for example,
take the path `backgroundColor.red.500`. This must translate to
`--background-color-red-500`. But if you had something like
`backgroundColor.lightBlue` it would be perfectly fine for that to
translate to `--background-color-lightBlue` internally (and thus the
utility be written as `bg-lightBlue`.

2. Tuple object keys are converted to kebab-case as well.

These keys are converted to "nested" key syntax internally and
typtically represent CSS property names.

For example:
```js
export default {
  theme: {
    fontSize: {
      xs: ["1.5rem", { lineHeight: "1.3" }]
    },
    
    fontFamily: {
      sans: ["Potato Mono", { fontVariationSettings: '"XHGT" 0.7' }]
    }
  }
}
```

The `lineHeight` key here must be converted to `line-height` because it
represents a CSS property name. The theme key that represents this value
is `--text-xs--line-height`. The same situation applies for the
`fontVariationSettings` where the theme key is
`--font-sans--font-variation-settings`.
@woohm402
Copy link
Contributor Author

@thecrypticace Ah, got it. Thanks for the clarification!

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.

Utility class name transforms lowercase+uppercase keys (camelCase/PascalCase) to kebab-case unexpectedly when using JavaScript config file

2 participants