Skip to content

Commit

Permalink
adjust docs to extendTailwindMerge usage
Browse files Browse the repository at this point in the history
  • Loading branch information
dcastil committed Aug 20, 2023
1 parent 1e6346b commit 941ac19
Show file tree
Hide file tree
Showing 3 changed files with 121 additions and 75 deletions.
122 changes: 83 additions & 39 deletions docs/api-reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,27 +59,29 @@ It can be used like this:

```ts
extendTailwindMerge({
theme: {
'my-scale': ['foo', 'bar']
extend: {
theme: {
'my-scale': ['foo', 'bar'],
},
classGroups: {
'my-group': [{ 'my-group': [fromTheme('my-scale'), fromTheme('spacing')] }],
'my-group-x': [{ 'my-group-x': [fromTheme('my-scale')] }],
},
},
classGroups: {
'my-group': [{ 'my-group': [fromTheme('my-scale'), fromTheme('spacing')] }]
'my-group-x': [{ 'my-group-x': [fromTheme('my-scale')] }]
}
})
```
## `extendTailwindMerge`
```ts
function extendTailwindMerge(
configExtension: Partial<Config>,
...createConfig: Array<(config: Config) => Config>
configExtension: ConfigExtension,
...createConfig: ((config: Config) => Config)[]
): TailwindMerge
function extendTailwindMerge(...createConfig: Array<(config: Config) => Config>): TailwindMerge
function extendTailwindMerge(...createConfig: ((config: Config) => Config)[]): TailwindMerge
```

Function to create merge function with custom config which extends the default config. Use this if you use the default Tailwind config and just extend it in some places.
Function to create merge function with custom config which extends the default config. Use this if you use the default Tailwind config and just modified it in some places.

> **Note**
> The function `extendTailwindMerge` computes a large data structure based on the config passed to it. I recommend to call it only once and store the result in a top-level variable instead of calling it inline within another repeatedly called function.
Expand All @@ -88,40 +90,82 @@ You provide it a `configExtension` object which gets [merged](#mergeconfigs) wit

```ts
const customTwMerge = extendTailwindMerge({
cacheSize: 0, // ← Disabling cache
// ↓ Optional cache size
// Here we're disabling the cache
cacheSize: 0,
// ↓ Optional prefix from TaiLwind config
prefix: 'tw-',
// ↓ Optional separator from TaiLwind config
separator: '_',
// ↓ Add values to existing theme scale or create a new one
// Not all theme keys form the Tailwind config are supported by default.
theme: {
spacing: ['sm', 'md', 'lg'],
},
// ↓ Here you define class groups
classGroups: {
// ↓ The `foo` key here is the class group ID
// ↓ Creates group of classes which have conflicting styles
// Classes here: foo, foo-2, bar-baz, bar-baz-1, bar-baz-2
foo: ['foo', 'foo-2', { 'bar-baz': ['', '1', '2'] }],
// ↓ Functions can also be used to match classes.
// Classes here: qux-auto, qux-1000, qux-1001,…
bar: [{ qux: ['auto', (value) => Number(value) >= 1000] }],
baz: ['baz-sm', 'baz-md', 'baz-lg'],
},
// ↓ Here you can define additional conflicts across different groups
conflictingClassGroups: {
// ↓ ID of class group which creates a conflict with…
// ↓ …classes from groups with these IDs
// In this case `twMerge('qux-auto foo') → 'foo'`
foo: ['bar'],

// ↓ Optional config overrides
// Only elements from the second level onwards are overridden
override: {
// ↓ Theme scales to override
// Not all theme keys from the Tailwind config are supported by default.
theme: {
colors: ['black', 'white', 'yellow-500'],
},
// ↓ Class groups to override
classGroups: {
// ↓ The `shadow` key here is the class group ID
// ↓ Creates group of classes which have conflicting styles
// Classes here: shadow-100, shadow-200, shadow-300, shadow-400, shadow-500
shadow: [{ shadow: ['100', '200', '300', '400', '500'] }],
},
// ↓ Conflicts across different groups to override
conflictingClassGroups: {
// ↓ ID of class group which creates a conflict with…
// ↓ …classes from groups with these IDs
// Here we remove the default conflict between the font-size and leading class
// groups.
'font-size': [],
},
// ↓ Conflicts between the postfix modifier of a group and a different class group to
// override
conflictingClassGroupModifiers: {
// You probably won't need this, but it follows the same shape as
// `conflictingClassGroups`.
},
},
// ↓ Here you can define conflicts between the postfix modifier of a group and a different class group.
conflictingClassGroupModifiers: {
// ↓ ID of class group whose postfix modifier creates a conflict with…
// ↓ …classes from groups with these IDs
// In this case `twMerge('qux-auto baz-sm/1000') → 'baz-sm/1000'`
baz: ['bar'],

// ↓ Optional config extensions
// Follows same shape as the `override` object.
extend: {
// ↓ Theme scales to extend or create
// Not all theme keys from the Tailwind config are supported by default.
theme: {
spacing: ['sm', 'md', 'lg'],
},
// ↓ Class groups to extend or create
classGroups: {
// ↓ The `animate` key here is the class group ID
// ↓ Adds class animate-shimmer to existing group with ID `animate` or creates
// new class group if it doesn't exist.
animate: ['animate-shimmer'],
// ↓ Functions can also be used to match classes
// They take the class part value as argument and return a boolean defining whether
// it is a match.
// Here we accept all string classes starting with `aspec-w-` followed by a number.
'aspect-w': [{ 'aspect-w': [(value) => Boolean(value) && !isNaN(value)] }],
'aspect-h': [{ 'aspect-h': [(value) => Boolean(value) && !isNaN(value)] }],
'aspect-reset': ['aspect-none'],
// ↓ You can also use validators exported by tailwind-merge
'prose-size': [{ prose: ['base', validators.isTshirtSize] }],
},
// ↓ Conflicts across different groups to extend or create
conflictingClassGroups: {
// ↓ ID of class group which creates a conflict with…
// ↓ …classes from groups with these IDs
// In this case `twMerge('aspect-w-5 aspect-none') → 'aspect-none'`
'aspect-reset': ['aspect-w', 'aspect-h'],
},
// ↓ Conflicts between the postfix modifier of a group and a different class group to
// extend or create
conflictingClassGroupModifiers: {
// You probably won't need this, but it follows the same shape as
// `conflictingClassGroups`.
},
},
})
```
Expand Down
42 changes: 24 additions & 18 deletions docs/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -160,29 +160,35 @@ If you modified one of these theme scales in your Tailwind config, you can add a

### Extending the tailwind-merge config

If you only need to extend the default tailwind-merge config, [`extendTailwindMerge`](./api-reference.md#extendtailwindmerge) is the easiest way to extend the config. You provide it a `configExtension` object which gets [merged](./api-reference.md#mergeconfigs) with the default config. Therefore, all keys here are optional.
If you only need to slightly modify the default tailwind-merge config, [`extendTailwindMerge`](./api-reference.md#extendtailwindmerge) is the easiest way to extend the config. You provide it a `configExtension` object which gets [merged](./api-reference.md#mergeconfigs) with the default config. Therefore, all keys here are optional.

```ts
import { extendTailwindMerge } from 'tailwind-merge'

const customTwMerge = extendTailwindMerge({
// ↓ Add values to existing theme scale or create a new one
theme: {
spacing: ['sm', 'md', 'lg'],
},
// ↓ Add values to existing class groups or define new ones
classGroups: {
foo: ['foo', 'foo-2', { 'bar-baz': ['', '1', '2'] }],
bar: [{ qux: ['auto', (value) => Number(value) >= 1000] }],
baz: ['baz-sm', 'baz-md', 'baz-lg'],
},
// ↓ Here you can define additional conflicts across class groups
conflictingClassGroups: {
foo: ['bar'],
},
// ↓ Define conflicts between postfix modifiers and class groups
conflictingClassGroupModifiers: {
baz: ['bar'],
// ↓ Override eleemnts from the default config
// It has the same shape as the `extend` object, so we're going to skip it here.
override: {},
// ↓ Extend values from the default config
extend: {
// ↓ Add values to existing theme scale or create a new one
theme: {
spacing: ['sm', 'md', 'lg'],
},
// ↓ Add values to existing class groups or define new ones
classGroups: {
foo: ['foo', 'foo-2', { 'bar-baz': ['', '1', '2'] }],
bar: [{ qux: ['auto', (value) => Number(value) >= 1000] }],
baz: ['baz-sm', 'baz-md', 'baz-lg'],
},
// ↓ Here you can define additional conflicts across class groups
conflictingClassGroups: {
foo: ['bar'],
},
// ↓ Define conflicts between postfix modifiers and class groups
conflictingClassGroupModifiers: {
baz: ['bar'],
},
},
})
```
Expand Down
32 changes: 14 additions & 18 deletions docs/recipes.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,19 @@ How to configure tailwind-merge with some common patterns.

> I have a custom shadow scale with the keys 100, 200 and 300 configured in Tailwind. How do I make tailwind-merge resolve conflicts among those?
You'll be able to do this by creating a custom `twMerge` functon with [`extendTailwindMerge`](./api-reference.md#extendtailwindmerge).
We'll be able to do this by creating a custom `twMerge` functon with [`extendTailwindMerge`](./api-reference.md#extendtailwindmerge).

First, check whether your particular theme scale is included in tailwind-merge's theme config object [here](./configuration.md#theme). In the hypothetical case that tailwind-merge supported Tailwind's `boxShadow` theme scale, you could add it to the tailwind-merge config like this:
First, we need to know whether we want to override or extend the default scale. Let's say we extended the default config by putting the scale into the `extend` key in the Tailwind config.

Then we check whether our particular theme scale is included in tailwind-merge's theme config object [here](./configuration.md#theme). In the hypothetical case that tailwind-merge supported Tailwind's `boxShadow` theme scale, we could add it to the tailwind-merge config like this:

```js
const customTwMerge = extendTailwindMerge({
theme: {
// The `boxShadow` key isn't actually supported
boxShadow: [{ shadow: ['100', '200', '300'] }],
extend: {
theme: {
// The `boxShadow` key isn't actually supported
boxShadow: [{ shadow: ['100', '200', '300'] }],
},
},
})
```
Expand All @@ -23,23 +27,15 @@ In the case of the `boxShadow` scale, tailwind-merge doesn't include it in the t

```js
const customTwMerge = extendTailwindMerge({
classGroups: {
shadow: [{ shadow: ['100', '200', '300'] }],
extend: {
classGroups: {
shadow: [{ shadow: ['100', '200', '300'] }],
},
},
})
```

Note that by using `extendTailwindMerge` we're only adding our custom classes to the existing ones in the config, so `twMerge('shadow-200 shadow-lg')` will return the string `shadow-lg`. In most cases that's fine because you won't use that class in your project.

If you expect classes like `shadow-lg` to be input in `twMerge` and don't want the class to cause incorrect merges, you can explicitly override the class group with [`createTailwindMerge`](./api-reference.md#createtailwindmerge), removing the default classes.

```js
const customTwMerge = createTailwindMerge(() => {
const config = getDefaultConfig()
config.classGroups.shadow = [{ shadow: ['100', '200', '300'] }]
return config
})
```
Note that by using the `extend` object we're only adding our custom classes to the existing ones in the config, so `twMerge('shadow-200 shadow-lg')` will return the string `shadow-lg`. If we want to override the class instead, we need to use the `override` object instead.

## Extracting classes with Tailwind's [`@apply`](https://tailwindcss.com/docs/reusing-styles#extracting-classes-with-apply)

Expand Down

0 comments on commit 941ac19

Please sign in to comment.