Skip to content
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

Reset default @theme values for non extend JS theme config #14672

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Fixed

- Ensure `theme` values defined outside of `extend` in JS configuration files overwrite all existing values for that namespace ([#14672](https://github.com/tailwindlabs/tailwindcss/pull/14672))
- _Upgrade (experimental)_: Speed up template migrations ([#14679](https://github.com/tailwindlabs/tailwindcss/pull/14679))

## [4.0.0-alpha.27] - 2024-10-15
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ export function migrateMediaScreen({
function migrate(root: Root) {
if (!designSystem || !userConfig) return

let resolvedUserConfig = resolveConfig(designSystem, [{ base: '', config: userConfig }])
let screens = resolvedUserConfig?.theme?.screens || {}
let { resolvedConfig } = resolveConfig(designSystem, [{ base: '', config: userConfig }])
let screens = resolvedConfig?.theme?.screens || {}

let mediaQueries = new DefaultMap<string, string | null>((name) => {
let value = designSystem?.resolveThemeValue(`--breakpoint-${name}`) ?? screens?.[name]
Expand Down
5 changes: 2 additions & 3 deletions packages/@tailwindcss-upgrade/src/migrate-js-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {
keyPathToCssProperty,
themeableValues,
} from '../../tailwindcss/src/compat/apply-config-to-theme'
import { applyKeyframesToAst } from '../../tailwindcss/src/compat/apply-keyframes-to-ast'
import { keyframesToRules } from '../../tailwindcss/src/compat/apply-keyframes-to-theme'
import { deepMerge } from '../../tailwindcss/src/compat/config/deep-merge'
import { mergeThemeExtension } from '../../tailwindcss/src/compat/config/resolve-config'
import type { ThemeConfig } from '../../tailwindcss/src/compat/config/types'
Expand Down Expand Up @@ -249,7 +249,6 @@ function onlyUsesAllowedTopLevelKeys(theme: ThemeConfig): boolean {
}

function keyframesToCss(keyframes: Record<string, unknown>): string {
let ast: AstNode[] = []
applyKeyframesToAst(ast, { theme: { keyframes } })
let ast: AstNode[] = keyframesToRules({ theme: { keyframes } })
return toCss(ast).trim() + '\n'
}
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ async function createResolvedUserConfig(fullConfigPath: string): Promise<Config>

return resolveConfig(noopDesignSystem, [
{ base: dirname(fullConfigPath), config: unresolvedUserConfig },
]) as any
]).resolvedConfig as any
}

const DEFAULT_CONFIG_FILES = [
Expand Down
13 changes: 8 additions & 5 deletions packages/tailwindcss/src/compat/apply-compat-hooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { rule, toCss, walk, WalkAction, type AstNode } from '../ast'
import type { DesignSystem } from '../design-system'
import { segment } from '../utils/segment'
import { applyConfigToTheme } from './apply-config-to-theme'
import { applyKeyframesToAst } from './apply-keyframes-to-ast'
import { applyKeyframesToTheme } from './apply-keyframes-to-theme'
import { createCompatConfig } from './config/create-compat-config'
import { resolveConfig } from './config/resolve-config'
import type { UserConfig } from './config/types'
Expand Down Expand Up @@ -215,12 +215,15 @@ function upgradeToFullPluginSupport({

let userConfig = [...pluginConfigs, ...configs]

let resolvedConfig = resolveConfig(designSystem, [
let { resolvedConfig } = resolveConfig(designSystem, [
{ config: createCompatConfig(designSystem.theme), base },
...userConfig,
{ config: { plugins: [darkModePlugin] }, base },
])
let resolvedUserConfig = resolveConfig(designSystem, userConfig)
let { resolvedConfig: resolvedUserConfig, replacedThemeKeys } = resolveConfig(
designSystem,
userConfig,
)

let pluginApi = buildPluginApi(designSystem, ast, resolvedConfig)

Expand All @@ -231,8 +234,8 @@ function upgradeToFullPluginSupport({
// Merge the user-configured theme keys into the design system. The compat
// config would otherwise expand into namespaces like `background-color` which
// core utilities already read from.
applyConfigToTheme(designSystem, resolvedUserConfig)
applyKeyframesToAst(ast, resolvedUserConfig)
applyConfigToTheme(designSystem, resolvedUserConfig, replacedThemeKeys)
applyKeyframesToTheme(designSystem, resolvedUserConfig, replacedThemeKeys)

registerThemeVariantOverrides(resolvedUserConfig, designSystem)
registerScreensConfig(resolvedUserConfig, designSystem)
Expand Down
63 changes: 56 additions & 7 deletions packages/tailwindcss/src/compat/apply-config-to-theme.test.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import { expect, test } from 'vitest'
import { buildDesignSystem } from '../design-system'
import { Theme } from '../theme'
import { Theme, ThemeOptions } from '../theme'
import { applyConfigToTheme } from './apply-config-to-theme'
import { resolveConfig } from './config/resolve-config'

test('Config values can be merged into the theme', () => {
test('config values can be merged into the theme', () => {
let theme = new Theme()
let design = buildDesignSystem(theme)

let resolvedUserConfig = resolveConfig(design, [
let { resolvedConfig, replacedThemeKeys } = resolveConfig(design, [
{
config: {
theme: {
Expand Down Expand Up @@ -54,7 +54,7 @@ test('Config values can be merged into the theme', () => {
base: '/root',
},
])
applyConfigToTheme(design, resolvedUserConfig)
applyConfigToTheme(design, resolvedConfig, replacedThemeKeys)

expect(theme.resolve('primary', ['--color'])).toEqual('#c0ffee')
expect(theme.resolve('sm', ['--breakpoint'])).toEqual('1234px')
Expand All @@ -75,11 +75,60 @@ test('Config values can be merged into the theme', () => {
])
})

test('Invalid keys are not merged into the theme', () => {
test('will reset default theme values with overwriting theme values', () => {
let theme = new Theme()
let design = buildDesignSystem(theme)

let resolvedUserConfig = resolveConfig(design, [
theme.add('--color-blue-400', 'lightblue', ThemeOptions.DEFAULT)
theme.add('--color-blue-500', 'blue', ThemeOptions.DEFAULT)
theme.add('--color-red-400', '#f87171')
theme.add('--color-red-500', '#ef4444')

let { resolvedConfig, replacedThemeKeys } = resolveConfig(design, [
{
config: {
theme: {
colors: {
blue: {
500: '#3b82f6',
},
red: {
500: 'red',
},
},
extend: {
colors: {
blue: {
600: '#2563eb',
},
red: {
600: '#dc2626',
},
},
},
},
},
base: '/root',
},
])
applyConfigToTheme(design, resolvedConfig, replacedThemeKeys)

expect(theme.namespace('--color')).toMatchInlineSnapshot(`
Map {
"red-400" => "#f87171",
"red-500" => "#ef4444",
"blue-500" => "#3b82f6",
"blue-600" => "#2563eb",
"red-600" => "#dc2626",
}
`)
})

test('invalid keys are not merged into the theme', () => {
let theme = new Theme()
let design = buildDesignSystem(theme)

let { resolvedConfig, replacedThemeKeys } = resolveConfig(design, [
{
config: {
theme: {
Expand All @@ -92,7 +141,7 @@ test('Invalid keys are not merged into the theme', () => {
},
])

applyConfigToTheme(design, resolvedUserConfig)
applyConfigToTheme(design, resolvedConfig, replacedThemeKeys)

let entries = Array.from(theme.entries())

Expand Down
13 changes: 12 additions & 1 deletion packages/tailwindcss/src/compat/apply-config-to-theme.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,18 @@ function resolveThemeValue(value: unknown, subValue: string | null = null): stri
return null
}

export function applyConfigToTheme(designSystem: DesignSystem, { theme }: ResolvedConfig) {
export function applyConfigToTheme(
designSystem: DesignSystem,
{ theme }: ResolvedConfig,
replacedThemeKeys: Set<string>,
) {
for (let resetThemeKey of replacedThemeKeys) {
let name = keyPathToCssProperty([resetThemeKey])
if (!name) continue

designSystem.theme.clearNamespace(`--${name}`, ThemeOptions.DEFAULT)
}

for (let [path, value] of themeableValues(theme)) {
if (typeof value !== 'string' && typeof value !== 'number') {
continue
Expand Down
54 changes: 0 additions & 54 deletions packages/tailwindcss/src/compat/apply-keyframes-to-ast.test.ts

This file was deleted.

11 changes: 0 additions & 11 deletions packages/tailwindcss/src/compat/apply-keyframes-to-ast.ts

This file was deleted.

Loading