Skip to content

Commit 7c8c994

Browse files
authored
Merge pull request #518 from dcastil/breaking-feature/513/tailwind-css-v4-support
Breaking: Tailwind CSS v4 support
2 parents 47c87d8 + 7f043a6 commit 7c8c994

36 files changed

+2040
-1153
lines changed

docs/api-reference.md

+54-35
Original file line numberDiff line numberDiff line change
@@ -118,20 +118,17 @@ When using TypeScript and you use custom class group IDs or theme group IDs, you
118118
type AdditionalClassGroupIds = 'aspect-w' | 'aspect-h' | 'aspect-reset'
119119
type AdditionalThemeGroupIds = never
120120

121-
const customTwMerge = extendTailwindMerge<AdditionalClassGroupIds, AdditionalThemeGroupIds>({
121+
const twMerge = extendTailwindMerge<AdditionalClassGroupIds, AdditionalThemeGroupIds>({
122122
// ↓ Optional cache size
123123
// Here we're disabling the cache
124124
cacheSize: 0,
125125
// ↓ Optional prefix from TaiLwind config
126-
prefix: 'tw-',
127-
// ↓ Optional separator from TaiLwind config
128-
separator: '_',
126+
prefix: 'tw',
129127

130128
// ↓ Optional config overrides
131129
// Only elements from the second level onwards are overridden
132130
override: {
133131
// ↓ Theme scales to override
134-
// Not all theme keys from the Tailwind config are supported by default.
135132
theme: {
136133
colors: ['black', 'white', 'yellow-500'],
137134
},
@@ -156,13 +153,15 @@ const customTwMerge = extendTailwindMerge<AdditionalClassGroupIds, AdditionalThe
156153
// You probably won't need this, but it follows the same shape as
157154
// `conflictingClassGroups`.
158155
},
156+
// ↓ Modifiers whose order among multiple modifiers should be preserved because their
157+
// order changes which element gets targeted. Overrides default value.
158+
orderSensitiveModifiers: ['before'],
159159
},
160160

161161
// ↓ Optional config extensions
162162
// Follows same shape as the `override` object.
163163
extend: {
164164
// ↓ Theme scales to extend or create
165-
// Not all theme keys from the Tailwind config are supported by default.
166165
theme: {
167166
spacing: ['sm', 'md', 'lg'],
168167
},
@@ -195,20 +194,23 @@ const customTwMerge = extendTailwindMerge<AdditionalClassGroupIds, AdditionalThe
195194
// You probably won't need this, but it follows the same shape as
196195
// `conflictingClassGroups`.
197196
},
197+
// ↓ Modifiers whose order among multiple modifiers should be preserved because their
198+
// order changes which element gets targeted. Extends default value.
199+
orderSensitiveModifiers: ['before'],
198200
},
199201
})
200202
```
201203

202204
Additionally, you can pass multiple `createConfig` functions (more to that in [`createTailwindMerge`](#createtailwindmerge)) which is convenient if you want to combine your config with third-party plugins.
203205

204206
```ts
205-
const customTwMerge = extendTailwindMerge({ … }, withSomePlugin)
207+
const twMerge = extendTailwindMerge({ … }, withSomePlugin)
206208
```
207209

208210
If you only use plugins, you can omit the `configExtension` object as well.
209211

210212
```ts
211-
const customTwMerge = extendTailwindMerge(withSomePlugin)
213+
const twMerge = extendTailwindMerge(withSomePlugin)
212214
```
213215

214216
## `createTailwindMerge`
@@ -228,8 +230,8 @@ You need to provide a function which resolves to the config tailwind-merge shoul
228230

229231
```ts
230232
// ↓ Callback passed to `createTailwindMerge` is called when
231-
// `customTwMerge` gets called the first time.
232-
const customTwMerge = createTailwindMerge(() => {
233+
// `twMerge` gets called the first time.
234+
const twMerge = createTailwindMerge(() => {
233235
const defaultConfig = getDefaultConfig()
234236

235237
return {
@@ -248,14 +250,15 @@ const customTwMerge = createTailwindMerge(() => {
248250
...defaultConfig.conflictingClassGroupModifiers,
249251
baz: ['bar'],
250252
},
253+
orderSensitiveModifiers: [...defaultConfig.orderSensitiveModifiers, 'before'],
251254
}
252255
})
253256
```
254257
255258
Same as in [`extendTailwindMerge`](#extendtailwindmerge) you can use multiple `createConfig` functions which is convenient if you want to combine your config with third-party plugins. Just keep in mind that the first `createConfig` function does not get passed any arguments, whereas the subsequent functions get each passed the config from the previous function.
256259
257260
```ts
258-
const customTwMerge = createTailwindMerge(getDefaultConfig, withSomePlugin, (config) => ({
261+
const twMerge = createTailwindMerge(getDefaultConfig, withSomePlugin, (config) => ({
259262
// ↓ Config returned by `withSomePlugin`
260263
...config,
261264
classGroups: {
@@ -281,7 +284,7 @@ Helper function to merge multiple tailwind-merge configs. Properties with the va
281284
When using TypeScript, you need to pass a union of all class group IDs and theme group IDs used in `configExtension` as generic arguments to `mergeConfigs` or pass `string` to both arguments to allow any IDs.
282285

283286
```ts
284-
const customTwMerge = createTailwindMerge(getDefaultConfig, (config) =>
287+
const twMerge = createTailwindMerge(getDefaultConfig, (config) =>
285288
mergeConfigs<'shadow' | 'animate' | 'prose'>(config, {
286289
override: {
287290
classGroups: {
@@ -305,43 +308,59 @@ const customTwMerge = createTailwindMerge(getDefaultConfig, (config) =>
305308

306309
```ts
307310
interface Validators {
308-
isLength(value: string): boolean
311+
isAny(value: string): boolean
312+
isAnyNonArbitrary(value: string): boolean
313+
isArbitraryImage(value: string): boolean
309314
isArbitraryLength(value: string): boolean
310-
isNumber(value: string): boolean
315+
isArbitraryNumber(value: string): boolean
316+
isArbitraryPosition(value: string): boolean
317+
isArbitraryShadow(value: string): boolean
318+
isArbitrarySize(value: string): boolean
319+
isArbitraryValue(value: string): boolean
320+
isArbitraryVariable(value: string): boolean
321+
isArbitraryVariableFamilyName(value: string): boolean
322+
isArbitraryVariableImage(value: string): boolean
323+
isArbitraryVariableLength(value: string): boolean
324+
isArbitraryVariablePosition(value: string): boolean
325+
isArbitraryVariableShadow(value: string): boolean
326+
isArbitraryVariableSize(value: string): boolean
327+
isFraction(value: string): boolean
311328
isInteger(value: string): boolean
329+
isNumber(value: string): boolean
312330
isPercent(value: string): boolean
313-
isArbitraryValue(value: string): boolean
314331
isTshirtSize(value: string): boolean
315-
isArbitrarySize(value: string): boolean
316-
isArbitraryPosition(value: string): boolean
317-
isArbitraryImage(value: string): boolean
318-
isArbitraryNumber(value: string): boolean
319-
isArbitraryShadow(value: string): boolean
320-
isAny(value: string): boolean
321332
}
322333
```
323334
324335
An object containing all the validators used in tailwind-merge. They are useful if you want to use a custom config with [`extendTailwindMerge`](#extendtailwindmerge) or [`createTailwindMerge`](#createtailwindmerge). E.g. the `classGroup` for padding is defined as
325336
326337
```ts
327-
const paddingClassGroup = [{ p: [validators.isLength] }]
338+
const paddingClassGroup = [{ p: [validators.isNumber] }]
328339
```
329340
330341
A brief summary for each validator:
331342
332-
- `isLength` checks whether a class part is a number (`3`, `1.5`), a fraction (`3/4`), or one of the strings `px`, `full` or `screen`.
333-
- `isArbitraryLength` checks for arbitrary length values (`[3%]`, `[4px]`, `[length:var(--my-var)]`).
334-
- `isNumber` checks for numbers (`3`, `1.5`)
335-
- `isArbitraryNumber` checks whether class part is an arbitrary value which starts with `number:` or is a number (`[number:var(--value)]`, `[450]`) which is necessary for font-weight and stroke-width classNames.
336-
- `isInteger` checks for integer values (`3`).
337-
- `isPercent` checks for percent values (`12.5%`) which is used for color stop positions.
338-
- `isArbitraryValue` checks whether the class part is enclosed in brackets (`[something]`)
339-
- `isTshirtSize`checks whether class part is a T-shirt size (`sm`, `xl`), optionally with a preceding number (`2xl`).
340-
- `isArbitrarySize` checks whether class part is an arbitrary value which starts with `size:` (`[size:200px_100px]`) which is necessary for background-size classNames.
341-
- `isArbitraryPosition` checks whether class part is an arbitrary value which starts with `position:` (`[position:200px_100px]`) which is necessary for background-position classNames.
342-
- `isArbitraryImage` checks whether class part is an arbitrary value which is an iamge, e.g. by starting with `image:`, `url:`, `linear-gradient(` or `url(` (`[url('/path-to-image.png')]`, `image:var(--maybe-an-image-at-runtime)]`) which is necessary for background-image classNames.
343-
- `isArbitraryShadow` checks whether class part is an arbitrary value which starts with the same pattern as a shadow value (`[0_35px_60px_-15px_rgba(0,0,0,0.3)]`), namely with two lengths separated by a underscore, optionally prepended by `inset`.
344-
- `isAny` always returns true. Be careful with this validator as it might match unwanted classes. I use it primarily to match colors or when I'm certain there are no other class groups in a namespace.
343+
- `isAny` always returns true. Be careful with this validator as it might match unwanted classes. I use it primarily to match colors or when I'm certain there are no other class groups in a namespace.
344+
- `isAnyNonArbitrary` checks if the class part is not an arbitrary value or arbitrary variable.
345+
- `isArbitraryImage` checks whether class part is an arbitrary value which is an iamge, e.g. by starting with `image:`, `url:`, `linear-gradient(` or `url(` (`[url('/path-to-image.png')]`, `image:var(--maybe-an-image-at-runtime)]`) which is necessary for background-image classNames.
346+
- `isArbitraryLength` checks for arbitrary length values (`[3%]`, `[4px]`, `[length:var(--my-var)]`).
347+
- `isArbitraryNumber` checks whether class part is an arbitrary value which starts with `number:` or is a number (`[number:var(--value)]`, `[450]`) which is necessary for font-weight and stroke-width classNames.
348+
- `isArbitraryPosition` checks whether class part is an arbitrary value which starts with `position:` (`[position:200px_100px]`) which is necessary for background-position classNames.
349+
- `isArbitraryShadow` checks whether class part is an arbitrary value which starts with the same pattern as a shadow value (`[0_35px_60px_-15px_rgba(0,0,0,0.3)]`), namely with two lengths separated by a underscore, optionally prepended by `inset`.
350+
- `isArbitrarySize` checks whether class part is an arbitrary value which starts with `size:` (`[size:200px_100px]`) which is necessary for background-size classNames.
351+
- `isArbitraryValue` checks whether the class part is enclosed in brackets (`[something]`)
352+
- `isArbitraryVariable` checks whether the class part is an arbitrary variable (`(--my-var)`)
353+
- `isArbitraryVariableFamilyName` checks whether class part is an arbitrary variable with the `family-name` label (`(family-name:--my-font)`)
354+
- `isArbitraryVariableImage` checks whether class part is an arbitrary variable with the `image` or `url` label (`(image:--my-image)`)
355+
- `isArbitraryVariableLength` checks whether class part is an arbitrary variable with the `length` label (`(length:--my-length)`)
356+
- `isArbitraryVariablePosition` checks whether class part is an arbitrary variable with the `position` label (`(position:--my-position)`)
357+
- `isArbitraryVariableShadow` checks whether class part is an arbitrary variable with the `shadow` label or not label at all (`(shadow:--my-shadow)`, `(--my-shadow)`)
358+
- `isArbitraryVariableSize` checks whether class part is an arbitrary variable with the `size`, `length` or `percentage` label (`(size:--my-size)`)
359+
- `isFraction` checks whether class part is a fraction of two numbers (`1/2`, `127/256`)
360+
- `isInteger` checks for integer values (`3`).
361+
- `isNumber` checks for numbers (`3`, `1.5`)
362+
- `isPercent` checks for percent values (`12.5%`) which is used for color stop positions.
363+
- `isTshirtSize`checks whether class part is a T-shirt size (`sm`, `xl`), optionally with a preceding number (`2xl`).
345364

346365
## `Config`
347366

0 commit comments

Comments
 (0)