KQ-1719 · RESET/MATCH

Reset Match

A set-new-password form whose confirmation shows how far it agrees with the password without ever showing a character: a rail between the fields draws a dot per character on each row, and while the confirmation agrees each new dot rises to its partner on the snap spring as the joint draws on flick. At the first difference a gap opens — the dot drops hollow under a caret and the rest hang loose — and when the two agree with every rule met a highlight runs along the joints in a cascade and a Match chip lands on recoil. Requirements are checked live and spoken as they flip, toggles and the requirement list are keyboard reachable, and a refusal nudges the field on a symmetric tween with the reason.

KQ-1719 · RESET/MATCH

Set a new password

for ines.park@fernworks.app

10 / 17

Requirements

  • At least 12 characters, met
  • Upper and lower case, met
  • A number, met
  • A symbol, like ! or #, met

Used before: Fernworks-2025!

4 of 4 rules · matches 10 of 17

Install

One command — the source lands in your repo. Or copy it from the Code tab.

$ pnpm dlx shadcn@latest add @kinetiq/reset-match

Props

rules
ResetMatchRule[]
default defaultResetMatchRules
The requirements ({ id, label, test }), checked live as the new password is typed.
lineStyle
"line" | "stitch" | "capsule"
default "line"
How a matched pair is joined on the rail: a short line, a cross-stitch, or one merged capsule.
density
"compact" | "regular" | "roomy"
default "regular"
Field heights (36, 40, 44px), gaps and the size of the rail.
accent
string
default "var(--accent-bright)"
Joints, locked dots, the match chip and met ticks; any CSS colour.
isReused
(password: string) => boolean | Promise<boolean>
default —
Asked on submit before onSubmit; true refuses the password with reusedMessage.
reusedMessage
string
default "You've used this password before. Choose one you haven't used on Fernworks."
Why a reused password is refused.
onSubmit
(password: string) => void | Promise<unknown>
default —
Fires with an accepted password. A returned promise shows Updating; a rejection shows its message under the field.
onContinue
() => void
default —
"Continue to sign in" was pressed on the done panel.
onCancel
() => void
default —
"Back to sign in" was pressed. Omit it to hide the link.
onResend
() => void
default —
"Send a new link" was pressed on the expired-link panel.
account
{ name: string; email: string }
default defaultResetMatchAccount
Whose password this is: named under the title and offered to password managers.
status
"ready" | "loading" | "error" | "done"
default "ready"
loading: the reset link is being checked; error: it has expired; done: the password is set.
title
string
default "Set a new password"
The heading.
submitLabel
string
default "Update password"
The submit button's words.
maxLength
number
default 64
Longest password the fields take; the rail tightens its pitch to fit it.
defaultPassword
string
default ""
What the new-password field starts with, uncontrolled — for a form resumed mid-way.
defaultConfirm
string
default ""
What the confirmation field starts with, uncontrolled.
onCheck
(check: ResetMatchCheck) => void
default —
Fires from each keystroke with counts and positions (never characters): rules met, lengths, matched prefix, where it differs, ready.
disabled
boolean
default false
Disables the fields and actions.
className
string
default —
Classes for the outer panel.