↩ Experiments

Length Input

June 2025

password

0/10

Description

This component was designed to provide clear, immediate, and satisfying feedback for a password input field. Standard inputs offer very little information beyond the character count. This experiment aims to create a more intuitive experience by visualizing the user's progress towards a length requirement in a novel way.

The Custom Cursor

The core of this experiment is the custom cursor. Instead of a standard blinking bar, the cursor is a pill that serves multiple functions: a position indicator, a progress bar, and a state notifier. To achieve this, the default text cursor is hidden with the CSS property caret-color: transparent;.

The cursor's position is calculated by measuring the width of the actual (but hidden) text. A span element, styled identically to the input text, is updated with the password. A useRef gives access to its offsetWidth, which then drives the left property of the cursor pill. This calculation is wrapped in a useEffect hook that triggers whenever the password changes, ensuring the cursor stays perfectly in sync with the text.

useEffect(() => {
  if (textRef.current) {
    const textWidth = textRef.current.offsetWidth;
    if (passwordLength > 0) {
      setCursorPosition(textWidth + 4);
    } else {
      setCursorPosition(0);
    }
  }
}, [password]);

Layered Feedback

The cursor provides layered feedback. Its horizontal position follows the text, as you'd expect. At the same time, its vertical fill (the green inner bar) grows in height, showing the user their progress towards the 10-character limit. This dual-purpose design makes efficient use of a single element to communicate multiple pieces of information.

When the 10-character limit is reached, the cursor provides a final piece of feedback. It morphs from a tall pill into a small, solid green circle and docks itself to the far right of the input field. This is handled entirely with CSS, triggered by adding a .limit_reached class to the container.

.cursor_pill_container {
  transition-property: left, width, height, border-radius, background-color;
  transition-duration: 0.1s, 0.3s, 0.3s, 0.3s, 0.3s;
}

.cursor_pill_container.limit_reached {
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background-color: green;
  transition-duration: 0.3s;
}

By defining different transition durations for each property, we can make the cursor feel snappy when typing (left: 0.1s) but smooth and deliberate during the morphing animation, creating a more refined user experience.