Skip to main content
EasyFrontendBuild

Build a PIN Code Input

Build a 4-digit PIN entry component inside the existing app container. It must behave like a real PIN pad: each box accepts exactly one digit, focus moves automatically between boxes as the user types and deletes, and t...

What you will practice

JavaScriptHTMLDOM & EventsForms & ValidationKeyboard HandlingFocus Management

Requirements

  • Render 4 single-character text inputs with `data-testid` values `pin-digit-0`, `pin-digit-1`, `pin-digit-2`, and `pin-digit-3` inside the app container.
  • Each input accepts only digit characters (0–9). Any non-digit keypress must be ignored and must not populate the input or advance focus.
  • When a digit is entered, focus automatically moves to the next input. If the last input is filled, focus stays on it.
  • When Backspace is pressed on an empty input, focus moves back to the previous input. If the first input is already focused, Backspace has no focus side-effect.
  • When all 4 inputs contain a digit, dispatch a custom `complete` event on the app container with `detail: { pin: "XXXX" }` where XXXX is the 4-digit string.
  • Render a button with `data-testid="clear-btn"` that clears all inputs and returns focus to the first input. The `complete` event may fire again after clearing if all 4 digits are re-entered.

Starter files

index.htmlEditable starter
main.jsEditable starter

What the judge checks

  • Runs in the browser environment with the browser-eval runner.
  • Uses a 8000ms judge budget.
  • Behavior rules include: Four Digit Inputs Render, Non Digit Keypresses Rejected, Digit Entry Advances Focus, Backspace On Empty Returns Focus.

Constraints

  • Use only vanilla JavaScript — no React, Vue, or other frameworks.
  • The `complete` event must be dispatched on the element with `data-testid="app"`, not on any individual input.

Example behavior

Input
User types '1', '2', '3', '4'
Output
complete event fires with detail.pin = '1234'

Each digit entry advances focus to the next box. After the 4th digit, the complete event fires.

Input
User types '1', then 'a', then '2'
Output
Inputs show '1', '', '2', '' — focus is on index 2

'a' is not a digit — it is ignored. Focus does not advance on a rejected keypress.

Follow-up

This component manages 4 independent DOM nodes. How would you structure this if the number of digits was configurable via a `data-length` attribute on the container?