Nasaq
Components

PasswordInput

Password field built on InputGroup with a show/hide toggle (aria-pressed), an optional strength meter and an optional requirement checklist.

PreviewOpen ↗

Code

import { Field, FieldLabel, PasswordInput } from "@fadymondy/nasaq/web";export function SignInPassword() {  return (    <Field>      <FieldLabel>Password</FieldLabel>      <PasswordInput autoComplete="current-password" />    </Field>  );}

Forms · beta

Live examples and controls: PasswordInput in the lab.

Install

npx shadcn@latest add https://docs.nasaqui.com/r/password-input.json

A password field with an eye button that shows or hides the text, and an optional strength meter under it. It is an InputGroup, so height, border, focus ring and invalid state match every other field, and it works inside Field for the label, description and error.

When to use

  • Sign in, sign up, change password, and any secret the person types and may want to check.
  • Set showStrength when the person is choosing a new password.

When not to use

  • One-time codes: use OtpInput.
  • API keys or tokens you display read-only: use CopyField from CopyButton.
  • Plain text: use Input from Field.

Import

import { PasswordInput } from "@fadymondy/nasaq/web";
// inside this monorepo: "@nasaq/web"

Quick start

import { Field, FieldLabel, PasswordInput } from "@fadymondy/nasaq/web";

export function SignInPassword() {
  return (
    <Field>
      <FieldLabel>Password</FieldLabel>
      <PasswordInput autoComplete="current-password" />
    </Field>
  );
}

Anatomy

PasswordInput                     data-slot="password-input"
├─ InputGroup
│  ├─ InputGroupInput             type="password" | "text"
│  └─ InputGroupAddon (end)
│     └─ Button                   data-slot="password-input-toggle", aria-pressed
├─ strength (only with showStrength)   data-slot="password-input-strength", data-score="0".."4"
│  ├─ Meter                       data-slot="meter"
│  └─ level word                  aria-live="polite"
└─ ul (only with rules)           data-slot="password-input-rules", aria-label="Password requirements"
   └─ li × n                      data-met when met, Check or Minus icon, sr-only "met" / "not met"

API

PasswordInput: every InputGroupInput prop except type (so autoComplete, name, value, defaultValue, onChange, disabled, required, ltr and ref all pass through to the <input>), plus:

PropTypeDefaultDescription
visiblebooleanControlled visibility.
defaultVisiblebooleanfalseInitial visibility when uncontrolled.
onVisibleChange(visible: boolean) => voidCalled when the toggle is pressed.
toggleLabelstring"Show password" / "إظهار كلمة المرور"Accessible name of the toggle. It does not change with state; aria-pressed does.
showStrengthbooleanfalseShow the strength meter and level word.
scorenumberestimatorStrength from 0 to 4. Rounded and clamped. Omit to use estimatePasswordStrength.
strengthLabelstring"Password strength" / "قوة كلمة المرور"Name of the meter.
strengthLevels[string, string, string, string, string]English or Arabic wordsWords for scores 0 to 4.
rulesboolean | PasswordPolicy | readonly PasswordRule[]Show a requirement checklist. true is 12 characters plus upper, lower, digit and symbol; a policy changes that; an array is shown as is.
ruleLabelsRecord<string, string>English or ArabicText per rule id. Needed for custom ids.
classNamestringClass for the outer wrapper.
inputClassNamestringClass for the <input>.

estimatePasswordStrength(password: string): PasswordScore: a small estimate from length and character classes. Returns 0 to 4. PasswordScore is 0 | 1 | 2 | 3 | 4. It is a hint, not a policy.

ScoreRule
0Empty, shorter than 6, or three or fewer distinct characters
16 or more characters
28 or more characters with two classes
310 or more characters with three classes
412 or more with four classes, or 16 or more with three

Classes are lower case, upper case, digit, symbol, and uncased letters such as Arabic.

computePasswordRules(password, policy?): PasswordRule[]: the length rule (with min) then one rule per class in policy.require (default upper, lower, digit, symbol). PasswordPolicy is { minLength?: number; require?: ("upper" | "lower" | "digit" | "symbol")[] }, minimum 12 by default. PasswordRule is { id; met: boolean; min?: number }.

computeRuleScore(rules): PasswordScore: 0 until length passes, then 1 plus one per other rule met, capped at 4. Pass it as score so the meter follows your policy instead of the estimate.

passwordMeetsPolicy(rules): boolean: true when every rule is met. Use it to block submit.

Examples

Sign up with the estimator

import { Field, FieldDescription, FieldLabel, PasswordInput } from "@fadymondy/nasaq/web";

export function NewPassword() {
  return (
    <Field>
      <FieldLabel>New password</FieldLabel>
      <PasswordInput autoComplete="new-password" showStrength />
      <FieldDescription>At least 8 characters.</FieldDescription>
    </Field>
  );
}

Your own estimator

import { PasswordInput } from "@fadymondy/nasaq/web";
import { useState } from "react";

// zxcvbn(value).score is already 0 to 4.
declare function zxcvbnScore(value: string): number;

export function Custom() {
  const [value, setValue] = useState("");
  return <PasswordInput showStrength value={value} score={zxcvbnScore(value)} onChange={(e) => setValue(e.target.value)} />;
}

A policy checklist

import { PasswordInput, computePasswordRules, computeRuleScore, passwordMeetsPolicy } from "@fadymondy/nasaq/web";
import { useState } from "react";

export function Policy() {
  const [value, setValue] = useState("");
  const rules = computePasswordRules(value, { minLength: 10 });
  return (
    <form onSubmit={(e) => passwordMeetsPolicy(rules) || e.preventDefault()}>
      <PasswordInput autoComplete="new-password" showStrength score={computeRuleScore(rules)} rules={rules} value={value} onChange={(e) => setValue(e.target.value)} />
    </form>
  );
}

Arabic

import { Field, FieldLabel, PasswordInput } from "@fadymondy/nasaq/web";

export function ArabicPassword() {
  return (
    <Field>
      <FieldLabel>كلمة مرور جديدة</FieldLabel>
      <PasswordInput autoComplete="new-password" showStrength placeholder="أدخل كلمة المرور" />
    </Field>
  );
}

Accessibility

KeyAction
TabMoves from the input to the toggle.
Enter / Space on the toggleShows or hides the password.
  • The toggle is a button with a constant aria-label and aria-pressed for the state, so a screen reader says "Show password, toggle button, pressed" and never a contradicting label.
  • The meter is role="meter" with aria-valuenow 0 to 4 and an aria-label. The level word sits in an aria-live="polite" region, so it is spoken when it changes.
  • Caller must localise: toggleLabel, strengthLabel and strengthLevels when not using English or Arabic.
  • The checklist is a labelled list. Each item ends with a visually hidden ", met" or ", not met", so the state is not carried by the tick or the colour alone. It is not live: re-reading on every key would be noisy. Show the unmet rule in the field error on submit.
  • Set autoComplete so password managers work: current-password to sign in, new-password to create one.
  • The input sets autoCapitalize="none", autoCorrect="off" and spellCheck={false}.

RTL & i18n

  • The toggle sits at the inline end: the right in English, the left in Arabic. The meter fills from the inline start.
  • The value keeps the input's natural direction and is not mirrored. Pass ltr to pin the typed value to left-to-right in an Arabic form, which keeps symbols in order.
  • Built-in English and Arabic strings follow the Nasaq locale.
  • The estimator counts code points, so Arabic letters and emoji are one character each.

Styling & tokens

  • Border, radius, focus ring: --nq-* tokens through InputGroup. Meter fill uses the danger, warning, info and success tokens.
  • Target [data-slot="password-input-strength"][data-score="3"] to style by score.
  • aria-invalid turns the border to the danger colour. Extend with className and inputClassName.

Do / Don't

  • Do set autoComplete on every password field.
  • Do use the meter only when creating a password.
  • Don't rely on the estimator as a security rule: enforce the policy on the server.
  • Don't put a strength meter on a sign-in form.

Lab

https://docs.nasaqui.com/?path=/docs/components-forms-password-input--docs

On this page