Skip to content

feat(forms): add autocomplete attributes to email, password and code inputs - #1495

Open
demolaf wants to merge 5 commits into
mainfrom
feat/form-autocomplete-attributes
Open

demolaf wants to merge 5 commits into
mainfrom
feat/form-autocomplete-attributes

Conversation

@demolaf

@demolaf demolaf commented Sep 21, 2026

Copy link
Copy Markdown
Member

Closes #1493.

Adds autocomplete attributes to every email, password, phone and verification-code input across the React, Angular and shadcn packages, plus the shadcn example app, which keeps its own copies of the forms. None of them set the attribute before, so browsers and password managers had nothing to identify the fields with and Edge flagged autofill problems on the sign-in and sign-up forms.

Changes

  • username on every email identifier field, current-password on sign-in, new-password on sign-up, name on the sign-up display name, tel on phone fields, one-time-code on verification codes, and off on MFA enrollment display names, which are factor nicknames rather than the person's name
  • Angular FormInputComponent takes internal autocomplete, placeholder and maxlength inputs, since unlike React and shadcn it does not spread arbitrary input props; this also fixes the TOTP assertion form, whose placeholder="123456" and maxlength="6" previously landed on the host element and never reached the input
  • Angular email-link and forgot-password forms now pass type="email" to match React and shadcn, so native constraint validation fires on submit there and the browser's untranslated bubble pre-empts the library's localised invalidEmail message

Why username and not email

username is the token credential managers key on to identify the account-name field and email is not, so marking an identifier email leaves the account-name half of the new-password pairing to browser heuristics; where those miss, the credential is saved with no account name and is never offered back on sign-in. Every form naming an account uses it, so the token stays consistent wherever a credential is saved or looked up.

Apple's Password AutoFill guidance says to set autocomplete="username" with type="email" when a site uses email addresses as user names, and Chromium's form-styles document uses username on the identifier for sign-in and sign-up alike. This issue asked for email on sign-up, so these values deviate from the request.

…inputs

No input in any of the three UI packages set an autocomplete hint, so browsers and password managers had nothing to work with and Edge reported autofill issues on the sign-in and sign-up forms.

React and shadcn already spread arbitrary input props, so those only needed the attribute at each call site. Angular's FormInputComponent hardcoded its input bindings with no passthrough, so it now takes an `autocomplete` input and binds it as an attribute, absent rather than empty when unset.

Values follow web.dev, which splits its guidance by form: `username` and `current-password` on sign-in, `email` and `new-password` on sign-up, `email` on the email-link and forgot-password forms, `name` on the sign-up display name, `tel` on phone fields, and `one-time-code` on verification codes. The MFA enrollment display name is the second factor's nickname rather than the person's name, so it gets `off` to stop browsers filling a real name into a factor label. The shadcn OTP fields are untouched because input-otp already defaults to `one-time-code`.

Also fixes an angular parity bug on the same lines: the email-link and forgot-password forms never passed `type`, so they rendered as plain text inputs while their react counterparts rendered `type="email"`.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces standard HTML autocomplete attributes (such as 'email', 'username', 'current-password', 'new-password', 'tel', 'one-time-code', and 'off') to various authentication form inputs across the Angular, React, and Shadcn packages. These changes improve accessibility, user experience, and integration with browser autofill features and password managers. Corresponding unit tests have been updated to verify the presence of these attributes. There are no review comments, and the changes look solid, so I have no additional feedback to provide.

FormInputComponent declared no inputs for placeholder or maxlength, so the `placeholder="123456"` and `maxlength="6"` on the TOTP assertion form landed on the fui-form-input host element and never reached the `<input>`. React's equivalent form rendered both, so angular users got neither the hint nor the length cap.

The existing spec hid this. `getByPlaceholderText` matched the host element and passed while the inner input had no placeholder at all, so the assertion now reads the attributes off the input itself. Both attributes are bound with `[attr.*]`, so they stay absent when unset.

Also extends the autocomplete attributes to the shadcn example app, which keeps its own copies of the forms with no sync script back to the registry.
The sign-up identifier was `email` and the sign-in identifier was `username`, so the same field carried two different tokens in one library. `email` is not a token credential managers key on to identify the account-name field, which left the account-name half of the `new-password` pairing to heuristics: where they miss, the credential saves with no account name and is then not offered back on sign-in.

Apple's Password AutoFill docs cover this case directly, saying to set `autocomplete="username"` with `type="email"` when the site uses email addresses as user names, and Chromium's form-styles document uses `username` on the identifier for sign-in and sign-up alike. Forgot-password follows for the same reason, since the user is naming an existing account there.

The email-link form keeps `email`. No password credential exists in a passwordless flow, so there is nothing for a manager to pair.
The new `autocomplete`, `placeholder` and `maxlength` inputs are bound with `[attr.*]`, so an unset input drops the attribute instead of rendering a literal "undefined". Nothing pinned that, and it is the one way the binding could regress silently. Verified the assertion is not vacuous: swapping `[attr.autocomplete]` for interpolation fails it.
@demolaf
demolaf marked this pull request as ready for review September 21, 2026 15:56
The email-link identifier was the last one left on `email`, which contradicted the reasoning behind the other three. It names the same account as sign-in, so a credential saved at sign-up was keyed on `username` while this form asked the browser for an address-book email, and the saved account was not offered back.

The earlier justification, that no password credential exists in a passwordless flow, was about the absent password field rather than the identifier, so it did not apply.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add autocomplete attributes to v7 React email/password forms

2 participants