AniUI Academy

Build a password strength meter

easyAccessibility+160 XP

Build a password input that scores strength live as the user types.

Score is based on four signals: length ≥ 8, contains a lowercase letter, contains an uppercase letter, contains a digit or symbol. Each adds 1 to the score (0–4).

The label updates: 0 → Empty, 1 → Weak, 2 → Fair, 3 → Good, 4 → Strong. The meter bar fills proportionally.

Requirements

  • The input is `<input type="password" data-testid="password" />`.
  • The score label is `<p data-testid="strength-label">`, with text one of: Empty, Weak, Fair, Good, Strong.
  • The score bar is `<div data-testid="strength-bar" aria-valuenow="N" aria-valuemin="0" aria-valuemax="4" role="progressbar" />` with aria-valuenow equal to the current score (0–4).
  • An empty password renders label "Empty" and aria-valuenow="0".
  • A `<p data-testid="strength-announce" role="status" aria-live="polite">` announces the current label, so a screen reader hears strength changes without the user focusing the meter.

Where it's been asked

  • Microsoft
  • Google
  • Stripe
  • Razorpay

From public interview reports — a build very like this one has shown up in a round at these companies. Not an exhaustive list.

Stuck? The react course covers the ideas this problem is built on.

import { useState } from "react";

const LABELS = ["Empty", "Weak", "Fair", "Good", "Strong"];

export default function App() {
  const [password, setPassword] = useState("");

  // TODO: compute score (0..4) from password; look up the label.
  const score = 0;
  const label = LABELS[score];

  return (
    <div style={{ fontFamily: "sans-serif", padding: 16, maxWidth: 320 }}>
      <input
        type="password"
        data-testid="password"
        value={password}
        onChange={(e) => setPassword(e.target.value)}
        style={{ width: "100%", padding: 8 }}
      />
      <div
        data-testid="strength-bar"
        role="progressbar"
        aria-valuenow={score}
        aria-valuemin={0}
        aria-valuemax={4}
        style={{ height: 8, background: "#eee", borderRadius: 4, marginTop: 8 }}
      >
        <div style={{ height: "100%", width: `${(score / 4) * 100}%`, background: "#4caf50" }} />
      </div>
      <p data-testid="strength-label" style={{ margin: 4 }}>{label}</p>
      <p data-testid="strength-announce" role="status" aria-live="polite" style={{ position: "absolute", left: -9999 }}>
        {label}
      </p>
    </div>
  );
}

Ready to check it?

5 tests run against your rendered component, right here in your browser. Sign in to claim the XP when you pass.

Need a nudge?

Reveal a conceptual hint or the reference solution. Both were written and reviewed with the problem — no runtime magic.

Discussion

Sign in to post
Sign in to join the conversation.Sign in

No comments yet. Be the first to say something.