Skip to content

Commit cd95d5e

Browse files
authored
Merge pull request #818 from nicksan222/fix/password-mismatch-flash
Fix password mismatch flash in authentication
2 parents 9d05c2c + 761113b commit cd95d5e

4 files changed

Lines changed: 34 additions & 21 deletions

File tree

src/components/ory/flowcomponents/Nodes/OryButton.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import { useFormContext } from "react-hook-form";
88
import type { OryNodeButtonProps } from "@ory/elements-react";
99
import { FingerPrintIcon } from "@heroicons/react/24/outline";
1010
import { Button } from "@/components/ui/button";
11-
import { usePasswordMismatch } from "../PasswordField";
11+
import { usePasswordMismatch } from "@/hooks/usePasswordMismatch";
1212

1313
export function OryButton({ node, buttonProps }: OryNodeButtonProps) {
1414
const label = node.meta.label?.text ?? "";

src/components/ory/flowcomponents/Nodes/OryRegistrationInput.tsx

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,24 +3,32 @@
33

44
"use client";
55

6-
import { useState } from "react";
6+
import { useEffect, useState } from "react";
77
import { useFormContext } from "react-hook-form";
88
import type { OryNodeInputProps } from "@ory/elements-react";
99
import { Label } from "@/components/ui/label";
10-
import {
11-
CONFIRM_PASSWORD_LABEL,
12-
PasswordField,
13-
usePasswordMismatch,
14-
} from "../PasswordField";
10+
import { usePasswordMismatch } from "@/hooks/usePasswordMismatch";
11+
import { CONFIRM_PASSWORD_LABEL, PasswordField } from "../PasswordField";
1512
import { OryInput } from "./OryInput";
1613

1714
export function OryRegistrationInput(props: OryNodeInputProps) {
1815
const { node, attributes, onClick } = props;
19-
const { register } = useFormContext();
16+
const {
17+
register,
18+
resetField,
19+
formState: { isSubmitting },
20+
} = useFormContext();
2021
const mismatch = usePasswordMismatch();
2122
const [confirmTouched, setConfirmTouched] = useState(false);
2223
const { value, name, autocomplete, maxlength, ...rest } = attributes;
2324

25+
useEffect(() => {
26+
if (isSubmitting) {
27+
resetField("confirmPassword");
28+
setConfirmTouched(false);
29+
}
30+
}, [isSubmitting, resetField]);
31+
2432
// Only the password field gets the extra confirmation field. Every other
2533
// node (email, name, hidden, csrf, …) renders exactly like the standard
2634
// input, so we delegate to OryInput rather than duplicating that logic.
@@ -30,7 +38,7 @@ export function OryRegistrationInput(props: OryNodeInputProps) {
3038

3139
// Show the mismatch error only once the confirm field has been touched, but
3240
// keep it watch-driven so it clears live as soon as the values match.
33-
const showMismatch = confirmTouched && mismatch;
41+
const showMismatch = !isSubmitting && confirmTouched && mismatch;
3442

3543
return (
3644
<div className="flex flex-col gap-1">

src/components/ory/flowcomponents/PasswordField.tsx

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
import { useState } from "react";
77
import type { FocusEventHandler, MouseEventHandler } from "react";
8-
import { useFormContext, type UseFormRegisterReturn } from "react-hook-form";
8+
import type { UseFormRegisterReturn } from "react-hook-form";
99
import { Eye, EyeOff } from "lucide-react";
1010
import { Button } from "@/components/ui/button";
1111

@@ -14,17 +14,6 @@ const PASSWORD_FIELD_CLASS =
1414

1515
export const CONFIRM_PASSWORD_LABEL = "Confirm Password";
1616

17-
export function usePasswordMismatch(): boolean {
18-
const { watch, getValues } = useFormContext();
19-
const password = watch("password");
20-
const confirmPassword = watch("confirmPassword");
21-
const hasConfirmField = "confirmPassword" in getValues();
22-
if (!hasConfirmField) {
23-
return false;
24-
}
25-
return password !== confirmPassword;
26-
}
27-
2817
export function PasswordField({
2918
field,
3019
label,

src/hooks/usePasswordMismatch.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// Copyright 2026 L3montree GmbH and the DevGuard Contributors.
2+
// SPDX-License-Identifier: AGPL-3.0-or-later
3+
4+
import { useFormContext } from "react-hook-form";
5+
6+
export function usePasswordMismatch(): boolean {
7+
const { watch, getValues } = useFormContext();
8+
const password = watch("password");
9+
const confirmPassword = watch("confirmPassword");
10+
const hasConfirmField = "confirmPassword" in getValues();
11+
12+
if (!hasConfirmField) {
13+
return false;
14+
}
15+
return password !== confirmPassword;
16+
}

0 commit comments

Comments
 (0)