Сброс пароля с индикатором надёжности — форма авторизации на Tailwind
Формы авторизации

Сброс пароля с индикатором надёжности

Форма нового пароля с живой проверкой требований

Живой просмотр

Промпт

Создайте карточку сброса пароля на Tailwind CSS. Добавьте заголовок, строку с именем аккаунта, для которого сбрасывается пароль, поле нового пароля, индикатор надёжности из четырёх сегментов, который начинается пустым, небольшую текстовую метку уровня надёжности, поле подтверждения пароля и список требований, где каждый пункт имеет атрибут data-rule. Завершите полноширинной тёмной кнопкой отправки и ссылкой возврата ко входу. Затем добавьте JavaScript, который оценивает пароль при каждом нажатии клавиши — длина, цифра, символ, смешанный регистр — закрашивает соответствующее число сегментов индикатора янтарным, а затем зелёным, выводит в метку значения «Слабый / Средний / Хороший / Надёжный», переключает каждую строку списка между приглушённой точкой и зелёной галочкой по мере выполнения правила и держит кнопку отправки отключённой, пока не выполнены все правила, включая совпадение двух полей.

Вставьте это в Claude, Cursor, v0 или любой другой AI-инструмент для разработки.

Исходный код
Tailwind
<div class="flex min-h-screen items-center justify-center bg-neutral-100 p-6">
  <div class="w-full max-w-md rounded-2xl border border-neutral-200 bg-white p-8 shadow-sm">
    <h1 class="text-xl font-semibold text-neutral-900">Choose a new password</h1>
    <p class="mt-1 text-sm text-neutral-500">Resetting the password for <span class="font-medium text-neutral-700">sam@northwind.co</span></p>
    <form class="mt-6 space-y-4">
      <input id="pw" type="password" placeholder="New password"
        class="w-full rounded-xl border border-neutral-200 px-3.5 py-2.5 text-sm outline-none focus:border-neutral-900 focus:ring-4 focus:ring-neutral-900/10" />
      <div>
        <div id="meter" class="flex gap-1.5">
          <span class="h-1.5 flex-1 rounded-full bg-neutral-200"></span>
          <span class="h-1.5 flex-1 rounded-full bg-neutral-200"></span>
          <span class="h-1.5 flex-1 rounded-full bg-neutral-200"></span>
          <span class="h-1.5 flex-1 rounded-full bg-neutral-200"></span>
        </div>
        <p class="mt-1.5 text-xs text-neutral-500">Strength: <span id="strength" class="font-medium text-neutral-900">—</span></p>
      </div>
      <input id="confirm" type="password" placeholder="Confirm new password"
        class="w-full rounded-xl border border-neutral-200 px-3.5 py-2.5 text-sm outline-none focus:border-neutral-900 focus:ring-4 focus:ring-neutral-900/10" />
      <ul class="space-y-1.5 text-xs">
        <li data-rule="length" class="flex items-center gap-2 text-neutral-400"><span data-icon>•</span> At least 12 characters</li>
        <li data-rule="number" class="flex items-center gap-2 text-neutral-400"><span data-icon>•</span> Contains a number</li>
        <li data-rule="symbol" class="flex items-center gap-2 text-neutral-400"><span data-icon>•</span> Contains a symbol</li>
        <li data-rule="match" class="flex items-center gap-2 text-neutral-400"><span data-icon>•</span> Both passwords match</li>
      </ul>
      <button id="submit" disabled class="w-full cursor-not-allowed rounded-xl bg-neutral-900 py-2.5 text-sm font-medium text-white opacity-40 transition hover:bg-neutral-800">Update password</button>
    </form>
    <p class="mt-6 text-center text-sm text-neutral-500">
      <a href="#" class="font-medium text-neutral-900 hover:underline">← Back to sign in</a>
    </p>
  </div>
</div>
Исходный код
JavaScript
var pw = document.getElementById("pw");
var confirm = document.getElementById("confirm");
var segments = [].slice.call(document.querySelectorAll("#meter span"));
var strength = document.getElementById("strength");
var submit = document.getElementById("submit");
var rules = [].slice.call(document.querySelectorAll("[data-rule]"));

var LABELS = ["—", "Weak", "Fair", "Good", "Strong"];

function check(value, other) {
  return {
    length: value.length >= 12,
    number: /[0-9]/.test(value),
    symbol: /[^A-Za-z0-9]/.test(value),
    match: value.length > 0 && value === other
  };
}

function render() {
  var value = pw.value;
  var passed = check(value, confirm.value);

  // Score the password itself; "match" is a gate on submit, not a strength signal.
  var score = 0;
  if (passed.length) score += 1;
  if (passed.number) score += 1;
  if (passed.symbol) score += 1;
  if (/[a-z]/.test(value) && /[A-Z]/.test(value)) score += 1;
  if (!value) score = 0;

  segments.forEach(function (seg, i) {
    var filled = i < score;
    seg.className =
      "h-1.5 flex-1 rounded-full " +
      (!filled ? "bg-neutral-200" : score >= 4 ? "bg-green-500" : score >= 2 ? "bg-amber-500" : "bg-red-500");
  });

  strength.textContent = LABELS[score];

  rules.forEach(function (row) {
    var ok = passed[row.getAttribute("data-rule")];
    row.className = "flex items-center gap-2 " + (ok ? "text-green-600" : "text-neutral-400");
    row.querySelector("[data-icon]").textContent = ok ? "✓" : "•";
  });

  var ready = passed.length && passed.number && passed.symbol && passed.match;
  submit.disabled = !ready;
  submit.classList.toggle("opacity-40", !ready);
  submit.classList.toggle("cursor-not-allowed", !ready);
}

pw.addEventListener("input", render);
confirm.addEventListener("input", render);
render();