3 min read
Custom Checkbox Using Motion Library

I read Josh’s articles about SVGs and wanted to try something of my own.

I built a checkbox button using Motion. It is a great animation library, simple and effective.

I won’t go into details about it here.

This is the custom checkbox:

Click Me!

Using motion’s motion component, I can animate anything, including SVG paths.

Controlling the pathLength property of the SVG path, I can create a drawing effect as you saw when you clicked the checkbox.

Here is the code:

import { motion } from "motion/react"
import { useState } from "react"

const Checkbox = () => {
  const [checked, setChecked] = useState(false);

  return (
   <div className="flex items-center gap-4">
      <input type="checkbox" className="hidden" checked={checked} />
      <motion.div whileTap={{ scale: 0.85 }} 
      onClick={() => { setChecked(!checked) }} 
      className="flex items-center justify-center border-2 border-black rounded  w-6 h-6 cursor-pointer"
      >
        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256">
         <rect width="256" height="256" fill="none" />
         <motion.path
          initial={{ pathLength: 0 }}
          animate={{ pathLength: checked ? 1 : 0 }}
          color={"black"}
          strokeWidth={16}
          transition={{
            duration: 0.75,
            ease: 'easeInOut',
          }} 
          d="M104,147.43l98.34-97.09a8,8,..."
          fill="none" stroke="currentColor" /></svg>

         </motion.div>
      <span>Click Me!</span>

    </div>
  )
}

export default Checkbox;

So I used whileTap to add a tap effect where the checkbox scales down a bit when clicked, for the path element, I set the initial pathLength to 0 and used animate attribute to let motion know this is what I intend to animate where it becomes 1 when checked and 0 when unchecked.Lastly a transition to control the duration and easing of the animation. I love how the animation is interruptible, click as fast as you can and see how it behaves!

You may notice the lines aren’t joined at the ends, this is because I didn’t set the strokeLinecap property to round, you can try it out yourself. It will become like this:

Click Me!

It will have a dot in the checkbox since it is not parth of pathLength. There are couple ways to handle this but this is not my concern here.

I’m thinking of building a component library using motion and svgs, nothing for use just for fun.

I have this radio button too:

Click Me!

That’s it! This is nothing much, but imagine what you can build onwards using svgs and motion!