mirror of
https://github.com/tailwindlabs/tailwindcss.git
synced 2025-12-08 21:36:08 +00:00
Don't crash when setting JS theme value to null (#16210)
Closes #16035 In v3 it was possible to unset a specific color namespace by setting doing something like this: ```js export default { theme: { extend: { colors: { red: null, }, }, }, } ``` This pattern would crash in v4 right now due to the theme access function not being able to work on the red property being a `null`. This PR fixes this crash. However it leaves the behavior as-is for now so that the red namespace _defined via CSS will still be accessible_. This is technically different from v3 but fixing this would be more work as we only allow unsetting top-level namespaces in the interop layer (via the non-`extend`-theme-object). I would recommend migrating to the v4 API for doing these partial namespace resets if you want to get rid of the defaults in v4: ```css @theme { --color-red-*: initial; } ``` ## Test plan The crash was mainly captured via the test in `compat/config.test.ts` but I've added two more tests across the different levels of abstractions so that it's clear what `null` should be doing. --------- Co-authored-by: Robin Malfait <malfait.robin@gmail.com>
This commit is contained in:
parent
5601fb50a9
commit
3b61277e7a
@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fix a crash when setting JS theme values to `null` ([#16210](https://github.com/tailwindlabs/tailwindcss/pull/16210))
|
||||
- Ensure CSS variables in arbitrary values are properly decoded ([#16206](https://github.com/tailwindlabs/tailwindcss/pull/16206))
|
||||
- Ensure that the `containers` JS theme key is added to the `--container-*` namespace ([#16169](https://github.com/tailwindlabs/tailwindcss/pull/16169))
|
||||
- Fix missing `@keyframes` definition ([#16237](https://github.com/tailwindlabs/tailwindcss/pull/16237))
|
||||
|
||||
@ -223,3 +223,39 @@ test('converts opacity modifiers from decimal to percentage values', () => {
|
||||
expect(theme.resolve('20', ['--opacity'])).toEqual('20%')
|
||||
expect(theme.resolve('25', ['--opacity'])).toEqual('25%')
|
||||
})
|
||||
|
||||
test('handles setting theme keys to null', async () => {
|
||||
let theme = new Theme()
|
||||
let design = buildDesignSystem(theme)
|
||||
|
||||
theme.add('--color-blue-400', 'blue', ThemeOptions.DEFAULT)
|
||||
theme.add('--color-blue-500', '#3b82f6')
|
||||
theme.add('--color-red-400', 'red', ThemeOptions.DEFAULT)
|
||||
theme.add('--color-red-500', '#ef4444')
|
||||
|
||||
let { resolvedConfig, replacedThemeKeys } = resolveConfig(design, [
|
||||
{
|
||||
config: {
|
||||
theme: {
|
||||
extend: {
|
||||
colors: {
|
||||
blue: null,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
base: '/root',
|
||||
reference: false,
|
||||
},
|
||||
])
|
||||
applyConfigToTheme(design, resolvedConfig, replacedThemeKeys)
|
||||
|
||||
expect(theme.namespace('--color')).toMatchInlineSnapshot(`
|
||||
Map {
|
||||
"blue-400" => "blue",
|
||||
"blue-500" => "#3b82f6",
|
||||
"red-400" => "red",
|
||||
"red-500" => "#ef4444",
|
||||
}
|
||||
`)
|
||||
})
|
||||
|
||||
@ -1628,3 +1628,54 @@ test('old theme values are merged with their renamed counterparts in the CSS the
|
||||
|
||||
expect(didCallPluginFn).toHaveBeenCalled()
|
||||
})
|
||||
|
||||
test('handles setting theme keys to null', async () => {
|
||||
let compiler = await compile(
|
||||
css`
|
||||
@theme default {
|
||||
--color-red-50: oklch(0.971 0.013 17.38);
|
||||
--color-red-100: oklch(0.936 0.032 17.717);
|
||||
}
|
||||
@config "./my-config.js";
|
||||
@tailwind utilities;
|
||||
@theme {
|
||||
--color-red-100: oklch(0.936 0.032 17.717);
|
||||
--color-red-200: oklch(0.885 0.062 18.334);
|
||||
}
|
||||
`,
|
||||
{
|
||||
loadModule: async () => {
|
||||
return {
|
||||
module: {
|
||||
theme: {
|
||||
extend: {
|
||||
colors: {
|
||||
red: null,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
base: '/root',
|
||||
}
|
||||
},
|
||||
},
|
||||
)
|
||||
|
||||
expect(compiler.build(['bg-red-50', 'bg-red-100', 'bg-red-200'])).toMatchInlineSnapshot(`
|
||||
":root, :host {
|
||||
--color-red-50: oklch(0.971 0.013 17.38);
|
||||
--color-red-100: oklch(0.936 0.032 17.717);
|
||||
--color-red-200: oklch(0.885 0.062 18.334);
|
||||
}
|
||||
.bg-red-50 {
|
||||
background-color: var(--color-red-50);
|
||||
}
|
||||
.bg-red-100 {
|
||||
background-color: var(--color-red-100);
|
||||
}
|
||||
.bg-red-200 {
|
||||
background-color: var(--color-red-200);
|
||||
}
|
||||
"
|
||||
`)
|
||||
})
|
||||
|
||||
@ -254,3 +254,48 @@ test('theme keys can read from the CSS theme', () => {
|
||||
new Set(['colors', 'accentColor', 'placeholderColor', 'caretColor', 'transitionColor']),
|
||||
)
|
||||
})
|
||||
|
||||
test('handles null as theme values', () => {
|
||||
let theme = new Theme()
|
||||
theme.add('--color-red-50', 'red')
|
||||
theme.add('--color-red-100', 'red')
|
||||
|
||||
let design = buildDesignSystem(theme)
|
||||
|
||||
let { resolvedConfig, replacedThemeKeys } = resolveConfig(design, [
|
||||
{
|
||||
config: {
|
||||
theme: {
|
||||
colors: ({ theme }) => ({
|
||||
// Reads from the --color-* namespace
|
||||
...theme('color'),
|
||||
}),
|
||||
},
|
||||
},
|
||||
base: '/root',
|
||||
reference: false,
|
||||
},
|
||||
{
|
||||
config: {
|
||||
theme: {
|
||||
extend: {
|
||||
colors: {
|
||||
red: null,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
base: '/root',
|
||||
reference: false,
|
||||
},
|
||||
])
|
||||
|
||||
expect(resolvedConfig).toMatchObject({
|
||||
theme: {
|
||||
colors: {
|
||||
red: null,
|
||||
},
|
||||
},
|
||||
})
|
||||
expect(replacedThemeKeys).toEqual(new Set(['colors']))
|
||||
})
|
||||
|
||||
@ -224,7 +224,7 @@ function get(obj: any, path: string[]) {
|
||||
let key = path[i]
|
||||
|
||||
// The key does not exist so concatenate it with the next key
|
||||
if (obj[key] === undefined) {
|
||||
if (obj?.[key] === undefined) {
|
||||
if (path[i + 1] === undefined) {
|
||||
return undefined
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user