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