ben-rogerson / twin.macro

🦹‍♂️ Twin blends the magic of Tailwind with the flexibility of css-in-js (emotion, styled-components, solid-styled-components, stitches and goober) at build time.
MIT License
7.92k stars 183 forks source link

Add option to move keyframes to global styles #758

Closed ben-rogerson closed 1 year ago

ben-rogerson commented 1 year ago

This option moves the @keyframes created from animate-x classes to global styles. It was added to provide support for Stitches that doesn't support inline @keyframes.

Here's what global styles looks like with { moveKeyframesToGlobalStyles: true } in your twin config:

import { globalStyles } from "twin.macro"
globalStyles

// ↓ ↓ ↓ ↓ ↓ ↓

({
  // ...rest of global styles
  "@keyframes spin": {
    "to": {
      "transform": "rotate(360deg)"
    }
  },
  "@keyframes ping": {
    "75%, 100%": {
      "transform": "scale(2)",
      "opacity": "0"
    }
  },
  "@keyframes pulse": {
    "50%": {
      "opacity": ".5"
    }
  },
  "@keyframes bounce": {
    "0%, 100%": {
      "transform": "translateY(-25%)",
      "animationTimingFunction": "cubic-bezier(0.8,0,1,1)"
    },
    "50%": {
      "transform": "none",
      "animationTimingFunction": "cubic-bezier(0,0,0.2,1)"
    }
  }
});

and on the animate-x classes:

tw`animate-bounce`

// ↓ ↓ ↓ ↓ ↓ ↓

// moveKeyframesToGlobalStyles: true
({
  "animation": "bounce 1s infinite"
});

// moveKeyframesToGlobalStyles: false (default)
({
  "@keyframes bounce": {
    "0%, 100%": {
      "transform": "translateY(-25%)",
      "animationTimingFunction": "cubic-bezier(0.8,0,1,1)"
    },
    "50%": {
      "transform": "none",
      "animationTimingFunction": "cubic-bezier(0,0,0.2,1)"
    }
  },
  "animation": "bounce 1s infinite"
});

closes #753

ben-rogerson commented 1 year ago

During testing I noticed that animate-bounce wasn't bouncing but the other animate classes worked fine.

In dev tools, I saw that after stitches added the keyframe values to the <head> it looks like this:

@keyframes bounce { 0%,100% { transform: translateY(-25%); animation-timing-function: cubic-bezier(0.8,0,1,1) }} 
@keyframes bounce { 50% { transform: none; animation-timing-function: cubic-bezier(0,0,0.2,1) }}

when there should be a single @\keyframes container:

@keyframes bounce { 0%,100% { transform: translateY(-25%); animation-timing-function: cubic-bezier(0.8,0,1,1) } 50% { transform: none; animation-timing-function: cubic-bezier(0,0,0.2,1) }}

@ajmnz Have you noticed similar? Seems to be an issue when the keyframes have multiple "steps"?