feat: Browser autofill support for login form (#521)

* fix: add name and autocomplete attributes to auth form inputs

Password managers (1Password, Bitwarden, etc.) rely on the HTML `name`
and `autocomplete` attributes to detect and fill credential fields.
The login and setup forms were missing both, preventing password managers
from offering autofill.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* docs: add JSDoc docstrings to auth form components

Adds JSDoc comments to all exported functions and the internal
validateSetupForm helper in the auth form files, bringing docstring
coverage above the 80% threshold required by CodeRabbit.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix: explicitly set name props on SetupForm credential inputs

The three AuthInputField calls in SetupForm were relying on the
id-to-name fallback (name={name ?? id}) inside AuthInputField.
Adding explicit name props makes the password-manager contract
self-contained in SetupForm and resilient to future id changes.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Benjamin <1159333+benjaminburzan@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Benjamin
2026-03-16 12:00:14 +01:00
committed by GitHub
parent 95bcee0ec4
commit 72ff134b31
3 changed files with 36 additions and 0 deletions

View File

@@ -17,6 +17,11 @@ const initialState: SetupFormState = {
confirmPassword: '',
};
/**
* Validates the account-setup form state.
* @returns An error message string if validation fails, or `null` when the
* form is valid.
*/
function validateSetupForm(formState: SetupFormState): string | null {
if (!formState.username.trim() || !formState.password || !formState.confirmPassword) {
return 'Please fill in all fields.';
@@ -37,6 +42,12 @@ function validateSetupForm(formState: SetupFormState): string | null {
return null;
}
/**
* Account setup / registration form.
* Uses `autoComplete="new-password"` on password fields so that password
* managers recognise this as a registration flow and offer to save the new
* credentials after submission.
*/
export default function SetupForm() {
const { register } = useAuth();
@@ -79,31 +90,37 @@ export default function SetupForm() {
<form onSubmit={handleSubmit} className="space-y-4">
<AuthInputField
id="username"
name="username"
label="Username"
value={formState.username}
onChange={(value) => updateField('username', value)}
placeholder="Enter your username"
isDisabled={isSubmitting}
autoComplete="username"
/>
<AuthInputField
id="password"
name="password"
label="Password"
value={formState.password}
onChange={(value) => updateField('password', value)}
placeholder="Enter your password"
isDisabled={isSubmitting}
type="password"
autoComplete="new-password"
/>
<AuthInputField
id="confirmPassword"
name="confirmPassword"
label="Confirm Password"
value={formState.confirmPassword}
onChange={(value) => updateField('confirmPassword', value)}
placeholder="Confirm your password"
isDisabled={isSubmitting}
type="password"
autoComplete="new-password"
/>
<AuthErrorAlert errorMessage={errorMessage} />