Skip to content

Commit

Permalink
Add CSS filter support (#3923)
Browse files Browse the repository at this point in the history
* Implement `filter` helper classes with all methods

* Rename filter plugins/utilities, drop filter opacity, add drop shadow

* Remove non-final default filter values

* Working on default filter values, add basic JIT support

* Working on blur values

* New blur values (these are ~okay)

* Match drop-shadow values to box-shadows by eye as best as possible

* Update tests

* Fix kitchen sink test

* Add filter variants configuration

* Move drop-shadow to end of filters list

Co-Authored-By: Peter Neupauer <peter@neupauer.sk>

* Add invert variants configuration

* Add backdrop-filter utilities

* Update tests

* Transition filters by default

* Alphabetize new config keys

* Optimize filter plugins for JIT + add arbitrary value support

Except for drop-shadow, will add that once we can think it through a bit.

Co-authored-by: Nick Schmidt <nick@kreativgebiet.com>
Co-authored-by: Peter Neupauer <peter@neupauer.sk>
  • Loading branch information
3 people committed May 7, 2021
1 parent 359ce6b commit a05b369
Show file tree
Hide file tree
Showing 36 changed files with 11,398 additions and 38 deletions.
2,588 changes: 2,582 additions & 6 deletions __tests__/fixtures/tailwind-output-flagged.css

Large diffs are not rendered by default.

2,588 changes: 2,582 additions & 6 deletions __tests__/fixtures/tailwind-output-important.css

Large diffs are not rendered by default.

2,588 changes: 2,582 additions & 6 deletions __tests__/fixtures/tailwind-output-no-color-opacity.css

Large diffs are not rendered by default.

2,588 changes: 2,582 additions & 6 deletions __tests__/fixtures/tailwind-output.css

Large diffs are not rendered by default.

22 changes: 22 additions & 0 deletions jit/corePlugins/index.js
Expand Up @@ -292,6 +292,28 @@ module.exports = {
ringOffsetWidth: require('./ringOffsetWidth'),
ringOffsetColor: require('./ringOffsetColor'),

filter: require('../../lib/plugins/filter').default(),
blur: require('../../lib/plugins/blur').default(),
brightness: require('../../lib/plugins/brightness').default(),
contrast: require('../../lib/plugins/contrast').default(),
dropShadow: require('../../lib/plugins/dropShadow').default(),
grayscale: require('../../lib/plugins/grayscale').default(),
hueRotate: require('../../lib/plugins/hueRotate').default(),
invert: require('../../lib/plugins/invert').default(),
saturate: require('../../lib/plugins/saturate').default(),
sepia: require('../../lib/plugins/sepia').default(),

backdropFilter: require('../../lib/plugins/backdropFilter').default(),
backdropBlur: require('../../lib/plugins/backdropBlur').default(),
backdropBrightness: require('../../lib/plugins/backdropBrightness').default(),
backdropContrast: require('../../lib/plugins/backdropContrast').default(),
backdropGrayscale: require('../../lib/plugins/backdropGrayscale').default(),
backdropHueRotate: require('../../lib/plugins/backdropHueRotate').default(),
backdropInvert: require('../../lib/plugins/backdropInvert').default(),
backdropOpacity: require('../../lib/plugins/backdropOpacity').default(),
backdropSaturate: require('../../lib/plugins/backdropSaturate').default(),
backdropSepia: require('../../lib/plugins/backdropSepia').default(),

transitionProperty: require('./transitionProperty'),
transitionDelay: require('./transitionDelay'),
transitionDuration: require('./transitionDuration'),
Expand Down
51 changes: 51 additions & 0 deletions jit/tests/arbitrary-values.test.css
Expand Up @@ -136,6 +136,57 @@
.text-\[2\.23rem\] {
font-size: 2.23rem;
}
.blur-\[15px\] {
--tw-blur: blur(15px);
}
.brightness-\[300\%\] {
--tw-brightness: brightness(300%);
}
.contrast-\[2\.4\] {
--tw-contrast: contrast(2.4);
}
.grayscale-\[0\.55\] {
--tw-grayscale: grayscale(0.55);
}
.hue-rotate-\[0\.8turn\] {
--tw-hue-rotate: hue-rotate(0.8turn);
}
.invert-\[0\.75\] {
--tw-invert: invert(0.75);
}
.saturate-\[180\%\] {
--tw-saturate: saturate(180%);
}
.sepia-\[0\.2\] {
--tw-sepia: sepia(0.2);
}
.backdrop-blur-\[11px\] {
--tw-backdrop-blur: blur(11px);
}
.backdrop-brightness-\[1\.23\] {
--tw-backdrop-brightness: brightness(1.23);
}
.backdrop-contrast-\[0\.87\] {
--tw-backdrop-contrast: contrast(0.87);
}
.backdrop-grayscale-\[0\.42\] {
--tw-backdrop-grayscale: grayscale(0.42);
}
.backdrop-hue-rotate-\[1\.57rad\] {
--tw-backdrop-hue-rotate: hue-rotate(1.57rad);
}
.backdrop-invert-\[0\.66\] {
--tw-backdrop-invert: invert(0.66);
}
.backdrop-opacity-\[22\%\] {
--tw-backdrop-opacity: opacity(22%);
}
.backdrop-saturate-\[144\%\] {
--tw-backdrop-saturate: saturate(144%);
}
.backdrop-sepia-\[0\.38\] {
--tw-backdrop-sepia: sepia(0.38);
}
.duration-\[2s\] {
transition-duration: 2s;
}
Expand Down
17 changes: 17 additions & 0 deletions jit/tests/arbitrary-values.test.html
Expand Up @@ -43,5 +43,22 @@
<div class="duration-[var(--app-duration)]"></div>
<div class="p-[var(--app-padding)]"></div>
<div class="inset-[11px]"></div>
<div class="blur-[15px]"></div>
<div class="brightness-[300%]"></div>
<div class="contrast-[2.4]"></div>
<div class="grayscale-[0.55]"></div>
<div class="hue-rotate-[0.8turn]"></div>
<div class="invert-[0.75]"></div>
<div class="saturate-[180%]"></div>
<div class="sepia-[0.2]"></div>
<div class="backdrop-blur-[11px]"></div>
<div class="backdrop-brightness-[1.23]"></div>
<div class="backdrop-contrast-[0.87]"></div>
<div class="backdrop-grayscale-[0.42]"></div>
<div class="backdrop-hue-rotate-[1.57rad]"></div>
<div class="backdrop-invert-[0.66]"></div>
<div class="backdrop-opacity-[22%]"></div>
<div class="backdrop-saturate-[144%]"></div>
<div class="backdrop-sepia-[0.38]"></div>
</body>
</html>
1 change: 1 addition & 0 deletions jit/tests/arbitrary-values.test.js
Expand Up @@ -9,6 +9,7 @@ function run(input, config = {}) {

test('arbitrary values', () => {
let config = {
mode: 'jit',
purge: [path.resolve(__dirname, './arbitrary-values.test.html')],
corePlugins: { preflight: false },
theme: {},
Expand Down
90 changes: 89 additions & 1 deletion jit/tests/basic-usage.test.css
Expand Up @@ -633,9 +633,97 @@
.ring-offset-blue-300 {
--tw-ring-offset-color: #93c5fd;
}
.filter {
--tw-blur: var(--tw-empty, /*!*/ /*!*/);
--tw-brightness: var(--tw-empty, /*!*/ /*!*/);
--tw-contrast: var(--tw-empty, /*!*/ /*!*/);
--tw-grayscale: var(--tw-empty, /*!*/ /*!*/);
--tw-hue-rotate: var(--tw-empty, /*!*/ /*!*/);
--tw-invert: var(--tw-empty, /*!*/ /*!*/);
--tw-saturate: var(--tw-empty, /*!*/ /*!*/);
--tw-sepia: var(--tw-empty, /*!*/ /*!*/);
--tw-drop-shadow: var(--tw-empty, /*!*/ /*!*/);
filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale)
var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow);
}
.filter-none {
filter: none;
}
.blur-md {
--tw-blur: blur(12px);
}
.brightness-150 {
--tw-brightness: brightness(1.5);
}
.contrast-50 {
--tw-contrast: contrast(0.5);
}
.drop-shadow-md {
--tw-drop-shadow: drop-shadow(0 4px 3px rgba(0, 0, 0, 0.07))
drop-shadow(0 2px 2px rgba(0, 0, 0, 0.06));
}
.grayscale {
--tw-grayscale: grayscale(100%);
}
.hue-rotate-60 {
--tw-hue-rotate: hue-rotate(60deg);
}
.invert {
--tw-invert: invert(100%);
}
.saturate-200 {
--tw-saturate: saturate(2);
}
.sepia {
--tw-sepia: sepia(100%);
}
.backdrop-filter {
--tw-backdrop-blur: var(--tw-empty, /*!*/ /*!*/);
--tw-backdrop-brightness: var(--tw-empty, /*!*/ /*!*/);
--tw-backdrop-contrast: var(--tw-empty, /*!*/ /*!*/);
--tw-backdrop-grayscale: var(--tw-empty, /*!*/ /*!*/);
--tw-backdrop-hue-rotate: var(--tw-empty, /*!*/ /*!*/);
--tw-backdrop-invert: var(--tw-empty, /*!*/ /*!*/);
--tw-backdrop-opacity: var(--tw-empty, /*!*/ /*!*/);
--tw-backdrop-saturate: var(--tw-empty, /*!*/ /*!*/);
--tw-backdrop-sepia: var(--tw-empty, /*!*/ /*!*/);
backdrop-filter: var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast)
var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert)
var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia);
}
.backdrop-filter-none {
backdrop-filter: none;
}
.backdrop-blur-lg {
--tw-backdrop-blur: blur(16px);
}
.backdrop-brightness-50 {
--tw-backdrop-brightness: brightness(0.5);
}
.backdrop-contrast-0 {
--tw-backdrop-contrast: contrast(0);
}
.backdrop-grayscale {
--tw-backdrop-grayscale: grayscale(100%);
}
.backdrop-hue-rotate-90 {
--tw-backdrop-hue-rotate: hue-rotate(90deg);
}
.backdrop-invert {
--tw-backdrop-invert: invert(100%);
}
.backdrop-opacity-75 {
--tw-backdrop-opacity: opacity(0.75);
}
.backdrop-saturate-150 {
--tw-backdrop-saturate: saturate(1.5);
}
.backdrop-sepia {
--tw-backdrop-sepia: sepia(100%);
}
.transition {
transition-property: background-color, border-color, color, fill, stroke, opacity, box-shadow,
transform;
transform, filter, backdrop-filter;
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
transition-duration: 150ms;
}
Expand Down
6 changes: 6 additions & 0 deletions jit/tests/basic-usage.test.html
Expand Up @@ -108,6 +108,12 @@
<div class="ring-offset-2"></div>
<div class="ring-opacity-40"></div>
<div class="ring ring-4"></div>
<div
class="filter filter-none blur-md brightness-150 contrast-50 drop-shadow-md grayscale hue-rotate-60 invert saturate-200 sepia"
></div>
<div
class="backdrop-filter backdrop-filter-none backdrop-blur-lg backdrop-brightness-50 backdrop-contrast-0 backdrop-grayscale backdrop-hue-rotate-90 backdrop-invert backdrop-opacity-75 backdrop-saturate-150 backdrop-sepia"
></div>
<div class="rotate-3"></div>
<div class="scale-95"></div>
<div class="skew-y-12 skew-x-12"></div>
Expand Down
14 changes: 7 additions & 7 deletions jit/tests/kitchen-sink.test.css
Expand Up @@ -314,11 +314,11 @@ div {
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000),
var(--tw-shadow);
}
.filter-none {
filter: none;
.magic-none {
magic: none;
}
.filter-grayscale {
filter: grayscale(100%);
.magic-tons {
magic: tons;
}
.custom-util {
background: #abcdef;
Expand Down Expand Up @@ -410,7 +410,7 @@ div {
@media (prefers-reduced-motion: no-preference) {
.motion-safe\:transition {
transition-property: background-color, border-color, color, fill, stroke, opacity, box-shadow,
transform;
transform, filter, backdrop-filter;
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
transition-duration: 150ms;
}
Expand All @@ -421,7 +421,7 @@ div {
@media (prefers-reduced-motion: reduce) {
.motion-reduce\:transition {
transition-property: background-color, border-color, color, fill, stroke, opacity, box-shadow,
transform;
transform, filter, backdrop-filter;
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
transition-duration: 150ms;
}
Expand Down Expand Up @@ -535,7 +535,7 @@ div {
@media (prefers-reduced-motion: no-preference) {
.md\:motion-safe\:hover\:transition:hover {
transition-property: background-color, border-color, color, fill, stroke, opacity, box-shadow,
transform;
transform, filter, backdrop-filter;
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
transition-duration: 150ms;
}
Expand Down
2 changes: 1 addition & 1 deletion jit/tests/kitchen-sink.test.html
Expand Up @@ -27,7 +27,7 @@
<div class="md:dark:motion-safe:foo:active:custom-util"></div>
<div class="aspect-w-1 aspect-h-2"></div>
<div class="aspect-w-3 aspect-h-4"></div>
<div class="filter-none filter-grayscale"></div>
<div class="magic-none magic-tons"></div>
<div class="focus:font-normal"></div>
<div class="font-medium"></div>
<div class="bg-gradient-to-r from-foo"></div>
Expand Down
8 changes: 4 additions & 4 deletions jit/tests/kitchen-sink.test.js
Expand Up @@ -55,11 +55,11 @@ test('it works', () => {
})
addUtilities(
{
'.filter-none': {
filter: 'none',
'.magic-none': {
magic: 'none',
},
'.filter-grayscale': {
filter: 'grayscale(100%)',
'.magic-tons': {
magic: 'tons',
},
},
['responsive', 'hover']
Expand Down
20 changes: 20 additions & 0 deletions src/corePluginList.js
Expand Up @@ -122,4 +122,24 @@ export const corePluginList = [
'animation',
'mixBlendMode',
'backgroundBlendMode',
'filter',
'blur',
'brightness',
'contrast',
'dropShadow',
'grayscale',
'hueRotate',
'invert',
'saturate',
'sepia',
'backdropFilter',
'backdropBlur',
'backdropBrightness',
'backdropContrast',
'backdropGrayscale',
'backdropHueRotate',
'backdropInvert',
'backdropOpacity',
'backdropSaturate',
'backdropSepia',
]
37 changes: 37 additions & 0 deletions src/plugins/backdropBlur.js
@@ -0,0 +1,37 @@
import _ from 'lodash'
const { asValue, nameClass } = require('../../jit/pluginUtils')

export default function () {
return function ({ config, matchUtilities, addUtilities, theme, variants }) {
if (config('mode') === 'jit') {
matchUtilities({
'backdrop-blur': (modifier, { theme }) => {
let value = asValue(modifier, theme.backdropBlur)

if (value === undefined) {
return []
}

return {
[nameClass('backdrop-blur', modifier)]: { '--tw-backdrop-blur': `blur(${value})` },
}
},
})
} else {
const utilities = _.fromPairs(
_.map(theme('backdropBlur'), (value, modifier) => {
return [
nameClass('backdrop-blur', modifier),
{
'--tw-backdrop-blur': Array.isArray(value)
? value.map((v) => `blur(${v})`).join(' ')
: `blur(${value})`,
},
]
})
)

addUtilities(utilities, variants('backdopBlur'))
}
}
}

0 comments on commit a05b369

Please sign in to comment.