From 5a36df700b5c90b4a5478799c73c1767c4c586f5 Mon Sep 17 00:00:00 2001 From: whereareiam Date: Thu, 22 Oct 2026 22:47:33 +0200 Subject: [PATCH] fix(auth): sign-in layout for password recovery, reset and activation Sign in and register follow GitHub's centred panel with the logo and title over a flat form, but Forgot password, Reset password and Activate account kept Forgejo's boxed card. They now use the same panel with the logo and title, and submit with a full-width button as sign-in does. Their content and forms are Forgejo's. Co-Authored-By: Claude Opus 5.5 --- src/build-output.test.ts | 9 ++++ styles/components/signin.ts | 5 ++ templates/user/auth/activate.tmpl | 60 ++++++++++++++++++++++++ templates/user/auth/forgot_passwd.tmpl | 38 +++++++++++++++ templates/user/auth/reset_passwd.tmpl | 64 ++++++++++++++++++++++++++ 5 files changed, 176 insertions(+) create mode 100644 templates/user/auth/activate.tmpl create mode 100644 templates/user/auth/forgot_passwd.tmpl create mode 100644 templates/user/auth/reset_passwd.tmpl diff --git a/src/build-output.test.ts b/src/build-output.test.ts index a978fa81..661d7f47 100644 --- a/src/build-output.test.ts +++ b/src/build-output.test.ts @@ -680,6 +680,15 @@ describe("Forgejo 15 native integration", () => { expect(read("navbar.tmpl")).toContain('{{.Team.NumMembers}}'); }); + it("lays out password recovery and activation like sign-in", () => { + for (const page of ["forgot_passwd.tmpl", "reset_passwd.tmpl", "activate.tmpl"]) { + const template = fs.readFileSync(path.join(ROOT_DIR, "templates", "user", "auth", page), "utf-8"); + expect(template, page).toContain('
'); + expect(template, page).toContain(' { const headerStyle = fs.readFileSync(path.join(ROOT_DIR, "styles", "templates", "repo", "header.ts"), "utf-8"); const headerTemplate = fs.readFileSync(path.join(ROOT_DIR, "templates", "repo", "home_header.tmpl"), "utf-8"); diff --git a/styles/components/signin.ts b/styles/components/signin.ts index fb960645..322179ad 100644 --- a/styles/components/signin.ts +++ b/styles/components/signin.ts @@ -143,6 +143,11 @@ const registration = css` .signin-footer { text-align: center; } + /* Recovery and activation forms submit with a full-width button, as sign-in does. */ + .ui.attached.segment > .inline.field > .ui.primary.button { + width: 100%; + margin: 0; + } } `; diff --git a/templates/user/auth/activate.tmpl b/templates/user/auth/activate.tmpl new file mode 100644 index 00000000..a80f66dc --- /dev/null +++ b/templates/user/auth/activate.tmpl @@ -0,0 +1,60 @@ +{{/* Forgejo 17's account activation page in the sign-in page's layout: the logo and title over the form. */}} +{{template "base/head" .}} +
+
+
+ +
+ {{template "base/alert" .}} + {{if .IsActivatePage}} + {{if .ServiceNotEnabled}} +

{{ctx.Locale.Tr "auth.disable_register_mail"}}

+ {{else if .ResendLimited}} +

{{ctx.Locale.Tr "auth.resent_limit_prompt"}}

+ {{else}} +

{{ctx.Locale.Tr "auth.confirmation_mail_sent_prompt" .SignedUser.Email .ActiveCodeLives}}

+ {{end}} + {{else}} + {{if .NeedsPassword}} +
+ + +
+
+ +
+ + {{else if .IsSendRegisterMail}} +

{{ctx.Locale.Tr "auth.confirmation_mail_sent_prompt" .Email .ActiveCodeLives}}

+ {{else if .IsCodeInvalid}} +

{{ctx.Locale.Tr "auth.invalid_code"}}

+ {{else if .IsPasswordInvalid}} +

{{ctx.Locale.Tr "auth.invalid_password"}}

+ {{else if .ManualActivationOnly}} +

{{ctx.Locale.Tr "auth.manual_activation_only"}}

+ {{else}} +

{{ctx.Locale.Tr "auth.has_unconfirmed_mail" .SignedUser.Name .SignedUser.Email}}

+
+
+ {{ctx.Locale.Tr "auth.change_unconfirmed_email_summary"}} + +

{{ctx.Locale.Tr "auth.change_unconfirmed_email"}}

+
+ + +
+
+ +
+ +
+ {{end}} + {{end}} +
+
+
+
+{{template "base/footer" .}} diff --git a/templates/user/auth/forgot_passwd.tmpl b/templates/user/auth/forgot_passwd.tmpl new file mode 100644 index 00000000..aac95f37 --- /dev/null +++ b/templates/user/auth/forgot_passwd.tmpl @@ -0,0 +1,38 @@ +{{/* Forgejo 17's password recovery page in the sign-in page's layout: the logo and title over the form. */}} +{{template "base/head" .}} +
+
+
+ +
+ {{template "base/alert" .}} + {{if .IsResetSent}} +

{{ctx.Locale.Tr "auth.reset_password_mail_sent_prompt" .Email .ResetPwdCodeLives}}

+ {{else if .IsResetRequest}} +
+ + +
+
+
+ +
+ {{else if .IsResetDisable}} +

+ {{if $.IsAdmin}} + {{ctx.Locale.Tr "auth.disable_forgot_password_mail_admin"}} + {{else}} + {{ctx.Locale.Tr "auth.disable_forgot_password_mail"}} + {{end}} +

+ {{else if .ResendLimited}} +

{{ctx.Locale.Tr "auth.resent_limit_prompt"}}

+ {{end}} +
+
+
+
+{{template "base/footer" .}} diff --git a/templates/user/auth/reset_passwd.tmpl b/templates/user/auth/reset_passwd.tmpl new file mode 100644 index 00000000..783da430 --- /dev/null +++ b/templates/user/auth/reset_passwd.tmpl @@ -0,0 +1,64 @@ +{{/* Forgejo 17's password reset page in the sign-in page's layout: the logo and title over the form. */}} +{{template "base/head" .}} +
+
+
+ + +
+ {{template "base/alert" .}} + {{if .user_email}} +
+ + +
+ {{end}} + {{if .IsResetForm}} +
+ + +
+ {{if not .user_signed_in}} +
+
+ + +
+
+ {{end}} + {{if .has_two_factor}} +

+ {{ctx.Locale.Tr "twofa"}} +

+
{{ctx.Locale.Tr "settings.twofa_is_enrolled"}}
+ {{if .scratch_code}} +
+ + +
+ + {{else}} +
+ + +
+ {{end}} + {{end}} +
+
+ + {{if and .has_two_factor (not .scratch_code)}} + {{ctx.Locale.Tr "auth.use_scratch_code"}} + {{end}} +
+ {{else}} +

{{ctx.Locale.Tr "auth.invalid_code_forgot_password" (printf "%s/user/forgot_password" AppSubUrl)}}

+ {{end}} +
+
+
+
+{{template "base/footer" .}}