diff --git a/__tests__/fixtures/tailwind-output-ie11.css b/__tests__/fixtures/tailwind-output-ie11.css index 760a22cf86e5..7e06186a7600 100644 --- a/__tests__/fixtures/tailwind-output-ie11.css +++ b/__tests__/fixtures/tailwind-output-ie11.css @@ -577,6 +577,50 @@ video { height: auto; } +@keyframes spin { + from { + transform: rotate(0deg); + } + + to { + transform: rotate(360deg); + } +} + +@keyframes ping { + 0% { + transform: scale(1); + opacity: 1; + } + + 75%, 100% { + transform: scale(2); + opacity: 0; + } +} + +@keyframes pulse { + 0%, 100% { + opacity: 1; + } + + 50% { + opacity: .5; + } +} + +@keyframes bounce { + 0%, 100% { + transform: translateY(-25%); + animation-timing-function: cubic-bezier(0.8,0,1,1); + } + + 50% { + transform: translateY(0); + animation-timing-function: cubic-bezier(0,0,0.2,1); + } +} + .container { width: 100%; } @@ -10950,6 +10994,26 @@ video { transition-delay: 1000ms; } +.animate-none { + animation: none; +} + +.animate-spin { + animation: spin 1s linear infinite; +} + +.animate-ping { + animation: ping 1s cubic-bezier(0, 0, 0.2, 1) infinite; +} + +.animate-pulse { + animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite; +} + +.animate-bounce { + animation: bounce 1s infinite; +} + .example { font-weight: 700; color: #f56565; @@ -21329,6 +21393,26 @@ video { transition-delay: 1000ms; } + .sm\:animate-none { + animation: none; + } + + .sm\:animate-spin { + animation: spin 1s linear infinite; + } + + .sm\:animate-ping { + animation: ping 1s cubic-bezier(0, 0, 0.2, 1) infinite; + } + + .sm\:animate-pulse { + animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite; + } + + .sm\:animate-bounce { + animation: bounce 1s infinite; + } + .sm\:example { font-weight: 700; color: #f56565; @@ -31709,6 +31793,26 @@ video { transition-delay: 1000ms; } + .md\:animate-none { + animation: none; + } + + .md\:animate-spin { + animation: spin 1s linear infinite; + } + + .md\:animate-ping { + animation: ping 1s cubic-bezier(0, 0, 0.2, 1) infinite; + } + + .md\:animate-pulse { + animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite; + } + + .md\:animate-bounce { + animation: bounce 1s infinite; + } + .md\:example { font-weight: 700; color: #f56565; @@ -42089,6 +42193,26 @@ video { transition-delay: 1000ms; } + .lg\:animate-none { + animation: none; + } + + .lg\:animate-spin { + animation: spin 1s linear infinite; + } + + .lg\:animate-ping { + animation: ping 1s cubic-bezier(0, 0, 0.2, 1) infinite; + } + + .lg\:animate-pulse { + animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite; + } + + .lg\:animate-bounce { + animation: bounce 1s infinite; + } + .lg\:example { font-weight: 700; color: #f56565; @@ -52469,6 +52593,26 @@ video { transition-delay: 1000ms; } + .xl\:animate-none { + animation: none; + } + + .xl\:animate-spin { + animation: spin 1s linear infinite; + } + + .xl\:animate-ping { + animation: ping 1s cubic-bezier(0, 0, 0.2, 1) infinite; + } + + .xl\:animate-pulse { + animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite; + } + + .xl\:animate-bounce { + animation: bounce 1s infinite; + } + .xl\:example { font-weight: 700; color: #f56565; diff --git a/__tests__/fixtures/tailwind-output-important.css b/__tests__/fixtures/tailwind-output-important.css index 0949bc69edae..c8c61c6339bf 100644 --- a/__tests__/fixtures/tailwind-output-important.css +++ b/__tests__/fixtures/tailwind-output-important.css @@ -577,6 +577,50 @@ video { height: auto; } +@keyframes spin { + from { + transform: rotate(0deg); + } + + to { + transform: rotate(360deg); + } +} + +@keyframes ping { + 0% { + transform: scale(1); + opacity: 1; + } + + 75%, 100% { + transform: scale(2); + opacity: 0; + } +} + +@keyframes pulse { + 0%, 100% { + opacity: 1; + } + + 50% { + opacity: .5; + } +} + +@keyframes bounce { + 0%, 100% { + transform: translateY(-25%); + animation-timing-function: cubic-bezier(0.8,0,1,1); + } + + 50% { + transform: translateY(0); + animation-timing-function: cubic-bezier(0,0,0.2,1); + } +} + .container { width: 100%; } @@ -14336,6 +14380,26 @@ video { transition-delay: 1000ms !important; } +.animate-none { + animation: none !important; +} + +.animate-spin { + animation: spin 1s linear infinite !important; +} + +.animate-ping { + animation: ping 1s cubic-bezier(0, 0, 0.2, 1) infinite !important; +} + +.animate-pulse { + animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite !important; +} + +.animate-bounce { + animation: bounce 1s infinite !important; +} + .example { font-weight: 700; color: #f56565; @@ -28101,6 +28165,26 @@ video { transition-delay: 1000ms !important; } + .sm\:animate-none { + animation: none !important; + } + + .sm\:animate-spin { + animation: spin 1s linear infinite !important; + } + + .sm\:animate-ping { + animation: ping 1s cubic-bezier(0, 0, 0.2, 1) infinite !important; + } + + .sm\:animate-pulse { + animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite !important; + } + + .sm\:animate-bounce { + animation: bounce 1s infinite !important; + } + .sm\:example { font-weight: 700; color: #f56565; @@ -41867,6 +41951,26 @@ video { transition-delay: 1000ms !important; } + .md\:animate-none { + animation: none !important; + } + + .md\:animate-spin { + animation: spin 1s linear infinite !important; + } + + .md\:animate-ping { + animation: ping 1s cubic-bezier(0, 0, 0.2, 1) infinite !important; + } + + .md\:animate-pulse { + animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite !important; + } + + .md\:animate-bounce { + animation: bounce 1s infinite !important; + } + .md\:example { font-weight: 700; color: #f56565; @@ -55633,6 +55737,26 @@ video { transition-delay: 1000ms !important; } + .lg\:animate-none { + animation: none !important; + } + + .lg\:animate-spin { + animation: spin 1s linear infinite !important; + } + + .lg\:animate-ping { + animation: ping 1s cubic-bezier(0, 0, 0.2, 1) infinite !important; + } + + .lg\:animate-pulse { + animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite !important; + } + + .lg\:animate-bounce { + animation: bounce 1s infinite !important; + } + .lg\:example { font-weight: 700; color: #f56565; @@ -69399,6 +69523,26 @@ video { transition-delay: 1000ms !important; } + .xl\:animate-none { + animation: none !important; + } + + .xl\:animate-spin { + animation: spin 1s linear infinite !important; + } + + .xl\:animate-ping { + animation: ping 1s cubic-bezier(0, 0, 0.2, 1) infinite !important; + } + + .xl\:animate-pulse { + animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite !important; + } + + .xl\:animate-bounce { + animation: bounce 1s infinite !important; + } + .xl\:example { font-weight: 700; color: #f56565; diff --git a/__tests__/fixtures/tailwind-output-no-color-opacity.css b/__tests__/fixtures/tailwind-output-no-color-opacity.css index cc84a1b6e569..14ab13e58703 100644 --- a/__tests__/fixtures/tailwind-output-no-color-opacity.css +++ b/__tests__/fixtures/tailwind-output-no-color-opacity.css @@ -577,6 +577,50 @@ video { height: auto; } +@keyframes spin { + from { + transform: rotate(0deg); + } + + to { + transform: rotate(360deg); + } +} + +@keyframes ping { + 0% { + transform: scale(1); + opacity: 1; + } + + 75%, 100% { + transform: scale(2); + opacity: 0; + } +} + +@keyframes pulse { + 0%, 100% { + opacity: 1; + } + + 50% { + opacity: .5; + } +} + +@keyframes bounce { + 0%, 100% { + transform: translateY(-25%); + animation-timing-function: cubic-bezier(0.8,0,1,1); + } + + 50% { + transform: translateY(0); + animation-timing-function: cubic-bezier(0,0,0.2,1); + } +} + .container { width: 100%; } @@ -11888,6 +11932,26 @@ video { transition-delay: 1000ms; } +.animate-none { + animation: none; +} + +.animate-spin { + animation: spin 1s linear infinite; +} + +.animate-ping { + animation: ping 1s cubic-bezier(0, 0, 0.2, 1) infinite; +} + +.animate-pulse { + animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite; +} + +.animate-bounce { + animation: bounce 1s infinite; +} + .example { font-weight: 700; color: #f56565; @@ -23205,6 +23269,26 @@ video { transition-delay: 1000ms; } + .sm\:animate-none { + animation: none; + } + + .sm\:animate-spin { + animation: spin 1s linear infinite; + } + + .sm\:animate-ping { + animation: ping 1s cubic-bezier(0, 0, 0.2, 1) infinite; + } + + .sm\:animate-pulse { + animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite; + } + + .sm\:animate-bounce { + animation: bounce 1s infinite; + } + .sm\:example { font-weight: 700; color: #f56565; @@ -34523,6 +34607,26 @@ video { transition-delay: 1000ms; } + .md\:animate-none { + animation: none; + } + + .md\:animate-spin { + animation: spin 1s linear infinite; + } + + .md\:animate-ping { + animation: ping 1s cubic-bezier(0, 0, 0.2, 1) infinite; + } + + .md\:animate-pulse { + animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite; + } + + .md\:animate-bounce { + animation: bounce 1s infinite; + } + .md\:example { font-weight: 700; color: #f56565; @@ -45841,6 +45945,26 @@ video { transition-delay: 1000ms; } + .lg\:animate-none { + animation: none; + } + + .lg\:animate-spin { + animation: spin 1s linear infinite; + } + + .lg\:animate-ping { + animation: ping 1s cubic-bezier(0, 0, 0.2, 1) infinite; + } + + .lg\:animate-pulse { + animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite; + } + + .lg\:animate-bounce { + animation: bounce 1s infinite; + } + .lg\:example { font-weight: 700; color: #f56565; @@ -57159,6 +57283,26 @@ video { transition-delay: 1000ms; } + .xl\:animate-none { + animation: none; + } + + .xl\:animate-spin { + animation: spin 1s linear infinite; + } + + .xl\:animate-ping { + animation: ping 1s cubic-bezier(0, 0, 0.2, 1) infinite; + } + + .xl\:animate-pulse { + animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite; + } + + .xl\:animate-bounce { + animation: bounce 1s infinite; + } + .xl\:example { font-weight: 700; color: #f56565; diff --git a/__tests__/fixtures/tailwind-output.css b/__tests__/fixtures/tailwind-output.css index 97596e0bc334..064db9040184 100644 --- a/__tests__/fixtures/tailwind-output.css +++ b/__tests__/fixtures/tailwind-output.css @@ -577,6 +577,50 @@ video { height: auto; } +@keyframes spin { + from { + transform: rotate(0deg); + } + + to { + transform: rotate(360deg); + } +} + +@keyframes ping { + 0% { + transform: scale(1); + opacity: 1; + } + + 75%, 100% { + transform: scale(2); + opacity: 0; + } +} + +@keyframes pulse { + 0%, 100% { + opacity: 1; + } + + 50% { + opacity: .5; + } +} + +@keyframes bounce { + 0%, 100% { + transform: translateY(-25%); + animation-timing-function: cubic-bezier(0.8,0,1,1); + } + + 50% { + transform: translateY(0); + animation-timing-function: cubic-bezier(0,0,0.2,1); + } +} + .container { width: 100%; } @@ -14336,6 +14380,26 @@ video { transition-delay: 1000ms; } +.animate-none { + animation: none; +} + +.animate-spin { + animation: spin 1s linear infinite; +} + +.animate-ping { + animation: ping 1s cubic-bezier(0, 0, 0.2, 1) infinite; +} + +.animate-pulse { + animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite; +} + +.animate-bounce { + animation: bounce 1s infinite; +} + .example { font-weight: 700; color: #f56565; @@ -28101,6 +28165,26 @@ video { transition-delay: 1000ms; } + .sm\:animate-none { + animation: none; + } + + .sm\:animate-spin { + animation: spin 1s linear infinite; + } + + .sm\:animate-ping { + animation: ping 1s cubic-bezier(0, 0, 0.2, 1) infinite; + } + + .sm\:animate-pulse { + animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite; + } + + .sm\:animate-bounce { + animation: bounce 1s infinite; + } + .sm\:example { font-weight: 700; color: #f56565; @@ -41867,6 +41951,26 @@ video { transition-delay: 1000ms; } + .md\:animate-none { + animation: none; + } + + .md\:animate-spin { + animation: spin 1s linear infinite; + } + + .md\:animate-ping { + animation: ping 1s cubic-bezier(0, 0, 0.2, 1) infinite; + } + + .md\:animate-pulse { + animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite; + } + + .md\:animate-bounce { + animation: bounce 1s infinite; + } + .md\:example { font-weight: 700; color: #f56565; @@ -55633,6 +55737,26 @@ video { transition-delay: 1000ms; } + .lg\:animate-none { + animation: none; + } + + .lg\:animate-spin { + animation: spin 1s linear infinite; + } + + .lg\:animate-ping { + animation: ping 1s cubic-bezier(0, 0, 0.2, 1) infinite; + } + + .lg\:animate-pulse { + animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite; + } + + .lg\:animate-bounce { + animation: bounce 1s infinite; + } + .lg\:example { font-weight: 700; color: #f56565; @@ -69399,6 +69523,26 @@ video { transition-delay: 1000ms; } + .xl\:animate-none { + animation: none; + } + + .xl\:animate-spin { + animation: spin 1s linear infinite; + } + + .xl\:animate-ping { + animation: ping 1s cubic-bezier(0, 0, 0.2, 1) infinite; + } + + .xl\:animate-pulse { + animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite; + } + + .xl\:animate-bounce { + animation: bounce 1s infinite; + } + .xl\:example { font-weight: 700; color: #f56565; diff --git a/src/corePlugins.js b/src/corePlugins.js index f1211ba361e2..41e2f79ab506 100644 --- a/src/corePlugins.js +++ b/src/corePlugins.js @@ -97,6 +97,7 @@ import backgroundOpacity from './plugins/backgroundOpacity' import borderOpacity from './plugins/borderOpacity' import textOpacity from './plugins/textOpacity' import placeholderOpacity from './plugins/placeholderOpacity' +import animation from './plugins/animation' import configurePlugins from './util/configurePlugins' @@ -201,5 +202,6 @@ export default function({ corePlugins: corePluginConfig }) { transitionTimingFunction, transitionDuration, transitionDelay, + animation, }) } diff --git a/src/plugins/animation.js b/src/plugins/animation.js new file mode 100644 index 000000000000..50ad186d2920 --- /dev/null +++ b/src/plugins/animation.js @@ -0,0 +1,26 @@ +import _ from 'lodash' + +export default function() { + return function({ addBase, addUtilities, e, theme, variants }) { + const keyframesConfig = theme('keyframes') + const keyframesStyles = _.fromPairs( + _.toPairs(keyframesConfig).map(([name, keyframes]) => { + return [`@keyframes ${name}`, keyframes] + }) + ) + addBase(keyframesStyles) + + const animationConfig = theme('animation') + const utilities = _.fromPairs( + _.toPairs(animationConfig).map(([suffix, animation]) => { + return [ + `.${e(`animate-${suffix}`)}`, + { + animation, + }, + ] + }) + ) + addUtilities(utilities, variants('animation')) + } +} diff --git a/stubs/defaultConfig.stub.js b/stubs/defaultConfig.stub.js index bab7b16d4434..f75f95f3f13c 100644 --- a/stubs/defaultConfig.stub.js +++ b/stubs/defaultConfig.stub.js @@ -622,6 +622,37 @@ module.exports = { '700': '700ms', '1000': '1000ms', }, + animation: { + none: 'none', + spin: 'spin 1s linear infinite', + ping: 'ping 1s cubic-bezier(0, 0, 0.2, 1) infinite', + pulse: 'pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite', + bounce: 'bounce 1s infinite', + }, + keyframes: { + spin: { + from: { transform: 'rotate(0deg)' }, + to: { transform: 'rotate(360deg)' }, + }, + ping: { + '0%': { transform: 'scale(1)', opacity: '1' }, + '75%, 100%': { transform: 'scale(2)', opacity: '0' }, + }, + pulse: { + '0%, 100%': { opacity: '1' }, + '50%': { opacity: '.5' }, + }, + bounce: { + '0%, 100%': { + transform: 'translateY(-25%)', + animationTimingFunction: 'cubic-bezier(0.8,0,1,1)', + }, + '50%': { + transform: 'translateY(0)', + animationTimingFunction: 'cubic-bezier(0,0,0.2,1)', + }, + }, + }, }, variants: { accessibility: ['responsive', 'focus'], @@ -722,6 +753,7 @@ module.exports = { transitionTimingFunction: ['responsive'], transitionDuration: ['responsive'], transitionDelay: ['responsive'], + animation: ['responsive'], }, corePlugins: {}, plugins: [],