Password Input
Password entry field with a built-in visibility toggle and an optional four-segment strength meter. Shares its styling and form behavior with Input, so mixed forms stay visually uniform.
<arc-password-input> Overview
>
PasswordInput is the sibling of Input specialized for secret entry. It wraps a native `<input type="password">` with the same label, placeholder, validation, and size treatment as Input, and adds two password-specific affordances: an inline eye button that toggles the field between masked and plain text, and an optional strength meter driven by a self-contained heuristic.
The visibility toggle persists the user's choice — revealing the password does not silently revert on blur, which matches platform conventions and avoids surprising users mid-edit. The toggle is a real button with `aria-pressed` state and an accessible name, so screen-reader users get the same control.
When `show-strength` is set, a four-segment meter and text label ("Weak" through "Strong") render under the field. The score considers length thresholds, character-class variety, and penalises repeated characters, sequential runs like "abcd" or "1234", and the most common leaked passwords. The heuristic runs entirely client-side with no network calls. The meter exposes `role="meter"` semantics and announces changes politely for assistive technology.
PasswordInput participates in native forms through ElementInternals just like Input: it submits its value under `name`, supports `required` constraint validation, and resets with `form.reset()`. Use `autocomplete="new-password"` on registration and change-password forms so password managers offer to generate a credential.Guidelines
When to use
- Always provide a `label` so the field is accessible to screen readers
- Set `autocomplete="new-password"` on sign-up and change-password forms so password managers can generate credentials
- Enable `show-strength` on password-creation flows to give users live feedback
- Listen to `arc-strength-change` if you gate submission on a minimum score
- Pair with Form for coordinated validation and an error summary
- Keep the `error` prop for server-side or policy failures (e.g. "Password was found in a breach")
When not to use
- Do not show the strength meter on login forms — it only makes sense when creating a password
- Do not treat the heuristic score as a security guarantee; enforce real policy on the server
- Do not force the field back to masked while the user is typing — the toggle state is theirs
- Do not use placeholder text as the only label
- Do not block paste into the field — pasting from a password manager is a best practice
Features
- Visibility toggle button with `aria-pressed` state and eye / eye-off iconography
- User choice persists — the field does not re-mask on blur
- Optional four-segment strength meter with Weak / Fair / Good / Strong label
- Self-contained strength heuristic: length, character variety, common-password and pattern penalties
- `arc-strength-change` event exposes the 0-4 score for custom policy UI
- Native form participation via `ElementInternals`: submission, reset, and required validation
- `autocomplete` pass-through (defaults to `current-password`) for password-manager integration
- Identical field styling to Input — labels, sizes, error state, and focus rings match
- Meter uses `role="meter"` with aria value semantics and polite live announcements
Preview
Usage
This component requires JavaScript. No pure HTML/CSS version is available — use the Web Component directly or a framework wrapper.
<!-- Login: masked field with visibility toggle -->
<arc-password-input label="Password" name="password" required></arc-password-input>
<!-- Sign-up: strength meter + password-manager generation -->
<arc-password-input
label="New password"
name="new-password"
autocomplete="new-password"
show-strength
required
></arc-password-input>
<script>
document.querySelector('[show-strength]').addEventListener('arc-strength-change', (e) => {
console.log('strength score:', e.detail.score); // 0-4
});
</script> import { PasswordInput } from '@arclux/arc-ui-react';
{/* Login */}
<PasswordInput label="Password" name="password" required />
{/* Sign-up with strength meter */}
<PasswordInput
label="New password"
name="new-password"
autocomplete="new-password"
showStrength
required
onArcStrengthChange={(e) => setScore(e.detail.score)}
/> <script setup>
import { PasswordInput } from '@arclux/arc-ui-vue';
</script>
<template>
<!-- Login -->
<PasswordInput label="Password" name="password" required />
<!-- Sign-up with strength meter -->
<PasswordInput
label="New password"
name="new-password"
autocomplete="new-password"
show-strength
required
@arc-strength-change="(e) => console.log('strength score:', e.detail.score)"
/>
</template> <script>
import { PasswordInput } from '@arclux/arc-ui-svelte';
</script>
<!-- Login -->
<PasswordInput label="Password" name="password" required />
<!-- Sign-up with strength meter -->
<PasswordInput
label="New password"
name="new-password"
autocomplete="new-password"
showStrength
required
on:arc-strength-change={(e) => console.log('strength score:', e.detail.score)}
/> import { Component } from '@angular/core';
import { PasswordInput } from '@arclux/arc-ui-angular';
@Component({
imports: [PasswordInput],
template: `
<!-- Login -->
<arc-password-input label="Password" name="password" required></arc-password-input>
<!-- Sign-up with strength meter -->
<arc-password-input
label="New password"
name="new-password"
autocomplete="new-password"
showStrength
required
(arcStrengthChange)="onStrength($event)"
></arc-password-input>
`,
})
export class PasswordFormComponent {
onStrength(e: CustomEvent) {
console.log('strength score:', e.detail.score);
}
} <div style="display:flex; flex-direction:column; width:100%; max-width:400px; gap:16px;">
<arc-password-input label="Password" name="password" required></arc-password-input>
<arc-password-input label="New password" name="new-password" autocomplete="new-password" show-strength required></arc-password-input>
</div> API
-
autoValidatesbooleanfalse - Runs its own constraint logic — owns the whole validity flag set.
-
namestring'' - The `name` attribute sent with form data on submission. Also used by the Form component to track field state.
-
labelstring'' - Visible label rendered above the field. Automatically associated with the input via a generated id.
-
placeholderstring'' - Hint text displayed when the field is empty. Use it for guidance, never as a substitute for the label.
-
valuestring'' - The current value of the field. Can be set programmatically; updated internally on each keystroke.
-
disabledbooleanfalse - Prevents interaction (including the visibility toggle) and applies a muted visual treatment.
-
requiredbooleanfalse - Marks the field as required and enables native constraint validation on form submission.
-
errorstring'' - Error message displayed below the field. When set, the border turns red and the message is announced.
-
size'sm' | 'md' | 'lg''md' - Controls the field size. Options: 'sm', 'md', 'lg'.
-
autocompletestring'current-password' - Passed through to the inner input. Use `new-password` on registration or change-password forms so password managers offer generation.
-
show-strengthbooleanfalse - Renders a four-segment strength meter with a Weak / Fair / Good / Strong label under the field, scored by a built-in heuristic (length, character variety, common-pattern penalties).
-
formAssociatedbooleantrue -
propertiesobject{ required: { type: Boolean, reflect: true }, readonly: { type: Boolean, reflect: true }, } - Lit merges static properties up the prototype chain, so every consumer gets these without declaring them. `required` participates in constraint validation below; `readonly` reflects for styling and is enforced by each component's interaction handlers (the mixin can't know which gestures mutate state).
-
form -
validity -
validationMessage -
readonlybooleanfalse
Events
-
arc-strength-change - Fired when the strength score changes (only while show-strength is set), with { score } detail (0-4)
-
arc-inputdetail: { value: string } - Fired on each keystroke with { value } detail
-
arc-changedetail: { value: string } - Fired on blur when value has changed, with { value } detail
See Also
- Input Versatile form control supporting single-line text, email, password, and multiline textarea modes with built-in label, placeholder, and validation states. Pairs with Form for complete data-entry workflows.
- OTP Input A one-time password input that renders a row of individual character boxes with auto-advance, paste support, and configurable length and input type.
- Pin Input One-character-per-box input for PINs, OTPs, and verification codes with auto-advance, paste support, and optional masking.
- Form Form wrapper with built-in validation, error aggregation, and submit handling. Composes Input, Textarea, and Button into a cohesive data-entry workflow.
- Frameworks Guide