Zip Code Checker Component

A beautiful and customizable input component for collecting user information with engaging ripple effects

background
I built this Zip Code Checker as a small UI experiment focused on interaction and polish. The idea was to make a simple input feel more engaging through layout, spacing, and subtle animation.
It's a client-side Next.js component using React state for the input and a DOM-based ripple effect for instant visual feedback when the button is clicked. The background image acts as both a design element and an interaction surface, keeping everything contained and clean.
The inspiration came from modern SaaS landing pages that check availability by location—I wanted it to feel friendly, lightweight, and responsive, while still being easy to extend with real validation or API logic later.

Component Structure

The component uses Next.js Image optimization for the background, React state for input management, and a ref to handle the ripple effect positioning:


const ZipCodeChecker = () => {
  const [zipCode, setZipCode] = useState('');
  const imageWrapperRef = useRef<HTMLDivElement>(null);

  const handleSubmit = (e: React.FormEvent) => {
    e.preventDefault();
    // Handle zip code validation
  };

  return (
    <div ref={imageWrapperRef} className="relative overflow-hidden rounded-2xl">
      <Image
        src="/your-background-image.jpg"
        alt="Background"
        width={1200}
        height={600}
        className="object-cover"
      />
      <form onSubmit={handleSubmit} className="absolute inset-0 flex flex-col items-center justify-center">
        <input
          type="text"
          value={zipCode}
          onChange={(e) => setZipCode(e.target.value)}
          placeholder="Enter zip code"
          className="px-4 py-2 rounded-lg"
        />
        <button 
          onClick={createRipple}
          className="mt-4 px-6 py-3 bg-blue-600 text-white rounded-lg"
        >
          Check Availability
        </button>
      </form>
    </div>
  );
};

Ripple Click Effect

To create the ripple click effect, I use a DOM reference. This allows me to insert a temporary element exactly where the user clicks, without adding extra markup.

When the Check Availability button is clicked, a ripple is created and positioned using the mouse coordinates and the container's bounds:


const createRipple = (e: React.MouseEvent<HTMLButtonElement>) => {
  const button = e.currentTarget;
  const wrapper = imageWrapperRef.current;
  
  if (!wrapper) return;
  
  const ripple = document.createElement('span');
  const rect = wrapper.getBoundingClientRect();
  
  ripple.style.left = `${e.clientX - rect.left}px`;
  ripple.style.top = `${e.clientY - rect.top}px`;
  ripple.classList.add('ripple');
  
  wrapper.appendChild(ripple);
  
  setTimeout(() => {
    ripple.remove();
  }, 600);
};

The ripple element is dynamically created, positioned at the click coordinates relative to the container, and then removed after the animation completes.

Ripple Animation CSS

The ripple effect is achieved through CSS animations that scale and fade the element:


.ripple {
  position: absolute;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.6);
  width: 100px;
  height: 100px;
  margin-top: -50px;
  margin-left: -50px;
  animation: ripple-effect 0.6s ease-out;
  pointer-events: none;
}

@keyframes ripple-effect {
  0% {
    transform: scale(0);
    opacity: 1;
  }
  100% {
    transform: scale(4);
    opacity: 0;
  }
}

The animation scales the ripple from 0 to 4x its size while fading it out, creating a smooth, water-like expansion effect. The pointer-events: none ensures it doesn't interfere with other interactions.

Key Features

  • Optimized background image using Next.js Image component
  • Dynamic ripple effect triggered on button click
  • Clean, centered layout with Tailwind CSS
  • Responsive design that adapts to different screen sizes
  • Easy to extend with real API validation logic

Here's the source code, I hope you like it :)

prash240303/crafts/ZipCodeChecker