driftkit
Recipes/Form Micro-Interactions

Form Micro-Interactions

Complete form flow: floating labels, error shake, success checkmark, and button state transitions — all spring-powered.

BeginnerInputButtonToast

Live Demo

Try submitting empty, then fill in valid values. Watch the error shake, success checkmarks, and button state change.

The Micro-Interactions

📝
Floating label

Label animates from placeholder position to above-input with spring scale + translate. No layout shift.

🫨
Error shake

Keyframe X displacement: [0, -8, 8, -4, 4, 0]. Decaying amplitude = physical feel. Not a spring — intentionally sharp.

Success checkmark

Scale from 0 + rotate from -90° with spring. The overshoot from the spring makes it feel like it "pops" into place.

🔄
Button state machine

AnimatePresence mode="wait" crossfades between idle → loading → success. Each state slides in from below, out to above.

Key Code

// Floating label — spring-animated y + scale
<motion.label
  animate={{
    y: isActive ? 8 : 18,
    scale: isActive ? 0.75 : 1,
  }}
  transition={{ type: "spring", stiffness: 500, damping: 30, mass: 0.5 }}
>
  {label}
</motion.label>

// Error shake — keyframe x displacement
<motion.div animate={error ? { x: [0, -8, 8, -4, 4, 0] } : {}}>
  <input ... />
</motion.div>

// Button state transition — AnimatePresence + mode="wait"
<AnimatePresence mode="wait">
  {state === "loading" && (
    <motion.span
      initial={{ opacity: 0, y: 10 }}
      animate={{ opacity: 1, y: 0 }}
      exit={{ opacity: 0, y: -10 }}
      transition={spring.snappy}
    >
      <Spinner /> Submitting...
    </motion.span>
  )}
</AnimatePresence>