Skip to content

components password

GitHub Actions edited this page Sep 22, 2026 · 1 revision

components/password

Import: import { PasswordInput } from "@tundralibs/ui/password"

Rendered in every variant on the catalogue (deno task build:demos, then demo/index.html). Guides: Getting started · rAPId integration · Theming.

Functions

PasswordInput

PasswordInput(props: PasswordInputProps): Html

A password field: the plain Input with a Show/Hide toggle, an optional strength bar under it, and match for a confirm field. Client-side only by nature — without JS the toggle and bar are hidden and the field is a normal password input. Pair with Form({ validate: true }) for inline messages, including "too weak" (strengthMin) and "does not match".

Types

PasswordStrength

  • "1"
  • "2"
  • "3"
  • "4"

PasswordInputProps

Prop Type Required Description
id string yes Required: the reveal toggle and a confirm field's match point at it.
name string yes
value string
placeholder string
size InputSize
required boolean
disabled boolean
invalid boolean
minLength number
maxLength number
autocomplete `"new-password" "current-password"`
strength boolean Show the strength bar (new passwords). password.js scores the value as it is typed — length, character classes, repeats, sequences, the most common passwords — into four levels; the bar is hidden while empty.
strengthMin PasswordStrength With strength: the lowest level the validator accepts (1 Too weak, 2 Weak, 3 Good, 4 Strong). Below it the field is invalid with the messages.strength text. The server must enforce its own rule too.
match string Selector of the password this one must equal — the confirm field: match: "#password".
reveal boolean The Show / Hide toggle. @default true
labels Partial Labels of the toggle and the strength levels, for translation.
messages ValidationMessages & { strength?: string }
attrs Attrs

Constants

  • DEFAULT_LABELS: { show: string; hide: string; strength: string; levels: typeOperator }

Usage

Each example as the rAPId call and the HTML it renders — the markup a plain page writes by hand. Icons are inline SVG in the real output; they are shortened to <svg …>…</svg> here.

Sign-in: current password with Show/Hide

PasswordInput({ id: "current", name: "password", required: true, autocomplete: "current-password" })
<div class="password" data-password data-strength-level="0">
  <div class="password__field">
    <input type="password" class="input password__input" id="current" name="password" required="" autocomplete="current-password">
    <button type="button" class="password__reveal js-only" data-password-reveal aria-controls="current" aria-pressed="false" data-label-show="Show" data-label-hide="Hide">Show</button>
  </div>
</div>

Sign-up: a new password with the strength bar, and its confirm field

strengthMin makes anything below Good invalid; match on the confirm field checks equality. Both need Form({ validate: true }) to show inline; the server still validates.

html`${
  FormField({
    id: "new-password",
    label: "Password",
    required: true,
    help: "At least 12 characters, mixed case, a number.",
    control: (a) =>
      PasswordInput({
        id: a.id,
        name: "password",
        required: true,
        minLength: 12,
        autocomplete: "new-password",
        strength: true,
        strengthMin: 3,
        messages: { minLength: "Use at least 12 characters.", strength: "Choose a stronger password." },
      }),
  })
}${
  FormField({
    id: "confirm",
    label: "Confirm password",
    required: true,
    control: (a) =>
      PasswordInput({
        id: a.id,
        name: "confirm",
        required: true,
        autocomplete: "new-password",
        match: "#new-password",
        messages: { match: "The passwords do not match." },
      }),
  })
}`
<div class="form-field">
  <label class="form-field__label" for="new-password">
    Password
    <span class="form-field__required" aria-hidden="true">*</span>
  </label>
  <div class="password" data-password data-strength-level="0">
    <div class="password__field">
      <input type="password" class="input password__input" data-msg-min-length="Use at least 12 characters." data-strength-min="3" data-msg-strength="Choose a stronger password." id="new-password" name="password" required="" minlength="12" autocomplete="new-password">
      <button type="button" class="password__reveal js-only" data-password-reveal aria-controls="new-password" aria-pressed="false" data-label-show="Show" data-label-hide="Hide">Show</button>
    </div>
    <div class="password__strength js-only" data-password-strength hidden>
      <div class="password__bar" aria-hidden="true">
        <i></i>
        <i></i>
        <i></i>
        <i></i>
      </div>
      <p class="password__strength-label">
        <span class="sr-only">Password strength:</span>
        <span data-password-label data-levels="Too weak|Weak|Good|Strong"></span>
      </p>
    </div>
  </div>
  <p class="form-field__help" id="new-password-help">At least 12 characters, mixed case, a number.</p>
</div>
<div class="form-field">
  <label class="form-field__label" for="confirm">
    Confirm password
    <span class="form-field__required" aria-hidden="true">*</span>
  </label>
  <div class="password" data-password data-strength-level="0">
    <div class="password__field">
      <input type="password" class="input password__input" data-msg-match="The passwords do not match." id="confirm" name="confirm" required="" autocomplete="new-password" data-match="#new-password">
      <button type="button" class="password__reveal js-only" data-password-reveal aria-controls="confirm" aria-pressed="false" data-label-show="Show" data-label-hide="Hide">Show</button>
    </div>
  </div>
</div>

CSS hooks

Classes defined by components/password/password.css — structural, token-driven; override from an unlayered stylesheet (see Theming):

.password, .password__bar, .password__field, .password__input, .password__reveal, .password__strength, .password__strength-label

Behaviour

components/password/password.js ships in ui.js (delegated on document, re-initialised after a rAPId swap).

Attributes it reads or writes: data-label-hide, data-label-show, data-levels, data-msg-strength, data-password, data-password-label, data-password-reveal, data-password-strength, data-strength-level, data-strength-min.

Events: rapid:swapped.

Clone this wiki locally