Support specifying gradient interpolation method via modifier (#14984)

This PR adds support for specifying a color interpolation method for all
gradient utilities using a modifier:

```html
<div class="bg-linear-to-r/oklab">
```

Supported bare values are any valid color space keyword, as well as the
special keywords `shorter`, `longer`, `increasing`, and `decreasing`,
which are shortcuts for `in oklch {keyword} hue`.

Arbitrary values are also supported and are used as-is, so the `in`
keyword is not automatically included for you:

```html
<div class="bg-linear-to-r/[in_oklab]">
```

Modifiers are not supported when using arbitrary values for the actual
gradient, as it's expected that your arbitrary gradient value contain
all of the details you want in your gradient:


```html
<!-- Won't work -->
<div class="bg-linear-[to_right]/oklab">

<!-- Do this -->
<div class="bg-linear-[to_right_in_oklab]">
```

Resolves https://github.com/tailwindlabs/tailwindcss/issues/14955, but
it may still be wise to make `oklab` the default since I do sort of
agree with the poster there that most people probably expect a gradient
between two colors to sort of just "fade" between them rather than
interpolate between them around the color wheel.

---------

Co-authored-by: Adam Wathan <4323180+adamwathan@users.noreply.github.com>
This commit is contained in:
Adam Wathan 2024-11-13 10:18:59 -05:00 • committed by GitHub
parent a8b99f76f4
commit 13f05e2711
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 911 additions and 105 deletions

View file

@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added
- Support opacity values in increments of `0.25` by default ([#14980](https://github.com/tailwindlabs/tailwindcss/pull/14980))
- Support specifying the color interpolation method for gradients via modifier ([#14984](https://github.com/tailwindlabs/tailwindcss/pull/14984))
## [4.0.0-alpha.33] - 2024-11-11

View file

@ -2,6 +2,222 @@
exports[`getClassList 1`] = `
[
"-bg-conic-0",
"-bg-conic-0/oklab",
"-bg-conic-0/oklch",
"-bg-conic-0/srgb",
"-bg-conic-0/hsl",
"-bg-conic-0/longer",
"-bg-conic-0/shorter",
"-bg-conic-0/increasing",
"-bg-conic-0/decreasing",
"-bg-conic-120",
"-bg-conic-120/oklab",
"-bg-conic-120/oklch",
"-bg-conic-120/srgb",
"-bg-conic-120/hsl",
"-bg-conic-120/longer",
"-bg-conic-120/shorter",
"-bg-conic-120/increasing",
"-bg-conic-120/decreasing",
"-bg-conic-150",
"-bg-conic-150/oklab",
"-bg-conic-150/oklch",
"-bg-conic-150/srgb",
"-bg-conic-150/hsl",
"-bg-conic-150/longer",
"-bg-conic-150/shorter",
"-bg-conic-150/increasing",
"-bg-conic-150/decreasing",
"-bg-conic-180",
"-bg-conic-180/oklab",
"-bg-conic-180/oklch",
"-bg-conic-180/srgb",
"-bg-conic-180/hsl",
"-bg-conic-180/longer",
"-bg-conic-180/shorter",
"-bg-conic-180/increasing",
"-bg-conic-180/decreasing",
"-bg-conic-210",
"-bg-conic-210/oklab",
"-bg-conic-210/oklch",
"-bg-conic-210/srgb",
"-bg-conic-210/hsl",
"-bg-conic-210/longer",
"-bg-conic-210/shorter",
"-bg-conic-210/increasing",
"-bg-conic-210/decreasing",
"-bg-conic-240",
"-bg-conic-240/oklab",
"-bg-conic-240/oklch",
"-bg-conic-240/srgb",
"-bg-conic-240/hsl",
"-bg-conic-240/longer",
"-bg-conic-240/shorter",
"-bg-conic-240/increasing",
"-bg-conic-240/decreasing",
"-bg-conic-270",
"-bg-conic-270/oklab",
"-bg-conic-270/oklch",
"-bg-conic-270/srgb",
"-bg-conic-270/hsl",
"-bg-conic-270/longer",
"-bg-conic-270/shorter",
"-bg-conic-270/increasing",
"-bg-conic-270/decreasing",
"-bg-conic-30",
"-bg-conic-30/oklab",
"-bg-conic-30/oklch",
"-bg-conic-30/srgb",
"-bg-conic-30/hsl",
"-bg-conic-30/longer",
"-bg-conic-30/shorter",
"-bg-conic-30/increasing",
"-bg-conic-30/decreasing",
"-bg-conic-300",
"-bg-conic-300/oklab",
"-bg-conic-300/oklch",
"-bg-conic-300/srgb",
"-bg-conic-300/hsl",
"-bg-conic-300/longer",
"-bg-conic-300/shorter",
"-bg-conic-300/increasing",
"-bg-conic-300/decreasing",
"-bg-conic-330",
"-bg-conic-330/oklab",
"-bg-conic-330/oklch",
"-bg-conic-330/srgb",
"-bg-conic-330/hsl",
"-bg-conic-330/longer",
"-bg-conic-330/shorter",
"-bg-conic-330/increasing",
"-bg-conic-330/decreasing",
"-bg-conic-60",
"-bg-conic-60/oklab",
"-bg-conic-60/oklch",
"-bg-conic-60/srgb",
"-bg-conic-60/hsl",
"-bg-conic-60/longer",
"-bg-conic-60/shorter",
"-bg-conic-60/increasing",
"-bg-conic-60/decreasing",
"-bg-conic-90",
"-bg-conic-90/oklab",
"-bg-conic-90/oklch",
"-bg-conic-90/srgb",
"-bg-conic-90/hsl",
"-bg-conic-90/longer",
"-bg-conic-90/shorter",
"-bg-conic-90/increasing",
"-bg-conic-90/decreasing",
"-bg-linear-0",
"-bg-linear-0/oklab",
"-bg-linear-0/oklch",
"-bg-linear-0/srgb",
"-bg-linear-0/hsl",
"-bg-linear-0/longer",
"-bg-linear-0/shorter",
"-bg-linear-0/increasing",
"-bg-linear-0/decreasing",
"-bg-linear-120",
"-bg-linear-120/oklab",
"-bg-linear-120/oklch",
"-bg-linear-120/srgb",
"-bg-linear-120/hsl",
"-bg-linear-120/longer",
"-bg-linear-120/shorter",
"-bg-linear-120/increasing",
"-bg-linear-120/decreasing",
"-bg-linear-150",
"-bg-linear-150/oklab",
"-bg-linear-150/oklch",
"-bg-linear-150/srgb",
"-bg-linear-150/hsl",
"-bg-linear-150/longer",
"-bg-linear-150/shorter",
"-bg-linear-150/increasing",
"-bg-linear-150/decreasing",
"-bg-linear-180",
"-bg-linear-180/oklab",
"-bg-linear-180/oklch",
"-bg-linear-180/srgb",
"-bg-linear-180/hsl",
"-bg-linear-180/longer",
"-bg-linear-180/shorter",
"-bg-linear-180/increasing",
"-bg-linear-180/decreasing",
"-bg-linear-210",
"-bg-linear-210/oklab",
"-bg-linear-210/oklch",
"-bg-linear-210/srgb",
"-bg-linear-210/hsl",
"-bg-linear-210/longer",
"-bg-linear-210/shorter",
"-bg-linear-210/increasing",
"-bg-linear-210/decreasing",
"-bg-linear-240",
"-bg-linear-240/oklab",
"-bg-linear-240/oklch",
"-bg-linear-240/srgb",
"-bg-linear-240/hsl",
"-bg-linear-240/longer",
"-bg-linear-240/shorter",
"-bg-linear-240/increasing",
"-bg-linear-240/decreasing",
"-bg-linear-270",
"-bg-linear-270/oklab",
"-bg-linear-270/oklch",
"-bg-linear-270/srgb",
"-bg-linear-270/hsl",
"-bg-linear-270/longer",
"-bg-linear-270/shorter",
"-bg-linear-270/increasing",
"-bg-linear-270/decreasing",
"-bg-linear-30",
"-bg-linear-30/oklab",
"-bg-linear-30/oklch",
"-bg-linear-30/srgb",
"-bg-linear-30/hsl",
"-bg-linear-30/longer",
"-bg-linear-30/shorter",
"-bg-linear-30/increasing",
"-bg-linear-30/decreasing",
"-bg-linear-300",
"-bg-linear-300/oklab",
"-bg-linear-300/oklch",
"-bg-linear-300/srgb",
"-bg-linear-300/hsl",
"-bg-linear-300/longer",
"-bg-linear-300/shorter",
"-bg-linear-300/increasing",
"-bg-linear-300/decreasing",
"-bg-linear-330",
"-bg-linear-330/oklab",
"-bg-linear-330/oklch",
"-bg-linear-330/srgb",
"-bg-linear-330/hsl",
"-bg-linear-330/longer",
"-bg-linear-330/shorter",
"-bg-linear-330/increasing",
"-bg-linear-330/decreasing",
"-bg-linear-60",
"-bg-linear-60/oklab",
"-bg-linear-60/oklch",
"-bg-linear-60/srgb",
"-bg-linear-60/hsl",
"-bg-linear-60/longer",
"-bg-linear-60/shorter",
"-bg-linear-60/increasing",
"-bg-linear-60/decreasing",
"-bg-linear-90",
"-bg-linear-90/oklab",
"-bg-linear-90/oklch",
"-bg-linear-90/srgb",
"-bg-linear-90/hsl",
"-bg-linear-90/longer",
"-bg-linear-90/shorter",
"-bg-linear-90/increasing",
"-bg-linear-90/decreasing",
"-bottom-0",
"-bottom-0.5",
"-bottom-1",
@ -1599,6 +1815,123 @@ exports[`getClassList 1`] = `
"bg-clip-content",
"bg-clip-padding",
"bg-clip-text",
"bg-conic",
"bg-conic/oklab",
"bg-conic/oklch",
"bg-conic/srgb",
"bg-conic/hsl",
"bg-conic/longer",
"bg-conic/shorter",
"bg-conic/increasing",
"bg-conic/decreasing",
"bg-conic-0",
"bg-conic-0/oklab",
"bg-conic-0/oklch",
"bg-conic-0/srgb",
"bg-conic-0/hsl",
"bg-conic-0/longer",
"bg-conic-0/shorter",
"bg-conic-0/increasing",
"bg-conic-0/decreasing",
"bg-conic-120",
"bg-conic-120/oklab",
"bg-conic-120/oklch",
"bg-conic-120/srgb",
"bg-conic-120/hsl",
"bg-conic-120/longer",
"bg-conic-120/shorter",
"bg-conic-120/increasing",
"bg-conic-120/decreasing",
"bg-conic-150",
"bg-conic-150/oklab",
"bg-conic-150/oklch",
"bg-conic-150/srgb",
"bg-conic-150/hsl",
"bg-conic-150/longer",
"bg-conic-150/shorter",
"bg-conic-150/increasing",
"bg-conic-150/decreasing",
"bg-conic-180",
"bg-conic-180/oklab",
"bg-conic-180/oklch",
"bg-conic-180/srgb",
"bg-conic-180/hsl",
"bg-conic-180/longer",
"bg-conic-180/shorter",
"bg-conic-180/increasing",
"bg-conic-180/decreasing",
"bg-conic-210",
"bg-conic-210/oklab",
"bg-conic-210/oklch",
"bg-conic-210/srgb",
"bg-conic-210/hsl",
"bg-conic-210/longer",
"bg-conic-210/shorter",
"bg-conic-210/increasing",
"bg-conic-210/decreasing",
"bg-conic-240",
"bg-conic-240/oklab",
"bg-conic-240/oklch",
"bg-conic-240/srgb",
"bg-conic-240/hsl",
"bg-conic-240/longer",
"bg-conic-240/shorter",
"bg-conic-240/increasing",
"bg-conic-240/decreasing",
"bg-conic-270",
"bg-conic-270/oklab",
"bg-conic-270/oklch",
"bg-conic-270/srgb",
"bg-conic-270/hsl",
"bg-conic-270/longer",
"bg-conic-270/shorter",
"bg-conic-270/increasing",
"bg-conic-270/decreasing",
"bg-conic-30",
"bg-conic-30/oklab",
"bg-conic-30/oklch",
"bg-conic-30/srgb",
"bg-conic-30/hsl",
"bg-conic-30/longer",
"bg-conic-30/shorter",
"bg-conic-30/increasing",
"bg-conic-30/decreasing",
"bg-conic-300",
"bg-conic-300/oklab",
"bg-conic-300/oklch",
"bg-conic-300/srgb",
"bg-conic-300/hsl",
"bg-conic-300/longer",
"bg-conic-300/shorter",
"bg-conic-300/increasing",
"bg-conic-300/decreasing",
"bg-conic-330",
"bg-conic-330/oklab",
"bg-conic-330/oklch",
"bg-conic-330/srgb",
"bg-conic-330/hsl",
"bg-conic-330/longer",
"bg-conic-330/shorter",
"bg-conic-330/increasing",
"bg-conic-330/decreasing",
"bg-conic-60",
"bg-conic-60/oklab",
"bg-conic-60/oklch",
"bg-conic-60/srgb",
"bg-conic-60/hsl",
"bg-conic-60/longer",
"bg-conic-60/shorter",
"bg-conic-60/increasing",
"bg-conic-60/decreasing",
"bg-conic-90",
"bg-conic-90/oklab",
"bg-conic-90/oklch",
"bg-conic-90/srgb",
"bg-conic-90/hsl",
"bg-conic-90/longer",
"bg-conic-90/shorter",
"bg-conic-90/increasing",
"bg-conic-90/decreasing",
"bg-contain",
"bg-cover",
"bg-current",
@ -1657,20 +1990,201 @@ exports[`getClassList 1`] = `
"bg-left",
"bg-left-bottom",
"bg-left-top",
"bg-linear-0",
"bg-linear-0/oklab",
"bg-linear-0/oklch",
"bg-linear-0/srgb",
"bg-linear-0/hsl",
"bg-linear-0/longer",
"bg-linear-0/shorter",
"bg-linear-0/increasing",
"bg-linear-0/decreasing",
"bg-linear-120",
"bg-linear-120/oklab",
"bg-linear-120/oklch",
"bg-linear-120/srgb",
"bg-linear-120/hsl",
"bg-linear-120/longer",
"bg-linear-120/shorter",
"bg-linear-120/increasing",
"bg-linear-120/decreasing",
"bg-linear-150",
"bg-linear-150/oklab",
"bg-linear-150/oklch",
"bg-linear-150/srgb",
"bg-linear-150/hsl",
"bg-linear-150/longer",
"bg-linear-150/shorter",
"bg-linear-150/increasing",
"bg-linear-150/decreasing",
"bg-linear-180",
"bg-linear-180/oklab",
"bg-linear-180/oklch",
"bg-linear-180/srgb",
"bg-linear-180/hsl",
"bg-linear-180/longer",
"bg-linear-180/shorter",
"bg-linear-180/increasing",
"bg-linear-180/decreasing",
"bg-linear-210",
"bg-linear-210/oklab",
"bg-linear-210/oklch",
"bg-linear-210/srgb",
"bg-linear-210/hsl",
"bg-linear-210/longer",
"bg-linear-210/shorter",
"bg-linear-210/increasing",
"bg-linear-210/decreasing",
"bg-linear-240",
"bg-linear-240/oklab",
"bg-linear-240/oklch",
"bg-linear-240/srgb",
"bg-linear-240/hsl",
"bg-linear-240/longer",
"bg-linear-240/shorter",
"bg-linear-240/increasing",
"bg-linear-240/decreasing",
"bg-linear-270",
"bg-linear-270/oklab",
"bg-linear-270/oklch",
"bg-linear-270/srgb",
"bg-linear-270/hsl",
"bg-linear-270/longer",
"bg-linear-270/shorter",
"bg-linear-270/increasing",
"bg-linear-270/decreasing",
"bg-linear-30",
"bg-linear-30/oklab",
"bg-linear-30/oklch",
"bg-linear-30/srgb",
"bg-linear-30/hsl",
"bg-linear-30/longer",
"bg-linear-30/shorter",
"bg-linear-30/increasing",
"bg-linear-30/decreasing",
"bg-linear-300",
"bg-linear-300/oklab",
"bg-linear-300/oklch",
"bg-linear-300/srgb",
"bg-linear-300/hsl",
"bg-linear-300/longer",
"bg-linear-300/shorter",
"bg-linear-300/increasing",
"bg-linear-300/decreasing",
"bg-linear-330",
"bg-linear-330/oklab",
"bg-linear-330/oklch",
"bg-linear-330/srgb",
"bg-linear-330/hsl",
"bg-linear-330/longer",
"bg-linear-330/shorter",
"bg-linear-330/increasing",
"bg-linear-330/decreasing",
"bg-linear-60",
"bg-linear-60/oklab",
"bg-linear-60/oklch",
"bg-linear-60/srgb",
"bg-linear-60/hsl",
"bg-linear-60/longer",
"bg-linear-60/shorter",
"bg-linear-60/increasing",
"bg-linear-60/decreasing",
"bg-linear-90",
"bg-linear-90/oklab",
"bg-linear-90/oklch",
"bg-linear-90/srgb",
"bg-linear-90/hsl",
"bg-linear-90/longer",
"bg-linear-90/shorter",
"bg-linear-90/increasing",
"bg-linear-90/decreasing",
"bg-linear-to-b",
"bg-linear-to-b/oklab",
"bg-linear-to-b/oklch",
"bg-linear-to-b/srgb",
"bg-linear-to-b/hsl",
"bg-linear-to-b/longer",
"bg-linear-to-b/shorter",
"bg-linear-to-b/increasing",
"bg-linear-to-b/decreasing",
"bg-linear-to-bl",
"bg-linear-to-bl/oklab",
"bg-linear-to-bl/oklch",
"bg-linear-to-bl/srgb",
"bg-linear-to-bl/hsl",
"bg-linear-to-bl/longer",
"bg-linear-to-bl/shorter",
"bg-linear-to-bl/increasing",
"bg-linear-to-bl/decreasing",
"bg-linear-to-br",
"bg-linear-to-br/oklab",
"bg-linear-to-br/oklch",
"bg-linear-to-br/srgb",
"bg-linear-to-br/hsl",
"bg-linear-to-br/longer",
"bg-linear-to-br/shorter",
"bg-linear-to-br/increasing",
"bg-linear-to-br/decreasing",
"bg-linear-to-l",
"bg-linear-to-l/oklab",
"bg-linear-to-l/oklch",
"bg-linear-to-l/srgb",
"bg-linear-to-l/hsl",
"bg-linear-to-l/longer",
"bg-linear-to-l/shorter",
"bg-linear-to-l/increasing",
"bg-linear-to-l/decreasing",
"bg-linear-to-r",
"bg-linear-to-r/oklab",
"bg-linear-to-r/oklch",
"bg-linear-to-r/srgb",
"bg-linear-to-r/hsl",
"bg-linear-to-r/longer",
"bg-linear-to-r/shorter",
"bg-linear-to-r/increasing",
"bg-linear-to-r/decreasing",
"bg-linear-to-t",
"bg-linear-to-t/oklab",
"bg-linear-to-t/oklch",
"bg-linear-to-t/srgb",
"bg-linear-to-t/hsl",
"bg-linear-to-t/longer",
"bg-linear-to-t/shorter",
"bg-linear-to-t/increasing",
"bg-linear-to-t/decreasing",
"bg-linear-to-tl",
"bg-linear-to-tl/oklab",
"bg-linear-to-tl/oklch",
"bg-linear-to-tl/srgb",
"bg-linear-to-tl/hsl",
"bg-linear-to-tl/longer",
"bg-linear-to-tl/shorter",
"bg-linear-to-tl/increasing",
"bg-linear-to-tl/decreasing",
"bg-linear-to-tr",
"bg-linear-to-tr/oklab",
"bg-linear-to-tr/oklch",
"bg-linear-to-tr/srgb",
"bg-linear-to-tr/hsl",
"bg-linear-to-tr/longer",
"bg-linear-to-tr/shorter",
"bg-linear-to-tr/increasing",
"bg-linear-to-tr/decreasing",
"bg-local",
"bg-no-repeat",
"bg-none",
"bg-origin-border",
"bg-origin-content",
"bg-origin-padding",
"bg-radial",
"bg-radial/oklab",
"bg-radial/oklch",
"bg-radial/srgb",
"bg-radial/hsl",
"bg-radial/longer",
"bg-radial/shorter",
"bg-radial/increasing",
"bg-radial/decreasing",
"bg-repeat",
"bg-repeat-x",
"bg-repeat-y",

View file

@ -10086,6 +10086,47 @@ test('bg', async () => {
'bg-linear-45',
'-bg-linear-45',
// With interpolation mode modifier
'bg-linear-to-r/oklch',
'bg-linear-to-r/oklab',
'bg-linear-to-r/hsl',
'bg-linear-to-r/srgb',
'bg-linear-to-r/longer',
'bg-linear-to-r/shorter',
'bg-linear-to-r/increasing',
'bg-linear-to-r/decreasing',
'bg-linear-to-r/[in_hsl_longer_hue]',
'bg-linear-45/oklab',
'-bg-linear-45/oklab',
'bg-linear-45/shorter',
'bg-linear-45/[in_hsl_longer_hue]',
'bg-conic/oklch',
'bg-conic/oklab',
'bg-conic/hsl',
'bg-conic/srgb',
'bg-conic/longer',
'bg-conic/shorter',
'bg-conic/increasing',
'bg-conic/decreasing',
'bg-conic/[in_hsl_longer_hue]',
'bg-conic-45/oklab',
'-bg-conic-45/oklab',
'bg-conic-45/shorter',
'bg-conic-45/[in_hsl_longer_hue]',
'bg-radial/oklch',
'bg-radial/oklab',
'bg-radial/hsl',
'bg-radial/srgb',
'bg-radial/longer',
'bg-radial/shorter',
'bg-radial/increasing',
'bg-radial/decreasing',
'bg-radial/[in_hsl_longer_hue]',
'bg-radial-[circle_at_center]',
// Invalid but proves not converted to `in oklch longer hue` when used
// as an arbitrary value
'bg-linear-to-r/[longer]',
'bg-[url(/image.png)]',
'bg-[url:var(--my-url)]',
'bg-[linear-gradient(to_bottom,red,blue)]',
@ -10203,11 +10244,21 @@ test('bg', async () => {
background-color: #0000;
}
.-bg-conic-45\\/oklab {
--tw-gradient-position: from calc(45 * -1) in oklab, ;
background-image: conic-gradient(var(--tw-gradient-stops));
}
.-bg-linear-45 {
--tw-gradient-position: calc(45deg * -1) in oklch, ;
background-image: linear-gradient(var(--tw-gradient-stops));
}
.-bg-linear-45\\/oklab {
--tw-gradient-position: calc(45deg * -1) in oklab, ;
background-image: linear-gradient(var(--tw-gradient-stops));
}
.-bg-linear-\\[1\\.3rad\\] {
--tw-gradient-position: calc(74.4845deg * -1), ;
background-image: linear-gradient(var(--tw-gradient-stops, calc(74.4845deg * -1)));
@ -10218,6 +10269,66 @@ test('bg', async () => {
background-image: linear-gradient(var(--tw-gradient-stops, calc(125deg * -1)));
}
.bg-conic-45\\/\\[in_hsl_longer_hue\\] {
--tw-gradient-position: from 45deg in hsl longer hue, ;
background-image: conic-gradient(var(--tw-gradient-stops));
}
.bg-conic-45\\/oklab {
--tw-gradient-position: from 45deg in oklab, ;
background-image: conic-gradient(var(--tw-gradient-stops));
}
.bg-conic-45\\/shorter {
--tw-gradient-position: from 45deg in oklch shorter hue, ;
background-image: conic-gradient(var(--tw-gradient-stops));
}
.bg-conic\\/\\[in_hsl_longer_hue\\] {
--tw-gradient-position: in hsl longer hue, ;
background-image: conic-gradient(var(--tw-gradient-stops));
}
.bg-conic\\/decreasing {
--tw-gradient-position: in oklch decreasing hue, ;
background-image: conic-gradient(var(--tw-gradient-stops));
}
.bg-conic\\/hsl {
--tw-gradient-position: in hsl, ;
background-image: conic-gradient(var(--tw-gradient-stops));
}
.bg-conic\\/increasing {
--tw-gradient-position: in oklch increasing hue, ;
background-image: conic-gradient(var(--tw-gradient-stops));
}
.bg-conic\\/longer {
--tw-gradient-position: in oklch longer hue, ;
background-image: conic-gradient(var(--tw-gradient-stops));
}
.bg-conic\\/oklab {
--tw-gradient-position: in oklab, ;
background-image: conic-gradient(var(--tw-gradient-stops));
}
.bg-conic\\/oklch {
--tw-gradient-position: in oklch, ;
background-image: conic-gradient(var(--tw-gradient-stops));
}
.bg-conic\\/shorter {
--tw-gradient-position: in oklch shorter hue, ;
background-image: conic-gradient(var(--tw-gradient-stops));
}
.bg-conic\\/srgb {
--tw-gradient-position: in srgb, ;
background-image: conic-gradient(var(--tw-gradient-stops));
}
.bg-gradient-to-b {
--tw-gradient-position: to bottom in oklch, ;
background-image: linear-gradient(var(--tw-gradient-stops));
@ -10263,6 +10374,21 @@ test('bg', async () => {
background-image: linear-gradient(var(--tw-gradient-stops));
}
.bg-linear-45\\/\\[in_hsl_longer_hue\\] {
--tw-gradient-position: 45deg in hsl longer hue, ;
background-image: linear-gradient(var(--tw-gradient-stops));
}
.bg-linear-45\\/oklab {
--tw-gradient-position: 45deg in oklab, ;
background-image: linear-gradient(var(--tw-gradient-stops));
}
.bg-linear-45\\/shorter {
--tw-gradient-position: 45deg in oklch shorter hue, ;
background-image: linear-gradient(var(--tw-gradient-stops));
}
.bg-linear-\\[1\\.3rad\\] {
--tw-gradient-position: 74.4845deg, ;
background-image: linear-gradient(var(--tw-gradient-stops, 74.4845deg));
@ -10303,6 +10429,56 @@ test('bg', async () => {
background-image: linear-gradient(var(--tw-gradient-stops));
}
.bg-linear-to-r\\/\\[in_hsl_longer_hue\\] {
--tw-gradient-position: to right in hsl longer hue, ;
background-image: linear-gradient(var(--tw-gradient-stops));
}
.bg-linear-to-r\\/\\[longer\\] {
--tw-gradient-position: to right longer, ;
background-image: linear-gradient(var(--tw-gradient-stops));
}
.bg-linear-to-r\\/decreasing {
--tw-gradient-position: to right in oklch decreasing hue, ;
background-image: linear-gradient(var(--tw-gradient-stops));
}
.bg-linear-to-r\\/hsl {
--tw-gradient-position: to right in hsl, ;
background-image: linear-gradient(var(--tw-gradient-stops));
}
.bg-linear-to-r\\/increasing {
--tw-gradient-position: to right in oklch increasing hue, ;
background-image: linear-gradient(var(--tw-gradient-stops));
}
.bg-linear-to-r\\/longer {
--tw-gradient-position: to right in oklch longer hue, ;
background-image: linear-gradient(var(--tw-gradient-stops));
}
.bg-linear-to-r\\/oklab {
--tw-gradient-position: to right in oklab, ;
background-image: linear-gradient(var(--tw-gradient-stops));
}
.bg-linear-to-r\\/oklch {
--tw-gradient-position: to right in oklch, ;
background-image: linear-gradient(var(--tw-gradient-stops));
}
.bg-linear-to-r\\/shorter {
--tw-gradient-position: to right in oklch shorter hue, ;
background-image: linear-gradient(var(--tw-gradient-stops));
}
.bg-linear-to-r\\/srgb {
--tw-gradient-position: to right in srgb, ;
background-image: linear-gradient(var(--tw-gradient-stops));
}
.bg-linear-to-t {
--tw-gradient-position: to top in oklch, ;
background-image: linear-gradient(var(--tw-gradient-stops));
@ -10318,6 +10494,56 @@ test('bg', async () => {
background-image: linear-gradient(var(--tw-gradient-stops));
}
.bg-radial-\\[circle_at_center\\] {
--tw-gradient-position: circle at center, ;
background-image: radial-gradient(var(--tw-gradient-stops, circle at center));
}
.bg-radial\\/\\[in_hsl_longer_hue\\] {
--tw-gradient-position: in hsl longer hue, ;
background-image: radial-gradient(var(--tw-gradient-stops));
}
.bg-radial\\/decreasing {
--tw-gradient-position: in oklch decreasing hue, ;
background-image: radial-gradient(var(--tw-gradient-stops));
}
.bg-radial\\/hsl {
--tw-gradient-position: in hsl, ;
background-image: radial-gradient(var(--tw-gradient-stops));
}
.bg-radial\\/increasing {
--tw-gradient-position: in oklch increasing hue, ;
background-image: radial-gradient(var(--tw-gradient-stops));
}
.bg-radial\\/longer {
--tw-gradient-position: in oklch longer hue, ;
background-image: radial-gradient(var(--tw-gradient-stops));
}
.bg-radial\\/oklab {
--tw-gradient-position: in oklab, ;
background-image: radial-gradient(var(--tw-gradient-stops));
}
.bg-radial\\/oklch {
--tw-gradient-position: in oklch, ;
background-image: radial-gradient(var(--tw-gradient-stops));
}
.bg-radial\\/shorter {
--tw-gradient-position: in oklch shorter hue, ;
background-image: radial-gradient(var(--tw-gradient-stops));
}
.bg-radial\\/srgb {
--tw-gradient-position: in srgb, ;
background-image: radial-gradient(var(--tw-gradient-stops));
}
.bg-\\[image\\:var\\(--my-gradient\\)\\] {
background-image: var(--my-gradient);
}
@ -10498,31 +10724,13 @@ test('bg', async () => {
'-bg-space',
'bg-none/foo',
'bg-gradient-to-t/foo',
'bg-gradient-to-tr/foo',
'bg-gradient-to-r/foo',
'bg-gradient-to-br/foo',
'bg-gradient-to-b/foo',
'bg-gradient-to-bl/foo',
'bg-gradient-to-l/foo',
'bg-gradient-to-tl/foo',
'bg-linear-to-t/foo',
'bg-linear-to-tr/foo',
'bg-linear-to-r/foo',
'bg-linear-to-br/foo',
'bg-linear-to-b/foo',
'bg-linear-to-bl/foo',
'bg-linear-to-l/foo',
'bg-linear-to-tl/foo',
'bg-[url(/image.png)]/foo',
'bg-[url:var(--my-url)]/foo',
'bg-[linear-gradient(to_bottom,red,blue)]/foo',
'bg-[image:var(--my-gradient)]/foo',
'bg-linear-[125deg]/foo',
'bg-linear-[1.3rad]/foo',
'bg-linear-[to_bottom]/foo',
'-bg-linear-[125deg]/foo',
'-bg-linear-[1.3rad]/foo',
'bg-linear-[to_bottom]/hsl',
'bg-conic-[45deg]/hsl',
'bg-conic-[circle_at_center]/hsl',
'bg-auto/foo',
'bg-cover/foo',
'bg-contain/foo',

View file

@ -2261,123 +2261,206 @@ export function createUtilities(theme: Theme) {
staticUtility('bg-none', [['background-image', 'none']])
for (let [value, direction] of [
['t', 'top'],
['tr', 'top right'],
['r', 'right'],
['br', 'bottom right'],
['b', 'bottom'],
['bl', 'bottom left'],
['l', 'left'],
['tl', 'top left'],
]) {
staticUtility(`bg-gradient-to-${value}`, [
['--tw-gradient-position', `to ${direction} in oklch,`],
['background-image', `linear-gradient(var(--tw-gradient-stops))`],
{
// Deprecated
for (let [value, direction] of [
['t', 'top'],
['tr', 'top right'],
['r', 'right'],
['br', 'bottom right'],
['b', 'bottom'],
['bl', 'bottom left'],
['l', 'left'],
['tl', 'top left'],
]) {
staticUtility(`bg-gradient-to-${value}`, [
['--tw-gradient-position', `to ${direction} in oklch,`],
['background-image', `linear-gradient(var(--tw-gradient-stops))`],
])
}
let suggestedModifiers = [
'oklab',
'oklch',
'srgb',
'hsl',
'longer',
'shorter',
'increasing',
'decreasing',
]
let linearGradientDirections = new Map([
['to-t', 'to top'],
['to-tr', 'to top right'],
['to-r', 'to right'],
['to-br', 'to bottom right'],
['to-b', 'to bottom'],
['to-bl', 'to bottom left'],
['to-l', 'to left'],
['to-tl', 'to top left'],
])
staticUtility(`bg-linear-to-${value}`, [
['--tw-gradient-position', `to ${direction} in oklch,`],
['background-image', `linear-gradient(var(--tw-gradient-stops))`],
])
}
function resolveInterpolationModifier(modifier: CandidateModifier | null) {
let interpolationMethod = 'in oklch'
function handleBgLinear({ negative }: { negative: boolean }) {
return (candidate: Extract<Candidate, { kind: 'functional' }>) => {
if (!candidate.value || candidate.modifier) return
if (modifier?.kind === 'named') {
switch (modifier.value) {
case 'longer':
case 'shorter':
case 'increasing':
case 'decreasing':
interpolationMethod = `in oklch ${modifier.value} hue`
break
default:
interpolationMethod = `in ${modifier.value}`
}
} else if (modifier?.kind === 'arbitrary') {
interpolationMethod = modifier.value
}
let value = candidate.value.value
return interpolationMethod
}
if (candidate.value.kind === 'arbitrary') {
let type = candidate.value.dataType ?? inferDataType(value, ['angle'])
function handleBgLinear({ negative }: { negative: boolean }) {
return (candidate: Extract<Candidate, { kind: 'functional' }>) => {
if (!candidate.value) return
switch (type) {
case 'angle': {
value = negative ? `calc(${value} * -1)` : `${value}`
if (candidate.value.kind === 'arbitrary') {
if (candidate.modifier) return
return [
decl('--tw-gradient-position', `${value},`),
decl('background-image', `linear-gradient(var(--tw-gradient-stops,${value}))`),
]
}
default: {
if (negative) return
let value = candidate.value.value
let type = candidate.value.dataType ?? inferDataType(value, ['angle'])
return [
decl('--tw-gradient-position', `${value},`),
decl('background-image', `linear-gradient(var(--tw-gradient-stops,${value}))`),
]
switch (type) {
case 'angle': {
value = negative ? `calc(${value} * -1)` : `${value}`
return [
decl('--tw-gradient-position', `${value},`),
decl('background-image', `linear-gradient(var(--tw-gradient-stops,${value}))`),
]
}
default: {
if (negative) return
return [
decl('--tw-gradient-position', `${value},`),
decl('background-image', `linear-gradient(var(--tw-gradient-stops,${value}))`),
]
}
}
}
} else {
if (!isPositiveInteger(value)) return
value = negative ? `calc(${value}deg * -1)` : `${value}deg`
let value = candidate.value.value
if (!negative && linearGradientDirections.has(value)) {
value = linearGradientDirections.get(value)!
} else if (isPositiveInteger(value)) {
value = negative ? `calc(${value}deg * -1)` : `${value}deg`
} else {
return
}
let interpolationMethod = resolveInterpolationModifier(candidate.modifier)
return [
decl('--tw-gradient-position', `${value} in oklch,`),
decl('--tw-gradient-position', `${value} ${interpolationMethod},`),
decl('background-image', `linear-gradient(var(--tw-gradient-stops))`),
]
}
}
}
utilities.functional('-bg-linear', handleBgLinear({ negative: true }))
utilities.functional('bg-linear', handleBgLinear({ negative: false }))
utilities.functional('-bg-linear', handleBgLinear({ negative: true }))
utilities.functional('bg-linear', handleBgLinear({ negative: false }))
function handleBgConic({ negative }: { negative: boolean }) {
return (candidate: Extract<Candidate, { kind: 'functional' }>) => {
if (candidate.modifier) return
suggest('bg-linear', () => [
{
values: [...linearGradientDirections.keys()],
modifiers: suggestedModifiers,
},
{
values: ['0', '30', '60', '90', '120', '150', '180', '210', '240', '270', '300', '330'],
supportsNegative: true,
modifiers: suggestedModifiers,
},
])
if (!candidate.value) {
return [
decl('--tw-gradient-position', `in oklch,`),
decl('background-image', `conic-gradient(var(--tw-gradient-stops))`),
]
}
function handleBgConic({ negative }: { negative: boolean }) {
return (candidate: Extract<Candidate, { kind: 'functional' }>) => {
if (candidate.value?.kind === 'arbitrary') {
if (candidate.modifier) return
let value = candidate.value.value
return [
decl('--tw-gradient-position', `${value},`),
decl('background-image', `conic-gradient(var(--tw-gradient-stops,${value}))`),
]
}
let value = candidate.value.value
let interpolationMethod = resolveInterpolationModifier(candidate.modifier)
if (!candidate.value) {
return [
decl('--tw-gradient-position', `${interpolationMethod},`),
decl('background-image', `conic-gradient(var(--tw-gradient-stops))`),
]
}
let value = candidate.value.value
if (candidate.value.kind === 'arbitrary') {
return [
decl('--tw-gradient-position', `${value},`),
decl('background-image', `conic-gradient(var(--tw-gradient-stops,${value}))`),
]
} else {
if (!isPositiveInteger(value)) return
value = negative ? `calc(${value} * -1)` : `${value}deg`
return [
decl('--tw-gradient-position', `from ${value} in oklch,`),
decl('--tw-gradient-position', `from ${value} ${interpolationMethod},`),
decl('background-image', `conic-gradient(var(--tw-gradient-stops))`),
]
}
}
utilities.functional('-bg-conic', handleBgConic({ negative: true }))
utilities.functional('bg-conic', handleBgConic({ negative: false }))
suggest('bg-conic', () => [
{
hasDefaultValue: true,
modifiers: suggestedModifiers,
},
{
values: ['0', '30', '60', '90', '120', '150', '180', '210', '240', '270', '300', '330'],
supportsNegative: true,
modifiers: suggestedModifiers,
},
])
utilities.functional('bg-radial', (candidate) => {
if (!candidate.value) {
let interpolationMethod = resolveInterpolationModifier(candidate.modifier)
return [
decl('--tw-gradient-position', `${interpolationMethod},`),
decl('background-image', `radial-gradient(var(--tw-gradient-stops))`),
]
}
if (candidate.value.kind === 'arbitrary') {
if (candidate.modifier) return
let value = candidate.value.value
return [
decl('--tw-gradient-position', `${value},`),
decl('background-image', `radial-gradient(var(--tw-gradient-stops,${value}))`),
]
}
})
suggest('bg-radial', () => [
{
hasDefaultValue: true,
modifiers: suggestedModifiers,
},
])
}
utilities.functional('-bg-conic', handleBgConic({ negative: true }))
utilities.functional('bg-conic', handleBgConic({ negative: false }))
utilities.functional('bg-radial', (candidate) => {
if (candidate.modifier) return
if (!candidate.value) {
return [
decl('--tw-gradient-position', `in oklch,`),
decl('background-image', `radial-gradient(var(--tw-gradient-stops))`),
]
}
if (candidate.value.kind === 'arbitrary') {
let value = candidate.value.value
return [
decl('--tw-gradient-position', `${value},`),
decl('background-image', `radial-gradient(var(--tw-gradient-stops,${value}))`),
]
}
})
utilities.functional('bg', (candidate) => {
if (!candidate.value) return