Skip to content

Commit

Permalink
Add gradient color stop position utilities (#10886)
Browse files Browse the repository at this point in the history
* add gradient color stop positions

* update tests to include gradient position color stop reset values

* add dedicated color stop position tests

* use `%` sign in the name of the uility

* update changelog

* ensure `length` values and css variables work
  • Loading branch information
RobinMalfait committed Mar 28, 2023
1 parent 0bfee99 commit 5115771
Show file tree
Hide file tree
Showing 14 changed files with 359 additions and 95 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Add `content-normal` and `content-stretch` utilities ([#10645](https://github.com/tailwindlabs/tailwindcss/pull/10645))
- Add `whitespace-break-spaces` utility ([#10729](https://github.com/tailwindlabs/tailwindcss/pull/10729))
- Add support for configuring default `font-variation-settings` for a `font-family` ([#10034](https://github.com/tailwindlabs/tailwindcss/pull/10034), [#10515](https://github.com/tailwindlabs/tailwindcss/pull/10515))
- Add gradient color stop position utilities ([#10886](https://github.com/tailwindlabs/tailwindcss/pull/10886))

### Fixed

Expand Down
25 changes: 17 additions & 8 deletions oxide/crates/core/src/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,14 +43,14 @@ impl<'a> Extractor<'a> {

#[cfg(test)]
pub fn unique_ord(input: &'a [u8], opts: ExtractorOptions) -> Vec<&'a [u8]> {
// This is an inefficient way to get an ordered, unique
// list as a Vec but it is only meant for testing.
let mut candidates = Self::all(input, opts);
let mut unique_list = FxHashSet::default();
unique_list.reserve(candidates.len());
candidates.retain(|c| unique_list.insert(*c));
// This is an inefficient way to get an ordered, unique
// list as a Vec but it is only meant for testing.
let mut candidates = Self::all(input, opts);
let mut unique_list = FxHashSet::default();
unique_list.reserve(candidates.len());
candidates.retain(|c| unique_list.insert(*c));

candidates
candidates
}
}

Expand Down Expand Up @@ -319,7 +319,16 @@ impl<'a> Extractor<'a> {

// Allowed characters in the candidate itself
// None of these can come after a closing bracket `]`
b'a'..=b'z' | b'A'..=b'Z' | b'0'..=b'9' | b'-' | b'_' | b'(' | b')' | b'!' | b'@'
b'a'..=b'z'
| b'A'..=b'Z'
| b'0'..=b'9'
| b'-'
| b'_'
| b'('
| b')'
| b'!'
| b'@'
| b'%'
if prev != b']' =>
{
/* TODO: The `b'@'` is necessary for custom separators like _@, maybe we can handle this in a better way... */
Expand Down
62 changes: 57 additions & 5 deletions src/corePlugins.js
Original file line number Diff line number Diff line change
Expand Up @@ -1756,40 +1756,92 @@ export let corePlugins = {
type: ['color', 'any'],
}

let positionOptions = {
values: theme('gradientColorStopPositions'),
type: ['length', 'percentage'],
}

matchUtilities(
{
from: (value) => {
let transparentToValue = transparentTo(value)

return {
'--tw-gradient-from': toColorValue(value, 'from'),
'--tw-gradient-to': transparentToValue,
'--tw-gradient-from': `${toColorValue(
value,
'from'
)} var(--tw-gradient-from-position)`,
'--tw-gradient-from-position': ' ',
'--tw-gradient-to': `${transparentToValue} var(--tw-gradient-from-position)`,
'--tw-gradient-to-position': ' ',
'--tw-gradient-stops': `var(--tw-gradient-from), var(--tw-gradient-to)`,
}
},
},
options
)

matchUtilities(
{
from: (value) => {
return {
'--tw-gradient-from-position': value,
}
},
},
positionOptions
)

matchUtilities(
{
via: (value) => {
let transparentToValue = transparentTo(value)

return {
'--tw-gradient-to': transparentToValue,
'--tw-gradient-via-position': ' ',
'--tw-gradient-to': `${transparentToValue} var(--tw-gradient-to-position)`,
'--tw-gradient-to-position': ' ',
'--tw-gradient-stops': `var(--tw-gradient-from), ${toColorValue(
value,
'via'
)}, var(--tw-gradient-to)`,
)} var(--tw-gradient-via-position), var(--tw-gradient-to)`,
}
},
},
options
)

matchUtilities(
{ to: (value) => ({ '--tw-gradient-to': toColorValue(value, 'to') }) },
{
via: (value) => {
return {
'--tw-gradient-via-position': value,
}
},
},
positionOptions
)

matchUtilities(
{
to: (value) => ({
'--tw-gradient-to': `${toColorValue(value, 'to')} var(--tw-gradient-to-position)`,
'--tw-gradient-to-position': ' ',
}),
},
options
)

matchUtilities(
{
to: (value) => {
return {
'--tw-gradient-to-position': value,
}
},
},
positionOptions
)
}
})(),

Expand Down
23 changes: 23 additions & 0 deletions stubs/config.full.js
Original file line number Diff line number Diff line change
Expand Up @@ -355,6 +355,29 @@ module.exports = {
},
gap: ({ theme }) => theme('spacing'),
gradientColorStops: ({ theme }) => theme('colors'),
gradientColorStopPositions: {
'0%': '0%',
'5%': '5%',
'10%': '10%',
'15%': '15%',
'20%': '20%',
'25%': '25%',
'30%': '30%',
'35%': '35%',
'40%': '40%',
'45%': '45%',
'50%': '50%',
'55%': '55%',
'60%': '60%',
'65%': '65%',
'70%': '70%',
'75%': '75%',
'80%': '80%',
'85%': '85%',
'90%': '90%',
'95%': '95%',
'100%': '100%',
},
grayscale: {
0: '0',
DEFAULT: '100%',
Expand Down
42 changes: 26 additions & 16 deletions tests/any-type.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@ crosscheck(({ stable, oxide }) => {
`

return run(input, config).then((result) => {
let oxideExpected = css`
oxide.expect(result.css).toMatchFormattedCss(css`
.inset-\[var\(--any-value\)\] {
inset: var(--any-value);
}
Expand Down Expand Up @@ -499,16 +499,22 @@ crosscheck(({ stable, oxide }) => {
background-color: var(--any-value);
}
.from-\[var\(--any-value\)\] {
--tw-gradient-from: var(--any-value);
--tw-gradient-to: #fff0;
--tw-gradient-from: var(--any-value) var(--tw-gradient-from-position);
--tw-gradient-from-position: ;
--tw-gradient-to: #fff0 var(--tw-gradient-from-position);
--tw-gradient-to-position: ;
--tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to);
}
.via-\[var\(--any-value\)\] {
--tw-gradient-to: #fff0;
--tw-gradient-stops: var(--tw-gradient-from), var(--any-value), var(--tw-gradient-to);
--tw-gradient-via-position: ;
--tw-gradient-to: #fff0 var(--tw-gradient-to-position);
--tw-gradient-to-position: ;
--tw-gradient-stops: var(--tw-gradient-from),
var(--any-value) var(--tw-gradient-via-position), var(--tw-gradient-to);
}
.to-\[var\(--any-value\)\] {
--tw-gradient-to: var(--any-value);
--tw-gradient-to: var(--any-value) var(--tw-gradient-to-position);
--tw-gradient-to-position: ;
}
.fill-\[var\(--any-value\)\] {
fill: var(--any-value);
Expand Down Expand Up @@ -732,8 +738,8 @@ crosscheck(({ stable, oxide }) => {
--tw-content: var(--any-value);
content: var(--tw-content);
}
`
let stableExpected = css`
`)
stable.expect(result.css).toMatchFormattedCss(css`
.inset-\[var\(--any-value\)\] {
inset: var(--any-value);
}
Expand Down Expand Up @@ -1056,16 +1062,22 @@ crosscheck(({ stable, oxide }) => {
--tw-bg-opacity: var(--any-value);
}
.from-\[var\(--any-value\)\] {
--tw-gradient-from: var(--any-value);
--tw-gradient-to: #fff0;
--tw-gradient-from: var(--any-value) var(--tw-gradient-from-position);
--tw-gradient-from-position: ;
--tw-gradient-to: #fff0 var(--tw-gradient-from-position);
--tw-gradient-to-position: ;
--tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to);
}
.via-\[var\(--any-value\)\] {
--tw-gradient-to: #fff0;
--tw-gradient-stops: var(--tw-gradient-from), var(--any-value), var(--tw-gradient-to);
--tw-gradient-via-position: ;
--tw-gradient-to: #fff0 var(--tw-gradient-to-position);
--tw-gradient-to-position: ;
--tw-gradient-stops: var(--tw-gradient-from),
var(--any-value) var(--tw-gradient-via-position), var(--tw-gradient-to);
}
.to-\[var\(--any-value\)\] {
--tw-gradient-to: var(--any-value);
--tw-gradient-to: var(--any-value) var(--tw-gradient-to-position);
--tw-gradient-to-position: ;
}
.fill-\[var\(--any-value\)\] {
fill: var(--any-value);
Expand Down Expand Up @@ -1298,9 +1310,7 @@ crosscheck(({ stable, oxide }) => {
--tw-content: var(--any-value);
content: var(--tw-content);
}
`
oxide.expect(result.css).toMatchFormattedCss(oxideExpected)
stable.expect(result.css).toMatchFormattedCss(stableExpected)
`)
})
})
test.todo('rewrite the any test to be easier to understand or break it up into multiple tests')
Expand Down
32 changes: 22 additions & 10 deletions tests/arbitrary-values.oxide.test.css
Original file line number Diff line number Diff line change
Expand Up @@ -659,28 +659,40 @@
background-image: var(--url);
}
.from-\[\#da5b66\] {
--tw-gradient-from: #da5b66;
--tw-gradient-to: #da5b6600;
--tw-gradient-from: #da5b66 var(--tw-gradient-from-position);
--tw-gradient-from-position: ;
--tw-gradient-to: #da5b6600 var(--tw-gradient-from-position);
--tw-gradient-to-position: ;
--tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to);
}
.from-\[var\(--color\)\] {
--tw-gradient-from: var(--color);
--tw-gradient-to: #fff0;
--tw-gradient-from: var(--color) var(--tw-gradient-from-position);
--tw-gradient-from-position: ;
--tw-gradient-to: #fff0 var(--tw-gradient-from-position);
--tw-gradient-to-position: ;
--tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to);
}
.via-\[\#da5b66\] {
--tw-gradient-to: #da5b6600;
--tw-gradient-stops: var(--tw-gradient-from), #da5b66, var(--tw-gradient-to);
--tw-gradient-via-position: ;
--tw-gradient-to: #da5b6600 var(--tw-gradient-to-position);
--tw-gradient-to-position: ;
--tw-gradient-stops: var(--tw-gradient-from), #da5b66 var(--tw-gradient-via-position),
var(--tw-gradient-to);
}
.via-\[var\(--color\)\] {
--tw-gradient-to: #fff0;
--tw-gradient-stops: var(--tw-gradient-from), var(--color), var(--tw-gradient-to);
--tw-gradient-via-position: ;
--tw-gradient-to: #fff0 var(--tw-gradient-to-position);
--tw-gradient-to-position: ;
--tw-gradient-stops: var(--tw-gradient-from), var(--color) var(--tw-gradient-via-position),
var(--tw-gradient-to);
}
.to-\[\#da5b66\] {
--tw-gradient-to: #da5b66;
--tw-gradient-to: #da5b66 var(--tw-gradient-to-position);
--tw-gradient-to-position: ;
}
.to-\[var\(--color\)\] {
--tw-gradient-to: var(--color);
--tw-gradient-to: var(--color) var(--tw-gradient-to-position);
--tw-gradient-to-position: ;
}
.bg-\[length\:200px_100px\] {
background-size: 200px 100px;
Expand Down
32 changes: 22 additions & 10 deletions tests/arbitrary-values.test.css
Original file line number Diff line number Diff line change
Expand Up @@ -688,28 +688,40 @@
background-image: var(--url);
}
.from-\[\#da5b66\] {
--tw-gradient-from: #da5b66;
--tw-gradient-to: #da5b6600;
--tw-gradient-from: #da5b66 var(--tw-gradient-from-position);
--tw-gradient-from-position: ;
--tw-gradient-to: #da5b6600 var(--tw-gradient-from-position);
--tw-gradient-to-position: ;
--tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to);
}
.from-\[var\(--color\)\] {
--tw-gradient-from: var(--color);
--tw-gradient-to: #fff0;
--tw-gradient-from: var(--color) var(--tw-gradient-from-position);
--tw-gradient-from-position: ;
--tw-gradient-to: #fff0 var(--tw-gradient-from-position);
--tw-gradient-to-position: ;
--tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to);
}
.via-\[\#da5b66\] {
--tw-gradient-to: #da5b6600;
--tw-gradient-stops: var(--tw-gradient-from), #da5b66, var(--tw-gradient-to);
--tw-gradient-via-position: ;
--tw-gradient-to: #da5b6600 var(--tw-gradient-to-position);
--tw-gradient-to-position: ;
--tw-gradient-stops: var(--tw-gradient-from), #da5b66 var(--tw-gradient-via-position),
var(--tw-gradient-to);
}
.via-\[var\(--color\)\] {
--tw-gradient-to: #fff0;
--tw-gradient-stops: var(--tw-gradient-from), var(--color), var(--tw-gradient-to);
--tw-gradient-via-position: ;
--tw-gradient-to: #fff0 var(--tw-gradient-to-position);
--tw-gradient-to-position: ;
--tw-gradient-stops: var(--tw-gradient-from), var(--color) var(--tw-gradient-via-position),
var(--tw-gradient-to);
}
.to-\[\#da5b66\] {
--tw-gradient-to: #da5b66;
--tw-gradient-to: #da5b66 var(--tw-gradient-to-position);
--tw-gradient-to-position: ;
}
.to-\[var\(--color\)\] {
--tw-gradient-to: var(--color);
--tw-gradient-to: var(--color) var(--tw-gradient-to-position);
--tw-gradient-to-position: ;
}
.bg-\[length\:200px_100px\] {
background-size: 200px 100px;
Expand Down
16 changes: 11 additions & 5 deletions tests/basic-usage.oxide.test.css
Original file line number Diff line number Diff line change
Expand Up @@ -607,16 +607,22 @@
background-image: linear-gradient(to right, var(--tw-gradient-stops));
}
.from-red-300 {
--tw-gradient-from: #fca5a5;
--tw-gradient-to: #fca5a500;
--tw-gradient-from: #fca5a5 var(--tw-gradient-from-position);
--tw-gradient-from-position: ;
--tw-gradient-to: #fca5a500 var(--tw-gradient-from-position);
--tw-gradient-to-position: ;
--tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to);
}
.via-purple-200 {
--tw-gradient-to: #e9d5ff00;
--tw-gradient-stops: var(--tw-gradient-from), #e9d5ff, var(--tw-gradient-to);
--tw-gradient-via-position: ;
--tw-gradient-to: #e9d5ff00 var(--tw-gradient-to-position);
--tw-gradient-to-position: ;
--tw-gradient-stops: var(--tw-gradient-from), #e9d5ff var(--tw-gradient-via-position),
var(--tw-gradient-to);
}
.to-blue-400 {
--tw-gradient-to: #60a5fa;
--tw-gradient-to: #60a5fa var(--tw-gradient-to-position);
--tw-gradient-to-position: ;
}
.decoration-slice {
-webkit-box-decoration-break: slice;
Expand Down
Loading

0 comments on commit 5115771

Please sign in to comment.