Sliding Number

0

Install the following dependencies

pnpm add lucide-react motion

Code

components/sliding-number.tsx

"use client";

import { AnimatePresence, motion } from "motion/react";
import { Plus, Minus } from "lucide-react";
import { useState } from "react";

const AnimatedNumber = () => {
  const [count, setCount] = useState(0);
  const [direction, setDirection] = useState(1);

  const handleAdd = () => {
    setDirection(1);
    setCount((prev) => prev + 1);
  };

  const handleMinus = () => {
    setDirection(-1);
    setCount((prev) => prev - 1);
  };

  return (
    <div className="bg-neutral-100 border border-neutral-100 items-center px-2 py-1 gap-2 justify-center rounded-lg flex">
      <button
        disabled={count <= 0}
        className="p-2 border disabled:opacity-50 border-neutral-50 text-neutral-800 bg-white active:bg-neutral-50 ring-1 ring-blue-50 rounded-md"
        onClick={handleMinus}
      >
        <Minus size={18} />
      </button>

      {/* Number */}
      <div className="relative w-6 h-6 overflow-hidden flex items-center justify-center">
        <AnimatePresence mode="popLayout" initial={false} custom={direction}>
          <motion.div
            key={count}
            custom={direction}
            initial={{
              y: direction * 25,
              opacity: 0,
              filter: "blur(2px)",
            }}
            animate={{
              y: 0,
              opacity: 1,
              filter: "blur(0px)",
            }}
            exit={{
              y: direction * -25,
              opacity: 0,
            }}
            transition={{
              duration: 0.2,
              ease: "easeInOut",
              damping: 5,
              stiffness: 80,
            }}
            className="absolute"
          >
            {count}
          </motion.div>
        </AnimatePresence>
      </div>

      <button
        className="p-2 border border-neutral-50 text-neutral-800 bg-white active:bg-neutral-50 ring-1 ring-blue-50 rounded-md"
        onClick={handleAdd}
      >
        <Plus size={18} />
      </button>
    </div>
  );
};

export default AnimatedNumber;

© Hitesh Suthar

Built with Chai & ❤

Coding