Password
A password input with a show / hide toggle.
Installation
Installs the style saved in lily.json. For a new Diamond project,
run lily-svelte init --style diamond first.
Install the lily base and `utils` (run once per project).
npx lily-svelte@latest init Copy the password source from the registry into $lib/components/ui/password.
Usage
<script lang="ts">
import { Password } from '$lib/components/ui/password';
let value = $state('');
</script>
<Password bind:value placeholder="Enter your password" /> Strength meter
Pass showStrength to render a strength bar. Scoring uses @zxcvbn-ts (a vetted estimator), not a homemade heuristic.
<Password bind:value showStrength /> npm install @zxcvbn-ts/core @zxcvbn-ts/language-common Reading the score
result binds the full zxcvbn result out, so form
validation can read score (0–4) or any of the crack-time estimates. minScore marks the input
invalid until the password reaches it.
<script lang="ts">
import type { ZxcvbnResult } from '@zxcvbn-ts/core';
let value = $state('');
let result = $state<ZxcvbnResult | null>(null);
const strongEnough = $derived((result?.score ?? -1) >= 3);
</script>
<Password bind:value bind:result minScore={3} showStrength /> Scoring is skipped entirely until something asks for it: a PasswordStrength part being
rendered, showStrength, or a minScore. A plain <Password /> never runs zxcvbn, and result stays null until one of those turns it on.
Parts
<Password /> is the composed happy path. When that layout does not fit — a label with your own
copy, the strength meter somewhere else, a different toggle — build it from the parts instead.
Pick something a machine will not guess.
<script lang="ts">
import {
PasswordRoot,
PasswordInput,
PasswordToggleVisibility,
PasswordStrength
} from '$lib/components/ui/password';
let value = $state('');
</script>
<PasswordRoot bind:value minScore={2}>
<div class="relative">
<PasswordInput placeholder="Enter your password" />
<PasswordToggleVisibility class="absolute end-1.5 top-1/2 -translate-y-1/2" />
</div>
<PasswordStrength labels={['Poor', 'Weak', 'Average', 'Strong', 'Secure']} />
</PasswordRoot> Only one field needs the meter? Give that one a PasswordStrength and leave it off the other —
each PasswordRoot is independent.