Skill Store 33

Creative Effects

Expert knowledge for artistic and creative animation effects - morphing shapes, liquid animations…

by thelobbi · MIT

The skill

Expert knowledge for artistic and creative animation effects - morphing shapes, liquid animations, glitch effects, distortion, and experimental visual techniques that push creative boundaries.

Creative Effects Skill

Expert knowledge for artistic and creative animation effects - morphing shapes, liquid animations, glitch effects, distortion, and experimental visual techniques that push creative boundaries.

When to Use

Activate this skill when:

  • User wants liquid/fluid animations
  • Creating morphing shape transitions
  • Building glitch or distortion effects
  • Need experimental/artistic visuals
  • Creating loading animations with personality
  • Building creative reveals and transitions

File Patterns

  • **/*.tsx with creative components
  • **/components/Creative*.tsx
  • **/components/Effect*.tsx
  • **/components/Liquid*.tsx

Creative Effect Types

1. Morphing Shapes

Liquid Button
import { motion, useAnimation } from 'framer-motion';

export function LiquidButton({ children }: { children: React.ReactNode }) {
  const controls = useAnimation();

  const liquidVariants = {
    rest: {
      d: "M0,20 Q25,0 50,20 T100,20 L100,80 Q75,100 50,80 T0,80 Z",
    },
    hover: {
      d: "M0,30 Q25,10 50,30 T100,30 L100,70 Q75,90 50,70 T0,70 Z",
    },
    tap: {
      d: "M0,25 Q25,15 50,25 T100,25 L100,75 Q75,85 50,75 T0,75 Z",
    },
  };

  return (
    <motion.button
      className="relative px-8 py-4 text-white font-medium"
      initial="rest"
      whileHover="hover"
      whileTap="tap"
    >
      <svg
        className="absolute inset-0 w-full h-full"
        viewBox="0 0 100 100"
        preserveAspectRatio="none"
      >
        <motion.path
          fill="url(#liquid-gradient)"
          variants={liquidVariants}
          transition={{ type: 'spring', stiffness: 300, damping: 20 }}
        />
        <defs>
          <linearGradient id="liquid-gradient" x1="0%" y1="0%" x2="100%" y2="100%">
            <stop offset="0%" stopColor="#667eea" />
            <stop offset="100%" stopColor="#764ba2" />
          </linearGradient>
        </defs>
      </svg>
      <span className="relative z-10">{children}</span>
    </motion.button>
  );
}
Morphing Blob
export function MorphingBlob() {
  const paths = [
    "M45.3,-51.2C58.3,-40.8,68.4,-25.6,71.8,-8.4C75.2,8.8,71.9,28,61.6,41.8C51.3,55.6,34,64,15.6,68.9C-2.8,73.8,-22.3,75.2,-38.1,67.6C-53.9,60,-66,43.4,-71.4,24.9C-76.8,6.4,-75.5,-14,-67.4,-30.7C-59.3,-47.4,-44.4,-60.4,-28.6,-69.7C-12.8,-79,-0.1,-84.6,8.9,-78.5C17.9,-72.4,32.3,-54.6,45.3,-51.2Z",
    "M39.9,-47.1C53.3,-36.9,66.7,-26.3,72.2,-11.9C77.7,2.5,75.4,20.7,66.4,35.1C57.4,49.5,41.7,60.1,24.6,66.2C7.5,72.3,-11,73.9,-27.8,68.4C-44.6,62.9,-59.7,50.3,-67.8,34.3C-75.9,18.3,-77,-1.1,-72.1,-18.7C-67.2,-36.3,-56.3,-52.1,-42.4,-62.1C-28.5,-72.1,-11.6,-76.3,1.8,-78.5C15.2,-80.7,26.5,-57.3,39.9,-47.1Z",
    "M42.7,-49.7C55.5,-38.8,66.1,-25.3,69.7,-9.8C73.3,5.7,69.9,23.2,60.6,37.4C51.3,51.6,36.1,62.5,19.3,68.3C2.5,74.1,-15.9,74.8,-32.8,68.7C-49.7,62.6,-65.1,49.7,-72.6,33.4C-80.1,17.1,-79.7,-2.6,-73.3,-20C-66.9,-37.4,-54.5,-52.5,-40.1,-63C-25.7,-73.5,-9.3,-79.4,3.6,-83.7C16.5,-88,29.9,-60.6,42.7,-49.7Z",
  ];

  return (
    <motion.svg viewBox="-100 -100 200 200" className="w-64 h-64">
      <motion.path
        fill="url(#blob-gradient)"
        animate={{
          d: paths,
        }}
        transition={{
          duration: 10,
          repeat: Infinity,
          ease: 'easeInOut',
        }}
      />
      <defs>
        <linearGradient id="blob-gradient" x1="0%" y1="0%" x2="100%" y2="100%">
          <stop offset="0%" stopColor="#667eea" />
          <stop offset="50%" stopColor="#764ba2" />
          <stop offset="100%" stopColor="#f093fb" />
        </linearGradient>
      </defs>
    </motion.svg>
  );
}

2. Glitch Effects

Glitch Text
export function GlitchText({ children }: { children: string }) {
  return (
    <div className="relative inline-block">
      {/* Main text */}
      <span className="relative z-10">{children}</span>

      {/* Glitch layer 1 - Red */}
      <motion.span
        className="absolute inset-0 text-red-500 opacity-80"
        style={{ clipPath: 'inset(0 0 0 0)' }}
        animate={{
          x: [-2, 2, -2],
          clipPath: [
            'inset(40% 0 61% 0)',
            'inset(92% 0 1% 0)',
            'inset(43% 0 1% 0)',
            'inset(25% 0 58% 0)',
          ],
        }}
        transition={{
          duration: 0.3,
          repeat: Infinity,
          repeatType: 'reverse',
        }}
      >
        {children}
      </motion.span>

      {/* Glitch layer 2 - Cyan */}
      <motion.span
        className="absolute inset-0 text-cyan-500 opacity-80"
        style={{ clipPath: 'inset(0 0 0 0)' }}
        animate={{
          x: [2, -2, 2],
          clipPath: [
            'inset(85% 0 7% 0)',
            'inset(15% 0 80% 0)',
            'inset(45% 0 50% 0)',
            'inset(70% 0 25% 0)',
          ],
        }}
        transition={{
          duration: 0.2,
          repeat: Infinity,
          repeatType: 'reverse',
        }}
      >
        {children}
      </motion.span>
    </div>
  );
}
Glitch Image
export function GlitchImage({ src, alt }: { src: string; alt: string }) {
  return (
    <div className="relative overflow-hidden">
      <img src={src} alt={alt} className="relative z-10" />

      <motion.img
        src={src}
        alt=""
        className="absolute inset-0 opacity-50"
        style={{ mixBlendMode: 'multiply' }}
        animate={{
          x: [-5, 5, -5],
          filter: ['hue-rotate(0deg)', 'hue-rotate(90deg)', 'hue-rotate(0deg)'],
        }}
        transition={{
          duration: 0.2,
          repeat: Infinity,
        }}
      />

      <motion.div
        className="absolute inset-0 bg-gradient-to-r from-red-500/20 to-cyan-500/20"
        animate={{
          opacity: [0, 0.3, 0],
          scaleY: [1, 1.02, 1],
        }}
        transition={{
          duration: 0.1,
          repeat: Infinity,
          repeatDelay: 2,
        }}
      />
    </div>
  );
}

3. Liquid/Fluid Effects

Liquid Fill
export function LiquidFill({ progress = 0.7 }: { progress?: number }) {
  const fillHeight = progress * 100;

  return (
    <div className="relative w-32 h-48 bg-slate-800 rounded-2xl overflow-hidden">
      {/* Liquid */}
      <motion.div
        className="absolute bottom-0 left-0 right-0 bg-gradient-to-t from-blue-600 to-blue-400"
        initial={{ height: 0 }}
        animate={{ height: `${fillHeight}%` }}
        transition={{ duration: 2, ease: 'easeOut' }}
      >
        {/* Wave effect */}
        <svg
          className="absolute top-0 left-0 w-full"
          viewBox="0 0 100 20"
          preserveAspectRatio="none"
          style={{ transform: 'translateY(-50%)' }}
        >
          <motion.path
            fill="currentColor"
            className="text-blue-400"
            d="M0,10 Q25,0 50,10 T100,10 L100,20 L0,20 Z"
            animate={{
              d: [
                "M0,10 Q25,0 50,10 T100,10 L100,20 L0,20 Z",
                "M0,10 Q25,20 50,10 T100,10 L100,20 L0,20 Z",
                "M0,10 Q25,0 50,10 T100,10 L100,20 L0,20 Z",
              ],
            }}
            transition={{
              duration: 2,
              repeat: Infinity,
              ease: 'easeInOut',
            }}
          />
        </svg>
      </motion.div>

      {/* Bubbles */}
      {Array.from({ length: 5 }).map((_, i) => (
        <motion.div
          key={i}
          className="absolute w-2 h-2 bg-white/30 rounded-full"
          style={{
            left: `${20 + i * 15}%`,
            bottom: 0,
          }}
          animate={{
            y: [0, -fillHeight * 2],
            opacity: [0, 1, 0],
            scale: [0.5, 1, 0.5],
          }}
          transition={{
            duration: 2 + Math.random(),
            delay: i * 0.3,
            repeat: Infinity,
          }}
        />
      ))}
    </div>
  );
}

4. Distortion Effects

Magnetic Button
export function MagneticButton({ children }: { children: React.ReactNode }) {
  const ref = useRef<HTMLButtonElement>(null);
  const [position, setPosition] = useState({ x: 0, y: 0 });

  const handleMouseMove = (e: React.MouseEvent) => {
    if (!ref.current) return;
    const rect = ref.current.getBoundingClientRect();
    const centerX = rect.left + rect.width / 2;
    const centerY = rect.top + rect.height / 2;

    const distanceX = e.clientX - centerX;
    const distanceY = e.clientY - centerY;

    setPosition({
      x: distanceX * 0.3,
      y: distanceY * 0.3,
    });
  };

  const handleMouseLeave = () => {
    setPosition({ x: 0, y: 0 });
  };

  return (
    <motion.button
      ref={ref}
      className="px-8 py-4 bg-gradient-to-r from-purple-500 to-pink-500 rounded-xl text-white font-medium"
      animate={{ x: position.x, y: position.y }}
      transition={{ type: 'spring', stiffness: 150, damping: 15 }}
      onMouseMove={handleMouseMove}
      onMouseLeave={handleMouseLeave}
    >
      {children}
    </motion.button>
  );
}
Elastic Container
export function ElasticContainer({ children }: { children: React.ReactNode }) {
  const [isPressed, setIsPressed] = useState(false);

  return (
    <motion.div
      className="cursor-pointer"
      animate={{
        scaleX: isPressed ? 1.1 : 1,
        scaleY: isPressed ? 0.9 : 1,
      }}
      transition={{
        type: 'spring',
        stiffness: 400,
        damping: 10,
      }}
      onMouseDown={() => setIsPressed(true)}
      onMouseUp={() => setIsPressed(false)}
      onMouseLeave={() => setIsPressed(false)}
    >
      {children}
    </motion.div>
  );
}

5. Creative Loaders

DNA Helix Loader
export function DNALoader() {
  const dots = Array.from({ length: 10 });

  return (
    <div className="flex items-center justify-center h-20">
      {dots.map((_, i) => (
        <div key={i} className="relative w-4 mx-0.5">
          <motion.div
            className="absolute w-3 h-3 bg-blue-500 rounded-full"
            animate={{
              y: [-15, 15, -15],
              scale: [1, 0.8, 1],
              opacity: [1, 0.5, 1],
            }}
            transition={{
              duration: 1,
              delay: i * 0.1,
              repeat: Infinity,
              ease: 'easeInOut',
            }}
          />
          <motion.div
            className="absolute w-3 h-3 bg-purple-500 rounded-full"
            animate={{
              y: [15, -15, 15],
              scale: [0.8, 1, 0.8],
              opacity: [0.5, 1, 0.5],
            }}
            transition={{
              duration: 1,
              delay: i * 0.1,
              repeat: Infinity,
              ease: 'easeInOut',
            }}
          />
        </div>
      ))}
    </div>
  );
}
Orbiting Loader
export function OrbitingLoader() {
  const orbits = [
    { radius: 20, duration: 1.5, color: '#667eea' },
    { radius: 35, duration: 2, color: '#764ba2' },
    { radius: 50, duration: 2.5, color: '#f093fb' },
  ];

  return (
    <div className="relative w-32 h-32">
      {/* Center dot */}
      <motion.div
        className="absolute top-1/2 left-1/2 w-4 h-4 -ml-2 -mt-2 bg-white rounded-full"
        animate={{ scale: [1, 1.2, 1] }}
        transition={{ duration: 1, repeat: Infinity }}
      />

      {/* Orbiting dots */}
      {orbits.map((orbit, i) => (
        <motion.div
          key={i}
          className="absolute top-1/2 left-1/2 w-3 h-3 -ml-1.5 -mt-1.5 rounded-full"
          style={{ backgroundColor: orbit.color }}
          animate={{
            x: [orbit.radius, 0, -orbit.radius, 0, orbit.radius],
            y: [0, orbit.radius, 0, -orbit.radius, 0],
          }}
          transition={{
            duration: orbit.duration,
            repeat: Infinity,
            ease: 'linear',
          }}
        />
      ))}
    </div>
  );
}

6. Reveal Effects

Mask Reveal
export function MaskReveal({
  children,
  delay = 0,
}: {
  children: React.ReactNode;
  delay?: number;
}) {
  return (
    <div className="relative overflow-hidden">
      <motion.div
        initial={{ y: '100%' }}
        animate={{ y: '0%' }}
        transition={{
          duration: 0.8,
          delay,
          ease: [0.25, 0.1, 0.25, 1],
        }}
      >
        {children}
      </motion.div>
      <motion.div
        className="absolute inset-0 bg-gradient-to-r from-purple-500 to-pink-500"
        initial={{ x: '0%' }}
        animate={{ x: '100%' }}
        transition={{
          duration: 0.6,
          delay: delay + 0.2,
          ease: [0.25, 0.1, 0.25, 1],
        }}
      />
    </div>
  );
}
Split Reveal
export function SplitReveal({ children }: { children: React.ReactNode }) {
  return (
    <div className="relative overflow-hidden">
      <div className="relative z-10">{children}</div>

      {/* Top curtain */}
      <motion.div
        className="absolute inset-x-0 top-0 h-1/2 bg-slate-900 origin-top"
        initial={{ scaleY: 1 }}
        animate={{ scaleY: 0 }}
        transition={{ duration: 0.8, ease: [0.25, 0.1, 0.25, 1] }}
      />

      {/* Bottom curtain */}
      <motion.div
        className="absolute inset-x-0 bottom-0 h-1/2 bg-slate-900 origin-bottom"
        initial={{ scaleY: 1 }}
        animate={{ scaleY: 0 }}
        transition={{ duration: 0.8, ease: [0.25, 0.1, 0.25, 1] }}
      />
    </div>
  );
}

Examples

<example> Context: User wants a liquid morphing button user: "Create a button that feels liquid when hovered" assistant: Using the LiquidButton component:

<LiquidButton>Get Started</LiquidButton>

The button's background morphs like liquid on hover and tap. </example>

<example> Context: User wants glitch text effect user: "Add a glitch effect to my heading" assistant: Using GlitchText:

<h1 className="text-4xl font-bold">
  <GlitchText>CYBERPUNK 2077</GlitchText>
</h1>

</example>

Related Skills

  • background-animations - Full-page creative backgrounds
  • accent-animations - Decorative elements
  • svg-animations - Path morphing

Author

Created by Brookside BI as part of React Animation Studio

Use this skill

Connect your agent to the Skill Store MCP server and ask for it by ref: thelobbi/creative-effects-24972944966.

Download SKILL.md · Markdown version

Details

Publisher
thelobbi
Category
Software Development › Frontend & UI
License
MIT
Updated
2026-10-08

References

More from thelobbi