Forms
Password input
Enters a password, with a way to check what was typed.
Installation
npx sinaui add password-inputCopy src/lib/ui/PasswordInput.svelte, Input.svelte, InputButton.svelte, Icon.svelte and tokens.css. No other
dependencies.
Examples
Signing in
The eye shows and hides the password without moving the cursor. Turn on Caps Lock while typing to see the warning.
<script lang="ts">
import PasswordInput from '#lib/ui/PasswordInput.svelte';
</script>
<PasswordInput label="Password" name="password" required />Choosing a new password
Password managers offer to suggest one, and a meter shows how strong it is.
At least 12 characters, mixing letters, numbers and symbols.
<script lang="ts">
import PasswordInput from '#lib/ui/PasswordInput.svelte';
let password = $state('');
</script>
<PasswordInput
label="New password"
bind:value={password}
isNew
hint="At least 12 characters, mixing letters, numbers and symbols."
/>With requirements
Each requirement ticks off as it's met, including ones a simple pattern can't express, like not using your own name. The confirm field says when the two don't match.
- At least 12 characters, not yet met
- An uppercase and a lowercase letter, not yet met
- A number, not yet met
- A symbol, like ! or #, not yet met
- Not your name, not yet met
- No character 3 times in a row, not yet met
<script lang="ts">
import PasswordInput from '#lib/ui/PasswordInput.svelte';
const name = 'Maryam al-Ijliya';
let password = $state('');
let confirm = $state('');
let confirmTouched = $state(false);
const rules = [
{ label: 'At least 12 characters', test: (v: string) => v.length >= 12 },
{
label: 'An uppercase and a lowercase letter',
test: (v: string) => /[a-z]/.test(v) && /[A-Z]/.test(v)
},
{ label: 'A number', test: (v: string) => /\d/.test(v) },
{ label: 'A symbol, like ! or #', test: (v: string) => /[^A-Za-z0-9\s]/.test(v) },
{
label: 'Not your name',
test: (v: string) =>
!!v &&
!name
.toLowerCase()
.split(/[\s-]+/)
.some((part) => part.length > 2 && v.toLowerCase().includes(part))
},
{ label: 'No character 3 times in a row', test: (v: string) => !!v && !/(.)\1\1/.test(v) }
];
// Mismatch is shown once they've left the confirm field, then updates live.
const mismatch = $derived(
confirmTouched && confirm !== password ? "The passwords don't match." : undefined
);
</script>
<div class="stack">
<PasswordInput label="New password" bind:value={password} isNew {rules} />
<PasswordInput
label="Confirm password"
bind:value={confirm}
autocomplete="new-password"
error={mismatch}
onblur={() => (confirmTouched = true)}
/>
</div>
<style>
.stack {
display: grid;
gap: 1rem;
inline-size: min(100%, 24rem);
}
</style>Props
| Prop | Type | Default |
|---|---|---|
label | string (required) | |
value | string, bindable | '' |
isNew | boolean | false |
rules | { label, test(value) }[] | |
hint, error | string |
Other input attributes (name, required, minlength) pass
through.
Accessibility
- The show button is a toggle: screen readers hear “Show password, toggle button, pressed” or not pressed.
- The Caps Lock warning and the strength are announced when they change.
- Requirements are part of the field's description, each read as met or not yet met; “All requirements met” is announced once they are.
- Autofill hints (
current-passwordornew-password) let password managers fill or suggest.