fix(auth): offer Google on the sign-up tab, not only on Log In (#345)
Linting / lint (pull_request) Canceled after 0s
SonarQube Analysis / sonarqube (pull_request) Canceled after 7s

The button was rendered inside the Log In tab's form only, so a visitor on Create Account saw no social option at all. Reported from a local run.

The mistake came from following the passkey button too closely. A passkey belongs only on Log In, and correctly so: you cannot register an account with one, since registration requires an account to register it against. Google is the opposite case. Creating an account is precisely what a new customer reaches for it to do, so leaving it off the sign-up tab hid the feature from the people it helps most — and hid it on the tab the modal opens on by default.

The label differs by tab and nothing else does. One endpoint serves both: it signs in a known identity, links a verified address, or creates an account, and the customer neither knows nor cares which will happen. So the wording matches what they came to that tab to do rather than what the server ends up doing. Both spellings are given in Google's identity guidelines alongside the mark.

The two consent checkboxes above it are deliberately not carried across. Google takes the customer off this site entirely, and a tick that survived that round trip would be a consent recorded from a form nobody submitted. They are asked again, with the same wording and through the same endpoints, on the step they land on afterwards — which is what #342 built that step for.

The end-to-end test asserts absence, like the one beside it, because local and QA have no credentials and absence is the behaviour that actually runs there.

Verified: frontend tsc, lint and build clean.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
synAdmin
2026-09-11 10:01:26 -05:00
co-authored by Claude Opus 5
parent 843c51dd91
commit 47dbd3ec65
3 changed files with 51 additions and 2 deletions
+13 -2
View File
@@ -37,6 +37,17 @@ function GoogleMark() {
type Props = Readonly<{
/** Where to send the customer back to. Validated again on the server. */
returnTo: string;
/**
* Which tab this sits on, which changes only the wording.
*
* One endpoint serves both: it signs in a known identity, links a verified
* address, or creates an account. The customer does not know or care which
* of those will happen, so the label matches what they came to the tab to
* do rather than what the server ends up doing.
*
* Both spellings are in Google identity guidelines alongside the mark.
*/
intent?: 'sign-in' | 'sign-up';
}>;
/**
@@ -51,7 +62,7 @@ type Props = Readonly<{
* here. It has to be, since anyone can type the URL, and doing it in one place
* beats doing it in two languages. See `google/returnTo.ts`.
*/
export default function GoogleSignInButton({ returnTo }: Props) {
export default function GoogleSignInButton({ returnTo, intent = 'sign-in' }: Props) {
return (
<Button
block
@@ -62,7 +73,7 @@ export default function GoogleSignInButton({ returnTo }: Props) {
window.location.assign(`/api/auth/google/start?returnTo=${encodeURIComponent(returnTo)}`);
}}
>
Sign in with Google
{intent === 'sign-up' ? 'Sign up with Google' : 'Sign in with Google'}
</Button>
);
}