Skip to content

Commit

Permalink
fix(default key): fix generation of css vars that had DEFAULT names i…
Browse files Browse the repository at this point in the history
…n their path

- Don't remove the "DEFAULT" key names on the css var path if it is not a leaf as tailwind doesn't remove these
- Update docs to reflect this reality
  • Loading branch information
RyanClementsHax committed Nov 18, 2023
1 parent 7776a58 commit 1d2f2b6
Show file tree
Hide file tree
Showing 30 changed files with 91 additions and 146 deletions.
28 changes: 2 additions & 26 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -720,7 +720,7 @@ require('tailwindcss-themer')({

The above config would generate a css variable of the name `--colors-myBrand-primary-500`. If for some reason, [camelCasing](https://en.wikipedia.org/wiki/Camel_case) is converted to [kebab-casing](https://www.theserverside.com/definition/Kebab-case), make sure you have tailwind `v3.0.12` or later installed as that version fixed that bug.

If you use `DEFAULT` anywhere on a path to a variable, it is dropped off of the generated css variable name.
If you use `DEFAULT` as a leaf value, it is dropped off of the generated css variable name.

```js
require('tailwindcss-themer')({
Expand All @@ -741,31 +741,7 @@ require('tailwindcss-themer')({
})
```

The above config would generate a css variable of the name `--colors-brand1-primary`.

Because of the way `DEFAULT` works, it is possible to have naming collisions. It is on the user of this plugin to ensure that none happen.

```js
require('tailwindcss-themer')({
defaultTheme: {
extend: {
colors: {
brand1: {
DEFAULT: {
primary: {
DEFAULT: 'red'
}
},
primary: 'blue'
}
}
}
}
// ...
})
```

`colors.brand1.DEFAULT.primary.DEFAULT` and `colors.brand1.primary` both would generate a css variable named `--colors-brand1-primary`. See [Default key](docs/config.md#default-key) for more details.
The above config would generate a css variable of the name `--colors-brand1-DEFAULT-primary`. See [Default key](docs/config.md#default-key) for more details.

If anywhere in the path, an array is encountered, the index is used in the generated css variable name.

Expand Down
110 changes: 10 additions & 100 deletions docs/config.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
- [Valid primitives](#valid-primitives)
- [DEFAULT key](#default-key)
- [Shorthand](#shorthand)
- [Gotcha's](#gotchas)
- [Callbacks](#callbacks)
- [Config mismatches](#config-mismatches)
- [Referencing tailwind's default theme](#referencing-tailwinds-default-theme)
Expand Down Expand Up @@ -169,7 +168,7 @@ require('tailwindcss-themer')({
```

```html
<!DOCTYPE html>
<!doctype html>
<html lang="en">
<head>
<!-- ... -->
Expand All @@ -184,7 +183,7 @@ require('tailwindcss-themer')({
```

```html
<!DOCTYPE html>
<!doctype html>
<html lang="en">
<head>
<!-- ... -->
Expand All @@ -199,7 +198,7 @@ require('tailwindcss-themer')({
```

```html
<!DOCTYPE html>
<!doctype html>
<html lang="en">
<head>
<!-- ... -->
Expand Down Expand Up @@ -260,40 +259,40 @@ require('tailwindcss-themer')({
You would then use the tailwind classes as normal

```html
<!DOCTYPE html>
<!doctype html>
<html lang="en">
<head>
<!-- ... -->
</head>
<body>
<!-- this has a border radius of .25rem since that is the default -->
<input aria-label="my input" class="border rounded-woahh" />
<input aria-label="my input" class="rounded-woahh border" />
</body>
</html>
```

```html
<!DOCTYPE html>
<!doctype html>
<html lang="en">
<head>
<!-- ... -->
</head>
<body class="special-border-radius">
<!-- this has a border radius of .5rem as specified in the special-border-radius config -->
<input aria-label="my input" class="border rounded-woahh" />
<input aria-label="my input" class="rounded-woahh border" />
</body>
</html>
```

```html
<!DOCTYPE html>
<!doctype html>
<html lang="en">
<head>
<!-- ... -->
</head>
<body class="double-border-radius">
<!-- this has a border radius of 1rem as specified in the double-border-radius config -->
<input aria-label="my input" class="border rounded-woahh" />
<input aria-label="my input" class="rounded-woahh border" />
</body>
</html>
```
Expand Down Expand Up @@ -377,7 +376,7 @@ Anything that can be parsed as a color is handled in a special way. See [Theming

### DEFAULT key

Tailwind lets you specify default values for certain configuration.
Tailwind lets you specify [default values for certain configuration](https://tailwindcss.com/docs/theme#core-plugins).

For example, if you had a palette, but wanted to specify a default value for that palette, you could use the `DEFAULT` key.

Expand Down Expand Up @@ -443,63 +442,6 @@ require('tailwindcss-themer')({

Styles like `text-primary` will now be themed.

`DEFAULT` doesn't have to be set to a string. It could also be set to other values like objects.

```js
require('tailwindcss-themer')({
// ...
themes: [
{
name: 'my-theme',
extend: {
colors: {
primary: {
DEFAULT: {
100: '#000111'
//...
},
brand1: {
// ...
},
brand2: {
// ...
}
}
}
}
}
]
})
```

This generates classes like `text-primary-100`, `text-primary-brand1-200`, etc.

You can even nest them.

```js
require('tailwindcss-themer')({
// ...
themes: [
{
name: 'my-theme',
extend: {
colors: {
brand1: {
DEFAULT: {
primary: {
DEFAULT: 'red'
}
}
}
}
}
}
]
})
```

This will generate classess like `text-brand1-primary`.

#### Shorthand

Because of how `DEFAULT` works, you can specify single default values as strings if that is the only value in the object.
Expand Down Expand Up @@ -542,38 +484,6 @@ require('tailwindcss-themer')({
})
```

#### Gotcha's

Because of how `DEFAULT` works, it is possible to have naming collisions.

Take the following for an example.

```js
require('tailwindcss-themer')({
// ...
themes: [
{
name: 'my-theme',
extend: {
colors: {
primary: {
DEFAULT: {
fontColor: 'red'
},
fontColor: {
DEFAULT: 'red'
}
}
}
}
}
// ...
]
})
```

`colors.primary.DEFAULT.fontColor` and `colors.primary.fontColor.DEFAULT` both create classes like `text-primary-fontColor`. It is on the consumer of this plugin to make sure these naming collisions don't happen.

### Callbacks

Tailwind [supports top level callbacks](https://tailwindcss.com/docs/theme#referencing-other-values) for referrencing other values in your config. This plugin supports that too.
Expand Down
4 changes: 1 addition & 3 deletions docs/themingColors.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,7 @@ require('tailwindcss-themer')({
},
foo: {
bar: {
DEFAULT: {
bazz: 'rgb(35, 0, 75)' // also parsed as a color
}
bazz: 'rgb(35, 0, 75)' // also parsed as a color
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion e2e/test_repos/drivers/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -250,4 +250,4 @@ export function parseClasses(config: MultiThemePluginOptions): string[] {
// Preventing purging of these styles makes writing tests with arbitrary classes
// easier since otherwise they'd have to define the styles they use when opening
// the repo instance
const stylesToKeep = ['bg-primary', 'font-title']
const stylesToKeep = ['bg-primary', 'bg-primary-DEFAULT-500', 'font-title']
51 changes: 47 additions & 4 deletions e2e/tests/configValues.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { expect } from '@playwright/test'
import { test } from '../test_repos/test'

test.describe('DEFAULT key', () => {
test('handles the DEFAULT key by removing it from the generated class name', async ({
test('removes the DEFAULT field name when it is a leaf', async ({
page,
testRepos
}) => {
Expand Down Expand Up @@ -40,8 +40,51 @@ test.describe('DEFAULT key', () => {
await expect(page).toHaveScreenshot()
})

// TODO: fix this test's snapshots
test('handles the DEFAULT key even when nested', async ({
test('doesnt remove the DEFAULT field name when not a leaf', async ({
page,
testRepos
}) => {
const { root } = await testRepos
.builder()
.withThemerConfig({
defaultTheme: {
extend: {
colors: {
primary: {
DEFAULT: {
500: 'blue'
}
}
}
}
},
themes: [
{
name: 'darkTheme',
extend: {
colors: {
primary: {
DEFAULT: {
500: 'red'
}
}
}
}
}
]
})
.open()

await root.item.overwriteClassTo('bg-primary-DEFAULT-500')

await expect(page).toHaveScreenshot()

await root.addClass('darkTheme')

await expect(page).toHaveScreenshot()
})

test('doesnt remove the DEFAULT field name when not a leaf even if one of its leaves has a DEFAULT field name', async ({
page,
testRepos
}) => {
Expand Down Expand Up @@ -80,7 +123,7 @@ test.describe('DEFAULT key', () => {
})
.open()

await root.item.overwriteClassTo('bg-primary-500')
await root.item.overwriteClassTo('bg-primary-DEFAULT-500')

await expect(page).toHaveScreenshot()

Expand Down
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file not shown.
Binary file not shown.
Binary file not shown.
1 change: 0 additions & 1 deletion e2e/tests/mediaQuery.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ test('can enable a theme using a media query', async ({ page, testRepos }) => {
await expect(page).toHaveScreenshot()
})

// TODO fix this test's snapshots
test('cant enable a theme using the theme name as a class if a media query provided', async ({
page,
testRepos
Expand Down
16 changes: 9 additions & 7 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import plugin from 'tailwindcss/plugin'
import { Config, PluginAPI } from 'tailwindcss/types/config'
import { PluginAPI } from 'tailwindcss/types/config'

import {
getThemesFromOptions,
Expand Down Expand Up @@ -82,14 +82,16 @@ const multiThemePlugin = plugin.withOptions<MultiThemePluginOptions>(
addThemeVariants(themes, api)
addThemeStyles(themes, api)
},
(options = defaultOptions) =>
({
(options = defaultOptions) => {
const extension = resolveThemeExtensionsAsTailwindExtension(
getThemesFromOptions(options)
)
return {
theme: {
extend: resolveThemeExtensionsAsTailwindExtension(
getThemesFromOptions(options)
)
extend: extension
}
}) as Config
}
}
)

export = multiThemePlugin
21 changes: 18 additions & 3 deletions src/utils/customPropUtils.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,25 @@ describe('customPropUtils', () => {
)
})

it('removes default path steps case insensitvely', () => {
it('removes default leaf path step case sensitively', () => {
expect(
toCustomPropName(['default', 'that', 'DEFAULT', 'someOtherThing'])
).toBe('--that-someOtherThing')
toCustomPropName([
'default',
'that',
'DEFAULT',
'someOtherThing',
'DEFAULT'
])
).toBe('--default-that-DEFAULT-someOtherThing')
expect(
toCustomPropName([
'default',
'that',
'DEFAULT',
'someOtherThing',
'default'
])
).toBe('--default-that-DEFAULT-someOtherThing-default')
})

it('throws when whitespace is encountered', () => {
Expand Down

0 comments on commit 1d2f2b6

Please sign in to comment.