Auth Password Reset
blockauthFour-stage password reset surface in a single card: request (email form) -> sent (check-your-inbox confirmation with "Open reset form" demo button) -> reset (new password + confirm with match validation) -> done (success confirmation linking back to sign-in). Pass `onRequest` (email) and `onReset` (password) callbacks; consumer wires the actual mail/db calls.
Installation
$pnpm dlx shadcn-svelte@latest add https://uipkge.dev/r/svelte/auth-password-reset.json$npx shadcn-svelte@latest add https://uipkge.dev/r/svelte/auth-password-reset.json$yarn dlx shadcn-svelte@latest add https://uipkge.dev/r/svelte/auth-password-reset.json$bunx shadcn-svelte@latest add https://uipkge.dev/r/svelte/auth-password-reset.jsonManifest:
https://uipkge.dev/r/svelte/auth-password-reset.jsonInstalls to:src/lib/components/blocks/auth-password-reset/Variants
Loading interactive previews…
Loading interactive previews…
npm dependencies
Files installed (1)
src/lib/components/blocks/auth-password-reset/AuthPasswordReset.svelte4.9 kB
<script lang="ts"> import { ArrowLeft, MailCheck } from '@lucide/svelte' import { Button } from '$lib/components/ui/button' import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from '$lib/components/ui/card' import { Input } from '$lib/components/ui/input' import { Label } from '$lib/components/ui/label' interface Props { signInHref?: string /** Fired with the email when the reset link is requested. Wire your mail call here. */ onRequest?: (email: string) => void /** Fired with the new password when it is set. Wire your db call here. */ onReset?: (password: string) => void } let { signInHref = '/login', onRequest, onReset }: Props = $props() type Stage = 'request' | 'sent' | 'reset' | 'done' let stage: Stage = $state('request') let email = $state('') let password = $state('') let confirm = $state('') const passwordsMatch = $derived(!confirm || password === confirm) function submitRequest(e: SubmitEvent) { e.preventDefault() if (!email) return onRequest?.(email) stage = 'sent' } function submitReset(e: SubmitEvent) { e.preventDefault() if (!password || !passwordsMatch) return onReset?.(password) stage = 'done' } </script> <div data-slot="auth-password-reset" class="bg-background flex min-h-svh items-center justify-center p-6"> <Card class="w-full max-w-sm"> {#if stage === 'request'} <CardHeader class="text-center"> <CardTitle class="text-2xl">Forgot password?</CardTitle> <CardDescription>Enter your email and we'll send you a reset link.</CardDescription> </CardHeader> <CardContent> <form class="space-y-4" onsubmit={submitRequest}> <div class="grid gap-2"> <Label for="reset-email">Email</Label> <Input id="reset-email" bind:value={email} type="email" placeholder="you@company.com" required /> </div> <Button type="submit" class="w-full">Send reset link</Button> </form> </CardContent> <CardFooter class="justify-center"> <a href={signInHref} class="text-muted-foreground hover:text-foreground inline-flex items-center gap-1 text-sm" > <ArrowLeft class="size-3" />Back to sign in </a> </CardFooter> {:else if stage === 'sent'} <CardContent class="space-y-4 pt-6 text-center"> <div class="bg-primary/10 text-primary mx-auto flex size-12 items-center justify-center rounded-full"> <MailCheck class="size-6" /> </div> <div class="space-y-1"> <h3 class="text-lg font-semibold">Check your inbox</h3> <p class="text-muted-foreground text-sm"> We've sent a reset link to <span class="text-foreground font-medium">{email}</span>. </p> </div> <Button variant="outline" class="w-full" onclick={() => (stage = 'reset')}>Open reset form (demo)</Button> <button type="button" class="text-muted-foreground hover:text-foreground text-xs underline-offset-4 hover:underline" onclick={() => (stage = 'request')} > Wrong email? </button> </CardContent> {:else if stage === 'reset'} <CardHeader class="text-center"> <CardTitle class="text-2xl">Set new password</CardTitle> <CardDescription>Pick a strong password you haven't used before.</CardDescription> </CardHeader> <CardContent> <form class="space-y-4" onsubmit={submitReset}> <div class="grid gap-2"> <Label for="reset-pw">New password</Label> <Input id="reset-pw" bind:value={password} type="password" autocomplete="new-password" required /> </div> <div class="grid gap-2"> <Label for="reset-confirm">Confirm password</Label> <Input id="reset-confirm" bind:value={confirm} type="password" autocomplete="new-password" aria-invalid={!passwordsMatch} required /> {#if !passwordsMatch} <p class="text-destructive text-xs">Passwords don't match.</p> {/if} </div> <Button type="submit" class="w-full">Reset password</Button> </form> </CardContent> {:else} <CardContent class="space-y-4 pt-6 text-center"> <div class="bg-success/10 text-success mx-auto flex size-12 items-center justify-center rounded-full"> <MailCheck class="size-6" /> </div> <div class="space-y-1"> <h3 class="text-lg font-semibold">All set</h3> <p class="text-muted-foreground text-sm"> Your password has been updated. You can now sign in with the new password. </p> </div> <a href={signInHref}><Button class="w-full">Continue to sign in</Button></a> </CardContent> {/if} </Card> </div>
Raw manifest:https://uipkge.dev/r/svelte/auth-password-reset.json