UNPKG

tailwindcss-motion

Version:

Tailwind Motion is a Tailwind CSS Plugin made by Rombo. It’s a simple, yet powerful, animation library for Tailwind CSS.

1,382 lines (1,377 loc) 67.9 kB
import createPlugin from 'tailwindcss/plugin.js'; import flattenColorPalette from 'tailwindcss/lib/util/flattenColorPalette.js'; // src/index.ts var allEnterAnimations = "var(--motion-scale-in-animation), var(--motion-translate-in-animation), var(--motion-rotate-in-animation), var(--motion-filter-in-animation), var(--motion-opacity-in-animation), var(--motion-background-color-in-animation), var(--motion-text-color-in-animation)"; var allExitAnimations = "var(--motion-scale-out-animation), var(--motion-translate-out-animation), var(--motion-rotate-out-animation), var(--motion-filter-out-animation), var(--motion-opacity-out-animation), var(--motion-background-color-out-animation), var(--motion-text-color-out-animation)"; var allLoopAnimations = "var(--motion-scale-loop-animation), var(--motion-translate-loop-animation), var(--motion-rotate-loop-animation), var(--motion-filter-loop-animation), var(--motion-opacity-loop-animation), var(--motion-background-color-loop-animation), var(--motion-text-color-loop-animation)"; var allLoopAndEnterAnimations = `${allEnterAnimations}, ${allLoopAnimations}`; var scaleInAnimation = "motion-scale-in calc(var(--motion-scale-duration, var(--motion-duration)) * var(--motion-scale-perceptual-duration-multiplier, var(--motion-perceptual-duration-multiplier))) var(--motion-scale-timing, var(--motion-timing)) var(--motion-scale-delay, var(--motion-delay)) both"; var scaleOutAnimation = "motion-scale-out calc(var(--motion-scale-duration, var(--motion-duration)) * var(--motion-scale-perceptual-duration-multiplier, var(--motion-perceptual-duration-multiplier))) var(--motion-scale-timing, var(--motion-timing)) var(--motion-scale-delay, var(--motion-delay)) both"; var scaleLoopAnimation = (type) => `motion-scale-loop-${type} calc(var(--motion-scale-duration, var(--motion-duration)) * var(--motion-scale-perceptual-duration-multiplier, var(--motion-perceptual-duration-multiplier))) var(--motion-scale-timing, var(--motion-timing)) var(--motion-scale-delay, var(--motion-delay)) both var(--motion-scale-loop-count, var(--motion-loop-count))`; var translateInAnimation = "motion-translate-in calc(var(--motion-translate-duration, var(--motion-duration)) * var(--motion-translate-perceptual-duration-multiplier, var(--motion-perceptual-duration-multiplier))) var(--motion-translate-timing, var(--motion-timing)) var(--motion-translate-delay, var(--motion-delay)) both"; var translateOutAnimation = "motion-translate-out calc(var(--motion-translate-duration, var(--motion-duration)) * var(--motion-translate-perceptual-duration-multiplier, var(--motion-perceptual-duration-multiplier))) var(--motion-translate-timing, var(--motion-timing)) var(--motion-translate-delay, var(--motion-delay)) both"; var translateLoopAnimation = (type) => `motion-translate-loop-${type} calc(var(--motion-translate-duration, var(--motion-duration)) * var(--motion-translate-perceptual-duration-multiplier, var(--motion-perceptual-duration-multiplier))) var(--motion-translate-timing, var(--motion-timing)) var(--motion-translate-delay, var(--motion-delay)) both var(--motion-translate-loop-count, var(--motion-loop-count))`; var rotateInAnimation = "motion-rotate-in calc(var(--motion-rotate-duration, var(--motion-duration)) * var(--motion-rotate-perceptual-duration-multiplier, var(--motion-perceptual-duration-multiplier))) var(--motion-rotate-timing, var(--motion-timing)) var(--motion-rotate-delay, var(--motion-delay)) both"; var rotateOutAnimation = "motion-rotate-out calc(var(--motion-rotate-duration, var(--motion-duration)) * var(--motion-rotate-perceptual-duration-multiplier, var(--motion-perceptual-duration-multiplier))) var(--motion-rotate-timing, var(--motion-timing)) var(--motion-rotate-delay, var(--motion-delay)) both"; var rotateLoopAnimation = (type) => `motion-rotate-loop-${type} calc(var(--motion-rotate-duration, var(--motion-duration)) * var(--motion-rotate-perceptual-duration-multiplier, var(--motion-perceptual-duration-multiplier))) var(--motion-rotate-timing, var(--motion-timing)) var(--motion-rotate-delay, var(--motion-delay)) both var(--motion-rotate-loop-count, var(--motion-loop-count))`; var filterInAnimation = "motion-filter-in calc(var(--motion-filter-duration, var(--motion-duration)) * var(--motion-filter-perceptual-duration-multiplier, var(--motion-perceptual-duration-multiplier))) var(--motion-filter-timing, var(--motion-timing)) var(--motion-filter-delay, var(--motion-delay)) both"; var filterOutAnimation = "motion-filter-out calc(var(--motion-filter-duration, var(--motion-duration)) * var(--motion-filter-perceptual-duration-multiplier, var(--motion-perceptual-duration-multiplier))) var(--motion-filter-timing, var(--motion-timing)) var(--motion-filter-delay, var(--motion-delay)) both"; var filterLoopAnimation = (type) => `motion-filter-loop-${type} calc(var(--motion-filter-duration, var(--motion-duration)) * var(--motion-filter-perceptual-duration-multiplier, var(--motion-perceptual-duration-multiplier))) var(--motion-filter-timing, var(--motion-timing)) var(--motion-filter-delay, var(--motion-delay)) both var(--motion-filter-loop-count, var(--motion-loop-count))`; var opacityInAnimation = "motion-opacity-in calc(var(--motion-opacity-duration, var(--motion-duration)) * var(--motion-opacity-perceptual-duration-multiplier, var(--motion-perceptual-duration-multiplier))) var(--motion-opacity-timing, var(--motion-timing)) var(--motion-opacity-delay, var(--motion-delay)) both"; var opacityOutAnimation = "motion-opacity-out calc(var(--motion-opacity-duration, var(--motion-duration)) * var(--motion-opacity-perceptual-duration-multiplier, var(--motion-perceptual-duration-multiplier))) var(--motion-opacity-timing, var(--motion-timing)) var(--motion-opacity-delay, var(--motion-delay)) both"; var opacityLoopAnimation = (type) => `motion-opacity-loop-${type} calc(var(--motion-opacity-duration, var(--motion-duration)) * var(--motion-opacity-perceptual-duration-multiplier, var(--motion-perceptual-duration-multiplier))) var(--motion-opacity-timing, var(--motion-timing)) var(--motion-opacity-delay, var(--motion-delay)) both var(--motion-opacity-loop-count, var(--motion-loop-count))`; var backgroundColorInAnimation = "motion-background-color-in calc(var(--motion-background-color-duration, var(--motion-duration)) * var(--motion-background-color-perceptual-duration-multiplier, var(--motion-perceptual-duration-multiplier))) var(--motion-background-color-timing, var(--motion-timing)) var(--motion-background-color-delay, var(--motion-delay)) both"; var backgroundColorOutAnimation = "motion-background-color-out calc(var(--motion-background-color-duration, var(--motion-duration)) * var(--motion-background-color-perceptual-duration-multiplier, var(--motion-perceptual-duration-multiplier))) var(--motion-background-color-timing, var(--motion-timing)) var(--motion-background-color-delay, var(--motion-delay)) both"; var backgroundColorLoopAnimation = (type) => `motion-background-color-loop-${type} calc(var(--motion-background-color-duration, var(--motion-duration)) * var(--motion-background-color-perceptual-duration-multiplier, var(--motion-perceptual-duration-multiplier))) var(--motion-background-color-timing, var(--motion-timing)) var(--motion-background-color-delay, var(--motion-delay)) both var(--motion-background-color-loop-count, var(--motion-loop-count))`; var textColorInAnimation = "motion-text-color-in calc(var(--motion-text-color-duration, var(--motion-duration)) * var(--motion-text-color-perceptual-duration-multiplier, var(--motion-perceptual-duration-multiplier))) var(--motion-text-color-timing, var(--motion-timing)) var(--motion-text-color-delay, var(--motion-delay)) both"; var textColorOutAnimation = "motion-text-color-out calc(var(--motion-text-color-duration, --motion-duration) * var(--motion-text-color-perceptual-duration-multiplier, --motion-perceptual-duration-multiplier)) var(--motion-text-color-timing, --motion-timing) var(--motion-text-color-delay, --motion-delay) both"; var textColorLoopAnimation = (type) => `motion-text-color-loop-${type} calc(var(--motion-text-color-duration, --motion-duration) * var(--motion-text-color-perceptual-duration-multiplier, --motion-perceptual-duration-multiplier)) var(--motion-text-color-timing, --motion-timing) var(--motion-text-color-delay, --motion-delay) both var(--motion-text-color-loop-count, --motion-loop-count)`; function addBaseAnimations(matchUtilities, theme) { matchUtilities( { "motion-scale-in": (value) => ({ "--motion-origin-scale-x": value, "--motion-origin-scale-y": value, "--motion-scale-in-animation": scaleInAnimation, animation: allLoopAndEnterAnimations }), "motion-scale-x-in": (value) => ({ "--motion-origin-scale-x": value, "--motion-scale-in-animation": scaleInAnimation, animation: allLoopAndEnterAnimations }), "motion-scale-y-in": (value) => ({ "--motion-origin-scale-y": value, "--motion-scale-in-animation": scaleInAnimation, animation: allLoopAndEnterAnimations }), "motion-scale-out": (value) => ({ "--motion-end-scale-x": value, "--motion-end-scale-y": value, "--motion-scale-out-animation": scaleOutAnimation, animation: allExitAnimations }), "motion-scale-x-out": (value) => ({ "--motion-end-scale-x": value, "--motion-scale-out-animation": scaleOutAnimation, animation: allExitAnimations }), "motion-scale-y-out": (value) => ({ "--motion-end-scale-y": value, "--motion-scale-out-animation": scaleOutAnimation, animation: allExitAnimations }) }, { values: theme("motionScale") } ); matchUtilities( { "motion-scale-x-loop": (value, { modifier }) => ({ "--motion-loop-scale-x": value, "--motion-scale-loop-animation": scaleLoopAnimation( modifier || "mirror" ), animationComposition: "accumulate", animation: allLoopAndEnterAnimations }), "motion-scale-y-loop": (value, { modifier }) => ({ "--motion-loop-scale-y": value, "--motion-scale-loop-animation": scaleLoopAnimation( modifier || "mirror" ), animationComposition: "accumulate", animation: allLoopAndEnterAnimations }), "motion-scale-loop": (value, { modifier }) => ({ "--motion-loop-scale-x": value, "--motion-loop-scale-y": value, "--motion-scale-loop-animation": scaleLoopAnimation( modifier || "mirror" ), animationComposition: "accumulate", animation: allLoopAndEnterAnimations }) }, { values: theme("motionScale"), modifiers: { mirror: "mirror", reset: "reset" } } ); matchUtilities( { "motion-translate-x-in": (value) => ({ "--motion-origin-translate-x": value, "--motion-translate-in-animation": translateInAnimation, animation: allLoopAndEnterAnimations }), "motion-translate-y-in": (value) => ({ "--motion-origin-translate-y": value, "--motion-translate-in-animation": translateInAnimation, animation: allLoopAndEnterAnimations }), "motion-translate-x-out": (value) => ({ "--motion-end-translate-x": value, "--motion-translate-out-animation": translateOutAnimation, animation: allExitAnimations }), "motion-translate-y-out": (value) => ({ "--motion-end-translate-y": value, "--motion-translate-out-animation": translateOutAnimation, animation: allExitAnimations }) }, { values: theme("motionTranslate"), supportsNegativeValues: true } ); matchUtilities( { "motion-translate-x-loop": (value, { modifier }) => { return { "--motion-loop-translate-x": value, "--motion-translate-loop-animation": translateLoopAnimation( modifier || "mirror" ), animationComposition: "accumulate", animation: allLoopAndEnterAnimations }; }, "motion-translate-y-loop": (value, { modifier }) => { return { "--motion-loop-translate-y": value, "--motion-translate-loop-animation": translateLoopAnimation( modifier || "mirror" ), animationComposition: "accumulate", animation: allLoopAndEnterAnimations }; } }, { values: theme("motionTranslate"), supportsNegativeValues: true, modifiers: { mirror: "mirror", reset: "reset" } } ); matchUtilities( { "motion-rotate-in": (value) => ({ "--motion-origin-rotate": value, "--motion-rotate-in-animation": rotateInAnimation, animation: allLoopAndEnterAnimations }), "motion-rotate-out": (value) => ({ "--motion-end-rotate": value, "--motion-rotate-out-animation": rotateOutAnimation, animation: allExitAnimations }) }, { values: theme("motionRotate"), supportsNegativeValues: true } ); matchUtilities( { "motion-rotate-loop": (value, { modifier }) => ({ "--motion-loop-rotate": value, "--motion-rotate-loop-animation": rotateLoopAnimation( modifier || "mirror" ), animationComposition: "accumulate", animation: allLoopAndEnterAnimations }) }, { values: theme("motionRotate"), supportsNegativeValues: true, modifiers: { mirror: "mirror", reset: "reset" } } ); matchUtilities( { "motion-blur-in": (value) => ({ "--motion-origin-blur": value, "--motion-filter-in-animation": filterInAnimation, animation: allLoopAndEnterAnimations }), "motion-blur-out": (value) => ({ "--motion-end-blur": value, "--motion-filter-out-animation": filterOutAnimation, animation: allExitAnimations }) }, { values: theme("motionBlur") } ); matchUtilities( { "motion-blur-loop": (value, { modifier }) => ({ "--motion-loop-blur": value, "--motion-filter-loop-animation": filterLoopAnimation( modifier || "mirror" ), animationComposition: "accumulate", animation: allLoopAndEnterAnimations }) }, { values: theme("motionBlur"), modifiers: { mirror: "mirror", reset: "reset" } } ); matchUtilities( { "motion-grayscale-in": (value) => ({ "--motion-origin-grayscale": value, "--motion-filter-in-animation": filterInAnimation, animation: allLoopAndEnterAnimations }), "motion-grayscale-out": (value) => ({ "--motion-end-grayscale": value, "--motion-filter-out-animation": filterOutAnimation, animation: allExitAnimations }) }, { values: theme("motionGrayscale") } ); matchUtilities( { "motion-grayscale-loop": (value, { modifier }) => ({ "--motion-loop-grayscale": value, "--motion-filter-loop-animation": filterLoopAnimation( modifier || "mirror" ), animationComposition: "accumulate", animation: allLoopAndEnterAnimations }) }, { values: theme("motionGrayscale"), modifiers: { mirror: "mirror", reset: "reset" } } ); matchUtilities( { "motion-opacity-in": (value) => ({ "--motion-origin-opacity": value, "--motion-opacity-in-animation": opacityInAnimation, animation: allLoopAndEnterAnimations }), "motion-opacity-out": (value) => ({ "--motion-end-opacity": value, "--motion-opacity-out-animation": opacityOutAnimation, animation: allExitAnimations }) }, { values: theme("motionOpacity") } ); matchUtilities( { "motion-opacity-loop": (value, { modifier }) => ({ // we need to subtract 1 because of animation composition "--motion-loop-opacity": `calc(${value} - 1)`, "--motion-opacity-loop-animation": opacityLoopAnimation( modifier || "mirror" ), animationComposition: "accumulate", animation: allLoopAndEnterAnimations }) }, { values: theme("motionOpacity"), modifiers: { mirror: "mirror", reset: "reset" } } ); matchUtilities( { "motion-bg-in": (value) => ({ "--motion-origin-background-color": value, "--motion-background-color-in-animation": backgroundColorInAnimation, animation: allLoopAndEnterAnimations }), "motion-bg-out": (value) => ({ "--motion-end-background-color": value, "--motion-background-color-out-animation": backgroundColorOutAnimation, animation: allExitAnimations }) }, { values: theme("motionBackgroundColor"), type: "color" } ); matchUtilities( { "motion-bg-loop": (value, { modifier }) => ({ "--motion-loop-background-color": value, "--motion-background-color-loop-animation": backgroundColorLoopAnimation(modifier || "mirror"), // no animation composition because it makes colors add animation: allLoopAndEnterAnimations }) }, { values: theme("motionBackgroundColor"), type: "color", modifiers: { mirror: "mirror", reset: "reset" } } ); matchUtilities( { "motion-text-in": (value) => ({ "--motion-origin-text-color": value, "--motion-text-color-in-animation": textColorInAnimation, animation: allLoopAndEnterAnimations }), "motion-text-out": (value) => ({ "--motion-end-text-color": value, "--motion-text-color-out-animation": textColorOutAnimation, animation: allExitAnimations }) }, { values: theme("motionTextColor"), type: "color" } ); matchUtilities( { "motion-text-loop": (value, { modifier }) => ({ "--motion-loop-text-color": value, "--motion-text-color-loop-animation": textColorLoopAnimation( modifier || "mirror" ), animationComposition: "accumulate", animation: allLoopAndEnterAnimations }) }, { values: theme("motionTextColor"), type: "color", modifiers: { mirror: "mirror", reset: "reset" } } ); } var baseAnimationsTheme = { motionScale: (theme) => ({ ...theme("scale"), DEFAULT: "50%" }), motionTranslate: { "0": "0%", "25": "25%", "50": "50%", "75": "75%", "100": "100%", "150": "150%", DEFAULT: "25%" }, motionRotate: (theme) => ({ ...theme("rotate"), DEFAULT: "12deg" }), motionBlur: (theme) => theme("blur"), motionGrayscale: (theme) => theme("grayscale"), motionOpacity: (theme) => ({ ...theme("opacity"), DEFAULT: "0", "0": "0.001" }), motionBackgroundColor: (theme) => flattenColorPalette(theme("colors")), motionTextColor: (theme) => flattenColorPalette(theme("colors")) }; // src/defaults.ts function addDefaults(addBase) { addBase({ /** * Easing functions */ "@property --motion-bounce": { syntax: '"*"', inherits: "false", "initial-value": "linear(0, 0.004, 0.016, 0.035, 0.063, 0.098, 0.141 13.6%, 0.25, 0.391, 0.563, 0.765,1, 0.891 40.9%, 0.848, 0.813, 0.785, 0.766, 0.754, 0.75, 0.754, 0.766, 0.785,0.813, 0.848, 0.891 68.2%, 1 72.7%, 0.973, 0.953, 0.941, 0.938, 0.941, 0.953,0.973, 1, 0.988, 0.984, 0.988, 1)" }, // from https://www.kvin.me/css-springs "@property --motion-spring-smooth": { syntax: '"*"', inherits: "false", "initial-value": "linear(0, 0.001 0.44%, 0.0045 0.94%, 0.0195 2.03%, 0.0446 3.19%, 0.0811 4.5%, 0.1598 6.82%, 0.3685 12.34%, 0.4693 15.17%, 0.5663, 0.6498 21.27%, 0.7215 24.39%, 0.7532 25.98%, 0.7829 27.65%, 0.8105, 0.8349 31.14%, 0.8573 32.95%, 0.8776 34.84%, 0.8964 36.87%, 0.9136 39.05%, 0.929 41.37%, 0.9421 43.77%, 0.9537 46.38%, 0.9636 49.14%, 0.9789 55.31%, 0.9888 62.35%, 0.9949 71.06%, 0.9982 82.52%, 0.9997 99.94%)" }, "@property --motion-spring-snappy": { syntax: '"*"', inherits: "false", "initial-value": "linear(0, 0.0014, 0.0053 1.02%, 0.0126, 0.0227 2.18%, 0.0517 3.41%, 0.094 4.79%, 0.1865 7.26%, 0.4182 12.77%, 0.5246 15.46%, 0.6249, 0.7112, 0.7831 23.95%, 0.8146 25.4%, 0.844, 0.8699 28.45%, 0.8935, 0.9139 31.64%, 0.932, 0.9473, 0.9601 36.65%, 0.9714 38.47%, 0.9808 40.35%, 0.9948 44.49%, 1.0031 49.43%, 1.0057 53.35%, 1.0063 58.14%, 1.0014 80.78%, 1.0001 99.94%)" }, "@property --motion-spring-bouncy": { syntax: '"*"', inherits: "false", "initial-value": "linear(0, 0.0018, 0.0069, 0.0151 1.74%, 0.0277 2.4%, 0.062 3.7%, 0.1115 5.15%, 0.2211 7.77%, 0.4778 13.21%, 0.5912 15.75%, 0.6987 18.44%, 0.7862 20.98%, 0.861 23.59%, 0.8926, 0.9205, 0.945 27.51%, 0.9671 28.89%, 0.9868, 1.003 31.79%, 1.0224 34.11%, 1.0358 36.58%, 1.0436 39.27%, 1.046 42.31%, 1.0446 44.71%, 1.0406 47.47%, 1.0118 61.84%, 1.0027 69.53%, 0.9981 80.49%, 0.9991 99.94%)" }, "@property --motion-spring-bouncier": { syntax: '"*"', inherits: "false", "initial-value": "linear(0, 0.0023, 0.0088, 0.0194 1.59%, 0.035 2.17%, 0.078 3.33%, 0.1415 4.64%, 0.2054 5.75%, 0.2821 6.95%, 0.5912 11.45%, 0.7205 13.43%, 0.8393 15.45%, 0.936 17.39%, 0.9778, 1.015, 1.0477, 1.0759, 1.0998 22.22%, 1.1203, 1.1364, 1.1484 25.26%, 1.1586 26.61%, 1.1629 28.06%, 1.1613 29.56%, 1.1537 31.2%, 1.1434 32.6%, 1.1288 34.19%, 1.0508 41.29%, 1.0174 44.87%, 1.0025 46.89%, 0.9911 48.87%, 0.9826 50.9%, 0.9769 53.03%, 0.9735 56.02%, 0.9748 59.45%, 0.9964 72.64%, 1.0031 79.69%, 1.0042 86.83%, 1.0008 99.97%)" }, "@property --motion-spring-bounciest": { syntax: '"*"', inherits: "false", "initial-value": "linear(0, 0.0032, 0.0131, 0.0294, 0.0524, 0.0824, 0.1192 1.54%, 0.2134 2.11%, 0.3102 2.59%, 0.4297 3.13%, 0.8732 4.95%, 1.0373, 1.1827 6.36%, 1.2972 7.01%, 1.3444, 1.3859, 1.4215, 1.4504, 1.4735, 1.4908, 1.5024, 1.5084 9.5%, 1.5091, 1.5061, 1.4993, 1.4886, 1.4745, 1.4565 11.11%, 1.4082 11.7%, 1.3585 12.2%, 1.295 12.77%, 1.0623 14.64%, 0.9773, 0.9031 16.08%, 0.8449 16.73%, 0.8014, 0.7701 17.95%, 0.7587, 0.7501, 0.7443, 0.7412 19.16%, 0.7421 19.68%, 0.7508 20.21%, 0.7672 20.77%, 0.7917 21.37%, 0.8169 21.87%, 0.8492 22.43%, 0.9681 24.32%, 1.0114, 1.0492 25.75%, 1.0789 26.41%, 1.1008, 1.1167, 1.1271, 1.1317 28.81%, 1.1314, 1.1271 29.87%, 1.1189 30.43%, 1.1063 31.03%, 1.0769 32.11%, 0.9941 34.72%, 0.9748 35.43%, 0.9597 36.09%, 0.9487, 0.9407, 0.9355, 0.933 38.46%, 0.9344 39.38%, 0.9421 40.38%, 0.9566 41.5%, 0.9989 44.12%, 1.0161 45.37%, 1.029 46.75%, 1.0341 48.1%, 1.0335 49.04%, 1.0295 50.05%, 1.0221 51.18%, 0.992 55.02%, 0.9854 56.38%, 0.9827 57.72%, 0.985 59.73%, 1.004 64.67%, 1.0088 67.34%, 1.0076 69.42%, 0.9981 74.28%, 0.9956 76.85%, 0.9961 79.06%, 1.0023 86.46%, 0.999 95.22%, 0.9994 100%)" }, /** * Enter animations origin values */ "@property --motion-origin-scale-x": { syntax: '"*"', inherits: "false", "initial-value": "100%" }, "@property --motion-origin-scale-y": { syntax: '"*"', inherits: "false", "initial-value": "100%" }, "@property --motion-origin-translate-x": { syntax: '"*"', inherits: "false", "initial-value": "0%" }, "@property --motion-origin-translate-y": { syntax: '"*"', inherits: "false", "initial-value": "0%" }, "@property --motion-origin-rotate": { syntax: '"*"', inherits: "false", "initial-value": "0deg" }, "@property --motion-origin-blur": { syntax: '"*"', inherits: "false", "initial-value": "0px" }, "@property --motion-origin-grayscale": { syntax: '"*"', inherits: "false", "initial-value": "0%" }, "@property --motion-origin-opacity": { syntax: '"*"', inherits: "false", "initial-value": "100%" }, "@property --motion-origin-background-color": { syntax: '"*"', inherits: "false" }, "@property --motion-origin-text-color": { syntax: '"*"', inherits: "false" }, /** * Exit animations end values */ "@property --motion-end-scale-x": { syntax: '"*"', inherits: "false", "initial-value": "100%" }, "@property --motion-end-scale-y": { syntax: '"*"', inherits: "false", "initial-value": "100%" }, "@property --motion-end-translate-x": { syntax: '"*"', inherits: "false", "initial-value": "0%" }, "@property --motion-end-translate-y": { syntax: '"*"', inherits: "false", "initial-value": "0%" }, "@property --motion-end-rotate": { syntax: '"*"', inherits: "false", "initial-value": "0deg" }, "@property --motion-end-blur": { syntax: '"*"', inherits: "false", "initial-value": "0px" }, "@property --motion-end-grayscale": { syntax: '"*"', inherits: "false", "initial-value": "0%" }, "@property --motion-end-opacity": { syntax: '"*"', inherits: "false", "initial-value": "100%" }, "@property --motion-end-background-color": { syntax: '"*"', inherits: "false" }, "@property --motion-end-text-color": { syntax: '"*"', inherits: "false" }, /** * Loop animations values */ "@property --motion-loop-scale-x": { syntax: '"*"', inherits: "false", "initial-value": "100%" }, "@property --motion-loop-scale-y": { syntax: '"*"', inherits: "false", "initial-value": "100%" }, "@property --motion-loop-translate-x": { syntax: '"*"', inherits: "false", "initial-value": "0%" }, "@property --motion-loop-translate-y": { syntax: '"*"', inherits: "false", "initial-value": "0%" }, "@property --motion-loop-rotate": { syntax: '"*"', inherits: "false", "initial-value": "0deg" }, "@property --motion-loop-blur": { syntax: '"*"', inherits: "false", "initial-value": "0px" }, "@property --motion-loop-grayscale": { syntax: '"*"', inherits: "false", "initial-value": "0%" }, "@property --motion-loop-opacity": { syntax: '"*"', inherits: "false", "initial-value": "100%" }, "@property --motion-loop-background-color": { syntax: '"*"', inherits: "false" }, "@property --motion-loop-text-color": { syntax: '"*"', inherits: "false" }, /** * Animation modifiers */ "@property --motion-duration": { syntax: '"*"', inherits: "false", "initial-value": "700ms" }, "@property --motion-timing": { syntax: '"*"', inherits: "false", "initial-value": "cubic-bezier(.165, .84, .44, 1)" }, "@property --motion-perceptual-duration-multiplier": { syntax: '"*"', inherits: "false", "initial-value": "1" }, "@property --motion-delay": { syntax: '"*"', inherits: "false", "initial-value": "0ms" }, "@property --motion-loop-count": { syntax: '"*"', inherits: "false", "initial-value": "infinite" }, /** * Default animations to none */ "@property --motion-scale-in-animation": { syntax: '"*"', inherits: "false", "initial-value": "none" }, "@property --motion-translate-in-animation": { syntax: '"*"', inherits: "false", "initial-value": "none" }, "@property --motion-rotate-in-animation": { syntax: '"*"', inherits: "false", "initial-value": "none" }, "@property --motion-filter-in-animation": { syntax: '"*"', inherits: "false", "initial-value": "none" }, "@property --motion-opacity-in-animation": { syntax: '"*"', inherits: "false", "initial-value": "none" }, "@property --motion-background-color-in-animation": { syntax: '"*"', inherits: "false", "initial-value": "none" }, "@property --motion-text-color-in-animation": { syntax: '"*"', inherits: "false", "initial-value": "none" }, "@property --motion-scale-out-animation": { syntax: '"*"', inherits: "false", "initial-value": "none" }, "@property --motion-translate-out-animation": { syntax: '"*"', inherits: "false", "initial-value": "none" }, "@property --motion-rotate-out-animation": { syntax: '"*"', inherits: "false", "initial-value": "none" }, "@property --motion-filter-out-animation": { syntax: '"*"', inherits: "false", "initial-value": "none" }, "@property --motion-opacity-out-animation": { syntax: '"*"', inherits: "false", "initial-value": "none" }, "@property --motion-background-color-out-animation": { syntax: '"*"', inherits: "false", "initial-value": "none" }, "@property --motion-text-color-out-animation": { syntax: '"*"', inherits: "false", "initial-value": "none" }, "@property --motion-scale-loop-animation": { syntax: '"*"', inherits: "false", "initial-value": "none" }, "@property --motion-translate-loop-animation": { syntax: '"*"', inherits: "false", "initial-value": "none" }, "@property --motion-rotate-loop-animation": { syntax: '"*"', inherits: "false", "initial-value": "none" }, "@property --motion-filter-loop-animation": { syntax: '"*"', inherits: "false", "initial-value": "none" }, "@property --motion-opacity-loop-animation": { syntax: '"*"', inherits: "false", "initial-value": "none" }, "@property --motion-background-color-loop-animation": { syntax: '"*"', inherits: "false", "initial-value": "none" }, "@property --motion-text-color-loop-animation": { syntax: '"*"', inherits: "false", "initial-value": "none" } }); } // src/keyframes.ts function addKeyframes(addBase) { addBase({ // if the user prefers reduced motion, don't apply the transform animations "@media screen and (prefers-reduced-motion: no-preference)": { "@keyframes motion-scale-in": { "0%": { scale: "var(--motion-origin-scale-x) var(--motion-origin-scale-y)" }, "100%": { scale: "1 1" } }, "@keyframes motion-scale-out": { "0%": { scale: "1 1" }, "100%": { scale: "var(--motion-end-scale-x) var(--motion-end-scale-y)" } }, "@keyframes motion-scale-loop-mirror": { "0%, 100%": { scale: "1 1" }, "50%": { scale: "var(--motion-loop-scale-x) var(--motion-loop-scale-y)" } }, "@keyframes motion-scale-loop-reset": { "0%": { scale: "1 1" }, "100%": { scale: "var(--motion-loop-scale-x) var(--motion-loop-scale-y)" } }, "@keyframes motion-translate-in": { "0%": { translate: "var(--motion-origin-translate-x) var(--motion-origin-translate-y)" }, "100%": { translate: "0 0" } }, "@keyframes motion-translate-out": { "0%": { translate: "0 0" }, "100%": { translate: "var(--motion-end-translate-x) var(--motion-end-translate-y)" } }, "@keyframes motion-translate-loop-mirror": { "0%, 100%": { translate: "0 0" }, "50%": { translate: "var(--motion-loop-translate-x) var(--motion-loop-translate-y)" } }, "@keyframes motion-translate-loop-reset": { "0%": { translate: "0 0" }, "100%": { translate: "var(--motion-loop-translate-x) var(--motion-loop-translate-y)" } }, "@keyframes motion-rotate-in": { "0%": { rotate: "var(--motion-origin-rotate)" }, "100%": { rotate: "0" } }, "@keyframes motion-rotate-out": { "0%": { rotate: "0" }, "100%": { rotate: "var(--motion-end-rotate)" } }, "@keyframes motion-rotate-loop-mirror": { "0%, 100%": { rotate: "0deg" }, "50%": { rotate: "var(--motion-loop-rotate)" } }, "@keyframes motion-rotate-loop-reset": { "0%": {}, "100%": { rotate: "var(--motion-loop-rotate)" } } }, "@keyframes motion-filter-in": { "0%": { filter: "blur(var(--motion-origin-blur)) grayscale(var(--motion-origin-grayscale))" }, "100%": { filter: "blur(0) grayscale(0)" } }, "@keyframes motion-filter-out": { "0%": { filter: "blur(0) grayscale(0)" }, "100%": { filter: "blur(var(--motion-end-blur)) grayscale(var(--motion-end-grayscale))" } }, "@keyframes motion-filter-loop-mirror": { "0%, 100%": { filter: "blur(0) grayscale(0)" }, "50%": { filter: "blur(var(--motion-loop-blur)) grayscale(var(--motion-loop-grayscale))" } }, "@keyframes motion-filter-loop-reset": { "0%": { filter: "blur(0) grayscale(0)" }, "100%": { filter: "blur(var(--motion-loop-blur)) grayscale(var(--motion-loop-grayscale))" } }, "@keyframes motion-opacity-in": { "0%": { opacity: "var(--motion-origin-opacity)" } }, "@keyframes motion-opacity-out": { "100%": { opacity: "var(--motion-end-opacity)" } }, "@keyframes motion-opacity-loop-mirror": { "0%, 100%": {}, "50%": { opacity: "var(--motion-loop-opacity)" } }, "@keyframes motion-opacity-loop-reset": { "0%": {}, "100%": { opacity: "var(--motion-loop-opacity)" } }, "@keyframes motion-background-color-in": { "0%": { backgroundColor: "var(--motion-origin-background-color)" } }, "@keyframes motion-background-color-out": { "100%": { backgroundColor: "var(--motion-end-background-color)" } }, "@keyframes motion-background-color-loop-mirror": { "0%, 100%": {}, "50%": { backgroundColor: "var(--motion-loop-background-color)" } }, "@keyframes motion-background-color-loop-reset": { "0%": {}, "100%": { backgroundColor: "var(--motion-loop-background-color)" } }, "@keyframes motion-text-color-in": { "0%": { color: "var(--motion-origin-text-color)" } }, "@keyframes motion-text-color-out": { "100%": { color: "var(--motion-end-text-color)" } }, "@keyframes motion-text-color-loop-mirror": { "0%, 100%": {}, "50%": { color: "var(--motion-loop-text-color)" } }, "@keyframes motion-text-color-loop-reset": { "0%": {}, "100%": { color: "var(--motion-loop-text-color)" } } }); } // src/modifiers.ts var springPerceptualMultipliers = { "var(--motion-spring-smooth)": "1.66", "var(--motion-spring-snappy)": "1.66", "var(--motion-spring-bouncy)": "1.66", "var(--motion-spring-bouncier)": "2.035", "var(--motion-spring-bounciest)": "5.285", "var(--motion-bounce)": "2" }; function addModifiers(matchUtilities, addUtilities, theme) { matchUtilities( { "motion-duration": (value, { modifier }) => { switch (modifier) { case "scale": return { "--motion-scale-duration": value }; case "translate": return { "--motion-translate-duration": value }; case "rotate": return { "--motion-rotate-duration": value }; case "blur": case "grayscale": return { "--motion-filter-duration": value }; case "opacity": return { "--motion-opacity-duration": value }; case "background": return { "--motion-background-color-duration": value }; case "text": return { "--motion-text-color-duration": value }; default: return { "--motion-duration": value }; } } }, { values: theme("motionDuration"), modifiers: { scale: "scale", translate: "translate", rotate: "rotate", blur: "blur", grayscale: "grayscale", opacity: "opacity", background: "background", text: "text" } } ); matchUtilities( { "motion-delay": (value, { modifier }) => { switch (modifier) { case "scale": return { "--motion-scale-delay": value }; case "translate": return { "--motion-translate-delay": value }; case "rotate": return { "--motion-rotate-delay": value }; case "blur": case "grayscale": return { "--motion-filter-delay": value }; case "opacity": return { "--motion-opacity-delay": value }; case "background": return { "--motion-background-color-delay": value }; case "text": return { "--motion-text-color-delay": value }; default: return { "--motion-delay": value }; } } }, { values: theme("motionDelay"), modifiers: { scale: "scale", translate: "translate", rotate: "rotate", blur: "blur", grayscale: "grayscale", opacity: "opacity", background: "background", text: "text" } } ); matchUtilities( { "motion-ease": (value, { modifier }) => { const perceptualDurationMultiplier = springPerceptualMultipliers[value] || 1; const isSpringWithBounce = [ "var(--motion-spring-bouncy)", "var(--motion-spring-bouncier)", "var(--motion-spring-bounciest)", "var(--motion-bounce)" ].includes(value); switch (modifier) { case "scale": return { "--motion-scale-timing": value, "--motion-scale-perceptual-duration-multiplier": `${perceptualDurationMultiplier}` }; case "translate": return { "--motion-translate-timing": value, "--motion-translate-perceptual-duration-multiplier": `${perceptualDurationMultiplier}` }; case "rotate": return { "--motion-rotate-timing": value, "--motion-rotate-perceptual-duration-multiplier": `${perceptualDurationMultiplier}` }; case "blur": case "grayscale": return { "--motion-filter-timing": value, "--motion-filter-perceptual-duration-multiplier": `${perceptualDurationMultiplier}` }; case "opacity": return { "--motion-opacity-timing": value, "--motion-opacity-perceptual-duration-multiplier": `${perceptualDurationMultiplier}` }; case "background": return { "--motion-background-color-timing": value, "--motion-background-color-perceptual-duration-multiplier": `${perceptualDurationMultiplier}` }; case "text": return { "--motion-text-color-timing": value, "--motion-text-color-perceptual-duration-multiplier": `${perceptualDurationMultiplier}` }; default: if (isSpringWithBounce) { return { "--motion-timing": value, "--motion-perceptual-duration-multiplier": `${perceptualDurationMultiplier}`, // filter, opacity, and color animations don't look good with bouncy springs // so we use a smooth spring for them "--motion-filter-timing": "var(--motion-spring-smooth)", "--motion-opacity-timing": "var(--motion-spring-smooth)", "--motion-background-color-timing": "var(--motion-spring-smooth)", "--motion-text-color-timing": "var(--motion-spring-smooth)", "--motion-filter-perceptual-duration-multiplier": "1.66", "--motion-opacity-perceptual-duration-multiplier": "1.66", "--motion-background-color-perceptual-duration-multiplier": "1.66", "--motion-text-color-perceptual-duration-multiplier": "1.66" }; } else { return { "--motion-timing": value, "--motion-perceptual-duration-multiplier": `${perceptualDurationMultiplier}` }; } } } }, { values: theme("motionTimingFunction"), modifiers: { scale: "scale", translate: "translate", rotate: "rotate", blur: "blur", grayscale: "grayscale", opacity: "opacity", background: "background", text: "text" } } ); addUtilities({ ".motion-paused": { animationPlayState: "paused", "&::before": { animationPlayState: "paused" }, "&::after": { animationPlayState: "paused" } }, ".motion-running": { animationPlayState: "running", "&::before": { animationPlayState: "running" }, "&::after": { animationPlayState: "running" } } }); matchUtilities( { "motion-loop": (value, { modifier }) => { switch (modifier) { case "scale": return { "--motion-scale-loop-count": value }; case "translate": return { "--motion-translate-loop-count": value }; case "rotate": return { "--motion-rotate-loop-count": value }; case "blur": case "grayscale": return { "--motion-filter-loop-count": value }; case "opacity": return { "--motion-opacity-loop-count": value }; case "background": return { "--motion-background-color-loop-count": value }; case "text": return { "--motion-text-color-loop-count": value }; default: return { "--motion-loop-count": value }; } } }, { values: theme("motionLoopCount"), modifiers: { scale: "scale", translate: "translate", rotate: "rotate", blur: "blur", grayscale: "grayscale", opacity: "opacity", background: "background", text: "text" } } ); } var modifiersTheme = { motionTimingFunction: (theme) => ({ ...theme("transitionTimingFunction"), "spring-smooth": "var(--motion-spring-smooth)", "spring-snappy": "var(--motion-spring-snappy)", "spring-bouncy": "var(--motion-spring-bouncy)", "spring-bouncier": "var(--motion-spring-bouncier)", "spring-bounciest": "var(--motion-spring-bounciest)", bounce: "var(--motion-bounce)", "in-quad": "cubic-bezier(.55, .085, .68, .53)", "in-cubic": "cubic-bezier(.550, .055, .675, .19)", "in-quart": "cubic-bezier(.895, .03, .685, .22)", "in-back": "cubic-bezier(0.6,-0.28,0.74,0.05)", "out-quad": "cubic-bezier(.25, .46, .45, .94)", "out-cubic": "cubic-bezier(.215, .61, .355, 1)", "out-quart": "cubic-bezier(.165, .84, .44, 1)", "out-back": "cubic-bezier(0.18,0.89,0.32,1.27)", "in-out-quad": "cubic-bezier(.455, .03, .515, .955)", "in-out-cubic": "cubic-bezier(.645, .045, .355, 1)", "in-out-quart": "cubic-bezier(.77, 0, .175, 1)", "in-out-back": "cubic-bezier(0.68,-0.55,0.27,1.55)" }), motionDuration: (theme) => ({ ...theme("transitionDuration"), 1500: "1500ms", 2e3: "2000ms", DEFAULT: "750ms" }), motionDelay: (theme) => ({ ...theme("motionDuration"), DEFAULT: "0ms" }), motionLoopCount: { infinite: "infinite", once: "1", twice: "2" } }; function addPresets(addComponents, matchComponents) { matchComponents( { "motion-preset-fade": (size) => { const durations = { sm: "300ms", md: "500ms", lg: "800ms" }; return { "--motion-origin-opacity": "0", "--motion-duration": durations[size], "--motion-opacity-in-animation": opacityInAnimation, animation: allLoopAndEnterAnimations }; }, "motion-preset-slide-right": (size) => { const distance = { sm: "5%", md: "25%", lg: "100%" }; return { "--motion-origin-translate-x": `-${distance[size]}`, "--motion-origin-opacity": "0", "--motion-opacity-in-animation": opacityInAnimation, "--motion-translate-in-animation": translateInAnimation, animation: allLoopAndEnterAnimations }; }, "motion-preset-slide-left": (size) => { const distance = { sm: "5%", md: "25%", lg: "100%" }; return { "--motion-origin-translate-x": distance[size], "--motion-origin-opacity": "0", "--motion-opacity-in-animation": opacityInAnimation, "--motion-translate-in-animation": translateInAnimation, animation: allLoopAndEnterAnimations }; }, "motion-preset-slide-up": (size) => { const distance = { sm: "5%", md: "25%", lg: "100%" }; return { "--motion-origin-translate-y": distance[size], "--motion-origin-opacity": "0", "--motion-opacity-in-animation": opacityInAnimation, "--motion-translate-in-animation": translateInAnimation, animation: allLoopAndEnterAnimations }; }, "motion-preset-slide-down": (size) => { const distance = { sm: "5%", md: "25%", lg: "100%" }; return { "--motion-origin-translate-y": `-${distance[size]}`, "--motion-origin-opacity": "0", "--motion-opacity-in-animation": opacityInAnimation, "--motion-translate-in-animation": translateInAnimation, animation: allLoopAndEnterAnimations }; }, "motion-preset-slide-up-right": (size) => { const distance = { sm: "5%", md: "25%", lg: "100%" }; return { "--motion-origin-translate-x": `-${distance[size]}`, "--motion-origin-translate-y": distance[size], "--motion-origin-opacity": "0", "--motion-opacity-in-animation": opacityInAnimation, "--motion-translate-in-animation": translateInAnimation, animation: allLoopAndEnterAnimations }; }, "motion-preset-slide-up-left": (size) => { const distance = { sm: "5%", md: "25%", lg: "100%" }; return { "--motion-origin-translate-x": distance[size], "--motion-origin-translate-y": distance[size], "--motion-origin-opacity": "0", "--motion-opacity-in-animation": opacityInAnimation, "--motion-translate-in-animation": translateInAnimation, animation: allLoopAndEnterAnimations }; }, "motion-preset-slide-down-left": (size) => { const distance = { sm: "5%", md: "25%", lg: "100%" }; return { "--motion-origin-translate-x": distance[size], "--motion-origin-translate-y": `-${distance[size]}`, "--motion-origin-opacity": "0", "--motion-opacity-in-animation": opacityInAnimation, "--motion-translate-in-animation": translateInAnimation, animation: allLoopAndEnterAnimations }; }, "motion-preset-slide-down-right": (size) => { const distance = { sm: "5%", md: "25%", lg: "100%" }; return { "--motion-origin-translate-x": `-${distance[size]}`, "--motion-origin-translate-y": `-${distance[size]}`, "--motion-origin-opacity": "0", "--motion-opacity-in-animation": opacityInAnimation, "--motion-translate-in-animation": translateInAnimation, animation: allLoopAndEnterAnimations }; }, "motion-preset-focus": (size) => { const blurSizes = { sm: "1.25px", md: "5px", lg: "10px" }; return { "--motion-origin-blur": blurSizes[size], "--motion-origin-opacity": "0", "--motion-opacity-in-animation": opacityInAnimation, "--motion-filter-in-animation": filterInAnimation, animation: allLoopAndEnterAnimations }; }, "motion-preset-blur-right": (size) => { const blurSizes = { sm: "1.25px", md: "5px", lg: "10px" }; const distance = { sm: "1%", md: "5%", lg: "25%" }; return { "--motion-origin-blur": blurSizes[size], "--motion-origin-translate-x": `-${distance[size]}`,