diff --git a/CHANGELOG.md b/CHANGELOG.md index 399e4c53d7c4..b7f3f1b4c55e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -50,6 +50,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Remove static `font-weight` utilities and add `--font-weight-*` values to the default theme ([#14883](https://github.com/tailwindlabs/tailwindcss/pull/14883)) - Rename `--transition-timing-function-*` variables to `--ease-*` ([#14886](https://github.com/tailwindlabs/tailwindcss/pull/14886)) - Rename `--width-*` variables to `--container-*` ([#14898](https://github.com/tailwindlabs/tailwindcss/pull/14898)) +- Rename `--font-size-*` variables to `--text-*` ([#14909](https://github.com/tailwindlabs/tailwindcss/pull/14909)) ## [4.0.0-alpha.31] - 2024-10-29 diff --git a/integrations/upgrade/js-config.test.ts b/integrations/upgrade/js-config.test.ts index 398402139853..ccc6e22f96cb 100644 --- a/integrations/upgrade/js-config.test.ts +++ b/integrations/upgrade/js-config.test.ts @@ -158,13 +158,13 @@ test( --color-red-500: #ef4444; --color-red-600: #dc2626; - --font-size-*: initial; - --font-size-xs: 0.75rem; - --font-size-xs--line-height: 1rem; - --font-size-sm: 0.875rem; - --font-size-sm--line-height: 1.5rem; - --font-size-base: 1rem; - --font-size-base--line-height: 2rem; + --text-*: initial; + --text-xs: 0.75rem; + --text-xs--line-height: 1rem; + --text-sm: 0.875rem; + --text-sm--line-height: 1.5rem; + --text-base: 1rem; + --text-base--line-height: 2rem; --width-*: initial; --width-0: 0%; diff --git a/packages/@tailwindcss-postcss/src/__snapshots__/index.test.ts.snap b/packages/@tailwindcss-postcss/src/__snapshots__/index.test.ts.snap index f17f1f775b9e..24d0c8fa484d 100644 --- a/packages/@tailwindcss-postcss/src/__snapshots__/index.test.ts.snap +++ b/packages/@tailwindcss-postcss/src/__snapshots__/index.test.ts.snap @@ -314,32 +314,32 @@ exports[`\`@import 'tailwindcss'\` is replaced with the generated CSS 1`] = ` --font-sans: ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; --font-serif: ui-serif, Georgia, Cambria, "Times New Roman", Times, serif; --font-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; - --font-size-xs: .75rem; - --font-size-xs--line-height: 1rem; - --font-size-sm: .875rem; - --font-size-sm--line-height: 1.25rem; - --font-size-base: 1rem; - --font-size-base--line-height: 1.5rem; - --font-size-lg: 1.125rem; - --font-size-lg--line-height: 1.75rem; - --font-size-xl: 1.25rem; - --font-size-xl--line-height: 1.75rem; - --font-size-2xl: 1.5rem; - --font-size-2xl--line-height: 2rem; - --font-size-3xl: 1.875rem; - --font-size-3xl--line-height: 2.25rem; - --font-size-4xl: 2.25rem; - --font-size-4xl--line-height: 2.5rem; - --font-size-5xl: 3rem; - --font-size-5xl--line-height: 1; - --font-size-6xl: 3.75rem; - --font-size-6xl--line-height: 1; - --font-size-7xl: 4.5rem; - --font-size-7xl--line-height: 1; - --font-size-8xl: 6rem; - --font-size-8xl--line-height: 1; - --font-size-9xl: 8rem; - --font-size-9xl--line-height: 1; + --text-xs: .75rem; + --text-xs--line-height: 1rem; + --text-sm: .875rem; + --text-sm--line-height: 1.25rem; + --text-base: 1rem; + --text-base--line-height: 1.5rem; + --text-lg: 1.125rem; + --text-lg--line-height: 1.75rem; + --text-xl: 1.25rem; + --text-xl--line-height: 1.75rem; + --text-2xl: 1.5rem; + --text-2xl--line-height: 2rem; + --text-3xl: 1.875rem; + --text-3xl--line-height: 2.25rem; + --text-4xl: 2.25rem; + --text-4xl--line-height: 2.5rem; + --text-5xl: 3rem; + --text-5xl--line-height: 1; + --text-6xl: 3.75rem; + --text-6xl--line-height: 1; + --text-7xl: 4.5rem; + --text-7xl--line-height: 1; + --text-8xl: 6rem; + --text-8xl--line-height: 1; + --text-9xl: 8rem; + --text-9xl--line-height: 1; --font-weight-thin: 100; --font-weight-extralight: 200; --font-weight-light: 300; @@ -551,8 +551,8 @@ exports[`\`@import 'tailwindcss'\` is replaced with the generated CSS 1`] = ` @layer utilities { .text-2xl { - font-size: var(--font-size-2xl); - line-height: var(--tw-leading, var(--font-size-2xl--line-height)); + font-size: var(--text-2xl); + line-height: var(--tw-leading, var(--text-2xl--line-height)); } .text-black\\/50 { diff --git a/packages/@tailwindcss-upgrade/src/template/codemods/theme-to-var.test.ts b/packages/@tailwindcss-upgrade/src/template/codemods/theme-to-var.test.ts index 120b446a308c..3dcbaeecac87 100644 --- a/packages/@tailwindcss-upgrade/src/template/codemods/theme-to-var.test.ts +++ b/packages/@tailwindcss-upgrade/src/template/codemods/theme-to-var.test.ts @@ -10,7 +10,7 @@ test.each([ // Handle special cases around `.1` in the `theme(…)` ['[--value:theme(spacing.1)]', '[--value:var(--spacing-1)]'], - ['[--value:theme(fontSize.xs.1.lineHeight)]', '[--value:var(--font-size-xs--line-height)]'], + ['[--value:theme(fontSize.xs.1.lineHeight)]', '[--value:var(--text-xs--line-height)]'], // Convert to `var(…)` if we can resolve the path ['[color:theme(colors.red.500)]', '[color:var(--color-red-500)]'], // Arbitrary property @@ -32,7 +32,7 @@ test.each([ ], // Use `theme(…)` (deeply nested) inside of a `calc(…)` function - ['text-[calc(theme(fontSize.xs)*2)]', 'text-[calc(var(--font-size-xs)*2)]'], + ['text-[calc(theme(fontSize.xs)*2)]', 'text-[calc(var(--text-xs)*2)]'], // Multiple `theme(… / …)` calls should result in modern syntax of `theme(…)` // - Can't convert to `var(…)` because that would lose the modifier. diff --git a/packages/tailwindcss/src/__snapshots__/index.test.ts.snap b/packages/tailwindcss/src/__snapshots__/index.test.ts.snap index 900ced186e49..760d4a9ec6f5 100644 --- a/packages/tailwindcss/src/__snapshots__/index.test.ts.snap +++ b/packages/tailwindcss/src/__snapshots__/index.test.ts.snap @@ -313,32 +313,32 @@ exports[`compiling CSS > \`@tailwind utilities\` is replaced by utilities using --font-sans: ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; --font-serif: ui-serif, Georgia, Cambria, "Times New Roman", Times, serif; --font-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; - --font-size-xs: .75rem; - --font-size-xs--line-height: 1rem; - --font-size-sm: .875rem; - --font-size-sm--line-height: 1.25rem; - --font-size-base: 1rem; - --font-size-base--line-height: 1.5rem; - --font-size-lg: 1.125rem; - --font-size-lg--line-height: 1.75rem; - --font-size-xl: 1.25rem; - --font-size-xl--line-height: 1.75rem; - --font-size-2xl: 1.5rem; - --font-size-2xl--line-height: 2rem; - --font-size-3xl: 1.875rem; - --font-size-3xl--line-height: 2.25rem; - --font-size-4xl: 2.25rem; - --font-size-4xl--line-height: 2.5rem; - --font-size-5xl: 3rem; - --font-size-5xl--line-height: 1; - --font-size-6xl: 3.75rem; - --font-size-6xl--line-height: 1; - --font-size-7xl: 4.5rem; - --font-size-7xl--line-height: 1; - --font-size-8xl: 6rem; - --font-size-8xl--line-height: 1; - --font-size-9xl: 8rem; - --font-size-9xl--line-height: 1; + --text-xs: .75rem; + --text-xs--line-height: 1rem; + --text-sm: .875rem; + --text-sm--line-height: 1.25rem; + --text-base: 1rem; + --text-base--line-height: 1.5rem; + --text-lg: 1.125rem; + --text-lg--line-height: 1.75rem; + --text-xl: 1.25rem; + --text-xl--line-height: 1.75rem; + --text-2xl: 1.5rem; + --text-2xl--line-height: 2rem; + --text-3xl: 1.875rem; + --text-3xl--line-height: 2.25rem; + --text-4xl: 2.25rem; + --text-4xl--line-height: 2.5rem; + --text-5xl: 3rem; + --text-5xl--line-height: 1; + --text-6xl: 3.75rem; + --text-6xl--line-height: 1; + --text-7xl: 4.5rem; + --text-7xl--line-height: 1; + --text-8xl: 6rem; + --text-8xl--line-height: 1; + --text-9xl: 8rem; + --text-9xl--line-height: 1; --font-weight-thin: 100; --font-weight-extralight: 200; --font-weight-light: 300; diff --git a/packages/tailwindcss/src/compat/apply-config-to-theme.test.ts b/packages/tailwindcss/src/compat/apply-config-to-theme.test.ts index f427f996392c..9a44a1719d06 100644 --- a/packages/tailwindcss/src/compat/apply-config-to-theme.test.ts +++ b/packages/tailwindcss/src/compat/apply-config-to-theme.test.ts @@ -82,9 +82,9 @@ test('config values can be merged into the theme', () => { 'Potato Mono', { '--font-variation-settings': '"XHGT" 0.7' }, ]) - expect(theme.resolve('sm', ['--font-size'])).toEqual('0.875rem') - expect(theme.resolve('base', ['--font-size'])).toEqual('1rem') - expect(theme.resolveWith('base', ['--font-size'], ['--line-height'])).toEqual([ + expect(theme.resolve('sm', ['--text'])).toEqual('0.875rem') + expect(theme.resolve('base', ['--text'])).toEqual('1rem') + expect(theme.resolveWith('base', ['--text'], ['--line-height'])).toEqual([ '1rem', { '--line-height': '1.5' }, ]) diff --git a/packages/tailwindcss/src/compat/apply-config-to-theme.ts b/packages/tailwindcss/src/compat/apply-config-to-theme.ts index e9682144afbc..22e658ac78af 100644 --- a/packages/tailwindcss/src/compat/apply-config-to-theme.ts +++ b/packages/tailwindcss/src/compat/apply-config-to-theme.ts @@ -128,6 +128,8 @@ export function themeableValues(config: ResolvedConfig['theme']): [string[], unk const IS_VALID_KEY = /^[a-zA-Z0-9-_%/\.]+$/ export function keyPathToCssProperty(path: string[]) { + path = structuredClone(path) + if (path[0] === 'colors') path[0] = 'color' if (path[0] === 'screens') path[0] = 'breakpoint' if (path[0] === 'borderRadius') path[0] = 'radius' @@ -135,6 +137,7 @@ export function keyPathToCssProperty(path: string[]) { if (path[0] === 'animation') path[0] = 'animate' if (path[0] === 'transitionTimingFunction') path[0] = 'ease' if (path[0] === 'fontFamily') path[0] = 'font' + if (path[0] === 'fontSize') path[0] = 'text' if (path[0] === 'maxWidth') path[0] = 'container' for (let part of path) { diff --git a/packages/tailwindcss/src/compat/config.test.ts b/packages/tailwindcss/src/compat/config.test.ts index c9f3414f9fd3..6bc18aae5afa 100644 --- a/packages/tailwindcss/src/compat/config.test.ts +++ b/packages/tailwindcss/src/compat/config.test.ts @@ -255,16 +255,16 @@ describe('theme callbacks', () => { }) => { let input = css` @theme default { - --font-size-base: 0rem; - --font-size-base--line-height: 1rem; - --font-size-md: 0rem; - --font-size-md--line-height: 1rem; - --font-size-xl: 0rem; - --font-size-xl--line-height: 1rem; + --text-base: 0rem; + --text-base--line-height: 1rem; + --text-md: 0rem; + --text-md--line-height: 1rem; + --text-xl: 0rem; + --text-xl--line-height: 1rem; } @theme { - --font-size-base: 100rem; - --font-size-md--line-height: 101rem; + --text-base: 100rem; + --text-md--line-height: 101rem; } @tailwind utilities; @config "./config.js"; @@ -323,8 +323,8 @@ describe('theme callbacks', () => { expect(compiler.build(['leading-base', 'leading-md', 'leading-xl', 'prose'])) .toMatchInlineSnapshot(` ":root { - --font-size-base: 100rem; - --font-size-md--line-height: 101rem; + --text-base: 100rem; + --text-md--line-height: 101rem; } .prose { [class~=lead-base] { diff --git a/packages/tailwindcss/src/compat/config/create-compat-config.ts b/packages/tailwindcss/src/compat/config/create-compat-config.ts index e141d6ed9357..5258eec24214 100644 --- a/packages/tailwindcss/src/compat/config/create-compat-config.ts +++ b/packages/tailwindcss/src/compat/config/create-compat-config.ts @@ -14,6 +14,10 @@ export function createCompatConfig(cssTheme: Theme): UserConfig { colors: ({ theme }) => theme('color', {}), extend: { + fontSize: ({ theme }) => ({ + ...theme('text', {}), + }), + boxShadow: ({ theme }) => ({ ...theme('shadow', {}), }), diff --git a/packages/tailwindcss/src/compat/flatten-color-palette.test.ts b/packages/tailwindcss/src/compat/flatten-color-palette.test.ts new file mode 100644 index 000000000000..3891bbece534 --- /dev/null +++ b/packages/tailwindcss/src/compat/flatten-color-palette.test.ts @@ -0,0 +1,32 @@ +import { expect, test } from 'vitest' +import { flattenColorPalette } from './flatten-color-palette' + +test('it should handle private __CSS_VALUES__ to resolve to the right value', () => { + expect( + flattenColorPalette({ + 'slate-100': '#000100', + 'slate-200': '#000200', + 'slate-300': '#000300', + 'slate-400': '#100400', + 'slate-500': '#100500', + __CSS_VALUES__: { + 'slate-100': 4, + 'slate-200': 4, + 'slate-300': 4, + 'slate-400': 0, + 'slate-500': 0, + } as any, + slate: { '200': '#200200', '400': '#200400', '600': '#200600' }, + 'slate-600': '#200600', + }), + ).toMatchInlineSnapshot(` + { + "slate-100": "#000100", + "slate-200": "#200200", + "slate-300": "#000300", + "slate-400": "#100400", + "slate-500": "#100500", + "slate-600": "#200600", + } + `) +}) diff --git a/packages/tailwindcss/src/compat/flatten-color-palette.ts b/packages/tailwindcss/src/compat/flatten-color-palette.ts index 198ae060d7c5..03191e2da7e6 100644 --- a/packages/tailwindcss/src/compat/flatten-color-palette.ts +++ b/packages/tailwindcss/src/compat/flatten-color-palette.ts @@ -1,3 +1,5 @@ +import { ThemeOptions } from '../theme' + type Colors = { [key: string | number]: string | Colors } @@ -6,6 +8,7 @@ export function flattenColorPalette(colors: Colors) { let result: Record = {} for (let [root, children] of Object.entries(colors ?? {})) { + if (root === '__CSS_VALUES__') continue if (typeof children === 'object' && children !== null) { for (let [parent, value] of Object.entries(flattenColorPalette(children))) { result[`${root}${parent === 'DEFAULT' ? '' : `-${parent}`}`] = value @@ -15,5 +18,13 @@ export function flattenColorPalette(colors: Colors) { } } + if ('__CSS_VALUES__' in colors) { + for (let [key, value] of Object.entries(colors.__CSS_VALUES__)) { + if ((Number(value) & ThemeOptions.DEFAULT) === 0) { + result[key] = colors[key] as string + } + } + } + return result } diff --git a/packages/tailwindcss/src/compat/plugin-api.test.ts b/packages/tailwindcss/src/compat/plugin-api.test.ts index bfe86c89538d..d200e22b42dc 100644 --- a/packages/tailwindcss/src/compat/plugin-api.test.ts +++ b/packages/tailwindcss/src/compat/plugin-api.test.ts @@ -401,8 +401,8 @@ describe('theme', async () => { @tailwind utilities; @plugin "my-plugin"; @theme reference { - --animation: pulse 1s linear infinite; - --animation-spin: spin 1s linear infinite; + --animate: pulse 1s linear infinite; + --animate-spin: spin 1s linear infinite; } ` @@ -459,8 +459,8 @@ describe('theme', async () => { @tailwind utilities; @plugin "my-plugin"; @theme reference { - --animation: pulse 1s linear infinite; - --animation-spin: spin 1s linear infinite; + --animate: pulse 1s linear infinite; + --animate-spin: spin 1s linear infinite; } ` @@ -513,8 +513,8 @@ describe('theme', async () => { @tailwind utilities; @plugin "my-plugin"; @theme reference { - --animation: pulse 1s linear infinite; - --animation-spin: spin 1s linear infinite; + --animate: pulse 1s linear infinite; + --animate-spin: spin 1s linear infinite; } ` @@ -560,8 +560,8 @@ describe('theme', async () => { @tailwind utilities; @plugin "my-plugin"; @theme reference { - --animation-simple-spin: spin 1s linear infinite; - --animation-simple-bounce: bounce 1s linear infinite; + --animate-simple-spin: spin 1s linear infinite; + --animate-simple-bounce: bounce 1s linear infinite; } ` @@ -884,8 +884,8 @@ describe('theme', async () => { @tailwind utilities; @plugin "my-plugin"; @theme { - --transition-timing-function-in: ease-in; - --transition-timing-function-out: ease-out; + --ease-in: ease-in; + --ease-out: ease-out; } ` diff --git a/packages/tailwindcss/src/compat/plugin-functions.ts b/packages/tailwindcss/src/compat/plugin-functions.ts index 711adc8c78ff..5f8fc8843383 100644 --- a/packages/tailwindcss/src/compat/plugin-functions.ts +++ b/packages/tailwindcss/src/compat/plugin-functions.ts @@ -4,6 +4,7 @@ import { withAlpha } from '../utilities' import { DefaultMap } from '../utils/default-map' import { unescape } from '../utils/escape' import { toKeyPath } from '../utils/to-key-path' +import { keyPathToCssProperty } from './apply-config-to-theme' import { deepMerge } from './config/deep-merge' import type { UserConfig } from './config/types' @@ -127,21 +128,7 @@ function readFromCss( // A nested tuple with additional data | [main: string, extra: Record] - let themeKey = path - // [1] should move into the nested object tuple. To create the CSS variable - // name for this, we replace it with an empty string that will result in two - // subsequent dashes when joined. - .map((path) => (path === '1' ? '' : path)) - - // Resolve the key path to a CSS variable segment - .map((part) => - part.replaceAll('.', '_').replace(/([a-z])([A-Z])/g, (_, a, b) => `${a}-${b.toLowerCase()}`), - ) - - // Remove the `DEFAULT` key at the end of a path - // We're reading from CSS anyway so it'll be a string - .filter((part, index) => part !== 'DEFAULT' || index !== path.length - 1) - .join('-') + let themeKey = keyPathToCssProperty(path) let map = new Map() let nested = new DefaultMap>( diff --git a/packages/tailwindcss/src/css-functions.test.ts b/packages/tailwindcss/src/css-functions.test.ts index cbb7d4e95f4e..26443abcb81e 100644 --- a/packages/tailwindcss/src/css-functions.test.ts +++ b/packages/tailwindcss/src/css-functions.test.ts @@ -352,8 +352,8 @@ describe('theme function', () => { expect( await compileCss(css` @theme { - --font-size-xs: 1337.75rem; - --font-size-xs--line-height: 1337rem; + --text-xs: 1337.75rem; + --text-xs--line-height: 1337rem; } .text { font-size: theme(fontSize.xs); @@ -362,8 +362,8 @@ describe('theme function', () => { `), ).toMatchInlineSnapshot(` ":root { - --font-size-xs: 1337.75rem; - --font-size-xs--line-height: 1337rem; + --text-xs: 1337.75rem; + --text-xs--line-height: 1337rem; } .text { diff --git a/packages/tailwindcss/src/index.test.ts b/packages/tailwindcss/src/index.test.ts index 6a60c11979c6..4e44129cb96c 100644 --- a/packages/tailwindcss/src/index.test.ts +++ b/packages/tailwindcss/src/index.test.ts @@ -1067,7 +1067,7 @@ describe('Parsing themes values from CSS', () => { } } - --font-size-lg: 20px; + --text-lg: 20px; } @tailwind utilities; `, @@ -1077,11 +1077,11 @@ describe('Parsing themes values from CSS', () => { ":root { --color-red: red; --animate-foo: foo 1s infinite; - --font-size-lg: 20px; + --text-lg: 20px; } .text-lg { - font-size: var(--font-size-lg); + font-size: var(--text-lg); } .accent-red { @@ -1103,8 +1103,8 @@ describe('Parsing themes values from CSS', () => { @theme { --color-red: #f00; --color-blue: #00f; - --font-size-sm: 13px; - --font-size-md: 16px; + --text-sm: 13px; + --text-md: 16px; --animate-spin: spin 1s infinite linear; @@ -1116,7 +1116,7 @@ describe('Parsing themes values from CSS', () => { } @theme { --color-*: initial; - --font-size-md: initial; + --text-md: initial; --animate-*: initial; --keyframes-*: initial; } @@ -1129,12 +1129,12 @@ describe('Parsing themes values from CSS', () => { ), ).toMatchInlineSnapshot(` ":root { - --font-size-sm: 13px; + --text-sm: 13px; --color-green: #0f0; } .text-sm { - font-size: var(--font-size-sm); + font-size: var(--text-sm); } .accent-green { @@ -1174,13 +1174,12 @@ describe('Parsing themes values from CSS', () => { `) }) - test('unsetting `--font-*` does not unset `--font-weight-*` or `--font-size-*`', async () => { + test('unsetting `--font-*` does not unset `--font-weight-*`', async () => { expect( await compileCss( css` @theme { --font-weight-bold: bold; - --font-size-sm: 14px; --font-sans: sans-serif; --font-serif: serif; } @@ -1190,12 +1189,11 @@ describe('Parsing themes values from CSS', () => { } @tailwind utilities; `, - ['font-bold', 'text-sm', 'font-sans', 'font-serif', 'font-body'], + ['font-bold', 'font-sans', 'font-serif', 'font-body'], ), ).toMatchInlineSnapshot(` ":root { --font-weight-bold: bold; - --font-size-sm: 14px; --font-body: Inter; } @@ -1203,10 +1201,6 @@ describe('Parsing themes values from CSS', () => { font-family: var(--font-body); } - .text-sm { - font-size: var(--font-size-sm); - } - .font-bold { --tw-font-weight: var(--font-weight-bold); font-weight: var(--font-weight-bold); @@ -1347,6 +1341,71 @@ describe('Parsing themes values from CSS', () => { `) }) + test('unsetting `--text-*` does not unset `--text-color-*`, `--text-underline-offset-*`, `--text-indent-*`, `--text-decoration-thickness-*` or `--text-decoration-color-*`', async () => { + expect( + await compileCss( + css` + @theme { + --text-color-potato: brown; + --text-underline-offset-potato: 4px; + --text-indent-potato: 6px; + --text-decoration-thickness-potato: 8px; + --text-decoration-color-salad: yellow; + --text-4xl: 60px; + } + @theme { + --text-*: initial; + --text-lg: 20px; + } + @tailwind utilities; + `, + [ + 'text-potato', + 'underline-offset-potato', + 'indent-potato', + 'decoration-potato', + 'decoration-salad', + 'text-lg', + ], + ), + ).toMatchInlineSnapshot(` + ":root { + --text-color-potato: brown; + --text-underline-offset-potato: 4px; + --text-indent-potato: 6px; + --text-decoration-thickness-potato: 8px; + --text-decoration-color-salad: yellow; + --text-lg: 20px; + } + + .indent-potato { + text-indent: var(--text-indent-potato); + } + + .text-lg { + font-size: var(--text-lg); + } + + .text-potato { + color: var(--text-color-potato); + } + + .decoration-salad { + -webkit-text-decoration-color: var(--text-decoration-color-salad); + -webkit-text-decoration-color: var(--text-decoration-color-salad); + text-decoration-color: var(--text-decoration-color-salad); + } + + .decoration-potato { + text-decoration-thickness: var(--text-decoration-thickness-potato); + } + + .underline-offset-potato { + text-underline-offset: var(--text-underline-offset-potato); + }" + `) + }) + test('unused keyframes are removed when an animation is unset', async () => { expect( await compileCss( diff --git a/packages/tailwindcss/src/intellisense.test.ts b/packages/tailwindcss/src/intellisense.test.ts index 48ec98a5a007..cccf3d4eb14a 100644 --- a/packages/tailwindcss/src/intellisense.test.ts +++ b/packages/tailwindcss/src/intellisense.test.ts @@ -11,8 +11,8 @@ function loadDesignSystem() { theme.add('--colors-red-500', 'red') theme.add('--colors-blue-500', 'blue') theme.add('--breakpoint-sm', '640px') - theme.add('--font-size-xs', '0.75rem') - theme.add('--font-size-xs--line-height', '1rem') + theme.add('--text-xs', '0.75rem') + theme.add('--text-xs--line-height', '1rem') theme.add('--perspective-dramatic', '100px') theme.add('--perspective-normal', '500px') theme.add('--opacity-background', '0.3') diff --git a/packages/tailwindcss/src/theme.ts b/packages/tailwindcss/src/theme.ts index 95f676133808..389b469941f6 100644 --- a/packages/tailwindcss/src/theme.ts +++ b/packages/tailwindcss/src/theme.ts @@ -14,6 +14,16 @@ export const enum ThemeOptions { const ignoredThemeKeyMap = new Map([ ['--font', ['--font-weight', '--font-size']], ['--inset', ['--inset-shadow', '--inset-ring']], + [ + '--text', + [ + '--text-color', + '--text-underline-offset', + '--text-indent', + '--text-decoration-thickness', + '--text-decoration-color', + ], + ], ]) function isIgnoredThemeKey(themeKey: ThemeKey, namespace: ThemeKey) { diff --git a/packages/tailwindcss/src/utilities.test.ts b/packages/tailwindcss/src/utilities.test.ts index 06605b1c0728..5af59338f096 100644 --- a/packages/tailwindcss/src/utilities.test.ts +++ b/packages/tailwindcss/src/utilities.test.ts @@ -12368,7 +12368,6 @@ test('font', async () => { @theme reference { --font-sans: ui-sans-serif, system-ui, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji'; - --font-size-xl: 24px; --font-weight-bold: 650; } @tailwind utilities; @@ -12381,7 +12380,6 @@ test('font', async () => { // font-weight '-font-bold', - 'font-size-xl', 'font-weight-bold', 'font-sans/foo', 'font-["arial_rounded"]/foo', @@ -14663,8 +14661,8 @@ test('text', async () => { @theme { --color-red-500: #ef4444; --line-height-6: 1.5rem; - --font-size-sm: 0.875rem; - --font-size-sm--line-height: 1.25rem; + --text-sm: 0.875rem; + --text-sm--line-height: 1.25rem; --line-height-9: 2.25rem; } @tailwind utilities; @@ -14720,14 +14718,14 @@ test('text', async () => { ":root { --color-red-500: #ef4444; --line-height-6: 1.5rem; - --font-size-sm: .875rem; - --font-size-sm--line-height: 1.25rem; + --text-sm: .875rem; + --text-sm--line-height: 1.25rem; --line-height-9: 2.25rem; } .text-sm { - font-size: var(--font-size-sm); - line-height: var(--tw-leading, var(--font-size-sm--line-height)); + font-size: var(--text-sm); + line-height: var(--tw-leading, var(--text-sm--line-height)); } .text-\\[12px\\]\\/6 { @@ -14756,12 +14754,12 @@ test('text', async () => { } .text-sm\\/6 { - font-size: var(--font-size-sm); + font-size: var(--text-sm); line-height: var(--line-height-6); } .text-sm\\/\\[4px\\] { - font-size: var(--font-size-sm); + font-size: var(--text-sm); line-height: 4px; } @@ -16222,13 +16220,13 @@ describe('custom utilities', () => { } @theme reference { - --font-size-sm: 0.875rem; - --font-size-sm--line-height: 1.25rem; + --text-sm: 0.875rem; + --text-sm--line-height: 1.25rem; } @utility text-sm { - font-size: var(--font-size-sm, 0.8755rem); - line-height: var(--font-size-sm--line-height, 1.255rem); + font-size: var(--text-sm, 0.8755rem); + line-height: var(--text-sm--line-height, 1.255rem); text-rendering: optimizeLegibility; } `) @@ -16237,10 +16235,10 @@ describe('custom utilities', () => { expect(optimizeCss(compiled).trim()).toMatchInlineSnapshot(` "@layer utilities { .text-sm { - font-size: var(--font-size-sm); - line-height: var(--tw-leading, var(--font-size-sm--line-height)); - font-size: var(--font-size-sm, .8755rem); - line-height: var(--font-size-sm--line-height, 1.255rem); + font-size: var(--text-sm); + line-height: var(--tw-leading, var(--text-sm--line-height)); + font-size: var(--text-sm, .8755rem); + line-height: var(--text-sm--line-height, 1.255rem); text-rendering: optimizeLegibility; } }" diff --git a/packages/tailwindcss/src/utilities.ts b/packages/tailwindcss/src/utilities.ts index f6b018fa0a41..321c7a6b8113 100644 --- a/packages/tailwindcss/src/utilities.ts +++ b/packages/tailwindcss/src/utilities.ts @@ -3915,7 +3915,7 @@ export function createUtilities(theme: Theme) { { let value = theme.resolveWith( candidate.value.value, - ['--font-size'], + ['--text'], ['--line-height', '--letter-spacing', '--font-weight'], ) if (value) { @@ -3967,7 +3967,7 @@ export function createUtilities(theme: Theme) { }, { values: [], - valueThemeKeys: ['--font-size'], + valueThemeKeys: ['--text'], modifiers: [], modifierThemeKeys: ['--line-height'], }, diff --git a/packages/tailwindcss/tests/ui.spec.ts b/packages/tailwindcss/tests/ui.spec.ts index c11d76a61fd8..b8e7a6c8e0a0 100644 --- a/packages/tailwindcss/tests/ui.spec.ts +++ b/packages/tailwindcss/tests/ui.spec.ts @@ -504,10 +504,10 @@ test('explicit leading utilities are respected when overriding font-size', async `, css` @theme { - --font-size-sm: 14px; - --font-size-sm--line-height: 16px; - --font-size-xl: 20px; - --font-size-xl--line-height: 24px; + --text-sm: 14px; + --text-sm--line-height: 16px; + --text-xl: 20px; + --text-xl--line-height: 24px; --line-height-tight: 8px; } `, @@ -536,10 +536,10 @@ test('explicit leading utilities are overridden by line-height modifiers', async `, css` @theme { - --font-size-sm: 14px; - --font-size-sm--line-height: 16px; - --font-size-xl: 20px; - --font-size-xl--line-height: 24px; + --text-sm: 14px; + --text-sm--line-height: 16px; + --text-xl: 20px; + --text-xl--line-height: 24px; --line-height-tight: 8px; } `, @@ -568,8 +568,8 @@ test('explicit tracking utilities are respected when overriding font-size', asyn `, css` @theme { - --font-size-sm--letter-spacing: 5px; - --font-size-xl--letter-spacing: 10px; + --text-sm--letter-spacing: 5px; + --text-xl--letter-spacing: 10px; --letter-spacing-tight: 1px; } `, @@ -598,8 +598,8 @@ test('explicit font-weight utilities are respected when overriding font-size', a `, css` @theme { - --font-size-sm--font-weight: 100; - --font-size-xl--font-weight: 200; + --text-sm--font-weight: 100; + --text-xl--font-weight: 200; } `, ) diff --git a/packages/tailwindcss/theme.css b/packages/tailwindcss/theme.css index 47d9ba12ebd7..ba6d9a538c64 100644 --- a/packages/tailwindcss/theme.css +++ b/packages/tailwindcss/theme.css @@ -359,32 +359,32 @@ 'Courier New', monospace; /* Type scale */ - --font-size-xs: 0.75rem; - --font-size-xs--line-height: 1rem; - --font-size-sm: 0.875rem; - --font-size-sm--line-height: 1.25rem; - --font-size-base: 1rem; - --font-size-base--line-height: 1.5rem; - --font-size-lg: 1.125rem; - --font-size-lg--line-height: 1.75rem; - --font-size-xl: 1.25rem; - --font-size-xl--line-height: 1.75rem; - --font-size-2xl: 1.5rem; - --font-size-2xl--line-height: 2rem; - --font-size-3xl: 1.875rem; - --font-size-3xl--line-height: 2.25rem; - --font-size-4xl: 2.25rem; - --font-size-4xl--line-height: 2.5rem; - --font-size-5xl: 3rem; - --font-size-5xl--line-height: 1; - --font-size-6xl: 3.75rem; - --font-size-6xl--line-height: 1; - --font-size-7xl: 4.5rem; - --font-size-7xl--line-height: 1; - --font-size-8xl: 6rem; - --font-size-8xl--line-height: 1; - --font-size-9xl: 8rem; - --font-size-9xl--line-height: 1; + --text-xs: 0.75rem; + --text-xs--line-height: 1rem; + --text-sm: 0.875rem; + --text-sm--line-height: 1.25rem; + --text-base: 1rem; + --text-base--line-height: 1.5rem; + --text-lg: 1.125rem; + --text-lg--line-height: 1.75rem; + --text-xl: 1.25rem; + --text-xl--line-height: 1.75rem; + --text-2xl: 1.5rem; + --text-2xl--line-height: 2rem; + --text-3xl: 1.875rem; + --text-3xl--line-height: 2.25rem; + --text-4xl: 2.25rem; + --text-4xl--line-height: 2.5rem; + --text-5xl: 3rem; + --text-5xl--line-height: 1; + --text-6xl: 3.75rem; + --text-6xl--line-height: 1; + --text-7xl: 4.5rem; + --text-7xl--line-height: 1; + --text-8xl: 6rem; + --text-8xl--line-height: 1; + --text-9xl: 8rem; + --text-9xl--line-height: 1; /* Font weights */ --font-weight-thin: 100;